Bug 959591 - Allow device storage media dirs to be overridden (esp useful for desktop). r=fabrice
authorDave Hylands <dhylands@mozilla.com>
Wed, 12 Mar 2014 14:15:03 -0700
changeset 173267 cdcc9accb82216d155aa2fa704bde0cbc2afe82b
parent 173266 4ce8fec4e2bcf9fa16e03146f03b79d9f6b0c764
child 173268 edfea182712fcbbda19ccf436e506076b9784f49
push id26397
push userkwierso@gmail.com
push dateThu, 13 Mar 2014 02:51:22 +0000
treeherdermozilla-central@c12c92db5588 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice
bugs959591
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 959591 - Allow device storage media dirs to be overridden (esp useful for desktop). r=fabrice
dom/devicestorage/nsDeviceStorage.cpp
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -43,16 +43,17 @@
 #include "nsCRT.h"
 #include "nsIObserverService.h"
 #include "GeneratedEvents.h"
 #include "nsIMIMEService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIPermissionManager.h"
 #include "nsIStringBundle.h"
 #include "nsIDocument.h"
+#include "nsPrintfCString.h"
 #include <algorithm>
 #include "private/pprio.h"
 #include "nsContentPermissionHelper.h"
 
 #include "mozilla/dom/DeviceStorageBinding.h"
 
 // Microsoft's API Name hackery sucks
 #undef CreateEvent
@@ -189,17 +190,17 @@ public:
 #if !defined(MOZ_WIDGET_GONK)
   nsCOMPtr<nsIFile> pictures;
   nsCOMPtr<nsIFile> videos;
   nsCOMPtr<nsIFile> music;
   nsCOMPtr<nsIFile> sdcard;
 #endif
   nsCOMPtr<nsIFile> apps;
   nsCOMPtr<nsIFile> crashes;
-  nsCOMPtr<nsIFile> temp;
+  nsCOMPtr<nsIFile> overrideRootDir;
 };
 
 static StaticRefPtr<GlobalDirs> sDirs;
 
 StaticAutoPtr<DeviceStorageTypeChecker>
   DeviceStorageTypeChecker::sDeviceStorageTypeChecker;
 
 DeviceStorageTypeChecker::DeviceStorageTypeChecker()
@@ -673,24 +674,45 @@ InitDirs()
     NS_NewLocalFile(NS_LITERAL_STRING("/data/b2g/mozilla/Crash Reports"),
                                       false,
                                       getter_AddRefs(sDirs->crashes));
 #endif
   }
 
   if (mozilla::Preferences::GetBool("device.storage.testing", false)) {
     dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile),
-                    getter_AddRefs(sDirs->temp));
-    if (sDirs->temp) {
-      sDirs->temp->AppendRelativeNativePath(
+                    getter_AddRefs(sDirs->overrideRootDir));
+    if (sDirs->overrideRootDir) {
+      sDirs->overrideRootDir->AppendRelativeNativePath(
         NS_LITERAL_CSTRING("device-storage-testing"));
-      sDirs->temp->Create(nsIFile::DIRECTORY_TYPE, 0777);
-      sDirs->temp->Normalize();
+    }
+  } else {
+    // For users running on desktop, it's convenient to be able to override
+    // all of the directories to point to a single tree, much like what happens
+    // on a real device.
+    const nsAdoptingString& overrideRootDir =
+      mozilla::Preferences::GetString("device.storage.overrideRootDir");
+    if (overrideRootDir) {
+      NS_NewLocalFile(overrideRootDir, false,
+                      getter_AddRefs(sDirs->overrideRootDir));
     }
   }
+
+  if (sDirs->overrideRootDir) {
+    nsresult rv
+      = sDirs->overrideRootDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
+    if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
+      nsString path;
+      sDirs->overrideRootDir->GetPath(path);
+      nsPrintfCString msg("DeviceStorage: Unable to create directory '%s'",
+                          NS_LossyConvertUTF16toASCII(path).get());
+      NS_WARNING(msg.get());
+    }
+    sDirs->overrideRootDir->Normalize();
+  }
 }
 
 void
 DeviceStorageFile::GetFullPath(nsAString &aFullPath)
 {
   aFullPath.Truncate();
   if (!mStorageName.EqualsLiteral("")) {
     aFullPath.AppendLiteral("/");
@@ -710,16 +732,17 @@ DeviceStorageFile::GetFullPath(nsAString
 // should be calculated in this method.
 void
 DeviceStorageFile::GetRootDirectoryForType(const nsAString& aStorageType,
                                            const nsAString& aStorageName,
                                            nsIFile** aFile)
 {
   nsCOMPtr<nsIFile> f;
   *aFile = nullptr;
+  bool allowOverride = true;
 
   InitDirs();
 
 #ifdef MOZ_WIDGET_GONK
   nsString volMountPoint;
   if (DeviceStorageTypeChecker::IsVolumeBased(aStorageType)) {
     nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
     NS_ENSURE_TRUE_VOID(vs);
@@ -756,41 +779,44 @@ DeviceStorageFile::GetRootDirectoryForTy
 #else
     f = sDirs->music;
 #endif
   }
 
   // Apps directory
   else if (aStorageType.EqualsLiteral(DEVICESTORAGE_APPS)) {
     f = sDirs->apps;
+    allowOverride = false;
   }
 
    // default SDCard
    else if (aStorageType.EqualsLiteral(DEVICESTORAGE_SDCARD)) {
 #ifdef MOZ_WIDGET_GONK
      NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
 #else
      f = sDirs->sdcard;
 #endif
   }
 
   // crash reports directory.
   else if (aStorageType.EqualsLiteral(DEVICESTORAGE_CRASHES)) {
     f = sDirs->crashes;
+    allowOverride = false;
   } else {
     // Not a storage type that we recognize. Return null
     return;
   }
 
   // In testing, we default all device storage types to a temp directory.
-  // sDirs->temp will only have been initialized (in InitDirs) if the
-  // preference device.storage.testing was set to true. We can't test the
-  // preference directly here, since we may not be on the main thread.
-  if (sDirs->temp) {
-    f = sDirs->temp;
+  // sDirs->overrideRootDir will only have been initialized (in InitDirs)
+  // if the preference device.storage.testing was set to true, or if
+  // device.storage.overrideRootDir is set. We can't test the preferences
+  // directly here, since we may not be on the main thread.
+  if (allowOverride && sDirs->overrideRootDir) {
+    f = sDirs->overrideRootDir;
   }
 
   if (f) {
     f->Clone(aFile);
   }
 }
 
 //static