Bug 1328546 - stylo: Support ServoStyleSheets in nsIStyleSheetService::PreloadSheet and nsIDOMWindowUtils::AddSheet. r=bholley
authorCameron McCormack <cam@mcc.id.au>
Thu, 05 Jan 2017 15:32:22 +0800
changeset 328119 c069e5e1e63f5d4ae8d7857f7b0d5798b81a657c
parent 328118 07de2edd9c25f73cda65ceefcf1f1986f036fe70
child 328120 7fe7e01ef361d56091d288bb78c5df47a3ea8358
push id31163
push userkwierso@gmail.com
push dateFri, 06 Jan 2017 01:30:45 +0000
treeherdermozilla-central@a14094edbad7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1328546
milestone53.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 1328546 - stylo: Support ServoStyleSheets in nsIStyleSheetService::PreloadSheet and nsIDOMWindowUtils::AddSheet. r=bholley MozReview-Commit-ID: 2KOMrnCf1Ag
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
layout/base/moz.build
layout/base/nsIPreloadedStyleSheet.idl
layout/base/nsIStyleSheetService.idl
layout/base/nsStyleSheetService.cpp
layout/style/PreloadedStyleSheet.cpp
layout/style/PreloadedStyleSheet.h
layout/style/StyleAnimationValue.cpp
layout/style/moz.build
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -108,16 +108,17 @@
 #include "nsDocument.h"
 #include "HTMLImageElement.h"
 #include "mozilla/css/ImageLoader.h"
 #include "mozilla/layers/APZCTreeManager.h" // for layers::ZoomToRectBehavior
 #include "mozilla/dom/Promise.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/dom/TimeoutManager.h"
+#include "mozilla/PreloadedStyleSheet.h"
 
 #ifdef XP_WIN
 #undef GetClassName
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
@@ -3445,32 +3446,37 @@ nsDOMWindowUtils::LoadSheetUsingURIStrin
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), aSheetURI);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return LoadSheet(uri, aSheetType);
 }
 
 NS_IMETHODIMP
-nsDOMWindowUtils::AddSheet(nsIDOMStyleSheet *aSheet, uint32_t aSheetType)
+nsDOMWindowUtils::AddSheet(nsIPreloadedStyleSheet* aSheet, uint32_t aSheetType)
 {
   NS_ENSURE_ARG_POINTER(aSheet);
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
                 aSheetType == USER_SHEET ||
                 aSheetType == AUTHOR_SHEET);
 
   nsCOMPtr<nsIDocument> doc = GetDocument();
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
-  nsIDocument::additionalSheetType type = convertSheetType(aSheetType);
-  RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
+  StyleSheet* sheet = nullptr;
+  auto preloadedSheet = static_cast<PreloadedStyleSheet*>(aSheet);
+  nsresult rv = preloadedSheet->GetSheet(doc->GetStyleBackendType(), &sheet);
+  NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
+
   if (sheet->GetOwningDocument()) {
     return NS_ERROR_INVALID_ARG;
   }
