Bug 1452143: Expose and honor a cssErrorReportingEnabled in the docshell. r?bholley draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 12 Apr 2018 11:59:09 +0200
changeset 783196 54edb6260b0b253a238f7d46ae0d66b93a1721c9
parent 783158 b579ffc7ad3238e0caebc81142b8dd986ae0ebd7
child 783197 f70ff2be9eef3ecf2e8315e8a9385de1345a6057
push id106640
push userbmo:emilio@crisal.io
push dateMon, 16 Apr 2018 19:43:11 +0000
reviewersbholley
bugs1452143
milestone61.0a1
Bug 1452143: Expose and honor a cssErrorReportingEnabled in the docshell. r?bholley The idea would be for parallel CSS parsing to check the static methods in ErrorReporter before loading the sheet. MozReview-Commit-ID: D7cedJQpz9K
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
layout/style/ErrorReporter.cpp
layout/style/ErrorReporter.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -357,16 +357,17 @@ nsDocShell::nsDocShell()
   , mAllowImages(true)
   , mAllowMedia(true)
   , mAllowDNSPrefetch(true)
   , mAllowWindowControl(true)
   , mAllowContentRetargeting(true)
   , mAllowContentRetargetingOnChildren(true)
   , mUseErrorPages(false)
   , mObserveErrorPages(true)
+  , mCSSErrorReportingEnabled(false)
   , mAllowAuth(true)
   , mAllowKeywordFixup(false)
   , mIsOffScreenBrowser(false)
   , mIsActive(true)
   , mDisableMetaRefreshWhenInactive(false)
   , mIsAppTab(false)
   , mUseGlobalHistory(false)
   , mUseRemoteTabs(false)
