Bug 1320651 - Only crash for real builtin sheet error. r=bz
authorWei-Cheng Pan <wpan@mozilla.com>
Tue, 06 Dec 2016 18:25:00 +0100
changeset 325376 1e325da15c787fffcddeeba92ea24b99e0d8d097
parent 325375 3bb432e68db4e89ce6b5e11f022cfe3ca04fd751
child 325377 e333afeac179b7919eef15620782e5ee0bda35f3
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersbz
bugs1320651
milestone53.0a1
Bug 1320651 - Only crash for real builtin sheet error. r=bz
layout/style/nsLayoutStylesheetCache.cpp
layout/style/nsLayoutStylesheetCache.h
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -9,25 +9,26 @@
 #include "nsAppDirectoryServiceDefs.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/SRIMetadata.h"
+#include "nsIConsoleService.h"
 #include "nsIFile.h"
 #include "nsNetUtil.h"
 #include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIXULRuntime.h"
 #include "nsPrintfCString.h"
 #include "nsXULAppAPI.h"
 
-// Includes for the crash report annotation in ErrorLoadingBuiltinSheet.
+// Includes for the crash report annotation in ErrorLoadingSheet.
 #ifdef MOZ_CRASHREPORTER
 #include "mozilla/Omnijar.h"
 #include "nsDirectoryService.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsExceptionHandler.h"
 #include "nsIChromeRegistry.h"
 #include "nsISimpleEnumerator.h"
 #include "nsISubstitutingProtocolHandler.h"
@@ -70,44 +71,44 @@ nsLayoutStylesheetCache::Observe(nsISupp
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::ScrollbarsSheet()
 {
   if (!mScrollbarsSheet) {
     // Scrollbars don't need access to unsafe rules
     LoadSheetURL("chrome://global/skin/scrollbars.css",
-                 &mScrollbarsSheet, eAuthorSheetFeatures);
+                 &mScrollbarsSheet, eAuthorSheetFeatures, eCrash);
   }
 
   return mScrollbarsSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::FormsSheet()
 {
   if (!mFormsSheet) {
     // forms.css needs access to unsafe rules
     LoadSheetURL("resource://gre-resources/forms.css",
-                 &mFormsSheet, eAgentSheetFeatures);
+                 &mFormsSheet, eAgentSheetFeatures, eCrash);
   }
 
   return mFormsSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::NumberControlSheet()
 {
   if (!sNumberControlEnabled) {
     return nullptr;
   }
 
   if (!mNumberControlSheet) {
     LoadSheetURL("resource://gre-resources/number-control.css",
-                 &mNumberControlSheet, eAgentSheetFeatures);
+                 &mNumberControlSheet, eAgentSheetFeatures, eCrash);
   }
 
   return mNumberControlSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::UserContentSheet()
 {
@@ -120,17 +121,17 @@ nsLayoutStylesheetCache::UserChromeSheet
   return mUserChromeSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::UASheet()
 {
   if (!mUASheet) {
     LoadSheetURL("resource://gre-resources/ua.css",
-                 &mUASheet, eAgentSheetFeatures);
+                 &mUASheet, eAgentSheetFeatures, eCrash);
   }
 
   return mUASheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::HTMLSheet()
 {
@@ -161,45 +162,45 @@ nsLayoutStylesheetCache::SVGSheet()
   return mSVGSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::MathMLSheet()
 {
   if (!mMathMLSheet) {
     LoadSheetURL("resource://gre-resources/mathml.css",
-                 &mMathMLSheet, eAgentSheetFeatures);
+                 &mMathMLSheet, eAgentSheetFeatures, eCrash);
   }
 
   return mMathMLSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::CounterStylesSheet()
 {
   return mCounterStylesSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::NoScriptSheet()
 {
   if (!mNoScriptSheet) {
     LoadSheetURL("resource://gre-resources/noscript.css",
-                 &mNoScriptSheet, eAgentSheetFeatures);
+                 &mNoScriptSheet, eAgentSheetFeatures, eCrash);
   }
 
   return mNoScriptSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::NoFramesSheet()
 {
   if (!mNoFramesSheet) {
     LoadSheetURL("resource://gre-resources/noframes.css",
-                 &mNoFramesSheet, eAgentSheetFeatures);
+                 &mNoFramesSheet, eAgentSheetFeatures, eCrash);
   }
 
   return mNoFramesSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::ChromePreferenceSheet(nsPresContext* aPresContext)
 {
@@ -220,28 +221,28 @@ nsLayoutStylesheetCache::ContentPreferen
   return mContentPreferenceSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::ContentEditableSheet()
 {
   if (!mContentEditableSheet) {
     LoadSheetURL("resource://gre/res/contenteditable.css",
-                 &mContentEditableSheet, eAgentSheetFeatures);
+                 &mContentEditableSheet, eAgentSheetFeatures, eCrash);
   }
 
   return mContentEditableSheet;
 }
 
 StyleSheet*
 nsLayoutStylesheetCache::DesignModeSheet()
 {
   if (!mDesignModeSheet) {
     LoadSheetURL("resource://gre/res/designmode.css",
-                 &mDesignModeSheet, eAgentSheetFeatures);
+                 &mDesignModeSheet, eAgentSheetFeatures, eCrash);
   }
 
   return mDesignModeSheet;
 }
 
 void
 nsLayoutStylesheetCache::Shutdown()
 {
@@ -323,31 +324,31 @@ nsLayoutStylesheetCache::nsLayoutStylesh
     obsSvc->AddObserver(this, "chrome-flush-caches", false);
   }
 
   InitFromProfile();
 
   // And make sure that we load our UA sheets.  No need to do this
   // per-profile, since they're profile-invariant.
   LoadSheetURL("resource://gre-resources/counterstyles.css",
-               &mCounterStylesSheet, eAgentSheetFeatures);
+               &mCounterStylesSheet, eAgentSheetFeatures, eCrash);
   LoadSheetURL("resource://gre-resources/html.css",
-               &mHTMLSheet, eAgentSheetFeatures);
+               &mHTMLSheet, eAgentSheetFeatures, eCrash);
   LoadSheetURL("chrome://global/content/minimal-xul.css",
-               &mMinimalXULSheet, eAgentSheetFeatures);
+               &mMinimalXULSheet, eAgentSheetFeatures, eCrash);
   LoadSheetURL("resource://gre-resources/quirk.css",
-               &mQuirkSheet, eAgentSheetFeatures);
+               &mQuirkSheet, eAgentSheetFeatures, eCrash);
   LoadSheetURL("resource://gre/res/svg.css",
-               &mSVGSheet, eAgentSheetFeatures);
+               &mSVGSheet, eAgentSheetFeatures, eCrash);
   LoadSheetURL("chrome://global/content/xul.css",
-               &mXULSheet, eAgentSheetFeatures);
+               &mXULSheet, eAgentSheetFeatures, eCrash);
 
   if (gUserContentSheetURL) {
     MOZ_ASSERT(XRE_IsContentProcess(), "Only used in content processes.");
-    LoadSheet(gUserContentSheetURL, &mUserContentSheet, eUserSheetFeatures);
+    LoadSheet(gUserContentSheetURL, &mUserContentSheet, eUserSheetFeatures, eLogToConsole);
     gUserContentSheetURL = nullptr;
   }
 
   // The remaining sheets are created on-demand do to their use being rarer
   // (which helps save memory for Firefox OS apps) or because they need to
   // be re-loadable in DependentPrefChanged.
 }
 