+
+  nsIDocument::additionalSheetType type = convertSheetType(aSheetType);
   return doc->AddAdditionalStyleSheet(type, sheet);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::RemoveSheet(nsIURI *aSheetURI, uint32_t aSheetType)
 {
   NS_ENSURE_ARG_POINTER(aSheetURI);
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -30,17 +30,17 @@ native nscolor(nscolor);
 typedef unsigned long long nsViewID;
 
 interface nsICycleCollectorListener;
 interface nsIDOMNode;
 interface nsIDOMNodeList;
 interface nsIDOMElement;
 interface nsIDOMHTMLCanvasElement;
 interface nsIDOMEvent;
-interface nsIDOMStyleSheet;
+interface nsIPreloadedStyleSheet;
 interface nsITransferable;
 interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 interface nsIFile;
 interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
@@ -1739,17 +1739,17 @@ interface nsIDOMWindowUtils : nsISupport
 
   /**
    * Adds a style sheet to the list of additional style sheets of the document.
    *
    * Style sheets can be preloaded with nsIStyleSheetService.preloadSheet.
    *
    * Sheets added via this API take effect immediately on the document.
    */
-  void addSheet(in nsIDOMStyleSheet sheet, in unsigned long type);
+  void addSheet(in nsIPreloadedStyleSheet sheet, in unsigned long type);
 
   /**
    * Remove the document style sheet at |sheetURI| from the list of additional 
    * style sheets of the document.  The removal takes effect immediately.
    */
   void removeSheet(in nsIURI sheetURI, in unsigned long type);
 
   /**
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -15,16 +15,17 @@ with Files('nsChangeHint.h'):
 
 with Files('nsBidi*'):
     BUG_COMPONENT = ('Core', 'Layout: Text')
 
 with Files('AccessibleCaret*'):
     BUG_COMPONENT = ('Core', 'Selection')
 
 XPIDL_SOURCES += [
+    'nsIPreloadedStyleSheet.idl',
     'nsIStyleSheetService.idl',
 ]
 
 if CONFIG['MOZ_DEBUG']:
     UNIFIED_SOURCES += [
         'nsAutoLayoutPhase.cpp',
     ]
 
new file mode 100644
--- /dev/null
+++ b/layout/base/nsIPreloadedStyleSheet.idl
@@ -0,0 +1,16 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+#include "nsISupports.idl"
+
+/**
+ * The nsIPreloadedStyleSheet interface is an opaque interface for
+ * style sheets returned by nsIStyleSheetService.preloadSheet, and
+ * which can be passed to nsIDOMWindowUtils.addSheet.
+ */
+[scriptable, builtinclass, uuid(2e2a84d0-2102-4b9e-9b78-1670623a582d)]
+interface nsIPreloadedStyleSheet : nsISupports
+{
+};
--- a/layout/base/nsIStyleSheetService.idl
+++ b/layout/base/nsIStyleSheetService.idl
@@ -2,18 +2,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 /* interface for managing user and user-agent style sheets */
 
 #include "nsISupports.idl"
 
+interface nsIPreloadedStyleSheet;
 interface nsIURI;
-interface nsIDOMStyleSheet;
 
 /*
  * nsIStyleSheetService allows extensions or embeddors to add to the
  * built-in list of user or agent style sheets.
  */
 
 [scriptable, uuid(4de68896-e8eb-41de-8237-a797b570ac4a)]
 interface nsIStyleSheetService : nsISupports
@@ -46,17 +46,18 @@ interface nsIStyleSheetService : nsISupp
    * added to the list of style sheets specified by |type|.
    */
   boolean sheetRegistered(in nsIURI sheetURI, in unsigned long type);
 
   /**
    * Synchronously loads a style sheet from |sheetURI| and returns the
    * new style sheet object. Can be used with nsIDOMWindowUtils.addSheet.
    */
-  nsIDOMStyleSheet preloadSheet(in nsIURI sheetURI, in unsigned long type);
+  nsIPreloadedStyleSheet preloadSheet(in nsIURI sheetURI,
+                                      in unsigned long type);
 
   /**
    * Remove the style sheet at |sheetURI| from the list of style sheets
    * specified by |type|.  The removal takes effect immediately, even for
    * already-loaded documents.
    */
   void unregisterSheet(in nsIURI sheetURI, in unsigned long type);
 };
--- a/layout/base/nsStyleSheetService.cpp
+++ b/layout/base/nsStyleSheetService.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 /* implementation of interface for managing user and user-agent style sheets */
 
 #include "nsStyleSheetService.h"
 #include "mozilla/CSSStyleSheet.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/PreloadedStyleSheet.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/Unused.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
