Bug 1431255 - Part XIII, Make <link> in UA Widget load stylesheets synchronously r=bzbarsky
authorTimothy Guan-tin Chien <timdream@gmail.com>
Tue, 07 Aug 2018 11:20:31 -0700
changeset 486763 dca187f7c72cd1db75109d1b2d8a24fcf866e905
parent 486762 c42039f3ffe7adf644c2d8ad7873300b2defbc50
child 486764 f2abc57ccd74ae228d4bfb382baf452de7f1c0b6
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1431255
milestone63.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 1431255 - Part XIII, Make <link> in UA Widget load stylesheets synchronously r=bzbarsky Set SheetLoadData::mSyncLoad to true when the link element is in a UA Widget. MozReview-Commit-ID: 2NPSJnL0rKl
layout/style/Loader.cpp
layout/style/SheetLoadData.h
toolkit/content/widgets/videocontrols.js
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -137,31 +137,32 @@ static const char* const gStateStrings[]
  ********************************/
 NS_IMPL_ISUPPORTS(SheetLoadData, nsIRunnable,
                   nsIThreadObserver)
 
 SheetLoadData::SheetLoadData(Loader* aLoader,
                              const nsAString& aTitle,
                              nsIURI* aURI,
                              StyleSheet* aSheet,
+                             bool aSyncLoad,
                              nsIStyleSheetLinkingElement* aOwningElement,
                              IsAlternate aIsAlternate,
                              MediaMatched aMediaMatches,
                              nsICSSLoaderObserver* aObserver,
                              nsIPrincipal* aLoaderPrincipal,
                              nsINode* aRequestingNode)
   : mLoader(aLoader)
   , mTitle(aTitle)
   , mEncoding(nullptr)
   , mURI(aURI)
   , mLineNumber(1)
   , mSheet(aSheet)
   , mNext(nullptr)
   , mPendingChildren(0)
-  , mSyncLoad(false)
+  , mSyncLoad(aSyncLoad)
   , mIsNonDocumentSheet(false)
   , mIsLoading(false)
   , mIsBeingParsed(false)
   , mIsCancelled(false)
   , mMustNotify(false)
   , mWasAlternate(aIsAlternate == IsAlternate::Yes)
   , mMediaMatched(aMediaMatches == MediaMatched::Yes)
   , mUseSystemPrincipal(false)
@@ -1895,16 +1896,17 @@ Loader::LoadInlineStyle(const SheetInfo&
     principal =
       BasePrincipal::Cast(aInfo.mTriggeringPrincipal)->PrincipalToInherit();
   }
 
   SheetLoadData* data = new SheetLoadData(this,
                                           aInfo.mTitle,
                                           nullptr,
                                           sheet,
+                                          false,
                                           owningElement,
                                           isAlternate,
                                           matched,
                                           aObserver,
                                           nullptr,
                                           aInfo.mContent);
 
   // We never actually load this, so just set its principal directly