@@ -417,47 +418,49 @@ nsLayoutStylesheetCache::InitFromProfile
   }
 
   contentFile->Clone(getter_AddRefs(chromeFile));
   if (!chromeFile) return;
 
   contentFile->Append(NS_LITERAL_STRING("userContent.css"));
   chromeFile->Append(NS_LITERAL_STRING("userChrome.css"));
 
-  LoadSheetFile(contentFile, &mUserContentSheet, eUserSheetFeatures);
-  LoadSheetFile(chromeFile, &mUserChromeSheet, eUserSheetFeatures);
+  LoadSheetFile(contentFile, &mUserContentSheet, eUserSheetFeatures, eLogToConsole);
+  LoadSheetFile(chromeFile, &mUserChromeSheet, eUserSheetFeatures, eLogToConsole);
 }
 
 void
 nsLayoutStylesheetCache::LoadSheetURL(const char* aURL,
                                       RefPtr<StyleSheet>* aSheet,
-                                      SheetParsingMode aParsingMode)
+                                      SheetParsingMode aParsingMode,
+                                      FailureAction aFailureAction)
 {
   nsCOMPtr<nsIURI> uri;
   NS_NewURI(getter_AddRefs(uri), aURL);
-  LoadSheet(uri, aSheet, aParsingMode);
+  LoadSheet(uri, aSheet, aParsingMode, aFailureAction);
   if (!aSheet) {
     NS_ERROR(nsPrintfCString("Could not load %s", aURL).get());
   }
 }
 
 void
 nsLayoutStylesheetCache::LoadSheetFile(nsIFile* aFile,
                                        RefPtr<StyleSheet>* aSheet,
-                                       SheetParsingMode aParsingMode)
+                                       SheetParsingMode aParsingMode,
+                                       FailureAction aFailureAction)
 {
   bool exists = false;
   aFile->Exists(&exists);
 
   if (!exists) return;
 
   nsCOMPtr<nsIURI> uri;
   NS_NewFileURI(getter_AddRefs(uri), aFile);
 
-  LoadSheet(uri, aSheet, aParsingMode);
+  LoadSheet(uri, aSheet, aParsingMode, aFailureAction);
 }
 
 #ifdef MOZ_CRASHREPORTER
 static inline nsresult
 ComputeCRC32(nsIFile* aFile, uint32_t* aResult)
 {
   PRFileDesc* fd;
   nsresult rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
@@ -725,56 +728,66 @@ AnnotateCrashReport(nsIURI* aURI)
   }
 
   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("SheetLoadFailure"),
                                      NS_ConvertUTF16toUTF8(annotation));
 }
 #endif
 
 static void
