diff options
Diffstat (limited to 'devtools/server/actors/resources/stylesheets.js')
-rw-r--r-- | devtools/server/actors/resources/stylesheets.js | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/devtools/server/actors/resources/stylesheets.js b/devtools/server/actors/resources/stylesheets.js new file mode 100644 index 0000000000..ef0b1b0f75 --- /dev/null +++ b/devtools/server/actors/resources/stylesheets.js @@ -0,0 +1,136 @@ +/* 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 { + TYPES: { STYLESHEET }, +} = require("resource://devtools/server/actors/resources/index.js"); + +loader.lazyRequireGetter( + this, + "CssLogic", + "resource://devtools/shared/inspector/css-logic.js" +); + +class StyleSheetWatcher { + constructor() { + this._onApplicableStylesheetAdded = + this._onApplicableStylesheetAdded.bind(this); + this._onStylesheetUpdated = this._onStylesheetUpdated.bind(this); + } + + /** + * Start watching for all stylesheets related to a given Target Actor. + * + * @param TargetActor targetActor + * The target actor from which we should observe css changes. + * @param Object options + * Dictionary object with following attributes: + * - onAvailable: mandatory function + * This will be called for each resource. + */ + async watch(targetActor, { onAvailable, onUpdated }) { + this._targetActor = targetActor; + this._onAvailable = onAvailable; + this._onUpdated = onUpdated; + + this._styleSheetsManager = targetActor.getStyleSheetsManager(); + + // Add event listener for new additions and updates + this._styleSheetsManager.on( + "applicable-stylesheet-added", + this._onApplicableStylesheetAdded + ); + this._styleSheetsManager.on( + "stylesheet-updated", + this._onStylesheetUpdated + ); + + // startWatching will emit applicable-stylesheet-added for already existing stylesheet + await this._styleSheetsManager.startWatching(); + } + + _onApplicableStylesheetAdded(styleSheetData) { + return this._notifyResourcesAvailable([styleSheetData]); + } + + _onStylesheetUpdated({ resourceId, updateKind, updates = {} }) { + this._notifyResourceUpdated(resourceId, updateKind, updates); + } + + async _toResource( + styleSheet, + { isCreatedByDevTools = false, fileName = null, resourceId } = {} + ) { + const resource = { + resourceId, + resourceType: STYLESHEET, + disabled: styleSheet.disabled, + constructed: styleSheet.constructed, + fileName, + href: styleSheet.href, + isNew: isCreatedByDevTools, + atRules: await this._styleSheetsManager.getAtRules(styleSheet), + nodeHref: this._styleSheetsManager._getNodeHref(styleSheet), + ruleCount: styleSheet.cssRules.length, + sourceMapBaseURL: + this._styleSheetsManager._getSourcemapBaseURL(styleSheet), + sourceMapURL: styleSheet.sourceMapURL, + styleSheetIndex: this._styleSheetsManager._getStyleSheetIndex(styleSheet), + system: CssLogic.isAgentStylesheet(styleSheet), + title: styleSheet.title, + }; + + return resource; + } + + async _notifyResourcesAvailable(styleSheets) { + const resources = await Promise.all( + styleSheets.map(async ({ resourceId, styleSheet, creationData }) => { + const resource = await this._toResource(styleSheet, { + resourceId, + isCreatedByDevTools: creationData?.isCreatedByDevTools, + fileName: creationData?.fileName, + }); + + return resource; + }) + ); + + await this._onAvailable(resources); + } + + _notifyResourceUpdated( + resourceId, + updateType, + { resourceUpdates, nestedResourceUpdates, event } + ) { + this._onUpdated([ + { + browsingContextID: this._targetActor.browsingContextID, + innerWindowId: this._targetActor.innerWindowId, + resourceType: STYLESHEET, + resourceId, + updateType, + resourceUpdates, + nestedResourceUpdates, + event, + }, + ]); + } + + destroy() { + this._styleSheetsManager.off( + "applicable-stylesheet-added", + this._onApplicableStylesheetAdded + ); + this._styleSheetsManager.off( + "stylesheet-updated", + this._onStylesheetUpdated + ); + } +} + +module.exports = StyleSheetWatcher; |