@@ -1954,16 +1956,22 @@ Loader::LoadStyleLink(const SheetInfo& a
     ? aInfo.mTriggeringPrincipal.get()
     : loadingPrincipal;
 
   nsINode* context = aInfo.mContent;
   if (!context) {
     context = mDocument;
   }
 
+  bool syncLoad = aInfo.mContent &&
+                  aInfo.mContent->IsInUAWidget() &&
+                  IsChromeURI(aInfo.mURI);
+  LOG(("  Link sync load: '%s'", syncLoad ? "true" : "false"));
+  MOZ_ASSERT_IF(syncLoad, !aObserver);
+
   nsresult rv = CheckContentPolicy(loadingPrincipal, principal, aInfo.mURI, context, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     // Don't fire the error event if our document is loaded as data.  We're
     // supposed to not even try to do loads in that case... Unfortunately, we
     // implement that via nsDataDocumentContentPolicy, which doesn't have a good
     // way to communicate back to us that _it_ is the thing that blocked the
     // load.
     if (aInfo.mContent && !mDocument->IsLoadedAsData()) {
@@ -1979,17 +1987,17 @@ Loader::LoadStyleLink(const SheetInfo& a
   }
 
   StyleSheetState state;
   RefPtr<StyleSheet> sheet;
   auto isAlternate = IsAlternateSheet(aInfo.mTitle, aInfo.mHasAlternateRel);
   rv = CreateSheet(aInfo,
                    principal,
                    eAuthorSheetFeatures,
-                   false,
+                   syncLoad,
                    state,
                    &sheet);
   if (NS_FAILED(rv)) {
     return Err(rv);
   }
 
   LOG(("  Sheet is alternate: %d", static_cast<int>(isAlternate)));
 
@@ -2019,31 +2027,33 @@ Loader::LoadStyleLink(const SheetInfo& a
     return LoadSheetResult { Completed::No, isAlternate, matched };
   }
 
   // Now we need to actually load it.
   SheetLoadData* data = new SheetLoadData(this,
                                           aInfo.mTitle,
                                           aInfo.mURI,
                                           sheet,
+                                          syncLoad,
                                           owningElement,
                                           isAlternate,
                                           matched,
                                           aObserver,
                                           principal,
                                           context);
   NS_ADDREF(data);
 
   auto result = LoadSheetResult { Completed::No, isAlternate, matched };
 
   MOZ_ASSERT(result.ShouldBlock() == !data->ShouldDefer(),
              "These should better match!");
 
   // If we have to parse and it's a non-blocking non-inline sheet, defer it.
-  if (state == eSheetNeedsParser &&
+  if (!syncLoad &&
+      state == eSheetNeedsParser &&
       mSheets->mLoadingDatas.Count() != 0 &&
       !result.ShouldBlock()) {
     LOG(("  Deferring sheet load"));
     URIPrincipalReferrerPolicyAndCORSModeHashKey key(data->mURI,
                                                      data->mLoaderPrincipal,
                                                      data->mSheet->GetCORSMode(),
                                                      data->mSheet->GetReferrerPolicy());
     mSheets->mPendingDatas.Put(&key, data);
@@ -2053,17 +2063,19 @@ Loader::LoadStyleLink(const SheetInfo& a
   }
 
   // Load completion will free the data
   rv = LoadSheet(data, state, false);
   if (NS_FAILED(rv)) {
     return Err(rv);
   }
 
-  data->mMustNotify = true;
+  if (!syncLoad) {
+    data->mMustNotify = true;
+  }
   return result;
 }
 
 static bool
 HaveAncestorDataWithURI(SheetLoadData *aData, nsIURI *aURI)
 {
   if (!aData->mURI) {
     // Inline style; this won't have any ancestors
@@ -2391,16 +2403,17 @@ Loader::PostLoadEvent(nsIURI* aURI,
   MOZ_ASSERT(aObserver || !mObservers.IsEmpty() || aElement,
              "Must have observer or element");
 
   RefPtr<SheetLoadData> evt =
     new SheetLoadData(this,
                       EmptyString(), // title doesn't matter here
                       aURI,
                       aSheet,
+                      false,
                       aElement,
                       aWasAlternate,
                       aMediaMatched,
                       aObserver,
                       nullptr,
                       mDocument);
 
   if (!mPostedEvents.AppendElement(evt)) {
--- a/layout/style/SheetLoadData.h
+++ b/layout/style/SheetLoadData.h
@@ -44,16 +44,17 @@ protected:
   virtual ~SheetLoadData();
 
 public:
   // Data for loading a sheet linked from a document
   SheetLoadData(Loader* aLoader,
                 const nsAString& aTitle,
                 nsIURI* aURI,
                 StyleSheet* aSheet,
+                bool aSyncLoad,
                 nsIStyleSheetLinkingElement* aOwningElement,
                 IsAlternate aIsAlternate,
                 MediaMatched aMediaMatched,
                 nsICSSLoaderObserver* aObserver,
                 nsIPrincipal* aLoaderPrincipal,
                 nsINode* aRequestingNode);
 
   // Data for loading a sheet linked from an @import rule
@@ -119,18 +120,19 @@ public:
 
   // Load data for the sheet that @import-ed us if we were @import-ed
   // during the parse
   RefPtr<SheetLoadData> mParentData;
 
   // Number of sheets we @import-ed that are still loading
   uint32_t mPendingChildren;
 
-  // mSyncLoad is true when the load needs to be synchronous -- right
-  // now only for LoadSheetSync and children of sync loads.
+  // mSyncLoad is true when the load needs to be synchronous.
+  // For LoadSheetSync, <link> to chrome stylesheets in UA Widgets,
+  // and children of sync loads.
   bool mSyncLoad : 1;
 
   // mIsNonDocumentSheet is true if the load was triggered by LoadSheetSync or
   // LoadSheet or an @import from such a sheet.  Non-document sheet loads can
   // proceed even if we have no document.
   bool mIsNonDocumentSheet : 1;
 
   // mIsLoading is true from the moment we are placed in the loader's
--- a/toolkit/content/widgets/videocontrols.js
+++ b/toolkit/content/widgets/videocontrols.js
@@ -259,16 +259,22 @@ this.VideoControlsImplPageWidget = class
               get: () => {
                 let controlId = control.id;
                 let propertyName = `--${controlId}-width`;
                 if (control.modifier) {
                   propertyName += "-" + control.modifier;
                 }
                 let preDefinedSize = this.controlBarComputedStyles.getPropertyValue(propertyName);
 
+                // This shouldn't happen, but if it does, the throw here turns
+                // intermittent oranges to perma-orange.
+                if (!preDefinedSize) {
+                  throw new Error("Stylesheet not loaded yet? propertyName: " + propertyName);
+                }
+
                 return parseInt(preDefinedSize, 10);
               }
             },
             isAdjustableControl: {
               value: true
             },
             modifier: {
               value: "",