-ErrorLoadingBuiltinSheet(nsIURI* aURI, const char* aMsg)
+ErrorLoadingSheet(nsIURI* aURI, const char* aMsg, FailureAction aFailureAction)
 {
+  nsPrintfCString errorMessage("%s loading built-in stylesheet '%s'",
+                               aMsg,
+                               aURI ? aURI->GetSpecOrDefault().get() : "");
+  if (aFailureAction == eLogToConsole) {
+    nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+    if (cs) {
+      cs->LogStringMessage(NS_ConvertUTF8toUTF16(errorMessage).get());
+      return;
+    }
+  }
+
 #ifdef MOZ_CRASHREPORTER
   AnnotateCrashReport(aURI);
 #endif
-
-  NS_RUNTIMEABORT(
-    nsPrintfCString("%s loading built-in stylesheet '%s'",
-                    aMsg, aURI ? aURI->GetSpecOrDefault().get() : "").get());
+  NS_RUNTIMEABORT(errorMessage.get());
 }
 
 void
 nsLayoutStylesheetCache::LoadSheet(nsIURI* aURI,
                                    RefPtr<StyleSheet>* aSheet,
-                                   SheetParsingMode aParsingMode)
+                                   SheetParsingMode aParsingMode,
+                                   FailureAction aFailureAction)
 {
   if (!aURI) {
-    ErrorLoadingBuiltinSheet(aURI, "null URI");
+    ErrorLoadingSheet(aURI, "null URI", eCrash);
     return;
   }
 
   auto& loader = mBackendType == StyleBackendType::Gecko ?
     gCSSLoader_Gecko :
     gCSSLoader_Servo;
 
   if (!loader) {
     loader = new mozilla::css::Loader(mBackendType);
     if (!loader) {
-      ErrorLoadingBuiltinSheet(aURI, "no Loader");
+      ErrorLoadingSheet(aURI, "no Loader", eCrash);
       return;
     }
   }
 
 #ifdef MOZ_CRASHREPORTER
   nsZipArchive::sFileCorruptedReason = nullptr;
 #endif
   nsresult rv = loader->LoadSheetSync(aURI, aParsingMode, true, aSheet);
   if (NS_FAILED(rv)) {
-    ErrorLoadingBuiltinSheet(aURI,
-      nsPrintfCString("LoadSheetSync failed with error %x", rv).get());
+    ErrorLoadingSheet(aURI,
+      nsPrintfCString("LoadSheetSync failed with error %x", rv).get(),
+      aFailureAction);
   }
 }
 
 /* static */ void
 nsLayoutStylesheetCache::InvalidateSheet(RefPtr<StyleSheet>* aGeckoSheet,
                                          RefPtr<StyleSheet>* aServoSheet)
 {
   MOZ_ASSERT(gCSSLoader_Gecko || gCSSLoader_Servo,
--- a/layout/style/nsLayoutStylesheetCache.h
+++ b/layout/style/nsLayoutStylesheetCache.h
@@ -17,16 +17,28 @@
 
 class nsIFile;
 class nsIURI;
 
 namespace mozilla {
 class CSSStyleSheet;
 } // namespace mozilla
 
+namespace mozilla {
+namespace css {
+
+// Enum defining how error should be handled.
+enum FailureAction {
+  eCrash = 0,
+  eLogToConsole
+};
+
+}
+}
+
 class nsLayoutStylesheetCache final
  : public nsIObserver
  , public nsIMemoryReporter
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIMEMORYREPORTER
 
@@ -73,22 +85,25 @@ class nsLayoutStylesheetCache final
 private:
   explicit nsLayoutStylesheetCache(mozilla::StyleBackendType aImpl);
   ~nsLayoutStylesheetCache();
 
   void InitFromProfile();
   void InitMemoryReporter();
   void LoadSheetURL(const char* aURL,
                     RefPtr<mozilla::StyleSheet>* aSheet,
-                    mozilla::css::SheetParsingMode aParsingMode);
+                    mozilla::css::SheetParsingMode aParsingMode,
+                    mozilla::css::FailureAction aFailureAction);
   void LoadSheetFile(nsIFile* aFile,
                      RefPtr<mozilla::StyleSheet>* aSheet,
-                     mozilla::css::SheetParsingMode aParsingMode);
+                     mozilla::css::SheetParsingMode aParsingMode,
+                     mozilla::css::FailureAction aFailureAction);
   void LoadSheet(nsIURI* aURI, RefPtr<mozilla::StyleSheet>* aSheet,
-                 mozilla::css::SheetParsingMode aParsingMode);
+                 mozilla::css::SheetParsingMode aParsingMode,
+                 mozilla::css::FailureAction aFailureAction);
   static void InvalidateSheet(RefPtr<mozilla::StyleSheet>* aGeckoSheet,
                               RefPtr<mozilla::StyleSheet>* aServoSheet);
   static void DependentPrefChanged(const char* aPref, void* aData);
   void BuildPreferenceSheet(RefPtr<mozilla::StyleSheet>* aSheet,
                             nsPresContext* aPresContext);
 
   static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache_Gecko;
   static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache_Servo;