Bug 1173320 - patch 5/8 - Cleanup manual string path management, r=smaug
☠☠ backed out by de7baace275a ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Sat, 19 Mar 2016 22:29:47 +0100
changeset 289574 8bf8e2fcedad3e92c25533087400e106d58bf3aa
parent 289573 3de390c6f47f7650bc5dcb0d1fde80660ff97a28
child 289575 23b0e55ff1db18caef396b2fa64e1b25b9a7dc44
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1173320
milestone48.0a1
Bug 1173320 - patch 5/8 - Cleanup manual string path management, r=smaug
dom/devicestorage/DeviceStorage.h
dom/devicestorage/nsDeviceStorage.cpp
dom/filesystem/CreateFileTask.cpp
dom/filesystem/DeviceStorageFileSystem.cpp
dom/filesystem/Directory.cpp
dom/filesystem/FileSystemBase.cpp
dom/filesystem/FileSystemBase.h
dom/filesystem/FileSystemPermissionRequest.cpp
dom/filesystem/FileSystemTaskBase.cpp
dom/filesystem/FileSystemUtils.cpp
dom/filesystem/FileSystemUtils.h
dom/filesystem/GetDirectoryListingTask.cpp
dom/filesystem/GetDirectoryListingTask.h
dom/filesystem/OSFileSystem.cpp
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -96,18 +96,19 @@ public:
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   bool IsAvailable();
   void GetFullPath(nsAString& aFullPath);
 
   // we want to make sure that the names of file can't reach
   // outside of the type of storage the user asked for.
-  bool IsSafePath();
-  bool IsSafePath(const nsAString& aPath);
+  bool IsSafePath() const;
+  bool ValidateAndSplitPath(const nsAString& aPath,
+                            nsTArray<nsString>* aParts = nullptr) const;
 
   void Dump(const char* label);
 
   nsresult Remove();
   nsresult Write(nsIInputStream* aInputStream);
   nsresult Write(InfallibleTArray<uint8_t>& bits);
   nsresult Append(nsIInputStream* aInputStream);
   nsresult Append(nsIInputStream* aInputStream,
@@ -132,17 +133,16 @@ public:
 
   nsresult CalculateSizeAndModifiedDate();
   nsresult CalculateMimeType();
   nsresult CreateFileDescriptor(mozilla::ipc::FileDescriptor& aFileDescriptor);
 
 private:
   ~DeviceStorageFile() {}
   void Init();
-  void NormalizeFilePath();
   void AppendRelativePath(const nsAString& aPath);
   void AccumDirectoryUsage(nsIFile* aFile,
                            uint64_t* aPicturesSoFar,
                            uint64_t* aVideosSoFar,
                            uint64_t* aMusicSoFar,
                            uint64_t* aTotalSoFar);
 };
 
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -25,16 +25,17 @@
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/Services.h"
 #include "mozilla/ipc/BackgroundUtils.h" // for PrincipalInfoToPrincipal
 
 #include "nsArrayUtils.h"
 #include "nsAutoPtr.h"
+#include "nsCharSeparatedTokenizer.h"
 #include "nsGlobalWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIFile.h"
 #include "nsIDirectoryEnumerator.h"
 #include "nsNetUtil.h"
 #include "nsIOutputStream.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIPrincipal.h"
@@ -71,20 +72,45 @@
 #define DEFAULT_THREAD_TIMEOUT_MS 30000
 #define STORAGE_CHANGE_EVENT "change"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::devicestorage;
 using namespace mozilla::ipc;
 
-namespace mozilla {
+namespace mozilla
+{
   MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc, PRFileDesc, PR_Close);
 } // namespace mozilla
 