@@ -1682,16 +1683,31 @@ nsDocShell::GetAllowJavascript(bool* aAl
 {
   NS_ENSURE_ARG_POINTER(aAllowJavascript);
 
   *aAllowJavascript = mAllowJavascript;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled)
+{
+  MOZ_ASSERT(aEnabled);
+  *aEnabled = mCSSErrorReportingEnabled;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetCssErrorReportingEnabled(bool aEnabled)
+{
+  mCSSErrorReportingEnabled = aEnabled;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocShell::SetAllowJavascript(bool aAllowJavascript)
 {
   mAllowJavascript = aAllowJavascript;
   RecomputeCanExecuteScripts();
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -885,16 +885,21 @@ private: // member functions
 
   already_AddRefed<mozilla::dom::ChildSHistory> GetRootSessionHistory();
 
   inline bool UseErrorPages()
   {
     return (mObserveErrorPages ? sUseErrorPages : mUseErrorPages);
   }
 
+  bool CSSErrorReportingEnabled() const
+  {
+    return mCSSErrorReportingEnabled;
+  }
+
 private: // data members
   static nsIURIFixup* sURIFixup;
 
   // Cached value of the "browser.xul.error_pages.enabled" preference.
   static bool sUseErrorPages;
 
 #ifdef DEBUG
   // We're counting the number of |nsDocShells| to help find leaks
@@ -1103,16 +1108,17 @@ private: // data members
   bool mAllowImages : 1;
   bool mAllowMedia : 1;
   bool mAllowDNSPrefetch : 1;
   bool mAllowWindowControl : 1;
   bool mAllowContentRetargeting : 1;
   bool mAllowContentRetargetingOnChildren : 1;
   bool mUseErrorPages : 1;
   bool mObserveErrorPages : 1;
+  bool mCSSErrorReportingEnabled : 1;
   bool mAllowAuth : 1;
   bool mAllowKeywordFixup : 1;
   bool mIsOffScreenBrowser : 1;
   bool mIsActive : 1;
   bool mDisableMetaRefreshWhenInactive : 1;
   bool mIsAppTab : 1;
   bool mUseGlobalHistory : 1;
   bool mUseRemoteTabs : 1;
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -284,21 +284,26 @@ interface nsIDocShell : nsIDocShellTreeI
 
   /**
    * This attribute allows chrome to tie in to handle DOM events that may
    * be of interest to chrome.
    */
   attribute nsIDOMEventTarget chromeEventHandler;
 
   /**
-    * This allows chrome to set a custom User agent on a specific docshell
-    */
+   * This allows chrome to set a custom User agent on a specific docshell
+   */
   attribute DOMString customUserAgent;
 
   /**
+   * Whether CSS error reporting is enabled.
+   */
+  attribute boolean cssErrorReportingEnabled;
+
+  /**
    * Whether to allow plugin execution
    */
   attribute boolean allowPlugins;
 
   /**
    * Whether to allow Javascript execution
    */
   attribute boolean allowJavascript;
--- a/layout/style/ErrorReporter.cpp
+++ b/layout/style/ErrorReporter.cpp
@@ -11,17 +11,19 @@
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/SystemGroup.h"
 #include "nsCSSScanner.h"
 #include "nsIConsoleService.h"
 #include "nsIDocument.h"
+#include "nsIDocShell.h"
 #include "nsIFactory.h"
+#include "nsINode.h"
 #include "nsIScriptError.h"
 #include "nsISensitiveInfoHiddenURI.h"
 #include "nsIStringBundle.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStyleUtil.h"
 #include "nsThreadUtils.h"
 #include "nsNetUtil.h"
 
@@ -129,19 +131,21 @@ ErrorReporter::ReleaseGlobals()
   NS_IF_RELEASE(sSpecCache);
 }
 
 ErrorReporter::ErrorReporter(const StyleSheet* aSheet,
                              const Loader* aLoader,
                              nsIURI* aURI)
   : mSheet(aSheet)
   , mLoader(aLoader)
-  , mURI(aURI),
-    mInnerWindowID(0), mErrorLineNumber(0), mPrevErrorLineNumber(0),
-    mErrorColNumber(0)
+  , mURI(aURI)
+  , mInnerWindowID(0)
+  , mErrorLineNumber(0)
+  , mPrevErrorLineNumber(0)
+  , mErrorColNumber(0)
 {
 }
 
 ErrorReporter::~ErrorReporter()
 {
   // Schedule deferred cleanup for cached data. We want to strike a
   // balance between performance and memory usage, so we only allow
   // short-term caching.
@@ -153,16 +157,64 @@ ErrorReporter::~ErrorReporter()
       // Peform the "deferred" cleanup immediately if the dispatch fails.
       sSpecCache->Run();
     } else {
       sSpecCache->SetPending();
     }
   }
 }
 
+bool
+ErrorReporter::ShouldReportErrors(const nsIDocument& aDoc)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  nsIDocShell* shell = aDoc.GetDocShell();
+  if (!shell) {
+    return false;
+  }
+
+  bool report = false;
+  shell->GetCssErrorReportingEnabled(&report);
+  return report;
+}
+
+bool
+ErrorReporter::ShouldReportErrors()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  EnsureGlobalsInitialized();
+  if (!sReportErrors) {
+    return false;
+  }
+
+  if (mInnerWindowID) {
+    // We already reported an error, and that has cleared mSheet and mLoader, so
+    // we'd get the bogus value otherwise.
+    return true;
+  }
+
+  if (mSheet) {
+    nsINode* owner = mSheet->GetOwnerNode()
+      ? mSheet->GetOwnerNode()
+      : mSheet->GetAssociatedDocument();
+
+    if (owner && ShouldReportErrors(*owner->OwnerDoc())) {
+      return true;
+    }
+  }
+
+  if (mLoader && mLoader->GetDocument() &&
+      ShouldReportErrors(*mLoader->GetDocument())) {
+    return true;
+  }
+
+  return false;
+}
+
 void
 ErrorReporter::OutputError()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(ShouldReportErrors());
 
   if (mError.IsEmpty()) {
     return;
@@ -253,41 +305,41 @@ void
 ErrorReporter::ClearError()
 {
   mError.Truncate();
 }
 
 void
 ErrorReporter::AddToError(const nsString &aErrorText)
 {
-  if (!ShouldReportErrors()) return;
+  MOZ_ASSERT(ShouldReportErrors());
 
   if (mError.IsEmpty()) {
     mError = aErrorText;
   } else {
     mError.AppendLiteral("  ");
     mError.Append(aErrorText);
   }
 }
 
 void
 ErrorReporter::ReportUnexpected(const char *aMessage)
 {
-  if (!ShouldReportErrors()) return;
+  MOZ_ASSERT(ShouldReportErrors());
 
   nsAutoString str;
   sStringBundle->GetStringFromName(aMessage, str);
   AddToError(str);
 }
 
 void
 ErrorReporter::ReportUnexpectedUnescaped(const char *aMessage,
                                          const nsAutoString& aParam)
 {
-  if (!ShouldReportErrors()) return;
+  MOZ_ASSERT(ShouldReportErrors());
 
   const char16_t *params[1] = { aParam.get() };
 
   nsAutoString str;
   sStringBundle->FormatStringFromName(aMessage, params, ArrayLength(params),
                                       str);
   AddToError(str);
 }
--- a/layout/style/ErrorReporter.h
+++ b/layout/style/ErrorReporter.h
@@ -4,23 +4,23 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* diagnostic reporting for CSS style sheet parser */
 
 #ifndef mozilla_css_ErrorReporter_h_
 #define mozilla_css_ErrorReporter_h_
 
-#include "nsString.h"
+#include "nsStringFwd.h"
 
 struct nsCSSToken;
+class nsIDocument;
 class nsIURI;
 
 namespace mozilla {
-class ServoStyleSheet;
 class StyleSheet;
 
 namespace css {
 
 class Loader;
 
 class ErrorReporter {
 public:
@@ -32,50 +32,48 @@ public:
   static void ReleaseGlobals();
   static void EnsureGlobalsInitialized()
   {
     if (MOZ_UNLIKELY(!sInitialized)) {
       InitGlobals();
     }
   }
 
-  bool ShouldReportErrors() const
-  {
-    EnsureGlobalsInitialized();
-    return sReportErrors;
-  }
+  static bool ShouldReportErrors(const nsIDocument&);
+
+  bool ShouldReportErrors();
 
   void OutputError(uint32_t aLineNumber,
                    uint32_t aLineOffset,
                    const nsACString& aSource);
   void ClearError();
 
   // In all overloads of ReportUnexpected, aMessage is a stringbundle
   // name, which will be processed as a format string with the
   // indicated number of parameters.
 
   // no parameters
   void ReportUnexpected(const char *aMessage);
   // one parameter which has already been escaped appropriately
-  void ReportUnexpectedUnescaped(const char *aMessage,
+  void ReportUnexpectedUnescaped(const char* aMessage,
                                  const nsAutoString& aParam);
 
 private:
   void OutputError();
   void AddToError(const nsString &aErrorText);
   static void InitGlobals();
 
   static bool sInitialized;
   static bool sReportErrors;
 
   nsAutoString mError;
   nsString mErrorLine;
   nsString mFileName;
-  const StyleSheet *mSheet;
-  const Loader *mLoader;
+  const StyleSheet* mSheet;
+  const Loader* mLoader;
   nsIURI *mURI;
   uint64_t mInnerWindowID;
   uint32_t mErrorLineNumber;
   uint32_t mPrevErrorLineNumber;
   uint32_t mErrorColNumber;
 };
 
 } // namespace css