Bug 1808870 - [devtools] Move getSheetOwnerNode to stylesheets-manager and delete actors/style-sheet.js r=nchevobbe

Depends on D166310

Differential Revision: https://phabricator.services.mozilla.com/D166311
This commit is contained in:
Julian Descottes 2023-01-17 08:06:16 +00:00
Родитель 7ddd2f77ff
Коммит d71c146658
5 изменённых файлов: 74 добавлений и 155 удалений

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

@ -56,7 +56,6 @@ DevToolsModules(
"storage.js",
"string.js",
"style-rule.js",
"style-sheet.js",
"style-sheets.js",
"target-configuration.js",
"thread-configuration.js",

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

@ -67,19 +67,18 @@ loader.lazyRequireGetter(
const lazy = {};
ChromeUtils.defineModuleGetter(lazy, "ExtensionContent", EXTENSION_CONTENT_JSM);
loader.lazyRequireGetter(
this,
["getSheetText"],
"resource://devtools/server/actors/style-sheet.js",
true
);
loader.lazyRequireGetter(
this,
"TouchSimulator",
"resource://devtools/server/actors/emulation/touch-simulator.js",
true
);
loader.lazyRequireGetter(
this,
["getStyleSheetText"],
"resource://devtools/server/actors/utils/stylesheet-utils.js",
true
);
function getWindowID(window) {
return window.windowGlobalChild.innerWindowId;
@ -1246,7 +1245,7 @@ const windowGlobalTargetPrototype = {
continue;
}
// Reparse the sheet so that we see the existing errors.
const onStyleSheetParsed = getSheetText(sheet)
const onStyleSheetParsed = getStyleSheetText(sheet)
.then(text => {
InspectorUtils.parseStyleSheet(sheet, text, /* aUpdate = */ false);
})

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

@ -23,6 +23,7 @@ DevToolsModules(
"sources-manager.js",
"stack.js",
"style-utils.js",
"stylesheet-utils.js",
"stylesheets-manager.js",
"track-change-emitter.js",
"walker-search.js",

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

@ -6,40 +6,20 @@
const { fetch } = require("resource://devtools/shared/DevToolsUtils.js");
// If the user edits a style sheet, we stash a copy of the edited text
// here, keyed by the style sheet. This way, if the tools are closed
// and then reopened, the edited text will be available. A weak map
// is used so that navigation by the user will eventually cause the
// edited text to be collected.
const modifiedStyleSheets = new WeakMap();
function getSheetText(sheet) {
const cssText = modifiedStyleSheets.get(sheet);
if (cssText !== undefined) {
return Promise.resolve(cssText);
}
if (!sheet.href) {
// this is an inline <style> sheet
const content = sheet.ownerNode.textContent;
return Promise.resolve(content);
}
return fetchStylesheet(sheet).then(({ content }) => content);
}
exports.getSheetText = getSheetText;
/**
* For imported stylesheets, `ownerNode` is null.
*
* To resolve the ownerNode for an imported stylesheet, loop on `parentStylesheet`
* until we reach the topmost stylesheet, which should have a valid ownerNode.
*
* Constructable stylesheets do not have an owner node and this method will
* return null.
*
* @param {StyleSheet}
* The stylesheet for which we want to retrieve the ownerNode.
* @return {DOMNode} The ownerNode
* @return {DOMNode|null} The ownerNode or null for constructable stylesheets.
*/
function getSheetOwnerNode(sheet) {
function getStyleSheetOwnerNode(sheet) {
// If this is not an imported stylesheet and we have an ownerNode available
// bail out immediately.
if (sheet.ownerNode) {
@ -56,47 +36,49 @@ function getSheetOwnerNode(sheet) {
return parentStyleSheet.ownerNode;
}
exports.getSheetOwnerNode = getSheetOwnerNode;
exports.getStyleSheetOwnerNode = getStyleSheetOwnerNode;
/**
* Get the charset of the stylesheet.
* Get the text of a stylesheet.
*
* TODO: A call site in window-global.js expects this method to return a promise
* so it is mandatory to keep it as an async function even if we are not using
* await explicitly. Bug 1810572.
*
* @param {StyleSheet}
* The stylesheet for which we want to retrieve the text.
* @returns {Promise}
*/
function getCSSCharset(sheet) {
if (sheet) {
// charset attribute of <link> or <style> element, if it exists
if (sheet.ownerNode?.getAttribute) {
const linkCharset = sheet.ownerNode.getAttribute("charset");
if (linkCharset != null) {
return linkCharset;
}
}
// charset of referring document.
if (sheet.ownerNode?.ownerDocument.characterSet) {
return sheet.ownerNode.ownerDocument.characterSet;
async function getStyleSheetText(styleSheet) {
if (!styleSheet.href) {
if (styleSheet.ownerNode) {
// this is an inline <style> sheet
return styleSheet.ownerNode.textContent;
}
// Constructed stylesheet.
// TODO(bug 1769933, bug 1809108): Maybe preserve authored text?
return "";
}
return "UTF-8";
return fetchStyleSheetText(styleSheet);
}
exports.getStyleSheetText = getStyleSheetText;
/**
* Fetch a stylesheet at the provided URL. Returns a promise that will resolve the
* result of the fetch command.
* Retrieve the content of a given stylesheet
*
* @return {Promise} a promise that resolves with an object with the following members
* on success:
* - content: the document at that URL, as a string,
* - contentType: the content type of the document
* If an error occurs, the promise is rejected with that error.
* @param {StyleSheet} styleSheet
* @returns {String}
*/
async function fetchStylesheet(sheet) {
const href = sheet.href;
async function fetchStyleSheetText(styleSheet) {
const href = styleSheet.href;
const options = {
loadFromCache: true,
policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET,
charset: getCSSCharset(sheet),
charset: getCSSCharset(styleSheet),
};
// Bug 1282660 - We use the system principal to load the default internal
@ -108,7 +90,7 @@ async function fetchStylesheet(sheet) {
const excludedProtocolsRe = /^(chrome|file|resource|moz-extension):\/\//;
if (!excludedProtocolsRe.test(href)) {
// Stylesheets using other protocols should use the content principal.
const ownerNode = getSheetOwnerNode(sheet);
const ownerNode = getStyleSheetOwnerNode(styleSheet);
if (ownerNode) {
// eslint-disable-next-line mozilla/use-ownerGlobal
options.window = ownerNode.ownerDocument.defaultView;
@ -124,7 +106,7 @@ async function fetchStylesheet(sheet) {
// The list of excluded protocols can be missing some protocols, try to use the
// system principal if the first fetch failed.
console.error(
`stylesheets actor: fetch failed for ${href},` +
`stylesheets: fetch failed for ${href},` +
` using system principal instead.`
);
options.window = undefined;
@ -132,5 +114,30 @@ async function fetchStylesheet(sheet) {
result = await fetch(href, options);
}
return result;
return result.content;
}
/**
* Get charset of a given stylesheet
*
* @param {StyleSheet} styleSheet
* @returns {String}
*/
function getCSSCharset(styleSheet) {
if (styleSheet) {
// charset attribute of <link> or <style> element, if it exists
if (styleSheet.ownerNode?.getAttribute) {
const linkCharset = styleSheet.ownerNode.getAttribute("charset");
if (linkCharset != null) {
return linkCharset;
}
}
// charset of referring document.
if (styleSheet.ownerNode?.ownerDocument.characterSet) {
return styleSheet.ownerNode.ownerDocument.characterSet;
}
}
return "UTF-8";
}

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

@ -5,7 +5,6 @@
"use strict";
const EventEmitter = require("resource://devtools/shared/event-emitter.js");
const { fetch } = require("resource://devtools/shared/DevToolsUtils.js");
const InspectorUtils = require("InspectorUtils");
const {
getSourcemapBaseURL,
@ -25,8 +24,8 @@ loader.lazyRequireGetter(
);
loader.lazyRequireGetter(
this,
["getSheetOwnerNode"],
"resource://devtools/server/actors/style-sheet.js",
["getStyleSheetOwnerNode", "getStyleSheetText"],
"resource://devtools/server/actors/utils/stylesheet-utils.js",
true
);
@ -274,17 +273,7 @@ class StyleSheetsManager extends EventEmitter {
return modifiedText;
}
if (!styleSheet.href) {
if (styleSheet.ownerNode) {
// this is an inline <style> sheet
return styleSheet.ownerNode.textContent;
}
// Constructed stylesheet.
// TODO(bug 176993): Maybe preserve authored text?
return "";
}
return this._fetchStyleSheet(styleSheet);
return getStyleSheetText(styleSheet);
}
/**
@ -424,82 +413,6 @@ class StyleSheetsManager extends EventEmitter {
});
}
/**
* Retrieve the content of a given stylesheet
*
* @param {StyleSheet} styleSheet
* @returns {String}
*/
async _fetchStyleSheet(styleSheet) {
const href = styleSheet.href;
const options = {
loadFromCache: true,
policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET,
charset: this._getCSSCharset(styleSheet),
};
// Bug 1282660 - We use the system principal to load the default internal
// stylesheets instead of the content principal since such stylesheets
// require system principal to load. At meanwhile, we strip the loadGroup
// for preventing the assertion of the userContextId mismatching.
// chrome|file|resource|moz-extension protocols rely on the system principal.
const excludedProtocolsRe = /^(chrome|file|resource|moz-extension):\/\//;
if (!excludedProtocolsRe.test(href)) {
// Stylesheets using other protocols should use the content principal.
const ownerNode = getSheetOwnerNode(styleSheet);
if (ownerNode) {
// eslint-disable-next-line mozilla/use-ownerGlobal
options.window = ownerNode.ownerDocument.defaultView;
options.principal = ownerNode.ownerDocument.nodePrincipal;
}
}
let result;
try {
result = await fetch(href, options);
} catch (e) {
// The list of excluded protocols can be missing some protocols, try to use the
// system principal if the first fetch failed.
console.error(
`stylesheets: fetch failed for ${href},` +
` using system principal instead.`
);
options.window = undefined;
options.principal = undefined;
result = await fetch(href, options);
}
return result.content;
}
/**
* Get charset of a given stylesheet
*
* @param {StyleSheet} styleSheet
* @returns {String}
*/
_getCSSCharset(styleSheet) {
if (styleSheet) {
// charset attribute of <link> or <style> element, if it exists
if (styleSheet.ownerNode?.getAttribute) {
const linkCharset = styleSheet.ownerNode.getAttribute("charset");
if (linkCharset != null) {
return linkCharset;
}
}
// charset of referring document.
if (styleSheet.ownerNode?.ownerDocument.characterSet) {
return styleSheet.ownerNode.ownerDocument.characterSet;
}
}
return "UTF-8";
}
/**
* Retrieve the CSSRuleList of a given stylesheet
*
@ -721,7 +634,7 @@ class StyleSheetsManager extends EventEmitter {
// When the style is injected via nsIDOMWindowUtils.loadSheet, even
// the parent style sheet has no owner, so default back to target actor
// document
const ownerNode = getSheetOwnerNode(styleSheet);
const ownerNode = getStyleSheetOwnerNode(styleSheet);
const ownerDocument = ownerNode
? ownerNode.ownerDocument
: this._targetActor.window;