stylesheets.js (3520B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 loader.lazyRequireGetter( 8 this, 9 "CssLogic", 10 "resource://devtools/shared/inspector/css-logic.js" 11 ); 12 13 class StyleSheetWatcher { 14 constructor() { 15 this._onApplicableStylesheetAdded = 16 this._onApplicableStylesheetAdded.bind(this); 17 this._onStylesheetUpdated = this._onStylesheetUpdated.bind(this); 18 this._onStylesheetRemoved = this._onStylesheetRemoved.bind(this); 19 } 20 21 /** 22 * Start watching for all stylesheets related to a given Target Actor. 23 * 24 * @param TargetActor targetActor 25 * The target actor from which we should observe css changes. 26 * @param Object options 27 * Dictionary object with following attributes: 28 * - onAvailable: mandatory function 29 * This will be called for each resource. 30 */ 31 async watch(targetActor, { onAvailable, onUpdated, onDestroyed }) { 32 this._targetActor = targetActor; 33 this._onAvailable = onAvailable; 34 this._onUpdated = onUpdated; 35 this._onDestroyed = onDestroyed; 36 37 this._styleSheetsManager = targetActor.getStyleSheetsManager(); 38 39 // watch will call onAvailable for already existing stylesheets 40 await this._styleSheetsManager.watch({ 41 onAvailable: this._onApplicableStylesheetAdded, 42 onUpdated: this._onStylesheetUpdated, 43 onDestroyed: this._onStylesheetRemoved, 44 }); 45 } 46 47 async _onApplicableStylesheetAdded(styleSheetData) { 48 const { resourceId, styleSheet, creationData } = styleSheetData; 49 const resource = await this._toResource(styleSheet, { 50 resourceId, 51 isCreatedByDevTools: creationData?.isCreatedByDevTools, 52 fileName: creationData?.fileName, 53 }); 54 55 this._onAvailable([resource]); 56 } 57 58 _onStylesheetUpdated({ resourceId, updateKind, updates = {} }) { 59 const { resourceUpdates, nestedResourceUpdates, event } = updates; 60 this._onUpdated([ 61 { 62 browsingContextID: this._targetActor.browsingContextID, 63 innerWindowId: this._targetActor.innerWindowId, 64 resourceId, 65 updateType: updateKind, 66 resourceUpdates, 67 nestedResourceUpdates, 68 event, 69 }, 70 ]); 71 } 72 73 _onStylesheetRemoved({ resourceId }) { 74 return this._onDestroyed([resourceId]); 75 } 76 77 async _toResource( 78 styleSheet, 79 { isCreatedByDevTools = false, fileName = null, resourceId } = {} 80 ) { 81 const { atRules, ruleCount } = 82 this._styleSheetsManager.getStyleSheetRuleCountAndAtRules(styleSheet); 83 84 const resource = { 85 resourceId, 86 disabled: styleSheet.disabled, 87 constructed: styleSheet.constructed, 88 fileName, 89 href: styleSheet.href, 90 isNew: isCreatedByDevTools, 91 atRules, 92 nodeHref: this._styleSheetsManager.getNodeHref(styleSheet), 93 ruleCount, 94 sourceMapBaseURL: 95 this._styleSheetsManager.getSourcemapBaseURL(styleSheet), 96 sourceMapURL: styleSheet.sourceMapURL, 97 styleSheetIndex: this._styleSheetsManager.getStyleSheetIndex(resourceId), 98 system: CssLogic.isAgentStylesheet(styleSheet), 99 title: styleSheet.title, 100 }; 101 102 return resource; 103 } 104 105 destroy() { 106 this._styleSheetsManager.unwatch({ 107 onAvailable: this._onApplicableStylesheetAdded, 108 onUpdated: this._onStylesheetUpdated, 109 onDestroyed: this._onStylesheetRemoved, 110 }); 111 } 112 } 113 114 module.exports = StyleSheetWatcher;