@@ -257,21 +258,24 @@ nsStyleSheetService::SheetRegistered(nsI
   NS_PRECONDITION(_retval, "Null out param");
 
   *_retval = (FindSheetByURI(mSheets[aSheetType], sheetURI) >= 0);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsStyleSheetService::PreloadSheet(nsIURI *aSheetURI, uint32_t aSheetType,
-                                  nsIDOMStyleSheet **aSheet)
+nsStyleSheetService::PreloadSheet(nsIURI* aSheetURI, uint32_t aSheetType,
+                                  nsIPreloadedStyleSheet** aSheet)
 {
   NS_PRECONDITION(aSheet, "Null out param");
   NS_ENSURE_ARG_POINTER(aSheetURI);
+
+  *aSheet = nullptr;
+
   css::SheetParsingMode parsingMode;
   switch (aSheetType) {
     case AGENT_SHEET:
       parsingMode = css::eAgentSheetFeatures;
       break;
 
     case USER_SHEET:
       parsingMode = css::eUserSheetFeatures;
@@ -281,31 +285,22 @@ nsStyleSheetService::PreloadSheet(nsIURI
       parsingMode = css::eAuthorSheetFeatures;
       break;
 
     default:
       NS_WARNING("invalid sheet type argument");
       return NS_ERROR_INVALID_ARG;
   }
 
-  // XXXheycam PreloadSheet can't support ServoStyleSheets until they implement
-  // nsIDOMStyleSheet.
-
-  RefPtr<css::Loader> loader = new css::Loader(StyleBackendType::Gecko);
-
-  RefPtr<StyleSheet> sheet;
-  nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet);
+  RefPtr<PreloadedStyleSheet> sheet;
+  nsresult rv = PreloadedStyleSheet::Create(aSheetURI, parsingMode,
+                                            getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  MOZ_ASSERT(sheet->IsGecko(),
-             "stylo: didn't expect Loader to create a ServoStyleSheet");
-
-  RefPtr<CSSStyleSheet> cssSheet = sheet->AsGecko();
-  cssSheet.forget(aSheet);
-
+  sheet.forget(aSheet);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStyleSheetService::UnregisterSheet(nsIURI *aSheetURI, uint32_t aSheetType)
 {
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
                 aSheetType == USER_SHEET ||
new file mode 100644
--- /dev/null
+++ b/layout/style/PreloadedStyleSheet.cpp
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:tabstop=2:expandtab:shiftwidth=2:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+/* a CSS style sheet returned from nsIStyleSheetService.preloadSheet */
+
+#include "PreloadedStyleSheet.h"
+
+namespace mozilla {
+
+PreloadedStyleSheet::PreloadedStyleSheet(nsIURI* aURI,
+                                         css::SheetParsingMode aParsingMode)
+  : mURI(aURI)
+  , mParsingMode(aParsingMode)
+{
+}
+
+/* static */ nsresult
+PreloadedStyleSheet::Create(nsIURI* aURI,
+                            css::SheetParsingMode aParsingMode,
+                            PreloadedStyleSheet** aResult)
+{
+  *aResult = nullptr;
+
+  // The nsIStyleSheetService.preloadSheet API doesn't tell us which backend
+  // the sheet will be used with, and it seems wasteful to eagerly create
+  // both a CSSStyleSheet and a ServoStyleSheet.  So instead, we guess that
+  // the sheet type we will want matches the current value of the stylo pref,
+  // and preload a sheet of that type.
+  //
+  // If we guess wrong, we will re-load the sheet later with the requested type,
+  // and we won't really have front loaded the loading time as the name
+  // "preload" might suggest.  Also, in theory we could get different data from
+  // fetching the URL again, but for the usage patterns of this API this is
+  // unlikely, and it doesn't seem worth trying to store the contents of the URL
+  // and duplicating a bunch of css::Loader's logic.
+
+  RefPtr<PreloadedStyleSheet> preloadedSheet =
+    new PreloadedStyleSheet(aURI, aParsingMode);
+  auto type = nsLayoutUtils::StyloEnabled() ? StyleBackendType::Servo
+                                            : StyleBackendType::Gecko;
+  StyleSheet* sheet;
+  nsresult rv = preloadedSheet->GetSheet(type, &sheet);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  preloadedSheet.forget(aResult);
+  return NS_OK;
+}
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PreloadedStyleSheet)
+  NS_INTERFACE_MAP_ENTRY(nsIPreloadedStyleSheet)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(PreloadedStyleSheet)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(PreloadedStyleSheet)
+
+NS_IMPL_CYCLE_COLLECTION(PreloadedStyleSheet, mGecko, mServo)
+
+nsresult
+PreloadedStyleSheet::GetSheet(StyleBackendType aType, StyleSheet** aResult)
+{
+  *aResult = nullptr;
+
+  RefPtr<StyleSheet>& sheet =
+    aType == StyleBackendType::Gecko ? mGecko : mServo;
+
+  if (!sheet) {
+    RefPtr<css::Loader> loader = new css::Loader(aType);
+    nsresult rv = loader->LoadSheetSync(mURI, mParsingMode, true, &sheet);
+    NS_ENSURE_SUCCESS(rv, rv);
+    MOZ_ASSERT(sheet);
+  }
+
+  *aResult = sheet;
+  return NS_OK;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/PreloadedStyleSheet.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:tabstop=2:expandtab:shiftwidth=2:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+/* a CSS style sheet returned from nsIStyleSheetService.preloadSheet */
+
+#ifndef mozilla_PreloadedStyleSheet_h
+#define mozilla_PreloadedStyleSheet_h
+
+#include "mozilla/css/SheetParsingMode.h"
+#include "mozilla/Result.h"
+#include "nsIPreloadedStyleSheet.h"
+
+namespace mozilla {
+
+class PreloadedStyleSheet : public nsIPreloadedStyleSheet
+{
+public:
+  // *aResult is addrefed.
+  static nsresult Create(nsIURI* aURI, css::SheetParsingMode aParsingMode,
+                         PreloadedStyleSheet** aResult);
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(PreloadedStyleSheet)
+
+  // *aResult is not addrefed, since the PreloadedStyleSheet holds a strong
+  // reference to the sheet.
+  nsresult GetSheet(StyleBackendType aType, StyleSheet** aResult);
+
+protected:
+  virtual ~PreloadedStyleSheet() {}
+
+private:
+  PreloadedStyleSheet(nsIURI* aURI, css::SheetParsingMode aParsingMode);
+
+  RefPtr<StyleSheet> mGecko;
+  RefPtr<StyleSheet> mServo;
+
+  nsCOMPtr<nsIURI> mURI;
+  css::SheetParsingMode mParsingMode;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_PreloadedStyleSheet_h
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Utilities for animation of computed style values */
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/RuleNodeCacheConditions.h"
 #include "mozilla/StyleAnimationValue.h"
+#include "mozilla/StyleSetHandle.h"
+#include "mozilla/StyleSetHandleInlines.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/UniquePtr.h"
 #include "nsStyleTransformMatrix.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsIStyleRule.h"
 #include "mozilla/css/StyleRule.h"
 #include "nsString.h"
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -87,16 +87,17 @@ EXPORTS.mozilla += [
     'CSSVariableResolver.h',
     'CSSVariableValues.h',
     'DeclarationBlock.h',
     'DeclarationBlockInlines.h',
     'DocumentStyleRootIterator.h',
     'HandleRefPtr.h',
     'IncrementalClearCOMRuleArray.h',
     'LayerAnimationInfo.h',
+    'PreloadedStyleSheet.h',
     'RuleNodeCacheConditions.h',
     'RuleProcessorCache.h',
     'ServoArcTypeList.h',
     'ServoBindingList.h',
     'ServoBindings.h',
     'ServoBindingTypes.h',
     'ServoCSSRuleList.h',
     'ServoDeclarationBlock.h',
@@ -192,16 +193,17 @@ UNIFIED_SOURCES += [
     'nsRuleNode.cpp',
     'nsStyleContext.cpp',
     'nsStyleCoord.cpp',
     'nsStyleSet.cpp',
     'nsStyleStruct.cpp',
     'nsStyleTransformMatrix.cpp',
     'nsStyleUtil.cpp',
     'nsTransitionManager.cpp',
+    'PreloadedStyleSheet.cpp',
     'RuleNodeCacheConditions.cpp',
     'RuleProcessorCache.cpp',
     'ServoBindings.cpp',
     'ServoCSSRuleList.cpp',
     'ServoDeclarationBlock.cpp',
     'ServoElementSnapshot.cpp',
     'ServoStyleRule.cpp',
     'ServoStyleSet.cpp',