Bug 1328546 - stylo: Support ServoStyleSheets in nsIStyleSheetService::PreloadSheet and nsIDOMWindowUtils::AddSheet. r?bholley
MozReview-Commit-ID: 2KOMrnCf1Ag
--- 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,33 +3446,40 @@ 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);
- NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
- if (sheet->GetOwningDocument()) {
+ auto preloadedSheet = static_cast<PreloadedStyleSheet*>(aSheet);
+
+ const PreloadedStyleSheet::SheetAndStatus& data =
+ preloadedSheet->GetSheet(doc->GetStyleBackendType());
+
+ NS_ENSURE_SUCCESS(data.mLoadStatus, data.mLoadStatus);
+ NS_ENSURE_TRUE(data.mSheet, NS_ERROR_FAILURE);
+
+ if (data.mSheet->GetOwningDocument()) {
return NS_ERROR_INVALID_ARG;
}
- return doc->AddAdditionalStyleSheet(type, sheet);
+
+ nsIDocument::additionalSheetType type = convertSheetType(aSheetType);
+ return doc->AddAdditionalStyleSheet(type, data.mSheet);
}
NS_IMETHODIMP
nsDOMWindowUtils::RemoveSheet(nsIURI *aSheetURI, uint32_t aSheetType)
{
NS_ENSURE_ARG_POINTER(aSheetURI);
NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
aSheetType == USER_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,18 +258,18 @@ 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);
css::SheetParsingMode parsingMode;
switch (aSheetType) {
case AGENT_SHEET:
parsingMode = css::eAgentSheetFeatures;
break;
@@ -281,31 +282,26 @@ 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<PreloadedStyleSheet> sheet =
+ new PreloadedStyleSheet(aSheetURI, parsingMode);
- RefPtr<StyleSheet> sheet;
- nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv = sheet->GetPreloadResult();
+ if (NS_FAILED(rv)) {
+ *aSheet = nullptr;
+ return 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,89 @@
+/* -*- 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)
+{
+ // 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.
+ GetSheet(nsLayoutUtils::StyloEnabled() ? StyleBackendType::Servo
+ : StyleBackendType::Gecko);
+}
+
+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_CLASS(PreloadedStyleSheet)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PreloadedStyleSheet)
+ if (tmp->mGecko) {
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGecko->mSheet);
+ }
+ if (tmp->mServo) {
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServo->mSheet);
+ }
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PreloadedStyleSheet)
+ if (tmp->mGecko) {
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mGecko->mSheet);
+ }
+ if (tmp->mServo) {
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mServo->mSheet);
+ }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+const PreloadedStyleSheet::SheetAndStatus&
+PreloadedStyleSheet::GetSheet(StyleBackendType aType)
+{
+ auto& data = aType == StyleBackendType::Gecko ? mGecko : mServo;
+
+ if (!data) {
+ RefPtr<css::Loader> loader = new css::Loader(aType);
+ data.emplace();
+ data->mLoadStatus =
+ loader->LoadSheetSync(mURI, mParsingMode, true, &data->mSheet);
+ }
+
+ return *data;
+}
+
+nsresult
+PreloadedStyleSheet::GetPreloadResult() const
+{
+ MOZ_ASSERT(mGecko.isSome() != mServo.isSome(),
+ "don't call GetPreloadResult after a second type of sheet has "
+ "been loaded");
+ if (mGecko.isSome()) {
+ return mGecko->mLoadStatus;
+ }
+ return mServo->mLoadStatus;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/PreloadedStyleSheet.h
@@ -0,0 +1,48 @@
+/* -*- 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/Maybe.h"
+#include "nsIPreloadedStyleSheet.h"
+
+namespace mozilla {
+
+class PreloadedStyleSheet : public nsIPreloadedStyleSheet
+{
+public:
+ struct SheetAndStatus
+ {
+ RefPtr<StyleSheet> mSheet;
+ nsresult mLoadStatus;
+ };
+
+ PreloadedStyleSheet(nsIURI* aURI, css::SheetParsingMode aParsingMode);
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS(PreloadedStyleSheet)
+
+ nsresult GetPreloadResult() const;
+ const SheetAndStatus& GetSheet(StyleBackendType aType);
+
+protected:
+ virtual ~PreloadedStyleSheet() {}
+
+private:
+ Maybe<SheetAndStatus> mGecko;
+ Maybe<SheetAndStatus> mServo;
+
+ nsCOMPtr<nsIURI> mURI;
+ css::SheetParsingMode mParsingMode;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_PreloadedStyleSheet_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',
@@ -193,16 +194,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',