Bug 724513 - Part 2 - nsAppRunner shouldn't assume the deletion of invalid startup cache file succeeded. r=mwu
authorGraeme McCutcheon <graememcc_firefox@graeme-online.co.uk>
Tue, 23 Oct 2012 17:46:51 +0100
changeset 112151 6ec71de7ba2d66438d9ee4ee03628ada27999c3c
parent 112150 eb5c570b8a0bf064a26b46cb6e8274b52b75eaa0
child 112152 b032c4cc9d7dc684bb112424e9d07dd4be8dd046
push id23798
push userryanvm@gmail.com
push dateSat, 03 Nov 2012 00:06:35 +0000
treeherdermozilla-central@6134edeea902 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmwu
bugs724513
milestone19.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 724513 - Part 2 - nsAppRunner shouldn't assume the deletion of invalid startup cache file succeeded. r=mwu
toolkit/xre/nsAppRunner.cpp
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -86,21 +86,23 @@
 #include "nsIWindowWatcher.h"
 #include "nsIXULAppInfo.h"
 #include "nsIXULRuntime.h"
 #include "nsPIDOMWindow.h"
 #include "nsIBaseWindow.h"
 #include "nsIWidget.h"
 #include "nsIDocShell.h"
 #include "nsAppShellCID.h"
+#include "mozilla/scache/StartupCache.h"
 
 #include "mozilla/unused.h"
 
 using namespace mozilla;
 using mozilla::unused;
+using mozilla::scache::StartupCache;
 
 #ifdef XP_WIN
 #include "nsIWinAppHelper.h"
 #include <windows.h>
 #include "cairo/cairo-features.h"
 
 #ifndef PROCESS_DEP_ENABLE
 #define PROCESS_DEP_ENABLE 0x1
@@ -2401,17 +2403,17 @@ static void BuildVersion(nsCString &aBuf
   aBuf.Append(gAppData->buildID);
   aBuf.Append('/');
   aBuf.Append(gToolkitBuildID);
 }
 
 static void
 WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
              const nsCString& aOSABI, nsIFile* aXULRunnerDir,
-             nsIFile* aAppDir)
+             nsIFile* aAppDir, bool invalidateCache)
 {
   nsCOMPtr<nsIFile> file;
   aProfileDir->Clone(getter_AddRefs(file));
   if (!file)
     return;
   file->AppendNative(FILE_COMPATIBILITY_INFO);
 
   nsAutoCString platformDir;
@@ -2444,53 +2446,65 @@ WriteVersion(nsIFile* aProfileDir, const
   PR_Write(fd, platformDir.get(), platformDir.Length());
 
   static const char kAppDirHeader[] = NS_LINEBREAK "LastAppDir=";
   if (aAppDir) {
     PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
     PR_Write(fd, appDir.get(), appDir.Length());
   }
 
+  static const char kInvalidationHeader[] = "InvalidateCaches=1" NS_LINEBREAK;
+  if (invalidateCache)
+    PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
+
   static const char kNL[] = NS_LINEBREAK;
   PR_Write(fd, kNL, sizeof(kNL) - 1);
 
   PR_Close(fd);
 }
 
-static void RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
+/**
+ * Returns true if the startup cache file was successfully removed.
+ * Returns false if file->Clone fails at any point (OOM) or if unable
+ * to remove the startup cache file. Note in particular the return value
+ * is unaffected by a failure to remove extensions.ini
+ */
+static bool
+RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
                                       bool aRemoveEMFiles)
 {
   nsCOMPtr<nsIFile> file;
   aProfileDir->Clone(getter_AddRefs(file));
   if (!file)
-    return;
+    return false;
 
   if (aRemoveEMFiles) {
     file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
     file->Remove(false);
   }
 
   aLocalProfileDir->Clone(getter_AddRefs(file));
   if (!file)
-    return;
+    return false;
 
 #if defined(XP_UNIX) || defined(XP_BEOS)
 #define PLATFORM_FASL_SUFFIX ".mfasl"
 #elif defined(XP_WIN) || defined(XP_OS2)
 #define PLATFORM_FASL_SUFFIX ".mfl"
 #endif
 
   file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
   file->Remove(false);
   
   file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
   file->Remove(false);
 
   file->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
-  file->Remove(true);
+  nsresult rv = file->Remove(true);
+  return NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
 }
 
 // To support application initiated restart via nsIAppStartup.quit, we
 // need to save various environment variables, and then restore them
 // before re-launching the application.
 
 static struct SavedVar {
   const char *name;
@@ -3528,45 +3542,49 @@ XREMain::XRE_mainStartup(bool* aExitFlag
  
   // Every time a profile is loaded by a build with a different version,
   // it updates the compatibility.ini file saying what version last wrote
   // the fastload caches.  On subsequent launches if the version matches, 
   // there is no need for re-registration.  If the user loads the same
   // profile in different builds the component registry must be
   // re-generated to prevent mysterious component loading failures.
   //
+  bool startupCacheValid = true;
   if (gSafeMode) {
-    RemoveComponentRegistries(mProfD, mProfLD, false);
+    startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
     WriteVersion(mProfD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
-                 mDirProvider.GetGREDir(), mAppData->directory);
+                 mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
   }
   else if (versionOK) {
     if (!cachesOK) {
       // Remove caches, forcing component re-registration.
       // The new list of additional components directories is derived from
       // information in "extensions.ini".
-      RemoveComponentRegistries(mProfD, mProfLD, false);
+      startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
         
       // Rewrite compatibility.ini to remove the flag
       WriteVersion(mProfD, version, osABI,
-                   mDirProvider.GetGREDir(), mAppData->directory);
+                   mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
     }
     // Nothing need be done for the normal startup case.
   }
   else {
     // Remove caches, forcing component re-registration
     // with the default set of components (this disables any potentially
     // troublesome incompatible XPCOM components). 
-    RemoveComponentRegistries(mProfD, mProfLD, true);
+    startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, true);
 
     // Write out version
     WriteVersion(mProfD, version, osABI,
-                 mDirProvider.GetGREDir(), mAppData->directory);
+                 mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
   }
 
+  if (!startupCacheValid)
+    StartupCache::IgnoreDiskCache();
+
   if (flagFile) {
     flagFile->Remove(true);
   }
 
   return 0;
 }
 
 /*