LCOV - code coverage report
Current view: top level - toolkit/xre - ProfileReset.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 81 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 file,
       4             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsIAppStartup.h"
       7             : #include "nsIFile.h"
       8             : #include "nsIStringBundle.h"
       9             : #include "nsIToolkitProfile.h"
      10             : #include "nsIWindowWatcher.h"
      11             : 
      12             : #include "ProfileReset.h"
      13             : 
      14             : #include "nsDirectoryServiceDefs.h"
      15             : #include "nsDirectoryServiceUtils.h"
      16             : #include "nsPIDOMWindow.h"
      17             : #include "nsPrintfCString.h"
      18             : #include "nsString.h"
      19             : #include "nsToolkitCompsCID.h"
      20             : #include "nsXPCOMCIDInternal.h"
      21             : #include "mozilla/XREAppData.h"
      22             : 
      23             : #include "mozilla/Services.h"
      24             : #include "prtime.h"
      25             : 
      26             : using namespace mozilla;
      27             : 
      28             : extern const XREAppData* gAppData;
      29             : 
      30             : static const char kProfileProperties[] =
      31             :   "chrome://mozapps/locale/profile/profileSelection.properties";
      32             : 
      33             : /**
      34             :  * Creates a new profile with a timestamp in the name to use for profile reset.
      35             :  */
      36             : nsresult
      37           0 : CreateResetProfile(nsIToolkitProfileService* aProfileSvc, const nsACString& aOldProfileName, nsIToolkitProfile* *aNewProfile)
      38             : {
      39           0 :   MOZ_ASSERT(aProfileSvc, "NULL profile service");
      40             : 
      41           0 :   nsCOMPtr<nsIToolkitProfile> newProfile;
      42             :   // Make the new profile the old profile (or "default-") + the time in seconds since epoch for uniqueness.
      43           0 :   nsAutoCString newProfileName;
      44           0 :   if (!aOldProfileName.IsEmpty()) {
      45           0 :     newProfileName.Assign(aOldProfileName);
      46           0 :     newProfileName.Append("-");
      47             :   } else {
      48           0 :     newProfileName.Assign("default-");
      49             :   }
      50           0 :   newProfileName.Append(nsPrintfCString("%" PRId64, PR_Now() / 1000));
      51           0 :   nsresult rv = aProfileSvc->CreateProfile(nullptr, // choose a default dir for us
      52             :                                            newProfileName,
      53           0 :                                            getter_AddRefs(newProfile));
      54           0 :   if (NS_FAILED(rv)) return rv;
      55             : 
      56           0 :   rv = aProfileSvc->Flush();
      57           0 :   if (NS_FAILED(rv)) return rv;
      58             : 
      59           0 :   newProfile.swap(*aNewProfile);
      60             : 
      61           0 :   return NS_OK;
      62             : }
      63             : 
      64             : /**
      65             :  * Delete the profile directory being reset after a backup and delete the local profile directory.
      66             :  */
      67             : nsresult
      68           0 : ProfileResetCleanup(nsIToolkitProfile* aOldProfile)
      69             : {
      70             :   nsresult rv;
      71           0 :   nsCOMPtr<nsIFile> profileDir;
      72           0 :   rv = aOldProfile->GetRootDir(getter_AddRefs(profileDir));
      73           0 :   if (NS_FAILED(rv)) return rv;
      74             : 
      75           0 :   nsCOMPtr<nsIFile> profileLocalDir;
      76           0 :   rv = aOldProfile->GetLocalDir(getter_AddRefs(profileLocalDir));
      77           0 :   if (NS_FAILED(rv)) return rv;
      78             : 
      79             :   // Get the friendly name for the backup directory.
      80           0 :   nsCOMPtr<nsIStringBundleService> sbs = mozilla::services::GetStringBundleService();
      81           0 :   if (!sbs) return NS_ERROR_FAILURE;
      82             : 
      83           0 :   nsCOMPtr<nsIStringBundle> sb;
      84           0 :   rv = sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
      85           0 :   if (!sb) return NS_ERROR_FAILURE;
      86             : 
      87           0 :   NS_ConvertUTF8toUTF16 appName(gAppData->name);
      88           0 :   const char16_t* params[] = {appName.get(), appName.get()};
      89             : 
      90           0 :   nsXPIDLString resetBackupDirectoryName;
      91             : 
      92             :   static const char16_t* kResetBackupDirectory = u"resetBackupDirectory";
      93           0 :   rv = sb->FormatStringFromName(kResetBackupDirectory, params, 2,
      94           0 :                                 getter_Copies(resetBackupDirectoryName));
      95             : 
      96             :   // Get info to copy the old root profile dir to the desktop as a backup.
      97           0 :   nsCOMPtr<nsIFile> backupDest, containerDest, profileDest;
      98           0 :   rv = NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(backupDest));
      99           0 :   if (NS_FAILED(rv)) {
     100             :     // Fall back to the home directory if the desktop is not available.
     101           0 :     rv = NS_GetSpecialDirectory(NS_OS_HOME_DIR, getter_AddRefs(backupDest));
     102           0 :     if (NS_FAILED(rv)) return rv;
     103             :   }
     104             : 
     105             :   // Try to create a directory for all the backups
     106           0 :   backupDest->Clone(getter_AddRefs(containerDest));
     107           0 :   containerDest->Append(resetBackupDirectoryName);
     108           0 :   rv = containerDest->Create(nsIFile::DIRECTORY_TYPE, 0700);
     109             :   // It's OK if it already exists, if and only if it is a directory
     110           0 :   if (rv == NS_ERROR_FILE_ALREADY_EXISTS) {
     111             :     bool containerIsDir;
     112           0 :     rv = containerDest->IsDirectory(&containerIsDir);
     113           0 :     if (NS_FAILED(rv) || !containerIsDir) {
     114           0 :       return rv;
     115             :     }
     116           0 :   } else if (NS_FAILED(rv)) {
     117           0 :     return rv;
     118             :   }
     119             : 
     120             :   // Get the name of the profile
     121           0 :   nsAutoString leafName;
     122           0 :   rv = profileDir->GetLeafName(leafName);
     123           0 :   if (NS_FAILED(rv)) return rv;
     124             : 
     125             :   // Try to create a unique directory for the profile:
     126           0 :   containerDest->Clone(getter_AddRefs(profileDest));
     127           0 :   profileDest->Append(leafName);
     128           0 :   rv = profileDest->CreateUnique(nsIFile::DIRECTORY_TYPE, 0700);
     129           0 :   if (NS_FAILED(rv)) return rv;
     130             : 
     131             :   // Get the unique profile name
     132           0 :   rv = profileDest->GetLeafName(leafName);
     133           0 :   if (NS_FAILED(rv)) return rv;
     134             : 
     135             :   // Delete the empty directory that CreateUnique just created.
     136           0 :   rv = profileDest->Remove(false);
     137           0 :   if (NS_FAILED(rv)) return rv;
     138             : 
     139             :   // Show a progress window while the cleanup happens since the disk I/O can take time.
     140           0 :   nsCOMPtr<nsIWindowWatcher> windowWatcher(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
     141           0 :   if (!windowWatcher) return NS_ERROR_FAILURE;
     142             : 
     143           0 :   nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
     144           0 :   if (!appStartup) return NS_ERROR_FAILURE;
     145             : 
     146           0 :   nsCOMPtr<mozIDOMWindowProxy> progressWindow;
     147           0 :   rv = windowWatcher->OpenWindow(nullptr,
     148             :                                  kResetProgressURL,
     149             :                                  "_blank",
     150             :                                  "centerscreen,chrome,titlebar",
     151             :                                  nullptr,
     152           0 :                                  getter_AddRefs(progressWindow));
     153           0 :   if (NS_FAILED(rv)) return rv;
     154             : 
     155             :   // Create a new thread to do the bulk of profile cleanup to stay responsive.
     156           0 :   nsCOMPtr<nsIThreadManager> tm = do_GetService(NS_THREADMANAGER_CONTRACTID);
     157           0 :   nsCOMPtr<nsIThread> cleanupThread;
     158           0 :   rv = tm->NewThread(0, 0, getter_AddRefs(cleanupThread));
     159           0 :   if (NS_SUCCEEDED(rv)) {
     160             :     nsCOMPtr<nsIRunnable> runnable = new ProfileResetCleanupAsyncTask(profileDir, profileLocalDir,
     161           0 :                                                                       containerDest, leafName);
     162           0 :     cleanupThread->Dispatch(runnable, nsIThread::DISPATCH_NORMAL);
     163             :     // The result callback will shut down the worker thread.
     164             : 
     165             :     // Wait for the cleanup thread to complete.
     166           0 :     SpinEventLoopUntil([&]() { return gProfileResetCleanupCompleted; });
     167             :   } else {
     168           0 :     gProfileResetCleanupCompleted = true;
     169           0 :     NS_WARNING("Cleanup thread creation failed");
     170           0 :     return rv;
     171             :   }
     172             :   // Close the progress window now that the cleanup thread is done.
     173           0 :   auto* piWindow = nsPIDOMWindowOuter::From(progressWindow);
     174           0 :   piWindow->Close();
     175             : 
     176             :   // Delete the old profile from profiles.ini. The folder was already deleted by the thread above.
     177           0 :   rv = aOldProfile->Remove(false);
     178           0 :   if (NS_FAILED(rv)) NS_WARNING("Could not remove the profile");
     179             : 
     180           0 :   return rv;
     181             : }

Generated by: LCOV version 1.13