+namespace {
+
+void
+NormalizeFilePath(nsAString& aPath)
+{
+#if defined(XP_WIN)
+  char16_t* cur = aPath.BeginWriting();
+  char16_t* end = aPath.EndWriting();
+  for (; cur < end; ++cur) {
+    if (char16_t('\\') == *cur) {
+      *cur = FILESYSTEM_DOM_PATH_SEPARATOR_CHAR;
+    }
+  }
+#endif
+}
+
+bool
+TokenizerIgnoreNothing(char16_t /* aChar */)
+{
+  return false;
+}
+
+} // anonymous namespace
+
 StaticAutoPtr<DeviceStorageUsedSpaceCache>
   DeviceStorageUsedSpaceCache::sDeviceStorageUsedSpaceCache;
 
 DeviceStorageUsedSpaceCache::DeviceStorageUsedSpaceCache()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mIOThread = new LazyIdleThread(
@@ -505,32 +531,33 @@ DeviceStorageFile::DeviceStorageFile(con
   , mLength(UINT64_MAX)
   , mLastModifiedDate(UINT64_MAX)
 {
   Init();
   AppendRelativePath(mRootDir);
   if (!mPath.EqualsLiteral("")) {
     AppendRelativePath(mPath);
   }
-  NormalizeFilePath();
+
+  NormalizeFilePath(mPath);
 }
 
 DeviceStorageFile::DeviceStorageFile(const nsAString& aStorageType,
                                      const nsAString& aStorageName,
                                      const nsAString& aPath)
   : mStorageType(aStorageType)
   , mStorageName(aStorageName)
   , mPath(aPath)
   , mEditable(false)
   , mLength(UINT64_MAX)
   , mLastModifiedDate(UINT64_MAX)
 {
   Init();
   AppendRelativePath(aPath);
-  NormalizeFilePath();
+  NormalizeFilePath(mPath);
 }
 
 DeviceStorageFile::DeviceStorageFile(const nsAString& aStorageType,
                                      const nsAString& aStorageName)
   : mStorageType(aStorageType)
   , mStorageName(aStorageName)
   , mEditable(false)
   , mLength(UINT64_MAX)
@@ -729,85 +756,100 @@ DeviceStorageFile::CreateUnique(const ns
   }
 
   return dsf.forget();
 }
 
 void
 DeviceStorageFile::SetPath(const nsAString& aPath) {
   mPath.Assign(aPath);
-  NormalizeFilePath();
+  NormalizeFilePath(mPath);
 }
 
 void
 DeviceStorageFile::SetEditable(bool aEditable) {
   mEditable = aEditable;
 }
 
 // we want to make sure that the names of file can't reach
 // outside of the type of storage the user asked for.
 bool
-DeviceStorageFile::IsSafePath()
+DeviceStorageFile::IsSafePath() const
 {
-  return IsSafePath(mRootDir) && IsSafePath(mPath);
+  return ValidateAndSplitPath(mRootDir) && ValidateAndSplitPath(mPath);
 }
 
 bool
-DeviceStorageFile::IsSafePath(const nsAString& aPath)
+DeviceStorageFile::ValidateAndSplitPath(const nsAString& aPath,
+                                        nsTArray<nsString>* aParts) const
 {
   nsAString::const_iterator start, end;
   aPath.BeginReading(start);
   aPath.EndReading(end);
 
   // if the path is a '~' or starts with '~/', return false.
   NS_NAMED_LITERAL_STRING(tilde, "~");
   NS_NAMED_LITERAL_STRING(tildeSlash, "~/");
   if (aPath.Equals(tilde) ||
       StringBeginsWith(aPath, tildeSlash)) {
     NS_WARNING("Path name starts with tilde!");
     return false;
-   }
-  // split on /.  if any token is "", ., or .., return false.
-  NS_ConvertUTF16toUTF8 cname(aPath);
-  char* buffer = cname.BeginWriting();
-  const char* token;
-
-  while ((token = nsCRT::strtok(buffer, "/", &buffer))) {
-    if (PL_strcmp(token, "") == 0 ||
-        PL_strcmp(token, ".") == 0 ||
-        PL_strcmp(token, "..") == 0 ) {
+  }
+
+  NS_NAMED_LITERAL_STRING(kCurrentDir, ".");
+  NS_NAMED_LITERAL_STRING(kParentDir, "..");
+
+  // Split path and check each path component.
+  nsCharSeparatedTokenizerTemplate<TokenizerIgnoreNothing>
+    tokenizer(aPath, FILESYSTEM_DOM_PATH_SEPARATOR_CHAR);
+
+  while (tokenizer.hasMoreTokens()) {
+    nsDependentSubstring pathComponent = tokenizer.nextToken();
+    // The path containing empty components, such as "foo//bar", is invalid.
+    // We don't allow paths, such as "../foo", "foo/./bar" and "foo/../bar",
+    // to walk up the directory.
+    if (pathComponent.IsEmpty() ||
+        pathComponent.Equals(kCurrentDir) ||
+        pathComponent.Equals(kParentDir)) {
       return false;
     }
+
+    if (aParts) {
+      aParts->AppendElement(pathComponent);
+    }
   }
   return true;
 }
 
 void
-DeviceStorageFile::NormalizeFilePath() {
-  FileSystemUtils::LocalPathToNormalizedPath(mPath, mPath);
-}
-
-void
-DeviceStorageFile::AppendRelativePath(const nsAString& aPath) {
+DeviceStorageFile::AppendRelativePath(const nsAString& aPath)
+{
   if (!mFile) {
     return;
   }
-  if (!IsSafePath(aPath)) {
+
+  nsTArray<nsString> parts;
+
+  if (!ValidateAndSplitPath(aPath, &parts)) {
     // All of the APIs (in the child) do checks to verify that the path is
     // valid and return PERMISSION_DENIED if a non-safe path is entered.
     // This check is done in the parent and prevents a compromised
     // child from bypassing the check. It shouldn't be possible for this
     // code path to be taken with a non-compromised child.
     NS_WARNING("Unsafe path detected - ignoring");
     NS_WARNING(NS_LossyConvertUTF16toASCII(aPath).get());
     return;
   }
-  nsString localPath;
-  FileSystemUtils::NormalizedPathToLocalPath(aPath, localPath);
-  mFile->AppendRelativePath(localPath);
+
+  for (uint32_t i = 0; i < parts.Length(); ++i) {
+    nsresult rv = mFile->AppendRelativePath(parts[i]);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return;
+    }
+  }
 }
 
 nsresult
 DeviceStorageFile::CreateFileDescriptor(FileDescriptor& aFileDescriptor)
 {
   if (!mFile) {
     return NS_ERROR_FAILURE;
   }
--- a/dom/filesystem/CreateFileTask.cpp
+++ b/dom/filesystem/CreateFileTask.cpp
@@ -163,18 +163,18 @@ CreateFileTask::GetRequestParams(const n
 
   aRv = mTargetPath->GetPath(param.realPath());
   if (NS_WARN_IF(aRv.Failed())) {
     return param;
   }
 
   param.replace() = mReplace;
   if (mBlobData) {
-    BlobChild* actor
-      = ContentChild::GetSingleton()->GetOrCreateActorForBlob(mBlobData);
+    BlobChild* actor =
+      ContentChild::GetSingleton()->GetOrCreateActorForBlob(mBlobData);
     if (actor) {
       param.data() = actor;
     }
   } else {
     param.data() = mArrayData;
   }
   return param;
 }
@@ -200,29 +200,30 @@ CreateFileTask::SetSuccessRequestResult(
   FileSystemFileResponse r = aValue;
   BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
   mTargetBlobImpl = actor->GetBlobImpl();
 }
 
 nsresult
 CreateFileTask::Work()
 {
-  class AutoClose
+  class MOZ_RAII AutoClose final
   {
   public:
     explicit AutoClose(nsIOutputStream* aStream)
       : mStream(aStream)
     {
       MOZ_ASSERT(aStream);
     }
 
     ~AutoClose()
     {
       mStream->Close();
     }
+
   private:
     nsCOMPtr<nsIOutputStream> mStream;
   };
 
   MOZ_ASSERT(XRE_IsParentProcess(),
              "Only call from parent process!");
   MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
 
--- a/dom/filesystem/DeviceStorageFileSystem.cpp
+++ b/dom/filesystem/DeviceStorageFileSystem.cpp
@@ -16,19 +16,18 @@
 #include "nsDeviceStorage.h"
 #include "nsIFile.h"
 #include "nsPIDOMWindow.h"
 #include "nsGlobalWindow.h"
 
 namespace mozilla {
 namespace dom {
 
-DeviceStorageFileSystem::DeviceStorageFileSystem(
-  const nsAString& aStorageType,
-  const nsAString& aStorageName)
+DeviceStorageFileSystem::DeviceStorageFileSystem(const nsAString& aStorageType,
+                                                 const nsAString& aStorageName)
   : mWindowId(0)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
 
   mStorageType = aStorageType;
   mStorageName = aStorageName;
 
   mRequiresPermissionChecks =
@@ -46,19 +45,16 @@ DeviceStorageFileSystem::DeviceStorageFi
                                              getter_AddRefs(rootFile));
 
   NS_WARN_IF(!rootFile || NS_FAILED(rootFile->GetPath(mLocalRootPath)));
 
   if (!XRE_IsParentProcess()) {
     return;
   }
 
-  FileSystemUtils::LocalPathToNormalizedPath(mLocalRootPath,
-    mNormalizedLocalRootPath);
-
   // DeviceStorageTypeChecker is a singleton object and must be initialized on
   // the main thread. We initialize it here so that we can use it on the worker
   // thread.
   DebugOnly<DeviceStorageTypeChecker*> typeChecker
     = DeviceStorageTypeChecker::CreateOrGet();
   MOZ_ASSERT(typeChecker);
 }
 
@@ -100,22 +96,25 @@ DeviceStorageFileSystem::GetRootName(nsA
 
 bool
 DeviceStorageFileSystem::IsSafeFile(nsIFile* aFile) const
 {
   MOZ_ASSERT(XRE_IsParentProcess(),
              "Should be on parent process!");
   MOZ_ASSERT(aFile);
 
-  // Check if this file belongs to this storage.
-  nsAutoString path;
-  if (NS_FAILED(aFile->GetPath(path))) {
+  nsCOMPtr<nsIFile> rootPath;
+  nsresult rv = NS_NewLocalFile(GetLocalRootPath(), false,
+                                getter_AddRefs(rootPath));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
-  if (!LocalPathToRealPath(path, path)) {
+
+  // Check if this file belongs to this storage.
+  if (NS_WARN_IF(!FileSystemUtils::IsDescendantPath(rootPath, aFile))) {
     return false;
   }
 
   // Check if the file type is compatible with the storage type.
   DeviceStorageTypeChecker* typeChecker
     = DeviceStorageTypeChecker::CreateOrGet();
   MOZ_ASSERT(typeChecker);
   return typeChecker->Check(mStorageType, aFile);
--- a/dom/filesystem/Directory.cpp
+++ b/dom/filesystem/Directory.cpp
@@ -33,16 +33,22 @@
 #endif
 
 namespace mozilla {
 namespace dom {
 
 namespace {
 
 bool
+TokenizerIgnoreNothing(char16_t /* aChar */)
+{
+  return false;
+}
+
+bool
 IsValidRelativeDOMPath(const nsString& aPath, nsTArray<nsString>& aParts)
 {
   // We don't allow empty relative path to access the root.
   if (aPath.IsEmpty()) {
     return false;
   }
 
   // Leading and trailing "/" are not allowed.
@@ -50,17 +56,19 @@ IsValidRelativeDOMPath(const nsString& a
       aPath.Last() == FILESYSTEM_DOM_PATH_SEPARATOR_CHAR) {
     return false;
   }
 
   NS_NAMED_LITERAL_STRING(kCurrentDir, ".");
   NS_NAMED_LITERAL_STRING(kParentDir, "..");
 
   // Split path and check each path component.
-  nsCharSeparatedTokenizer tokenizer(aPath, FILESYSTEM_DOM_PATH_SEPARATOR_CHAR);
+  nsCharSeparatedTokenizerTemplate<TokenizerIgnoreNothing>
+    tokenizer(aPath, FILESYSTEM_DOM_PATH_SEPARATOR_CHAR);
+
   while (tokenizer.hasMoreTokens()) {
     nsDependentSubstring pathComponent = tokenizer.nextToken();
     // The path containing empty components, such as "foo//bar", is invalid.
     // We don't allow paths, such as "../foo", "foo/./bar" and "foo/../bar",
     // to walk up the directory.
     if (pathComponent.IsEmpty() ||
         pathComponent.Equals(kCurrentDir) ||
         pathComponent.Equals(kParentDir)) {
--- a/dom/filesystem/FileSystemBase.cpp
+++ b/dom/filesystem/FileSystemBase.cpp
@@ -94,25 +94,10 @@ FileSystemBase::IsSafeFile(nsIFile* aFil
 }
 
 bool
 FileSystemBase::IsSafeDirectory(Directory* aDir) const
 {
   return false;
 }
 
-bool
-FileSystemBase::LocalPathToRealPath(const nsAString& aLocalPath,
-                                    nsAString& aRealPath) const
-{
-  nsAutoString path;
-  FileSystemUtils::LocalPathToNormalizedPath(aLocalPath, path);
-  if (!FileSystemUtils::IsDescendantPath(mNormalizedLocalRootPath, path)) {
-    aRealPath.Truncate();
-    return false;
-  }
-
-  aRealPath = Substring(path, mNormalizedLocalRootPath.Length());
-  return true;
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/filesystem/FileSystemBase.h
+++ b/dom/filesystem/FileSystemBase.h
@@ -82,28 +82,22 @@ public:
 
   // CC methods
   virtual void Unlink() {}
   virtual void Traverse(nsCycleCollectionTraversalCallback &cb) {}
 
 protected:
   virtual ~FileSystemBase();
 
-  bool
-  LocalPathToRealPath(const nsAString& aLocalPath, nsAString& aRealPath) const;
-
   // The local path of the root (i.e. the OS path, with OS path separators, of
   // the OS directory that acts as the root of this OSFileSystem).
   // Only available in the parent process.
   // In the child process, we don't use it and its value should be empty.
   nsString mLocalRootPath;
 
-  // The same, but with path separators normalized to "/".
-  nsString mNormalizedLocalRootPath;
-
   bool mShutdown;
 
   // The permission name required to access the file system.
   nsCString mPermission;
 
   bool mRequiresPermissionChecks;
 };
 
--- a/dom/filesystem/FileSystemPermissionRequest.cpp
+++ b/dom/filesystem/FileSystemPermissionRequest.cpp
@@ -10,31 +10,31 @@
 #include "mozilla/dom/FileSystemUtils.h"
 #include "nsIDocument.h"
 #include "nsPIDOMWindow.h"
 #include "nsContentPermissionHelper.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_ISUPPORTS(FileSystemPermissionRequest, nsIRunnable, nsIContentPermissionRequest)
+NS_IMPL_ISUPPORTS(FileSystemPermissionRequest, nsIRunnable,
+                  nsIContentPermissionRequest)
 
 // static
 void
 FileSystemPermissionRequest::RequestForTask(FileSystemTaskBase* aTask)
 {
   MOZ_ASSERT(aTask, "aTask should not be null!");
   MOZ_ASSERT(NS_IsMainThread());
   RefPtr<FileSystemPermissionRequest> request =
     new FileSystemPermissionRequest(aTask);
   NS_DispatchToCurrentThread(request);
 }
 
-FileSystemPermissionRequest::FileSystemPermissionRequest(
-  FileSystemTaskBase* aTask)
+FileSystemPermissionRequest::FileSystemPermissionRequest(FileSystemTaskBase* aTask)
   : mTask(aTask)
 {
   MOZ_ASSERT(mTask, "aTask should not be null!");
   MOZ_ASSERT(NS_IsMainThread());
 
   mTask->GetPermissionAccessType(mPermissionAccess);
 
   RefPtr<FileSystemBase> filesystem = mTask->GetFileSystem();
--- a/dom/filesystem/FileSystemTaskBase.cpp
+++ b/dom/filesystem/FileSystemTaskBase.cpp
@@ -18,17 +18,17 @@
 #include "mozilla/unused.h"
 #include "nsProxyRelease.h"
 
 namespace mozilla {
 namespace dom {
 
 namespace {
 
-class FileSystemReleaseRunnable : public nsRunnable
+class FileSystemReleaseRunnable final : public nsRunnable
 {
 public:
   explicit FileSystemReleaseRunnable(RefPtr<FileSystemBase>& aDoomed)
     : mDoomed(nullptr)
   {
     aDoomed.swap(mDoomed);
   }
 
--- a/dom/filesystem/FileSystemUtils.cpp
+++ b/dom/filesystem/FileSystemUtils.cpp
@@ -1,77 +1,20 @@
 /* -*- 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 "mozilla/dom/FileSystemUtils.h"
 
-#include "nsXULAppAPI.h"
-
 namespace mozilla {
 namespace dom {
 
-// static
-void
-FileSystemUtils::LocalPathToNormalizedPath(const nsAString& aLocal,
-                                           nsAString& aNorm)
-{
-  nsString result;
-  result = aLocal;
-#if defined(XP_WIN)
-  char16_t* cur = result.BeginWriting();
-  char16_t* end = result.EndWriting();
-  for (; cur < end; ++cur) {
-    if (char16_t('\\') == *cur)
-      *cur = char16_t('/');
-  }
-#endif
-  aNorm = result;
-}
-
-// static
-void
-FileSystemUtils::NormalizedPathToLocalPath(const nsAString& aNorm,
-                                           nsAString& aLocal)
-{
-  nsString result;
-  result = aNorm;
-#if defined(XP_WIN)
-  char16_t* cur = result.BeginWriting();
-  char16_t* end = result.EndWriting();
-  for (; cur < end; ++cur) {
-    if (char16_t('/') == *cur)
-      *cur = char16_t('\\');
-  }
-#endif
-  aLocal = result;
-}
-
-// static
-bool
-FileSystemUtils::IsDescendantPath(const nsAString& aPath,
-                                  const nsAString& aDescendantPath)
-{
-  // The descendant path should begin with its ancestor path.
-  nsAutoString prefix;
-  prefix = aPath + NS_LITERAL_STRING(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL);
-
-  // Check the sub-directory path to see if it has the parent path as prefix.
-  if (aDescendantPath.Length() < prefix.Length() ||
-      !StringBeginsWith(aDescendantPath, prefix)) {
-    return false;
-  }
-
-  return true;
-}
-
-// static
-bool
+/* static */ bool
 FileSystemUtils::IsDescendantPath(nsIFile* aFile,
                                   nsIFile* aDescendantFile)
 {
   nsAutoString path;
   nsresult rv = aFile->GetPath(path);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
--- a/dom/filesystem/FileSystemUtils.h
+++ b/dom/filesystem/FileSystemUtils.h
@@ -2,54 +2,34 @@
 /* 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/. */
 
 #ifndef mozilla_dom_FileSystemUtils_h
 #define mozilla_dom_FileSystemUtils_h
 
-#include "nsString.h"
+class nsIFile;
 
 namespace mozilla {
 namespace dom {
 
 #define FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL "/"
 #define FILESYSTEM_DOM_PATH_SEPARATOR_CHAR '/'
 
 /*
  * This class is for error handling.
  * All methods in this class are static.
  */
 class FileSystemUtils
 {
 public:
   /*
-   * Convert the path separator to "/".
-   */
-  static void
-  LocalPathToNormalizedPath(const nsAString& aLocal, nsAString& aNorm);
-
-  /*
-   * Convert the normalized path separator "/" to the system dependent path
-   * separator, which is "/" on Mac and Linux, and "\" on Windows.
-   */
-  static void
-  NormalizedPathToLocalPath(const nsAString& aNorm, nsAString& aLocal);
-
-  /*
    * Return true if aDescendantPath is a descendant of aPath.
    */
   static bool
   IsDescendantPath(nsIFile* aPath, nsIFile* aDescendantPath);
-
-  /*
-   * Return true if aDescendantPath is a descendant of aPath. Both aPath and
-   * aDescendantPath are absolute DOM path.
-   */
-  static bool
-  IsDescendantPath(const nsAString& aPath, const nsAString& aDescendantPath);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_FileSystemUtils_h
--- a/dom/filesystem/GetDirectoryListingTask.cpp
+++ b/dom/filesystem/GetDirectoryListingTask.cpp
@@ -123,25 +123,16 @@ GetDirectoryListingTask::GetRequestParam
     return FileSystemGetDirectoryListingParams();
   }
 
   return FileSystemGetDirectoryListingParams(aSerializedDOMPath, path,
                                              mType == Directory::eDOMRootDirectory,
                                              mFilters);
 }
 
-void
-GetDirectoryListingTask::CreateNormalizedRelativePath(const nsAString& aPath,
-                                                      nsAString& aRelativePath) const
-{
-  uint32_t rootPathLen = mFileSystem->GetLocalRootPath().Length();
-  FileSystemUtils::LocalPathToNormalizedPath(
-    Substring(aPath, rootPathLen, aPath.Length() - rootPathLen), aRelativePath);
-}
-
 FileSystemResponseValue
 GetDirectoryListingTask::GetSuccessRequestResult(ErrorResult& aRv) const
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
 
   InfallibleTArray<PBlobParent*> blobs;
 
   nsTArray<FileSystemDirectoryListingResponseData> inputs;
@@ -361,20 +352,21 @@ GetDirectoryListingTask::HandlerCallback
         mPromise->MaybeReject(rv);
         mPromise = nullptr;
         return;
       }
 
       MOZ_ASSERT(FileSystemUtils::IsDescendantPath(rootPath, directoryPath));
 #endif
 
-      RefPtr<Directory> directory = Directory::Create(mFileSystem->GetParentObject(),
-                                                      directoryPath,
-                                                      Directory::eNotDOMRootDirectory,
-                                                      mFileSystem);
+      RefPtr<Directory> directory =
+        Directory::Create(mFileSystem->GetParentObject(),
+                          directoryPath,
+                          Directory::eNotDOMRootDirectory,
+                          mFileSystem);
       MOZ_ASSERT(directory);
 
       // Propogate mFilter onto sub-Directory object:
       directory->SetContentFilters(mFilters);
       listing[i].SetAsDirectory() = directory;
     } else {
       MOZ_ASSERT(mTargetData[i].mType == Directory::BlobImplOrDirectoryPath::eBlobImpl);
       listing[i].SetAsFile() =
--- a/dom/filesystem/GetDirectoryListingTask.h
+++ b/dom/filesystem/GetDirectoryListingTask.h
@@ -65,20 +65,16 @@ private:
                           ErrorResult& aRv) override;
 
   virtual nsresult
   Work() override;
 
   virtual void
   HandlerCallback() override;
 
-  void
-  CreateNormalizedRelativePath(const nsAString& aPath,
-                               nsAString& aRelativePath) const;
-
   RefPtr<Promise> mPromise;
   nsCOMPtr<nsIFile> mTargetPath;
   nsString mFilters;
   Directory::DirectoryType mType;
 
   // We cannot store File or Directory objects bacause this object is created
   // on a different thread and File and Directory are not thread-safe.
   nsTArray<Directory::BlobImplOrDirectoryPath> mTargetData;
--- a/dom/filesystem/OSFileSystem.cpp
+++ b/dom/filesystem/OSFileSystem.cpp
@@ -15,18 +15,16 @@
 #include "nsIFile.h"
 
 namespace mozilla {
 namespace dom {
 
 OSFileSystem::OSFileSystem(const nsAString& aRootDir)
 {
   mLocalRootPath = aRootDir;
-  FileSystemUtils::LocalPathToNormalizedPath(mLocalRootPath,
-                                             mNormalizedLocalRootPath);
 
   // Non-mobile devices don't have the concept of separate permissions to
   // access different parts of devices storage like Pictures, or Videos, etc.
   mRequiresPermissionChecks = false;
 
 #ifdef DEBUG
   mPermission.AssignLiteral("never-used");
 #endif