Bug 1625930: Implement ResourceWatcher for stylesheet. r=ochameau

Differential Revision: https://phabricator.services.mozilla.com/D78239
This commit is contained in:
Daisuke Akatsuka 2020-07-08 14:05:29 +00:00
Родитель 2e741db198
Коммит 124d4687f9
4 изменённых файлов: 62 добавлений и 21 удалений

Просмотреть файл

@ -651,22 +651,17 @@ var StyleSheetsActor = protocol.ActorClassWithSpec(styleSheetsSpec, {
this.parentActor = targetActor; this.parentActor = targetActor;
this._onApplicableStateChanged = this._onApplicableStateChanged.bind(this);
this._onNewStyleSheetActor = this._onNewStyleSheetActor.bind(this); this._onNewStyleSheetActor = this._onNewStyleSheetActor.bind(this);
this._onSheetAdded = this._onSheetAdded.bind(this);
this._onWindowReady = this._onWindowReady.bind(this); this._onWindowReady = this._onWindowReady.bind(this);
this._transitionSheetLoaded = false; this._transitionSheetLoaded = false;
this.parentActor.on("stylesheet-added", this._onNewStyleSheetActor); this.parentActor.on("stylesheet-added", this._onNewStyleSheetActor);
this.parentActor.on("window-ready", this._onWindowReady); this.parentActor.on("window-ready", this._onWindowReady);
// We listen for StyleSheetApplicableStateChanged rather than
// StyleSheetAdded, because the latter will be sent before the
// rules are ready. Using the former (with a check to ensure that
// the sheet is enabled) ensures that the sheet is ready before we
// try to make an actor for it.
this.parentActor.chromeEventHandler.addEventListener( this.parentActor.chromeEventHandler.addEventListener(
"StyleSheetApplicableStateChanged", "StyleSheetApplicableStateChanged",
this._onSheetAdded, this._onApplicableStateChanged,
true true
); );
@ -688,7 +683,7 @@ var StyleSheetsActor = protocol.ActorClassWithSpec(styleSheetsSpec, {
this.parentActor.chromeEventHandler.removeEventListener( this.parentActor.chromeEventHandler.removeEventListener(
"StyleSheetApplicableStateChanged", "StyleSheetApplicableStateChanged",
this._onSheetAdded, this._onApplicableStateChanged,
true true
); );
@ -745,10 +740,7 @@ var StyleSheetsActor = protocol.ActorClassWithSpec(styleSheetsSpec, {
// Special case about:PreferenceStyleSheet, as it is generated on the // Special case about:PreferenceStyleSheet, as it is generated on the
// fly and the URI is not registered with the about: handler. // fly and the URI is not registered with the about: handler.
// https://bugzilla.mozilla.org/show_bug.cgi?id=935803#c37 // https://bugzilla.mozilla.org/show_bug.cgi?id=935803#c37
if ( if (sheet.href?.toLowerCase() === "about:preferencestylesheet") {
sheet.href &&
sheet.href.toLowerCase() == "about:preferencestylesheet"
) {
return false; return false;
} }
@ -756,18 +748,32 @@ var StyleSheetsActor = protocol.ActorClassWithSpec(styleSheetsSpec, {
}, },
/** /**
* Event handler that is called when a new style sheet is added to * Event handler that is called when the state of applicable of style sheet is changed.
* a document. In particular, StyleSheetApplicableStateChanged is
* listened for, because StyleSheetAdded is sent too early, before
* the rules are ready.
* *
* @param {Event} evt * For now, StyleSheetApplicableStateChanged event will be called at following timings.
* - Append <link> of stylesheet to document
* - Append <style> to document
* - Change disable attribute of stylesheet object
* - Change disable attribute of <link> to false
* When appending <link>, <style> or changing `disable` attribute to false, `applicable`
* is passed as true. The other hand, when changing `disable` to true, this will be
* false.
* NOTE: For now, StyleSheetApplicableStateChanged will not be called when removing the
* link and style element.
*
* @param {StyleSheetApplicableStateChanged}
* The triggering event. * The triggering event.
*/ */
_onSheetAdded: function(evt) { _onApplicableStateChanged: function({ applicable, stylesheet }) {
const sheet = evt.stylesheet; if (
if (this._shouldListSheet(sheet) && !this._haveAncestorWithSameURL(sheet)) { // Have interest in applicable stylesheet only.
this.parentActor.createStyleSheetActor(sheet); applicable &&
// No ownerNode means that this stylesheet is *not* associated to a DOM Element.
stylesheet.ownerNode &&
this._shouldListSheet(stylesheet) &&
!this._haveAncestorWithSameURL(stylesheet)
) {
this.parentActor.createStyleSheetActor(stylesheet);
} }
}, },

Просмотреть файл

@ -9,4 +9,5 @@ DevToolsModules(
'error-messages.js', 'error-messages.js',
'platform-messages.js', 'platform-messages.js',
'root-node.js', 'root-node.js',
'stylesheet.js',
) )

Просмотреть файл

@ -0,0 +1,31 @@
/* 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/. */
"use strict";
const {
ResourceWatcher,
} = require("devtools/shared/resources/resource-watcher");
module.exports = async function({ targetFront, onAvailable }) {
if (!targetFront.hasActor("styleSheets")) {
return;
}
const styleSheetsFront = await targetFront.getFront("stylesheets");
const styleSheets = await styleSheetsFront.getStyleSheets();
onAvailable(styleSheets.map(styleSheet => toResource(styleSheet, false)));
styleSheetsFront.on("stylesheet-added", (styleSheet, isNew) => {
onAvailable([toResource(styleSheet, isNew)]);
});
};
function toResource(styleSheet, isNew) {
return {
resourceType: ResourceWatcher.TYPES.STYLESHEET,
styleSheet,
isNew,
};
}

Просмотреть файл

@ -439,6 +439,7 @@ ResourceWatcher.TYPES = ResourceWatcher.prototype.TYPES = {
PLATFORM_MESSAGE: "platform-message", PLATFORM_MESSAGE: "platform-message",
DOCUMENT_EVENT: "document-event", DOCUMENT_EVENT: "document-event",
ROOT_NODE: "root-node", ROOT_NODE: "root-node",
STYLESHEET: "stylesheet",
}; };
module.exports = { ResourceWatcher }; module.exports = { ResourceWatcher };
@ -475,6 +476,8 @@ const LegacyListeners = {
}, },
[ResourceWatcher.TYPES [ResourceWatcher.TYPES
.ROOT_NODE]: require("devtools/shared/resources/legacy-listeners/root-node"), .ROOT_NODE]: require("devtools/shared/resources/legacy-listeners/root-node"),
[ResourceWatcher.TYPES
.STYLESHEET]: require("devtools/shared/resources/legacy-listeners/stylesheet"),
}; };
// Optional transformers for each type of resource. // Optional transformers for each type of resource.