Bug 1769771 - Differentiate inline from constructed stylesheets in rule view. r=nchevobbe

I think this is worth it, but needs localization changes so splitting
it out.

Differential Revision: https://phabricator.services.mozilla.com/D146683
This commit is contained in:
Emilio Cobos Álvarez 2022-05-19 22:32:28 +00:00
parent 32257d0c50
commit 05a8fc5ff9
11 changed files with 94 additions and 19 deletions

View file

@ -42,6 +42,7 @@ class StyleSheetFront extends FrontClassWithSpec(styleSheetSpec) {
this.href = form.href; this.href = form.href;
this.nodeHref = form.nodeHref; this.nodeHref = form.nodeHref;
this.disabled = form.disabled; this.disabled = form.disabled;
this.constructed = form.constructed;
this.title = form.title; this.title = form.title;
this.system = form.system; this.system = form.system;
this.styleSheetIndex = form.styleSheetIndex; this.styleSheetIndex = form.styleSheetIndex;

View file

@ -320,14 +320,18 @@ RuleEditor.prototype = {
* The original position object (url/line/column) or null. * The original position object (url/line/column) or null.
*/ */
_updateLocation: function(originalLocation) { _updateLocation: function(originalLocation) {
let displayURL = this.rule.sheet ? this.rule.sheet.href : null; let displayURL = this.rule.sheet?.href;
const constructed = this.rule.sheet?.constructed;
let line = this.rule.ruleLine; let line = this.rule.ruleLine;
if (originalLocation) { if (originalLocation) {
displayURL = originalLocation.url; displayURL = originalLocation.url;
line = originalLocation.line; line = originalLocation.line;
} }
let sourceTextContent = CssLogic.shortSource({ href: displayURL }); let sourceTextContent = CssLogic.shortSource({
constructed,
href: displayURL,
});
let title = displayURL ? displayURL : sourceTextContent; let title = displayURL ? displayURL : sourceTextContent;
if (line > 0) { if (line > 0) {
sourceTextContent += ":" + line; sourceTextContent += ":" + line;
@ -347,8 +351,7 @@ RuleEditor.prototype = {
".ruleview-rule-source-label" ".ruleview-rule-source-label"
); );
const title = this.rule.title; const title = this.rule.title;
const sourceHref = const sourceHref = this.rule.sheet?.href || title;
this.rule.sheet && this.rule.sheet.href ? this.rule.sheet.href : title;
const uaLabel = STYLE_INSPECTOR_L10N.getStr("rule.userAgentStyles"); const uaLabel = STYLE_INSPECTOR_L10N.getStr("rule.userAgentStyles");
sourceLabel.textContent = uaLabel + " " + title; sourceLabel.textContent = uaLabel + " " + title;

View file

@ -198,13 +198,15 @@ StyleSheetEditor.prototype = {
} }
if (!this.styleSheet.href) { if (!this.styleSheet.href) {
// TODO(bug 176993): Probably a different index + string for
// constructable stylesheets, they can't be meaningfully edited right now
// because we don't have their original text.
const index = this.styleSheetFriendlyIndex + 1 || 0; const index = this.styleSheetFriendlyIndex + 1 || 0;
return getString("inlineStyleSheet", index); return getString("inlineStyleSheet", index);
} }
if (!this._friendlyName) { if (!this._friendlyName) {
const sheetURI = this.styleSheet.href; this._friendlyName = shortSource(this.styleSheet);
this._friendlyName = shortSource({ href: sheetURI });
try { try {
this._friendlyName = decodeURI(this._friendlyName); this._friendlyName = decodeURI(this._friendlyName);
} catch (ex) { } catch (ex) {

View file

@ -69,6 +69,7 @@ class StyleSheetWatcher {
resourceId, resourceId,
resourceType: STYLESHEET, resourceType: STYLESHEET,
disabled: styleSheet.disabled, disabled: styleSheet.disabled,
constructed: styleSheet.constructed,
fileName, fileName,
href: styleSheet.href, href: styleSheet.href,
isNew: isCreatedByDevTools, isNew: isCreatedByDevTools,

View file

@ -375,6 +375,7 @@ var StyleSheetActor = protocol.ActorClassWithSpec(styleSheetSpec, {
href: this.href, href: this.href,
nodeHref: docHref, nodeHref: docHref,
disabled: this.rawSheet.disabled, disabled: this.rawSheet.disabled,
constructed: this.rawSheet.constructed,
title: this.rawSheet.title, title: this.rawSheet.title,
system: CssLogic.isAgentStylesheet(this.rawSheet), system: CssLogic.isAgentStylesheet(this.rawSheet),
styleSheetIndex: this.styleSheetIndex, styleSheetIndex: this.styleSheetIndex,

View file

@ -649,7 +649,9 @@ class StyleSheetsManager extends EventEmitter {
if (ownerNode.nodeType == ownerNode.DOCUMENT_NODE) { if (ownerNode.nodeType == ownerNode.DOCUMENT_NODE) {
return ownerNode.location.href; return ownerNode.location.href;
} else if (ownerNode.ownerDocument?.location) { }
if (ownerNode.ownerDocument?.location) {
return ownerNode.ownerDocument.location.href; return ownerNode.ownerDocument.location.href;
} }

View file

@ -17,6 +17,7 @@ const EXISTING_RESOURCES = [
"https://example.com/browser/devtools/shared/commands/resource/tests/style_document.html", "https://example.com/browser/devtools/shared/commands/resource/tests/style_document.html",
isNew: false, isNew: false,
disabled: false, disabled: false,
constructed: false,
ruleCount: 1, ruleCount: 1,
mediaRules: [], mediaRules: [],
}, },
@ -28,6 +29,17 @@ const EXISTING_RESOURCES = [
"https://example.com/browser/devtools/shared/commands/resource/tests/style_document.html", "https://example.com/browser/devtools/shared/commands/resource/tests/style_document.html",
isNew: false, isNew: false,
disabled: false, disabled: false,
constructed: false,
ruleCount: 1,
mediaRules: [],
},
{
styleText: "",
href: null,
nodeHref: null,
isNew: false,
disabled: false,
constructed: true,
ruleCount: 1, ruleCount: 1,
mediaRules: [], mediaRules: [],
}, },
@ -38,6 +50,7 @@ const EXISTING_RESOURCES = [
"https://example.org/browser/devtools/shared/commands/resource/tests/style_iframe.html", "https://example.org/browser/devtools/shared/commands/resource/tests/style_iframe.html",
isNew: false, isNew: false,
disabled: false, disabled: false,
constructed: false,
ruleCount: 1, ruleCount: 1,
mediaRules: [], mediaRules: [],
}, },
@ -49,12 +62,13 @@ const EXISTING_RESOURCES = [
"https://example.org/browser/devtools/shared/commands/resource/tests/style_iframe.html", "https://example.org/browser/devtools/shared/commands/resource/tests/style_iframe.html",
isNew: false, isNew: false,
disabled: false, disabled: false,
constructed: false,
ruleCount: 1, ruleCount: 1,
mediaRules: [], mediaRules: [],
}, },
]; ];
const ADDITIONAL_RESOURCE = { const ADDITIONAL_INLINE_RESOURCE = {
styleText: styleText:
"@media all { body { color: red; } } @media print { body { color: cyan; } } body { font-size: 10px; }", "@media all { body { color: red; } } @media print { body { color: cyan; } } body { font-size: 10px; }",
href: null, href: null,
@ -62,6 +76,7 @@ const ADDITIONAL_RESOURCE = {
"https://example.com/browser/devtools/shared/commands/resource/tests/style_document.html", "https://example.com/browser/devtools/shared/commands/resource/tests/style_document.html",
isNew: false, isNew: false,
disabled: false, disabled: false,
constructed: false,
ruleCount: 3, ruleCount: 3,
mediaRules: [ mediaRules: [
{ {
@ -81,6 +96,17 @@ const ADDITIONAL_RESOURCE = {
], ],
}; };
const ADDITIONAL_CONSTRUCTED_RESOURCE = {
styleText: "",
href: null,
nodeHref: null,
isNew: false,
disabled: false,
constructed: true,
ruleCount: 2,
mediaRules: [],
};
const ADDITIONAL_FROM_ACTOR_RESOURCE = { const ADDITIONAL_FROM_ACTOR_RESOURCE = {
styleText: "body { font-size: 10px; }", styleText: "body { font-size: 10px; }",
href: null, href: null,
@ -88,6 +114,7 @@ const ADDITIONAL_FROM_ACTOR_RESOURCE = {
"https://example.com/browser/devtools/shared/commands/resource/tests/style_document.html", "https://example.com/browser/devtools/shared/commands/resource/tests/style_document.html",
isNew: true, isNew: true,
disabled: false, disabled: false,
constructed: false,
ruleCount: 1, ruleCount: 1,
mediaRules: [], mediaRules: [],
}; };
@ -130,7 +157,7 @@ async function testResourceAvailableFeature() {
info("Check whether ResourceCommand gets additonal stylesheet"); info("Check whether ResourceCommand gets additonal stylesheet");
await ContentTask.spawn( await ContentTask.spawn(
tab.linkedBrowser, tab.linkedBrowser,
ADDITIONAL_RESOURCE.styleText, ADDITIONAL_INLINE_RESOURCE.styleText,
text => { text => {
const document = content.document; const document = content.document;
const stylesheet = document.createElement("style"); const stylesheet = document.createElement("style");
@ -143,11 +170,29 @@ async function testResourceAvailableFeature() {
); );
await assertResource( await assertResource(
availableResources[availableResources.length - 1], availableResources[availableResources.length - 1],
ADDITIONAL_RESOURCE ADDITIONAL_INLINE_RESOURCE
);
info("Check whether ResourceCommand gets additonal constructed stylesheet");
await ContentTask.spawn(tab.linkedBrowser, null, () => {
const document = content.document;
const s = new content.CSSStyleSheet();
// We use the different number of rules to meaningfully differentiate
// between constructed stylesheets.
s.replaceSync("foo { color: red } bar { color: blue }");
// TODO(bug 1751346): wrappedJSObject should be unnecessary.
document.wrappedJSObject.adoptedStyleSheets.push(s);
});
await waitUntil(
() => availableResources.length === EXISTING_RESOURCES.length + 2
);
await assertResource(
availableResources[availableResources.length - 1],
ADDITIONAL_CONSTRUCTED_RESOURCE
); );
info( info(
"Check whether ResourceCommand gets additonal stylesheet which is added by DevTool" "Check whether ResourceCommand gets additonal stylesheet which is added by DevTools"
); );
const styleSheetsFront = await targetCommand.targetFront.getFront( const styleSheetsFront = await targetCommand.targetFront.getFront(
"stylesheets" "stylesheets"
@ -156,7 +201,7 @@ async function testResourceAvailableFeature() {
ADDITIONAL_FROM_ACTOR_RESOURCE.styleText ADDITIONAL_FROM_ACTOR_RESOURCE.styleText
); );
await waitUntil( await waitUntil(
() => availableResources.length === EXISTING_RESOURCES.length + 2 () => availableResources.length === EXISTING_RESOURCES.length + 3
); );
await assertResource( await assertResource(
availableResources[availableResources.length - 1], availableResources[availableResources.length - 1],
@ -399,7 +444,10 @@ async function testNestedResourceUpdateFeature() {
function findMatchingExpectedResource(resource) { function findMatchingExpectedResource(resource) {
return EXISTING_RESOURCES.find( return EXISTING_RESOURCES.find(
expected => expected =>
resource.href === expected.href && resource.nodeHref === expected.nodeHref resource.href === expected.href &&
resource.nodeHref === expected.nodeHref &&
resource.ruleCount === expected.ruleCount &&
resource.constructed == expected.constructed
); );
} }
@ -473,6 +521,7 @@ async function assertResource(resource, expected) {
is(resource.nodeHref, expected.nodeHref, "nodeHref is correct"); is(resource.nodeHref, expected.nodeHref, "nodeHref is correct");
is(resource.isNew, expected.isNew, "isNew is correct"); is(resource.isNew, expected.isNew, "isNew is correct");
is(resource.disabled, expected.disabled, "disabled is correct"); is(resource.disabled, expected.disabled, "disabled is correct");
is(resource.constructed, expected.constructed, "constructed is correct");
is(resource.ruleCount, expected.ruleCount, "ruleCount is correct"); is(resource.ruleCount, expected.ruleCount, "ruleCount is correct");
assertMediaRules(resource.mediaRules, expected.mediaRules); assertMediaRules(resource.mediaRules, expected.mediaRules);
} }

View file

@ -8,7 +8,13 @@
<style> <style>
body { color: lime; } body { color: lime; }
</style> </style>
<link href="style_document.css" rel="stylesheet" type="text/css"/> <link href="style_document.css" rel="stylesheet">
<script>
"use strict";
const s = new CSSStyleSheet();
s.replaceSync("body { background-color: blue }");
document.adoptedStyleSheets.push(s);
</script>
</head> </head>
<body> <body>
<iframe src="https://example.org/browser/devtools/shared/commands/resource/tests/style_iframe.html"></iframe> <iframe src="https://example.org/browser/devtools/shared/commands/resource/tests/style_iframe.html"></iframe>

View file

@ -130,11 +130,16 @@ exports.isAgentStylesheet = function(sheet) {
* @param {CSSStyleSheet} sheet the DOM object for the style sheet. * @param {CSSStyleSheet} sheet the DOM object for the style sheet.
*/ */
exports.shortSource = function(sheet) { exports.shortSource = function(sheet) {
// Use a string like "inline" if there is no source href if (!sheet) {
if (!sheet || !sheet.href) {
return exports.l10n("rule.sourceInline"); return exports.l10n("rule.sourceInline");
} }
if (!sheet.href) {
return exports.l10n(
sheet.constructed ? "rule.sourceConstructed" : "rule.sourceInline"
);
}
// If the sheet is a data URL, return a trimmed version of it. // If the sheet is a data URL, return a trimmed version of it.
const dataUrl = sheet.href.trim().match(/^data:.*?,((?:.|\r|\n)*)$/); const dataUrl = sheet.href.trim().match(/^data:.*?,((?:.|\r|\n)*)$/);
if (dataUrl) { if (dataUrl) {

View file

@ -19,11 +19,14 @@ rule.status.BEST=Best Match
rule.status.MATCHED=Matched rule.status.MATCHED=Matched
rule.status.PARENT_MATCH=Parent Match rule.status.PARENT_MATCH=Parent Match
# LOCALIZATION NOTE (rule.sourceElement, rule.sourceInline): For each # LOCALIZATION NOTE (rule.sourceElement, rule.sourceInline,
# style property the panel shows the rules which hold that specific property. # rule.sourceConstructed): For each style property the panel shows the rules
# which hold that specific property.
# For every rule, the rule source is also displayed: a rule can come from a # For every rule, the rule source is also displayed: a rule can come from a
# file, from the same page (inline), or from the element itself (element). # file, from the same page (inline), from a constructed style sheet
# (constructed), or from the element itself (element).
rule.sourceInline=inline rule.sourceInline=inline
rule.sourceConstructed=constructed
rule.sourceElement=element rule.sourceElement=element
# LOCALIZATION NOTE (rule.inheritedFrom): Shown for CSS rules # LOCALIZATION NOTE (rule.inheritedFrom): Shown for CSS rules

View file

@ -48,4 +48,6 @@ interface StyleSheet {
readonly attribute DOMString sourceURL; readonly attribute DOMString sourceURL;
[ChromeOnly, Pure] [ChromeOnly, Pure]
readonly attribute Document? associatedDocument; readonly attribute Document? associatedDocument;
[ChromeOnly, Pure, BinaryName="isConstructed"]
readonly attribute boolean constructed;
}; };