Bug 1536796 - P1 - Introduce a flag (useDOSDevicePathSyntax) to nsILocalFileWin and a method (QM_NewLocalFile) to QuotaCommon; draft
authorTom Tung <ttung@mozilla.com>
Fri, 27 Mar 2020 10:15:57 +0000
changeset 2725575 2704fad9be6005e3b02e4e0b1fe12c06d0cd1246
parent 2709207 f985871b3e622041babc71f3770275f045ae7f33
child 2725576 cde85601dea48dce7f0f0cd5c8acc42574f36a64
push id510268
push userreviewbot
push dateFri, 27 Mar 2020 10:16:22 +0000
treeherdertry@cde85601dea4 [default view] [failures only]
bugs1536796
milestone76.0a1
Bug 1536796 - P1 - Introduce a flag (useDOSDevicePathSyntax) to nsILocalFileWin and a method (QM_NewLocalFile) to QuotaCommon; Summary: Differential Revision: https://phabricator.services.mozilla.com/D67873 Test Plan: Reviewers: Subscribers: Bug #: 1536796 Differential Diff: PHID-DIFF-ogk6riscuvs2b3oq7wtl
dom/quota/QuotaCommon.cpp
dom/quota/QuotaCommon.h
xpcom/io/nsILocalFileWin.idl
xpcom/io/nsLocalFileWin.cpp
xpcom/io/nsLocalFileWin.h
--- a/dom/quota/QuotaCommon.cpp
+++ b/dom/quota/QuotaCommon.cpp
@@ -1,16 +1,23 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "QuotaCommon.h"
 
+#include "mozilla/Logging.h"  // LazyLogModule
+#include "nsIFile.h"
+#ifdef XP_WIN
+#  include "nsILocalFileWin.h"
+#endif
+#include "nsXPCOM.h"
+
 namespace mozilla {
 namespace dom {
 namespace quota {
 
 namespace {
 
 LazyLogModule gLogger("QuotaManager");
 
@@ -60,11 +67,32 @@ void AnonymizeOriginString(nsACString& a
   int32_t start = aOriginString.FindChar(':');
   if (start < 0) {
     start = 0;
   }
 
   AnonymizeCString(aOriginString, start);
 }
 
+Result<nsCOMPtr<nsIFile>, nsresult> QM_NewLocalFile(const nsAString& aPath) {
+  nsCOMPtr<nsIFile> file;
+  nsresult rv =
+      NS_NewLocalFile(aPath, /* aFollowLinks */ false, getter_AddRefs(file));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return Err(rv);
+  }
+
+#ifdef XP_WIN
+  nsCOMPtr<nsILocalFileWin> winFile = do_QueryInterface(file, &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return Err(rv);
+  }
+
+  MOZ_ASSERT(winFile);
+  winFile->SetUseDOSDevicePathSyntax(true);
+#endif
+
+  return file;
+}
+
 }  // namespace quota
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/quota/QuotaCommon.h
+++ b/dom/quota/QuotaCommon.h
@@ -71,16 +71,17 @@
     {}
 
 #  define CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(_rv) return _rv
 
 #  define RETURN_STATUS_OR_RESULT(_status, _rv) return _rv
 #endif
 
 class nsIEventTarget;
+class nsIFile;
 
 namespace mozilla {
 
 class LogModule;
 
 namespace dom {
 namespace quota {
 
@@ -157,16 +158,18 @@ void StringifyTableKeys(const T& aTable,
     }
 
     const auto& key = iter.Get()->GetKey();
 
     aResult.Append(key);
   }
 }
 
+Result<nsCOMPtr<nsIFile>, nsresult> QM_NewLocalFile(const nsAString& aPath);
+
 class IntString : public nsAutoString {
  public:
   explicit IntString(int64_t aInteger) { AppendInt(aInteger); }
 };
 
 class IntCString : public nsAutoCString {
  public:
   explicit IntCString(int64_t aInteger) { AppendInt(aInteger); }
--- a/xpcom/io/nsILocalFileWin.idl
+++ b/xpcom/io/nsILocalFileWin.idl
@@ -75,15 +75,32 @@ interface nsILocalFileWin : nsIFile
      * Set or get windows specific file attributes.
      *
      * Throws NS_ERROR_FILE_INVALID_PATH for an invalid file.
      * Throws NS_ERROR_FAILURE if the set or get fails.
      */
     attribute unsigned long fileAttributesWin;
 
     /**
+     * Setting this to true will prepend the prefix "\\?\ to all parsed file
+     * paths which match ${Disk}:/.* (regex) syntax.
+     *
+     * There are two known issues (and potential more) which can be resolved by
+     * the prefix:
+     * - In the Windows API, the maximum length for a path is MAX_PATH in
+     *   general. However, Windows API has many functions that also have Unicode
+     *   versions to permit an extended-length path for a maximum total path
+     *   length of 32,767 characters. To specify an extended-length path, use
+     *   the "\\?\"  prefix.
+     *
+     * - A path component which ends with a dot is not allowed for Windows
+     *   API. Using the "\\?\" prefix can also resolved this issue.
+     */
+    attribute boolean useDOSDevicePathSyntax;
+
+    /**
      * Identical to nsIFile::openNSPRFileDesc except it also uses the
      * FILE_SHARE_DELETE flag.
     */
     [noscript] PRFileDescStar openNSPRFileDescShareDelete(in long flags,
                                                           in long mode);
 };
 
--- a/xpcom/io/nsLocalFileWin.cpp
+++ b/xpcom/io/nsLocalFileWin.cpp
@@ -2945,16 +2945,30 @@ nsLocalFile::SetFileAttributesWin(uint32
 
   if (SetFileAttributesW(mWorkingPath.get(), dwAttrs) == 0) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsLocalFile::GetUseDOSDevicePathSyntax(bool* aUseDOSDevicePathSyntax) {
+  MOZ_ASSERT(aUseDOSDevicePathSyntax);
+
+  *aUseDOSDevicePathSyntax = mUseDOSDevicePathSyntax;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetUseDOSDevicePathSyntax(bool aUseDOSDevicePathSyntax) {
+  mUseDOSDevicePathSyntax = aUseDOSDevicePathSyntax;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsLocalFile::Reveal() {
   // This API should be main thread only
   MOZ_ASSERT(NS_IsMainThread());
 
   // make sure mResolvedPath is set
   nsresult rv = Resolve();
   if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND) {
     return rv;
--- a/xpcom/io/nsLocalFileWin.h
+++ b/xpcom/io/nsLocalFileWin.h
@@ -60,16 +60,18 @@ class nsLocalFile final : public nsILoca
 
   nsLocalFile(const nsLocalFile& aOther);
   ~nsLocalFile() {}
 
   bool mDirty;  // cached information can only be used when this is false
   bool mResolveDirty;
   bool mFollowSymlinks;  // should we follow symlinks when working on this file
 
+  bool mUseDOSDevicePathSyntax = false;
+
   // this string will always be in native format!
   nsString mWorkingPath;
 
   // this will be the resolved path of shortcuts, it will *NEVER*
   // be returned to the user
   nsString mResolvedPath;
 
   // this string, if not empty, is the *short* pathname that represents