profile/dirserviceprovider/src/nsProfileDirServiceProvider.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsProfileDirServiceProvider.h"
     7 #include "nsProfileStringTypes.h"
     8 #include "nsProfileLock.h"
     9 #include "nsIFile.h"
    10 #include "nsDirectoryServiceDefs.h"
    11 #include "nsAppDirectoryServiceDefs.h"
    12 #include "nsISupportsUtils.h"
    13 #include "nsISimpleEnumerator.h"
    14 #include "nsIObserverService.h"
    16 // File Name Defines
    18 #define PREFS_FILE_50_NAME           NS_LITERAL_CSTRING("prefs.js")
    19 #define PREFS_FILE_METRO_50_NAME     NS_LITERAL_CSTRING("metro-prefs.js")
    20 #define USER_CHROME_DIR_50_NAME      NS_LITERAL_CSTRING("chrome")
    21 #define LOCAL_STORE_FILE_50_NAME     NS_LITERAL_CSTRING("localstore.rdf")
    22 #define PANELS_FILE_50_NAME          NS_LITERAL_CSTRING("panels.rdf")
    23 #define MIME_TYPES_FILE_50_NAME      NS_LITERAL_CSTRING("mimeTypes.rdf")
    24 #define BOOKMARKS_FILE_50_NAME       NS_LITERAL_CSTRING("bookmarks.html")
    25 #define DOWNLOADS_FILE_50_NAME       NS_LITERAL_CSTRING("downloads.rdf")
    26 #define SEARCH_FILE_50_NAME          NS_LITERAL_CSTRING("search.rdf" )
    28 //*****************************************************************************
    29 // nsProfileDirServiceProvider::nsProfileDirServiceProvider
    30 //*****************************************************************************
    32 nsProfileDirServiceProvider::nsProfileDirServiceProvider(bool aNotifyObservers) :
    33 #ifdef MOZ_PROFILELOCKING
    34   mProfileDirLock(nullptr),
    35 #endif
    36   mNotifyObservers(aNotifyObservers),
    37   mSharingEnabled(false)
    38 {
    39 }
    42 nsProfileDirServiceProvider::~nsProfileDirServiceProvider()
    43 {
    44 #ifdef MOZ_PROFILELOCKING
    45   delete mProfileDirLock;
    46 #endif
    47 }
    49 nsresult
    50 nsProfileDirServiceProvider::SetProfileDir(nsIFile* aProfileDir,
    51                                            nsIFile* aLocalProfileDir)
    52 {
    53   if (!aLocalProfileDir)
    54     aLocalProfileDir = aProfileDir;
    55   if (mProfileDir) {
    56     bool isEqual;
    57     if (aProfileDir &&
    58         NS_SUCCEEDED(aProfileDir->Equals(mProfileDir, &isEqual)) && isEqual) {
    59       NS_WARNING("Setting profile dir to same as current");
    60       return NS_OK;
    61     }
    62 #ifdef MOZ_PROFILELOCKING
    63     mProfileDirLock->Unlock();
    64 #endif
    65     UndefineFileLocations();
    66   }
    67   mProfileDir = aProfileDir;
    68   mLocalProfileDir = aLocalProfileDir;
    69   if (!mProfileDir)
    70     return NS_OK;
    72   nsresult rv = InitProfileDir(mProfileDir);
    73   if (NS_FAILED(rv))
    74     return rv;
    76   // Make sure that the local profile dir exists
    77   // we just try to create it - if it exists already, that'll fail; ignore
    78   // errors
    79   mLocalProfileDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
    81 #ifdef MOZ_PROFILELOCKING
    82   // Lock the non-shared sub-dir if we are sharing,
    83   // the whole profile dir if we are not.
    84   nsCOMPtr<nsIFile> dirToLock;
    85   if (mSharingEnabled)
    86     dirToLock = mNonSharedProfileDir;
    87   else
    88     dirToLock = mProfileDir;
    89   rv = mProfileDirLock->Lock(dirToLock, nullptr);
    90   if (NS_FAILED(rv))
    91     return rv;
    92 #endif
    94   if (mNotifyObservers) {
    95     nsCOMPtr<nsIObserverService> observerService =
    96              do_GetService("@mozilla.org/observer-service;1");
    97     if (!observerService)
    98       return NS_ERROR_FAILURE;
   100     NS_NAMED_LITERAL_STRING(context, "startup");
   101     // Notify observers that the profile has changed - Here they respond to new profile
   102     observerService->NotifyObservers(nullptr, "profile-do-change", context.get());
   103     // Now observers can respond to something another observer did on "profile-do-change"
   104     observerService->NotifyObservers(nullptr, "profile-after-change", context.get());
   105   }
   107   return NS_OK;
   108 }
   110 nsresult
   111 nsProfileDirServiceProvider::Register()
   112 {
   113   nsCOMPtr<nsIDirectoryService> directoryService =
   114           do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
   115   if (!directoryService)
   116     return NS_ERROR_FAILURE;
   117   return directoryService->RegisterProvider(this);
   118 }
   120 nsresult
   121 nsProfileDirServiceProvider::Shutdown()
   122 {
   123   if (!mNotifyObservers)
   124     return NS_OK;
   126   nsCOMPtr<nsIObserverService> observerService =
   127            do_GetService("@mozilla.org/observer-service;1");
   128   if (!observerService)
   129     return NS_ERROR_FAILURE;
   131   NS_NAMED_LITERAL_STRING(context, "shutdown-persist");
   132   observerService->NotifyObservers(nullptr, "profile-before-change", context.get());
   133   observerService->NotifyObservers(nullptr, "profile-before-change2", context.get());
   134   return NS_OK;
   135 }
   137 //*****************************************************************************
   138 // nsProfileDirServiceProvider::nsISupports
   139 //*****************************************************************************
   141 NS_IMPL_ISUPPORTS(nsProfileDirServiceProvider,
   142                   nsIDirectoryServiceProvider)
   144 //*****************************************************************************
   145 // nsProfileDirServiceProvider::nsIDirectoryServiceProvider
   146 //*****************************************************************************
   148 NS_IMETHODIMP
   149 nsProfileDirServiceProvider::GetFile(const char *prop, bool *persistant, nsIFile **_retval)
   150 {
   151   NS_ENSURE_ARG(prop);
   152   NS_ENSURE_ARG_POINTER(persistant);
   153   NS_ENSURE_ARG_POINTER(_retval);
   155   // Don't assert - we can be called many times before SetProfileDir() has been called.
   156   if (!mProfileDir)
   157     return NS_ERROR_FAILURE;
   159   *persistant = true;
   160   nsIFile* domainDir = mProfileDir;
   162   nsCOMPtr<nsIFile>  localFile;
   163   nsresult rv = NS_ERROR_FAILURE;
   165   if (strcmp(prop, NS_APP_PREFS_50_DIR) == 0) {
   166     rv = domainDir->Clone(getter_AddRefs(localFile));
   167   }
   168   else if (strcmp(prop, NS_APP_PREFS_50_FILE) == 0) {
   169     rv = domainDir->Clone(getter_AddRefs(localFile));
   170     if (NS_SUCCEEDED(rv))
   171       rv = localFile->AppendNative(PREFS_FILE_50_NAME);
   172   }
   173   else if (strcmp(prop, NS_METRO_APP_PREFS_50_FILE) == 0) {
   174     rv = domainDir->Clone(getter_AddRefs(localFile));
   175     if (NS_SUCCEEDED(rv))
   176       rv = localFile->AppendNative(PREFS_FILE_METRO_50_NAME);
   177   }
   178   else if (strcmp(prop, NS_APP_USER_PROFILE_50_DIR) == 0) {
   179     rv = domainDir->Clone(getter_AddRefs(localFile));
   180   }
   181   else if (strcmp(prop, NS_APP_USER_PROFILE_LOCAL_50_DIR) == 0) {
   182     rv = mLocalProfileDir->Clone(getter_AddRefs(localFile));
   183   }
   184   else if (strcmp(prop, NS_APP_USER_CHROME_DIR) == 0) {
   185     rv = domainDir->Clone(getter_AddRefs(localFile));
   186     if (NS_SUCCEEDED(rv))
   187       rv = localFile->AppendNative(USER_CHROME_DIR_50_NAME);
   188   }
   189   else if (strcmp(prop, NS_APP_LOCALSTORE_50_FILE) == 0) {
   190     rv = domainDir->Clone(getter_AddRefs(localFile));
   191     if (NS_SUCCEEDED(rv)) {
   192       rv = localFile->AppendNative(LOCAL_STORE_FILE_50_NAME);
   193       if (NS_SUCCEEDED(rv)) {
   194         // it's OK if we can't copy the file... it will be created
   195         // by client code.
   196         (void) EnsureProfileFileExists(localFile, domainDir);
   197       }
   198     }
   199   }
   200   else if (strcmp(prop, NS_APP_USER_PANELS_50_FILE) == 0) {
   201     rv = domainDir->Clone(getter_AddRefs(localFile));
   202     if (NS_SUCCEEDED(rv)) {
   203       rv = localFile->AppendNative(PANELS_FILE_50_NAME);
   204       if (NS_SUCCEEDED(rv))
   205         rv = EnsureProfileFileExists(localFile, domainDir);
   206     }
   207   }
   208   else if (strcmp(prop, NS_APP_USER_MIMETYPES_50_FILE) == 0) {
   209     rv = domainDir->Clone(getter_AddRefs(localFile));
   210     if (NS_SUCCEEDED(rv)) {
   211       rv = localFile->AppendNative(MIME_TYPES_FILE_50_NAME);
   212       if (NS_SUCCEEDED(rv))
   213         rv = EnsureProfileFileExists(localFile, domainDir);
   214     }
   215   }
   216   else if (strcmp(prop, NS_APP_BOOKMARKS_50_FILE) == 0) {
   217     rv = domainDir->Clone(getter_AddRefs(localFile));
   218     if (NS_SUCCEEDED(rv))
   219       rv = localFile->AppendNative(BOOKMARKS_FILE_50_NAME);
   220   }
   221   else if (strcmp(prop, NS_APP_DOWNLOADS_50_FILE) == 0) {
   222     rv = domainDir->Clone(getter_AddRefs(localFile));
   223     if (NS_SUCCEEDED(rv))
   224       rv = localFile->AppendNative(DOWNLOADS_FILE_50_NAME);
   225   }
   226   else if (strcmp(prop, NS_APP_SEARCH_50_FILE) == 0) {
   227     rv = domainDir->Clone(getter_AddRefs(localFile));
   228     if (NS_SUCCEEDED(rv)) {
   229       rv = localFile->AppendNative(SEARCH_FILE_50_NAME);
   230       if (NS_SUCCEEDED(rv))
   231         rv = EnsureProfileFileExists(localFile, domainDir);
   232     }
   233   }
   235   if (NS_FAILED(rv)) {
   236     return rv;
   237   }
   239   localFile.forget(_retval);
   240   return NS_OK;
   241 }
   243 //*****************************************************************************
   244 // Protected methods
   245 //*****************************************************************************
   247 nsresult
   248 nsProfileDirServiceProvider::Initialize()
   249 {
   250 #ifdef MOZ_PROFILELOCKING
   251   mProfileDirLock = new nsProfileLock;
   252   if (!mProfileDirLock)
   253     return NS_ERROR_OUT_OF_MEMORY;
   254 #endif
   256   return NS_OK;
   257 }
   259 nsresult
   260 nsProfileDirServiceProvider::InitProfileDir(nsIFile *profileDir)
   261 {
   262   // Make sure our "Profile" folder exists.
   263   // If it does not, copy the profile defaults to its location.
   265   nsresult rv;
   266   bool exists;
   267   rv = profileDir->Exists(&exists);
   268   if (NS_FAILED(rv))
   269     return rv;
   271   if (!exists) {
   272     nsCOMPtr<nsIFile> profileDefaultsDir;
   273     nsCOMPtr<nsIFile> profileDirParent;
   274     nsAutoCString profileDirName;
   276     (void)profileDir->GetParent(getter_AddRefs(profileDirParent));
   277     if (!profileDirParent)
   278       return NS_ERROR_FAILURE;
   279     rv = profileDir->GetNativeLeafName(profileDirName);
   280     if (NS_FAILED(rv))
   281       return rv;
   283     rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_50_DIR, getter_AddRefs(profileDefaultsDir));
   284     if (NS_FAILED(rv)) {
   285       rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR, getter_AddRefs(profileDefaultsDir));
   286       if (NS_FAILED(rv))
   287         return rv;
   288     }
   289     rv = profileDefaultsDir->CopyToNative(profileDirParent, profileDirName);
   290     if (NS_FAILED(rv)) {
   291         // if copying failed, lets just ensure that the profile directory exists.
   292         profileDirParent->AppendNative(profileDirName);
   293         rv = profileDirParent->Create(nsIFile::DIRECTORY_TYPE, 0700);
   294         if (NS_FAILED(rv))
   295             return rv;
   296     }
   298     rv = profileDir->SetPermissions(0700);
   299     if (NS_FAILED(rv))
   300       return rv;
   301   }
   302   else {
   303     bool isDir;
   304     rv = profileDir->IsDirectory(&isDir);
   306     if (NS_FAILED(rv))
   307       return rv;
   308     if (!isDir)
   309       return NS_ERROR_FILE_NOT_DIRECTORY;
   310   }
   312   if (mNonSharedDirName.Length())
   313     rv = InitNonSharedProfileDir();
   315   return rv;
   316 }
   318 nsresult
   319 nsProfileDirServiceProvider::InitNonSharedProfileDir()
   320 {
   321   nsresult rv;
   323   NS_ENSURE_STATE(mProfileDir);
   324   NS_ENSURE_STATE(mNonSharedDirName.Length());
   326   nsCOMPtr<nsIFile> localDir;
   327   rv = mProfileDir->Clone(getter_AddRefs(localDir));
   328   if (NS_SUCCEEDED(rv)) {
   329     rv = localDir->Append(mNonSharedDirName);
   330     if (NS_SUCCEEDED(rv)) {
   331       bool exists;
   332       rv = localDir->Exists(&exists);
   333       if (NS_SUCCEEDED(rv)) {
   334         if (!exists) {
   335           rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
   336         }
   337         else {
   338           bool isDir;
   339           rv = localDir->IsDirectory(&isDir);
   340           if (NS_SUCCEEDED(rv)) {
   341             if (!isDir)
   342               rv = NS_ERROR_FILE_NOT_DIRECTORY;
   343           }
   344         }
   345         if (NS_SUCCEEDED(rv))
   346           mNonSharedProfileDir = localDir;
   347       }
   348     }
   349   }
   350   return rv;
   351 }
   353 nsresult
   354 nsProfileDirServiceProvider::EnsureProfileFileExists(nsIFile *aFile, nsIFile *destDir)
   355 {
   356   nsresult rv;
   357   bool exists;
   359   rv = aFile->Exists(&exists);
   360   if (NS_FAILED(rv))
   361     return rv;
   362   if (exists)
   363     return NS_OK;
   365   nsCOMPtr<nsIFile> defaultsFile;
   367   // Attempt first to get the localized subdir of the defaults
   368   rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_50_DIR, getter_AddRefs(defaultsFile));
   369   if (NS_FAILED(rv)) {
   370     // If that has not been defined, use the top level of the defaults
   371     rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR, getter_AddRefs(defaultsFile));
   372     if (NS_FAILED(rv))
   373       return rv;
   374   }
   376   nsAutoCString leafName;
   377   rv = aFile->GetNativeLeafName(leafName);
   378   if (NS_FAILED(rv))
   379     return rv;
   380   rv = defaultsFile->AppendNative(leafName);
   381   if (NS_FAILED(rv))
   382     return rv;
   384   return defaultsFile->CopyTo(destDir, EmptyString());
   385 }
   387 nsresult
   388 nsProfileDirServiceProvider::UndefineFileLocations()
   389 {
   390   nsresult rv;
   392   nsCOMPtr<nsIProperties> directoryService =
   393            do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
   394   NS_ENSURE_TRUE(directoryService, NS_ERROR_FAILURE);
   396   (void) directoryService->Undefine(NS_APP_PREFS_50_DIR);
   397   (void) directoryService->Undefine(NS_APP_PREFS_50_FILE);
   398   (void) directoryService->Undefine(NS_APP_USER_PROFILE_50_DIR);
   399   (void) directoryService->Undefine(NS_APP_USER_CHROME_DIR);
   400   (void) directoryService->Undefine(NS_APP_LOCALSTORE_50_FILE);
   401   (void) directoryService->Undefine(NS_APP_USER_PANELS_50_FILE);
   402   (void) directoryService->Undefine(NS_APP_USER_MIMETYPES_50_FILE);
   403   (void) directoryService->Undefine(NS_APP_BOOKMARKS_50_FILE);
   404   (void) directoryService->Undefine(NS_APP_DOWNLOADS_50_FILE);
   405   (void) directoryService->Undefine(NS_APP_SEARCH_50_FILE);
   407   return NS_OK;
   408 }
   410 //*****************************************************************************
   411 // Global creation function
   412 //*****************************************************************************
   414 nsresult NS_NewProfileDirServiceProvider(bool aNotifyObservers,
   415                                          nsProfileDirServiceProvider** aProvider)
   416 {
   417   NS_ENSURE_ARG_POINTER(aProvider);
   418   *aProvider = nullptr;
   420   nsProfileDirServiceProvider *prov = new nsProfileDirServiceProvider(aNotifyObservers);
   421   if (!prov)
   422     return NS_ERROR_OUT_OF_MEMORY;
   423   nsresult rv = prov->Initialize();
   424   if (NS_FAILED(rv)) {
   425     delete prov;
   426     return rv;
   427   }
   428   NS_ADDREF(*aProvider = prov);
   429   return NS_OK;
   430 }

mercurial