зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1824886 - Rewrite AnonymousContent to use a shadow tree. r=smaug,TYLin,sfoster,devtools-reviewers,nchevobbe
Subtle things: * We now have shadow trees in NAC, inception! Only a couple lines of code in the style system had to be changed to match :host rules and so properly. * Had to make highlighters.css contentaccessible, because otherwise we can't load it from the shadow tree. I don't think it's a big deal. * I removed some of the code from highlighters.css that claimed that stuff inherited from the html element. That's just no longer true. * Had to switch from `setAttribute("style", ...)` to `.style = ...;`. This is needed because CSSOM from chrome code bypasses CSP (as AnonymousContent did), but setAttribute() doesn't, see bug 1424474. Differential Revision: https://phabricator.services.mozilla.com/D173998
This commit is contained in:
Родитель
c3b2365bfe
Коммит
bd1b363ff9
|
@ -16,12 +16,6 @@ let whitelist = [
|
|||
sourceName: /devtools\/content\/debugger\/src\/components\/([A-z\/]+).css/i,
|
||||
isFromDevTools: true,
|
||||
},
|
||||
// Highlighter CSS uses a UA-only pseudo-class, see bug 985597.
|
||||
{
|
||||
sourceName: /highlighters\.css$/i,
|
||||
errorMessage: /Unknown pseudo-class.*moz-native-anonymous/i,
|
||||
isFromDevTools: true,
|
||||
},
|
||||
// UA-only media features.
|
||||
{
|
||||
sourceName: /\b(autocomplete-item)\.css$/,
|
||||
|
@ -68,11 +62,6 @@ let whitelist = [
|
|||
/Unknown property ‘text-size-adjust’\. {2}Declaration dropped\./i,
|
||||
isFromDevTools: false,
|
||||
},
|
||||
{
|
||||
sourceName: /overlay\.css$/i,
|
||||
errorMessage: /Unknown pseudo-class.*moz-native-anonymous/i,
|
||||
isFromDevTools: false,
|
||||
},
|
||||
];
|
||||
|
||||
if (!Services.prefs.getBoolPref("layout.css.color-mix.enabled")) {
|
||||
|
@ -147,6 +136,7 @@ let propNameWhitelist = [
|
|||
// These variables are used in a shorthand, but the CSS parser deletes the values
|
||||
// when expanding the shorthands. See https://github.com/w3c/csswg-drafts/issues/2515
|
||||
{ propName: "--bezier-diagonal-color", isFromDevTools: true },
|
||||
{ propName: "--highlighter-font-family", isFromDevTools: true },
|
||||
|
||||
// This variable is used from CSS embedded in JS in adjustableTitle.js
|
||||
{ propName: "--icon-url", isFromDevTools: false },
|
||||
|
|
|
@ -110,6 +110,7 @@ class AnonymousContentOverlay {
|
|||
}
|
||||
return this._content;
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
|
@ -118,24 +119,12 @@ class AnonymousContentOverlay {
|
|||
let document = this.contentDocument;
|
||||
let window = document.ownerGlobal;
|
||||
|
||||
// Inject stylesheet
|
||||
if (!this.overlayFragment) {
|
||||
try {
|
||||
window.windowUtils.loadSheetUsingURIString(
|
||||
STYLESHEET_URL,
|
||||
window.windowUtils.AGENT_SHEET
|
||||
);
|
||||
} catch {
|
||||
// The method fails if the url is already loaded.
|
||||
}
|
||||
// Inject markup for the overlay UI
|
||||
this.overlayFragment = this.buildOverlay();
|
||||
}
|
||||
|
||||
this._content = document.insertAnonymousContent(
|
||||
this.overlayFragment.children[0]
|
||||
);
|
||||
|
||||
this._content = document.insertAnonymousContent();
|
||||
this._content.root.appendChild(this.overlayFragment.cloneNode(true));
|
||||
this.addEventListeners();
|
||||
|
||||
const hoverElementBox = new HoverElementBox(
|
||||
|
@ -304,6 +293,7 @@ class AnonymousContentOverlay {
|
|||
|
||||
const htmlString = `
|
||||
<div id="screenshots-component">
|
||||
<link rel="stylesheet" href="${STYLESHEET_URL}">
|
||||
<div id="${this.overlayId}">
|
||||
<div id="${this.previewId}">
|
||||
<div class="fixed-container">
|
||||
|
@ -1047,18 +1037,22 @@ class AnonLayer {
|
|||
this.content = content;
|
||||
}
|
||||
|
||||
_element(id) {
|
||||
return this.content.root.getElementById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show element with id this.id
|
||||
*/
|
||||
show() {
|
||||
this.content.removeAttributeForElement(this.id, "style");
|
||||
this._element(this.id).style = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide element with id this.id
|
||||
*/
|
||||
hide() {
|
||||
this.content.setAttributeForElement(this.id, "style", "display:none;");
|
||||
this._element(this.id).style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1097,11 +1091,9 @@ class HoverElementBox extends AnonLayer {
|
|||
let width =
|
||||
rect.left + rect.width > maxWidth ? maxWidth - rect.left : rect.width;
|
||||
|
||||
this.content.setAttributeForElement(
|
||||
this.id,
|
||||
"style",
|
||||
`top:${top}px;left:${left}px;height:${height}px;width:${width}px;`
|
||||
);
|
||||
this._element(
|
||||
this.id
|
||||
).style = `top:${top}px;left:${left}px;height:${height}px;width:${width}px;`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1304,38 +1296,17 @@ class HoverElementBox extends AnonLayer {
|
|||
* get the screenshots elements as the elements from a given point
|
||||
*/
|
||||
setPointerEventsNone() {
|
||||
this.content.setAttributeForElement(
|
||||
"screenshots-component",
|
||||
"style",
|
||||
"pointer-events:none;"
|
||||
);
|
||||
|
||||
let temp = this.content.getAttributeForElement(
|
||||
"screenshots-overlay-container",
|
||||
"style"
|
||||
);
|
||||
this.content.setAttributeForElement(
|
||||
"screenshots-overlay-container",
|
||||
"style",
|
||||
temp + "pointer-events:none;"
|
||||
);
|
||||
this._element("screenshots-component").style.pointerEvents = "none";
|
||||
this._element("screenshots-overlay-container").style.pointerEvents = "none";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the pointer events to the original state because we found the element
|
||||
*/
|
||||
resetPointerEvents() {
|
||||
this.content.setAttributeForElement("screenshots-component", "style", "");
|
||||
this._element("screenshots-component").style.pointerEvents = "";
|
||||
|
||||
let temp = this.content.getAttributeForElement(
|
||||
"screenshots-overlay-container",
|
||||
"style"
|
||||
);
|
||||
this.content.setAttributeForElement(
|
||||
"screenshots-overlay-container",
|
||||
"style",
|
||||
temp.replace("pointer-events:none;", "")
|
||||
);
|
||||
this._element("screenshots-overlay-container").style.pointerEvents = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1599,35 +1570,21 @@ class SelectionBox extends AnonLayer {
|
|||
* Draw the selected region for screenshotting
|
||||
*/
|
||||
show() {
|
||||
this.content.setAttributeForElement(
|
||||
"highlight",
|
||||
"style",
|
||||
`top:${this.top}px;left:${this.left}px;height:${this.height}px;width:${this.width}px;`
|
||||
);
|
||||
|
||||
this.content.setAttributeForElement(
|
||||
"bgTop",
|
||||
"style",
|
||||
`top:0px;height:${this.top}px;left:0px;width:100%;`
|
||||
);
|
||||
|
||||
this.content.setAttributeForElement(
|
||||
"bgBottom",
|
||||
"style",
|
||||
`top:${this.bottom}px;height:calc(100% - ${this.bottom}px);left:0px;width:100%;`
|
||||
);
|
||||
|
||||
this.content.setAttributeForElement(
|
||||
"bgLeft",
|
||||
"style",
|
||||
`top:${this.top}px;height:${this.height}px;left:0px;width:${this.left}px;`
|
||||
);
|
||||
|
||||
this.content.setAttributeForElement(
|
||||
"bgRight",
|
||||
"style",
|
||||
`top:${this.top}px;height:${this.height}px;left:${this.right}px;width:calc(100% - ${this.right}px);`
|
||||
);
|
||||
this._element(
|
||||
"highlight"
|
||||
).style = `top:${this.top}px;left:${this.left}px;height:${this.height}px;width:${this.width}px;`;
|
||||
this._element(
|
||||
"bgTop"
|
||||
).style = `top:0px;height:${this.top}px;left:0px;width:100%;`;
|
||||
this._element(
|
||||
"bgBottom"
|
||||
).style = `top:${this.bottom}px;height:calc(100% - ${this.bottom}px);left:0px;width:100%;`;
|
||||
this._element(
|
||||
"bgLeft"
|
||||
).style = `top:${this.top}px;height:${this.height}px;left:0px;width:${this.left}px;`;
|
||||
this._element(
|
||||
"bgRight"
|
||||
).style = `top:${this.top}px;height:${this.height}px;left:${this.right}px;width:calc(100% - ${this.right}px);`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1647,11 +1604,9 @@ class SelectionBox extends AnonLayer {
|
|||
* Hide the selected region
|
||||
*/
|
||||
hide() {
|
||||
this.content.setAttributeForElement("highlight", "style", "display:none;");
|
||||
this.content.setAttributeForElement("bgTop", "style", "display:none;");
|
||||
this.content.setAttributeForElement("bgBottom", "style", "display:none;");
|
||||
this.content.setAttributeForElement("bgLeft", "style", "display:none;");
|
||||
this.content.setAttributeForElement("bgRight", "style", "display:none;");
|
||||
for (let id of ["highlight", "bgTop", "bgBottom", "bgLeft", "bgRight"]) {
|
||||
this._element(id).style = `display:none;`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1826,11 +1781,7 @@ class ButtonsLayer extends AnonLayer {
|
|||
leftOrRight = `left:${boxLeft}px;`;
|
||||
}
|
||||
|
||||
this.content.setAttributeForElement(
|
||||
"buttons",
|
||||
"style",
|
||||
`top:${top}px;${leftOrRight}`
|
||||
);
|
||||
this._element("buttons").style = `top:${top}px;${leftOrRight}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1850,8 +1801,8 @@ class PreviewLayer extends AnonLayer {
|
|||
const xpos = Math.floor((10 * (clientX - width / 2)) / width);
|
||||
const ypos = Math.floor((10 * (clientY - height / 2)) / height);
|
||||
const move = `transform:translate(${xpos}px, ${ypos}px);`;
|
||||
this.content.setAttributeForElement("left-eye", "style", move);
|
||||
this.content.setAttributeForElement("right-eye", "style", move);
|
||||
this._element("left-eye").style = move;
|
||||
this._element("right-eye").style = move;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2135,11 +2086,9 @@ class ScreenshotsContainerLayer extends AnonLayer {
|
|||
* Draw the screenshots container
|
||||
*/
|
||||
drawScreenshotsContainer() {
|
||||
this.content.setAttributeForElement(
|
||||
this.id,
|
||||
"style",
|
||||
`top:0;left:0;width:${this.#width}px;height:${this.#height}px;`
|
||||
);
|
||||
this._element(this.id).style = `top:0;left:0;width:${
|
||||
this.#width
|
||||
}px;height:${this.#height}px;`;
|
||||
}
|
||||
|
||||
get hoverElementBoxRect() {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
:-moz-native-anonymous #screenshots-component {
|
||||
#screenshots-component {
|
||||
--in-content-page-background: #fff;
|
||||
|
||||
--in-content-button-text-color: rgb(21, 20, 26);
|
||||
|
@ -29,7 +29,7 @@
|
|||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:-moz-native-anonymous #screenshots-component {
|
||||
#screenshots-component {
|
||||
--in-content-page-background: #42414d;
|
||||
|
||||
--in-content-button-text-color: rgb(251,251,254);
|
||||
|
@ -45,7 +45,7 @@
|
|||
}
|
||||
|
||||
@media (forced-colors: active), (prefers-contrast) {
|
||||
:-moz-native-anonymous #screenshots-component {
|
||||
#screenshots-component {
|
||||
--in-content-page-background: Canvas;
|
||||
|
||||
--in-content-button-text-color: ButtonText;
|
||||
|
@ -72,7 +72,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #screenshots-component {
|
||||
#screenshots-component {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: clip;
|
||||
|
@ -85,7 +85,7 @@
|
|||
* Overlay content is position: fixed as we need to allow for the possiblily
|
||||
* of the document scrolling or changing size while the overlay is visible
|
||||
*/
|
||||
:-moz-native-anonymous #screenshots-overlay-container {
|
||||
#screenshots-overlay-container {
|
||||
/*
|
||||
Content CSS applying to the html element can impact the overlay.
|
||||
To avoid that, possible cases have been set to initial.
|
||||
|
@ -103,7 +103,7 @@
|
|||
cursor: crosshair;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #preview-container {
|
||||
#preview-container {
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
@ -112,7 +112,7 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #selection-container {
|
||||
#selection-container {
|
||||
overflow: clip;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -121,15 +121,15 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #screenshots-overlay-container[hidden] {
|
||||
#screenshots-overlay-container[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #screenshots-overlay-container[dragging] {
|
||||
#screenshots-overlay-container[dragging] {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #buttons {
|
||||
#buttons {
|
||||
position: absolute;
|
||||
margin: 10px 0;
|
||||
display: flex;
|
||||
|
@ -140,7 +140,7 @@
|
|||
padding: 4px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .screenshots-button {
|
||||
.screenshots-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -167,43 +167,43 @@
|
|||
background-color: var(--in-content-button-background);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .screenshots-button:focus-visible,
|
||||
:-moz-native-anonymous #screenshots-cancel-button:focus-visible {
|
||||
.screenshots-button:focus-visible,
|
||||
#screenshots-cancel-button:focus-visible {
|
||||
outline: 2px solid var(--in-content-focus-outline-color);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .screenshots-button:hover {
|
||||
.screenshots-button:hover {
|
||||
background-color: var(--in-content-button-background-hover);
|
||||
border-color: var(--in-content-button-border-color-hover);
|
||||
color: var(--in-content-button-text-color-hover);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .screenshots-button:active {
|
||||
.screenshots-button:active {
|
||||
background-color: var(--in-content-button-background-active);
|
||||
border-color: var(--in-content-button-border-color-active);
|
||||
color: var(--in-content-button-text-color-active);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .primary {
|
||||
.primary {
|
||||
background-color: var(--in-content-primary-button-background);
|
||||
border-color: var(--in-content-primary-button-border-color);
|
||||
color: var(--in-content-primary-button-text-color);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .primary:hover {
|
||||
.primary:hover {
|
||||
background-color: var(--in-content-primary-button-background-hover);
|
||||
border-color: var(--in-content-primary-button-border-color-hover);
|
||||
color: var(--in-content-primary-button-text-color-hover);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .primary:active {
|
||||
.primary:active {
|
||||
background-color: var(--in-content-primary-button-background-active);
|
||||
border-color: var(--in-content-primary-button-border-color-active);
|
||||
color: var(--in-content-primary-button-text-color-active);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #screenshots-cancel-button {
|
||||
#screenshots-cancel-button {
|
||||
background-color: transparent;
|
||||
margin-top: 40px;
|
||||
width: fit-content;
|
||||
|
@ -211,43 +211,43 @@
|
|||
color: #fff;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #screenshots-cancel-button:hover {
|
||||
#screenshots-cancel-button:hover {
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
@media (forced-colors: active), (prefers-contrast) {
|
||||
:-moz-native-anonymous #screenshots-cancel-button {
|
||||
#screenshots-cancel-button {
|
||||
border-color: ButtonBorder;
|
||||
color: CanvasText;
|
||||
}
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .screenshots-button > img {
|
||||
.screenshots-button > img {
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #cancel > img {
|
||||
#cancel > img {
|
||||
content: url("chrome://global/skin/icons/close.svg");
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #copy > img {
|
||||
#copy > img {
|
||||
content: url("chrome://global/skin/icons/edit-copy.svg");
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #download > img {
|
||||
#download > img {
|
||||
content: url("chrome://browser/skin/downloads/downloads.svg");
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #download > img,
|
||||
:-moz-native-anonymous #copy > img {
|
||||
#download > img,
|
||||
#copy > img {
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .fixed-container {
|
||||
.fixed-container {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -261,20 +261,20 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .face-container {
|
||||
.face-container {
|
||||
position: relative;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .face {
|
||||
.face {
|
||||
width: 62px;
|
||||
height: 62px;
|
||||
display: block;
|
||||
background-image: url("chrome://browser/content/screenshots/icon-welcome-face-without-eyes.svg");
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .eye {
|
||||
.eye {
|
||||
background-color: #fff;
|
||||
width: 10px;
|
||||
height: 14px;
|
||||
|
@ -285,7 +285,7 @@
|
|||
top: 19px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .eyeball {
|
||||
.eyeball {
|
||||
position: absolute;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
|
@ -296,19 +296,19 @@
|
|||
z-index: 10;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .left {
|
||||
.left {
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .right {
|
||||
.right {
|
||||
margin-inline-start: 20px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .preview-instructions {
|
||||
.preview-instructions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: pulse 125mm cubic-bezier(0.07, 0.95, 0, 1);
|
||||
animation: pulse 125ms cubic-bezier(0.07, 0.95, 0, 1);
|
||||
color: #fff;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "segoe ui", "helvetica neue", helvetica, ubuntu, roboto, noto, arial, sans-serif;
|
||||
font-size: 24px;
|
||||
|
@ -319,12 +319,12 @@
|
|||
}
|
||||
|
||||
@media (forced-colors: active), (prefers-contrast) {
|
||||
:-moz-native-anonymous .preview-instructions {
|
||||
.preview-instructions {
|
||||
color: CanvasText;
|
||||
}
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #hover-highlight {
|
||||
#hover-highlight {
|
||||
animation: fade-in 125ms forwards cubic-bezier(0.07, 0.95, 0, 1);
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 1px;
|
||||
|
@ -333,7 +333,7 @@
|
|||
z-index: 11;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous #hover-highlight::before {
|
||||
#hover-highlight::before {
|
||||
border: 2px dashed rgba(255, 255, 255, 0.4);
|
||||
bottom: 0;
|
||||
content: "";
|
||||
|
@ -343,13 +343,13 @@
|
|||
top: 0;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .bghighlight {
|
||||
.bghighlight {
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
position: absolute;
|
||||
overflow: clip;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .highlight {
|
||||
.highlight {
|
||||
border-radius: 1px;
|
||||
border: 2px dashed rgba(255, 255, 255, 0.8);
|
||||
box-sizing: border-box;
|
||||
|
@ -359,7 +359,7 @@
|
|||
z-index: 2;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target {
|
||||
.mover-target {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -368,7 +368,7 @@
|
|||
pointer-events: auto;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target.direction-topLeft {
|
||||
.mover-target.direction-topLeft {
|
||||
cursor: nwse-resize;
|
||||
height: 60px;
|
||||
left: -30px;
|
||||
|
@ -376,7 +376,7 @@
|
|||
width: 60px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target.direction-top {
|
||||
.mover-target.direction-top {
|
||||
cursor: ns-resize;
|
||||
height: 60px;
|
||||
inset-inline-start: 0;
|
||||
|
@ -385,7 +385,7 @@
|
|||
z-index: 4;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target.direction-topRight {
|
||||
.mover-target.direction-topRight {
|
||||
cursor: nesw-resize;
|
||||
height: 60px;
|
||||
right: -30px;
|
||||
|
@ -393,7 +393,7 @@
|
|||
width: 60px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target.direction-left {
|
||||
.mover-target.direction-left {
|
||||
cursor: ew-resize;
|
||||
height: 100%;
|
||||
left: -30px;
|
||||
|
@ -402,7 +402,7 @@
|
|||
z-index: 4;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target.direction-right {
|
||||
.mover-target.direction-right {
|
||||
cursor: ew-resize;
|
||||
height: 100%;
|
||||
right: -30px;
|
||||
|
@ -411,7 +411,7 @@
|
|||
z-index: 4;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target.direction-bottomLeft {
|
||||
.mover-target.direction-bottomLeft {
|
||||
bottom: -30px;
|
||||
cursor: nesw-resize;
|
||||
height: 60px;
|
||||
|
@ -419,7 +419,7 @@
|
|||
width: 60px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target.direction-bottom {
|
||||
.mover-target.direction-bottom {
|
||||
bottom: -30px;
|
||||
cursor: ns-resize;
|
||||
height: 60px;
|
||||
|
@ -428,7 +428,7 @@
|
|||
z-index: 4;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target.direction-bottomRight {
|
||||
.mover-target.direction-bottomRight {
|
||||
bottom: -30px;
|
||||
cursor: nwse-resize;
|
||||
height: 60px;
|
||||
|
@ -436,11 +436,11 @@
|
|||
width: 60px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover-target:hover .mover {
|
||||
.mover-target:hover .mover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .mover {
|
||||
.mover {
|
||||
background-color: #fff;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
|
||||
|
@ -451,31 +451,31 @@
|
|||
width: 16px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .small-selection .mover {
|
||||
.small-selection .mover {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .direction-topLeft .mover,
|
||||
:-moz-native-anonymous .direction-left .mover,
|
||||
:-moz-native-anonymous .direction-bottomLeft .mover {
|
||||
.direction-topLeft .mover,
|
||||
.direction-left .mover,
|
||||
.direction-bottomLeft .mover {
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .direction-topLeft .mover,
|
||||
:-moz-native-anonymous .direction-top .mover,
|
||||
:-moz-native-anonymous .direction-topRight .mover {
|
||||
.direction-topLeft .mover,
|
||||
.direction-top .mover,
|
||||
.direction-topRight .mover {
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .direction-topRight .mover,
|
||||
:-moz-native-anonymous .direction-right .mover,
|
||||
:-moz-native-anonymous .direction-bottomRight .mover {
|
||||
.direction-topRight .mover,
|
||||
.direction-right .mover,
|
||||
.direction-bottomRight .mover {
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .direction-bottomRight .mover,
|
||||
:-moz-native-anonymous .direction-bottom .mover,
|
||||
:-moz-native-anonymous .direction-bottomLeft .mover {
|
||||
.direction-bottomRight .mover,
|
||||
.direction-bottom .mover,
|
||||
.direction-bottomLeft .mover {
|
||||
bottom: -1px;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class ManifestIssue extends PureComponent {
|
|||
case MANIFEST_ISSUE_LEVELS.ERROR:
|
||||
default:
|
||||
return {
|
||||
src: "chrome://devtools/skin/images/error-small.svg",
|
||||
src: "resource://devtools-shared-images/error-small.svg",
|
||||
localizationId: "icon-error",
|
||||
};
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ exports[`ManifestIssue renders the expected snapshot for an error 1`] = `
|
|||
>
|
||||
<img
|
||||
className="manifest-issue__icon manifest-issue__icon--error"
|
||||
src="chrome://devtools/skin/images/error-small.svg"
|
||||
src="resource://devtools-shared-images/error-small.svg"
|
||||
/>
|
||||
</Localized>
|
||||
<span>
|
||||
|
|
|
@ -158,7 +158,7 @@ html[dir="rtl"] .img.more-tabs {
|
|||
}
|
||||
|
||||
.img.resume {
|
||||
mask-image: url(chrome://devtools/content/shared/images/resume.svg);
|
||||
mask-image: url(resource://devtools-shared-images/resume.svg);
|
||||
}
|
||||
|
||||
.img.search {
|
||||
|
@ -182,7 +182,7 @@ html[dir="rtl"] .img.more-tabs {
|
|||
}
|
||||
|
||||
.img.stepOver {
|
||||
mask-image: url(chrome://devtools/content/shared/images/stepOver.svg);
|
||||
mask-image: url(resource://devtools-shared-images/stepOver.svg);
|
||||
}
|
||||
|
||||
.img.tab {
|
||||
|
|
|
@ -15,9 +15,11 @@ const TEST_LEVELS = [2, 1, 0.5];
|
|||
// Returns the expected style attribute value to check for on the highlighter's elements
|
||||
// node, for the values given.
|
||||
const expectedStyle = (w, h, z) =>
|
||||
(z !== 1 ? `transform-origin:top left; transform:scale(${1 / z}); ` : "") +
|
||||
`position:absolute; width:${w * z}px;height:${h * z}px; ` +
|
||||
"overflow:hidden";
|
||||
(z !== 1
|
||||
? `transform-origin: left top 0px; transform: scale(${1 / z}); `
|
||||
: "") +
|
||||
`position: absolute; width: ${w * z}px; height: ${h * z}px; ` +
|
||||
"overflow: hidden;";
|
||||
|
||||
add_task(async function () {
|
||||
const { inspector, highlighterTestFront } = await openInspectorForURL(
|
||||
|
|
|
@ -814,6 +814,11 @@ function waitForStyleEditor(toolbox, href) {
|
|||
// A helper that resolves the promise once it receives an editor that
|
||||
// matches the expected href. Returns false if the editor was not correct.
|
||||
const gotEditor = editor => {
|
||||
if (!editor) {
|
||||
info("Editor went away after selected?");
|
||||
return false;
|
||||
}
|
||||
|
||||
const currentHref = editor.styleSheet.href;
|
||||
if (!href || (href && currentHref.endsWith(href))) {
|
||||
info("Stylesheet editor selected");
|
||||
|
|
|
@ -147,7 +147,6 @@ devtools.jar:
|
|||
skin/images/alert-tiny.svg (themes/images/alert-tiny.svg)
|
||||
skin/images/arrow-dropdown-12.svg (themes/images/arrow-dropdown-12.svg)
|
||||
skin/images/error.svg (themes/images/error.svg)
|
||||
skin/images/error-small.svg (themes/images/error-small.svg)
|
||||
skin/images/error-tiny.svg (themes/images/error-tiny.svg)
|
||||
skin/images/info.svg (themes/images/info.svg)
|
||||
skin/images/info-small.svg (themes/images/info-small.svg)
|
||||
|
|
|
@ -336,7 +336,7 @@
|
|||
}
|
||||
|
||||
.security-state-broken {
|
||||
background-image: url(chrome://devtools/skin/images/error-small.svg);
|
||||
background-image: url(resource://devtools-shared-images/error-small.svg);
|
||||
width: 16px;
|
||||
fill: var(--theme-icon-error-color);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
height: 12px;
|
||||
content: "";
|
||||
vertical-align: -2px;
|
||||
background-image: url(chrome://devtools/skin/images/error-small.svg);
|
||||
background-image: url(resource://devtools-shared-images/error-small.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
-moz-context-properties: fill;
|
||||
|
|
|
@ -750,5 +750,5 @@ select.playback-rate-selector.devtools-button:not(:empty, :disabled, .checked):h
|
|||
}
|
||||
|
||||
.animation-element-picker::before {
|
||||
background-image: url("chrome://devtools/content/shared/images/command-pick.svg");
|
||||
background-image: url("resource://devtools-shared-images/command-pick.svg");
|
||||
}
|
||||
|
|
|
@ -473,7 +473,7 @@
|
|||
}
|
||||
|
||||
.toolbox-error::before {
|
||||
background-image: url("chrome://devtools/skin/images/error-small.svg");
|
||||
background-image: url("resource://devtools-shared-images/error-small.svg");
|
||||
fill: var(--theme-icon-error-color) !important;
|
||||
}
|
||||
|
||||
|
@ -488,7 +488,7 @@
|
|||
}
|
||||
|
||||
#command-button-pick::before {
|
||||
background-image: url("chrome://devtools/content/shared/images/command-pick.svg");
|
||||
background-image: url("resource://devtools-shared-images/command-pick.svg");
|
||||
}
|
||||
|
||||
#command-button-pick.accessibility::before {
|
||||
|
@ -496,7 +496,7 @@
|
|||
}
|
||||
|
||||
#command-button-pick.remote-fenix::before {
|
||||
background-image: url("chrome://devtools/content/shared/images/command-pick-remote-touch.svg");
|
||||
background-image: url("resource://devtools-shared-images/command-pick-remote-touch.svg");
|
||||
}
|
||||
|
||||
/* Command button images */
|
||||
|
|
|
@ -296,7 +296,7 @@
|
|||
|
||||
.message.error > .icon {
|
||||
color: var(--theme-icon-error-color);
|
||||
background-image: url(chrome://devtools/skin/images/error-small.svg);
|
||||
background-image: url(resource://devtools-shared-images/error-small.svg);
|
||||
}
|
||||
|
||||
.message.warn > .icon {
|
||||
|
|
|
@ -1801,7 +1801,10 @@ class CssGridHighlighter extends AutoRefreshHighlighter {
|
|||
setIgnoreLayoutChanges(true);
|
||||
|
||||
// Set z-index.
|
||||
this.markup.content.setStyle("z-index", this.options.zIndex);
|
||||
this.markup.content.root.firstElementChild.style.setProperty(
|
||||
"z-index",
|
||||
this.options.zIndex
|
||||
);
|
||||
|
||||
const root = this.getElement("root");
|
||||
const cells = this.getElement("cells");
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,9 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
"highlighters.css",
|
||||
)
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
DIRS += [
|
||||
"utils",
|
||||
"css",
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
|
|
|
@ -205,7 +205,8 @@ class Infobar {
|
|||
*/
|
||||
getTextContent(id) {
|
||||
const anonymousContent = this.markup.content;
|
||||
return anonymousContent.getTextContentForElement(`${this.prefix}${id}`);
|
||||
return anonymousContent.root.getElementById(`${this.prefix}${id}`)
|
||||
.textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,7 +8,6 @@ const {
|
|||
getCurrentZoom,
|
||||
getWindowDimensions,
|
||||
getViewportDimensions,
|
||||
loadSheet,
|
||||
} = require("resource://devtools/shared/layout/utils.js");
|
||||
const EventEmitter = require("resource://devtools/shared/event-emitter.js");
|
||||
|
||||
|
@ -45,7 +44,8 @@ exports.removePseudoClassLock = (...args) =>
|
|||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const STYLESHEET_URI = "resource://devtools/server/actors/highlighters.css";
|
||||
const STYLESHEET_URI =
|
||||
"resource://devtools-highlighter-styles/highlighters.css";
|
||||
|
||||
const _tokens = Symbol("classList/tokens");
|
||||
|
||||
|
@ -239,14 +239,6 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
|||
this.anonymousContentWindow = this.highlighterEnv.window;
|
||||
this.pageListenerTarget = this.highlighterEnv.pageListenerTarget;
|
||||
|
||||
// For now highlighters.css is injected in content as a ua sheet because
|
||||
// we no longer support scoped style sheets (see bug 1345702).
|
||||
// If it did, highlighters.css would be injected as an anonymous content
|
||||
// node using CanvasFrameAnonymousContentHelper instead.
|
||||
loadSheet(this.anonymousContentWindow, STYLESHEET_URI);
|
||||
|
||||
const node = this.nodeBuilder();
|
||||
|
||||
// It was stated that hidden documents don't accept
|
||||
// `insertAnonymousContent` calls yet. That doesn't seems the case anymore,
|
||||
// at least on desktop. Therefore, removing the code that was dealing with
|
||||
|
@ -257,7 +249,6 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
|||
// to ensure the anonymous content will be rendered (see Bug 1580394).
|
||||
const forceSynchronousLayoutUpdate = !this.waitForDocumentToLoad;
|
||||
this._content = this.anonymousContentDocument.insertAnonymousContent(
|
||||
node,
|
||||
forceSynchronousLayoutUpdate
|
||||
);
|
||||
} catch (e) {
|
||||
|
@ -278,13 +269,18 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
|||
{ once: true }
|
||||
);
|
||||
});
|
||||
this._content =
|
||||
this.anonymousContentDocument.insertAnonymousContent(node);
|
||||
this._content = this.anonymousContentDocument.insertAnonymousContent();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
const link = this.anonymousContentDocument.createElement("link");
|
||||
link.href = STYLESHEET_URI;
|
||||
link.rel = "stylesheet";
|
||||
this._content.root.appendChild(link);
|
||||
this._content.root.appendChild(this.nodeBuilder());
|
||||
|
||||
this._initialized();
|
||||
},
|
||||
|
||||
|
@ -312,36 +308,42 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_getNodeById(id) {
|
||||
return this.content?.root.getElementById(id);
|
||||
},
|
||||
|
||||
getComputedStylePropertyValue(id, property) {
|
||||
return (
|
||||
this.content && this.content.getComputedStylePropertyValue(id, property)
|
||||
);
|
||||
const node = this._getNodeById(id);
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
return this.anonymousContentWindow
|
||||
.getComputedStyle(node)
|
||||
.getPropertyValue(property);
|
||||
},
|
||||
|
||||
getTextContentForElement(id) {
|
||||
return this.content && this.content.getTextContentForElement(id);
|
||||
return this._getNodeById(id)?.textContent;
|
||||
},
|
||||
|
||||
setTextContentForElement(id, text) {
|
||||
if (this.content) {
|
||||
this.content.setTextContentForElement(id, text);
|
||||
const node = this._getNodeById(id);
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
node.textContent = text;
|
||||
},
|
||||
|
||||
setAttributeForElement(id, name, value) {
|
||||
if (this.content) {
|
||||
this.content.setAttributeForElement(id, name, value);
|
||||
}
|
||||
this._getNodeById(id)?.setAttribute(name, value);
|
||||
},
|
||||
|
||||
getAttributeForElement(id, name) {
|
||||
return this.content && this.content.getAttributeForElement(id, name);
|
||||
return this._getNodeById(id)?.getAttribute(name);
|
||||
},
|
||||
|
||||
removeAttributeForElement(id, name) {
|
||||
if (this.content) {
|
||||
this.content.removeAttributeForElement(id, name);
|
||||
}
|
||||
this._getNodeById(id)?.removeAttribute(name);
|
||||
},
|
||||
|
||||
hasAttributeForElement(id, name) {
|
||||
|
@ -349,7 +351,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
|||
},
|
||||
|
||||
getCanvasContext(id, type = "2d") {
|
||||
return this.content && this.content.getCanvasContext(id, type);
|
||||
return this._getNodeById(id)?.getContext(type);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -544,7 +546,8 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
|||
const zoom = getCurrentZoom(node);
|
||||
// Hide the root element and force the reflow in order to get the proper window's
|
||||
// dimensions without increasing them.
|
||||
this.setAttributeForElement(id, "style", "display: none");
|
||||
const root = this._getNodeById(id);
|
||||
root.style.display = "none";
|
||||
node.offsetWidth;
|
||||
|
||||
let { width, height } = getWindowDimensions(boundaryWindow);
|
||||
|
@ -556,9 +559,8 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
|||
height *= zoom;
|
||||
}
|
||||
|
||||
value += `position:absolute; width:${width}px;height:${height}px; overflow:hidden`;
|
||||
|
||||
this.setAttributeForElement(id, "style", value);
|
||||
value += `position:absolute; width:${width}px;height:${height}px; overflow:hidden;`;
|
||||
root.style = value;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,7 +37,6 @@ DevToolsModules(
|
|||
"errordocs.js",
|
||||
"frame.js",
|
||||
"heap-snapshot-file.js",
|
||||
"highlighters.css",
|
||||
"highlighters.js",
|
||||
"layout.js",
|
||||
"manifest.js",
|
||||
|
|
|
@ -663,7 +663,17 @@ class StyleSheetsManager extends EventEmitter {
|
|||
this._targetActor.window.document,
|
||||
true
|
||||
);
|
||||
return styleSheets.indexOf(styleSheet);
|
||||
let i = 0;
|
||||
for (const sheet of styleSheets) {
|
||||
if (!this._shouldListSheet(sheet)) {
|
||||
continue;
|
||||
}
|
||||
if (sheet == styleSheet) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -815,13 +825,18 @@ class StyleSheetsManager extends EventEmitter {
|
|||
* @returns {Boolean}
|
||||
*/
|
||||
_shouldListSheet(styleSheet) {
|
||||
// Special case about:PreferenceStyleSheet, as it is generated on the
|
||||
// fly and the URI is not registered with the about: handler.
|
||||
// Special case about:PreferenceStyleSheet, as it is generated on the fly
|
||||
// and the URI is not registered with the about: handler.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=935803#c37
|
||||
if (styleSheet.href?.toLowerCase() === "about:preferencestylesheet") {
|
||||
const href = styleSheet.href?.toLowerCase();
|
||||
if (href === "about:preferencestylesheet") {
|
||||
return false;
|
||||
}
|
||||
// FIXME(bug 1826538): Make accessiblecaret.css and similar UA-widget
|
||||
// sheets system sheets, then remove this special-case.
|
||||
if (href === "resource://content-accessible/accessiblecaret.css") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,11 @@
|
|||
<!--
|
||||
Test that css-logic calculates CSS specificity properly
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test css-logic specificity</title>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
</head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test css-logic specificity</title>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<body style="background:blue;">
|
||||
<script type="application/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
window.onload = function() {
|
||||
|
@ -37,7 +35,7 @@ Test that css-logic calculates CSS specificity properly
|
|||
|
||||
function createDocument() {
|
||||
let text = TEST_DATA.map(i=>i.text).join(",");
|
||||
text = '<style type="text/css">' + text + " {color:red;}</style>";
|
||||
text = '<style>' + text + " {color:red;}</style>";
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
document.body.innerHTML = text;
|
||||
}
|
||||
|
@ -52,11 +50,18 @@ Test that css-logic calculates CSS specificity properly
|
|||
const cssLogic = new CssLogic();
|
||||
|
||||
cssLogic.highlight(document.body);
|
||||
const cssSheet = cssLogic.sheets[0];
|
||||
|
||||
// There could be more stylesheets due to e.g, accessiblecaret, so find the
|
||||
// right one.
|
||||
info(`Sheets: ${cssLogic.sheets.map(s => s.href).join(", ")}`);
|
||||
|
||||
const cssSheet = cssLogic.sheets.find(s => s.href == location.href);
|
||||
const cssRule = cssSheet.domSheet.cssRules[0];
|
||||
const selectors = CssLogic.getSelectors(cssRule);
|
||||
|
||||
info("Iterating over the test selectors");
|
||||
is(selectors.length, TEST_DATA.length, "Should be the right rule");
|
||||
|
||||
info("Iterating over the test selectors: " + selectors.join(", "));
|
||||
for (let i = 0; i < selectors.length; i++) {
|
||||
const selectorText = selectors[i];
|
||||
info("Testing selector " + selectorText);
|
||||
|
|
|
@ -32,16 +32,16 @@ window.onload = async function() {
|
|||
const id = elementID => `${highlighter.ID_CLASS_PREFIX}${elementID}`;
|
||||
|
||||
function isHidden(elementID) {
|
||||
const attr = anonymousContent.getAttributeForElement(id(elementID), "hidden");
|
||||
const attr = anonymousContent.root.getElementById(id(elementID)).getAttribute("hidden");
|
||||
return typeof attr === "string" && attr == "true";
|
||||
}
|
||||
|
||||
function getReason() {
|
||||
return anonymousContent.getTextContentForElement(id("reason"));
|
||||
return anonymousContent.root.getElementById(id("reason")).textContent;
|
||||
}
|
||||
|
||||
function isOverlayShown() {
|
||||
const attr = anonymousContent.getAttributeForElement(id("root"), "overlay");
|
||||
const attr = anonymousContent.root.getElementById(id("root")).getAttribute("overlay");
|
||||
return typeof attr === "string" && attr == "true";
|
||||
}
|
||||
|
||||
|
|
|
@ -125,6 +125,18 @@ add_task(async function () {
|
|||
await testNestedResourceUpdateFeature();
|
||||
});
|
||||
|
||||
function pushAvailableResource(availableResources) {
|
||||
// TODO(bug 1826538): Find a better way of dealing with these.
|
||||
return function (resources) {
|
||||
for (const resource of resources) {
|
||||
if (resource.href?.startsWith("resource://")) {
|
||||
continue;
|
||||
}
|
||||
availableResources.push(resource);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function testResourceAvailableFeature() {
|
||||
info("Check resource available feature of the ResourceCommand");
|
||||
|
||||
|
@ -143,7 +155,7 @@ async function testResourceAvailableFeature() {
|
|||
info("Check whether ResourceCommand gets existing stylesheet");
|
||||
const availableResources = [];
|
||||
await resourceCommand.watchResources([resourceCommand.TYPES.STYLESHEET], {
|
||||
onAvailable: resources => availableResources.push(...resources),
|
||||
onAvailable: pushAvailableResource(availableResources),
|
||||
});
|
||||
|
||||
is(
|
||||
|
@ -238,7 +250,7 @@ async function testResourceUpdateFeature() {
|
|||
const availableResources = [];
|
||||
const updates = [];
|
||||
await resourceCommand.watchResources([resourceCommand.TYPES.STYLESHEET], {
|
||||
onAvailable: resources => availableResources.push(...resources),
|
||||
onAvailable: pushAvailableResource(availableResources),
|
||||
onUpdated: newUpdates => updates.push(...newUpdates),
|
||||
});
|
||||
is(
|
||||
|
@ -376,7 +388,7 @@ async function testNestedResourceUpdateFeature() {
|
|||
const availableResources = [];
|
||||
const updates = [];
|
||||
await resourceCommand.watchResources([resourceCommand.TYPES.STYLESHEET], {
|
||||
onAvailable: resources => availableResources.push(...resources),
|
||||
onAvailable: pushAvailableResource(availableResources),
|
||||
onUpdated: newUpdates => updates.push(...newUpdates),
|
||||
});
|
||||
is(
|
||||
|
|
До Ширина: | Высота: | Размер: 538 B После Ширина: | Высота: | Размер: 538 B |
|
@ -0,0 +1,13 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
"command-pick-remote-touch.svg",
|
||||
"command-pick.svg",
|
||||
"error-small.svg",
|
||||
"resume.svg",
|
||||
"stepOver.svg",
|
||||
)
|
|
@ -5,18 +5,11 @@
|
|||
devtools.jar:
|
||||
% content devtools %content/
|
||||
content/shared/webextension-fallback.html (webextension-fallback.html)
|
||||
# Those images are in devtools/shared (and not in devtools/client/debugger/images like
|
||||
# the other debugger images) because they are used in both the debugger UI and in the
|
||||
# PausedDebuggerOverlay (which is in devtools/server).
|
||||
content/shared/images/resume.svg (images/resume.svg)
|
||||
content/shared/images/stepOver.svg (images/stepOver.svg)
|
||||
# These images are in devtools/shared (and not in devtools/client/themes/images/) because
|
||||
# they're also used in the RemoteNodePickerNotice (which is in devtools/server).
|
||||
content/shared/images/command-pick.svg (images/command-pick.svg)
|
||||
content/shared/images/command-pick-remote-touch.svg (images/command-pick-remote-touch.svg)
|
||||
% resource devtools %modules/devtools/
|
||||
% resource devtools-client-jsonview resource://devtools/client/jsonview/ contentaccessible=yes
|
||||
% resource devtools-client-shared resource://devtools/client/shared/ contentaccessible=yes
|
||||
% resource devtools-highlighter-styles resource://devtools/server/actors/highlighters/css/ contentaccessible=yes
|
||||
% resource devtools-shared-images resource://devtools/shared/images/ contentaccessible=true
|
||||
% content devtools-jsonview-styles %modules/devtools/client/jsonview/css/ contentaccessible=yes
|
||||
# The typical approach would be to list all the resource files in this manifest
|
||||
# for installation. Instead of doing this, use the DevToolsModules syntax via
|
||||
|
|
|
@ -12,6 +12,7 @@ DIRS += [
|
|||
"compatibility",
|
||||
"discovery",
|
||||
"heapsnapshot",
|
||||
"images",
|
||||
"inspector",
|
||||
"jsbeautify",
|
||||
"layout",
|
||||
|
|
|
@ -5,216 +5,41 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AnonymousContent.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/dom/AnonymousContentBinding.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsStyledElement.h"
|
||||
#include "HTMLCanvasElement.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
// Ref counting and cycle collection
|
||||
NS_IMPL_CYCLE_COLLECTION(AnonymousContent, mContentNode)
|
||||
NS_IMPL_CYCLE_COLLECTION(AnonymousContent, mHost, mRoot)
|
||||
|
||||
AnonymousContent::AnonymousContent(already_AddRefed<Element> aContentNode)
|
||||
: mContentNode(aContentNode) {
|
||||
MOZ_ASSERT(mContentNode);
|
||||
already_AddRefed<AnonymousContent> AnonymousContent::Create(Document& aDoc) {
|
||||
RefPtr<Element> host = aDoc.CreateHTMLElement(nsGkAtoms::div);
|
||||
if (!host) {
|
||||
return nullptr;
|
||||
}
|
||||
host->SetAttr(kNameSpaceID_None, nsGkAtoms::role, u"presentation"_ns, false);
|
||||
RefPtr<ShadowRoot> root = host->AttachShadowWithoutNameChecks(
|
||||
ShadowRootMode::Closed, Element::DelegatesFocus::No);
|
||||
root->SetIsUAWidget();
|
||||
return do_AddRef(new AnonymousContent(host.forget(), root.forget()));
|
||||
}
|
||||
|
||||
AnonymousContent::AnonymousContent(already_AddRefed<Element> aHost,
|
||||
already_AddRefed<ShadowRoot> aRoot)
|
||||
: mHost(aHost), mRoot(aRoot) {
|
||||
MOZ_ASSERT(mHost);
|
||||
MOZ_ASSERT(mRoot);
|
||||
}
|
||||
|
||||
AnonymousContent::~AnonymousContent() = default;
|
||||
|
||||
void AnonymousContent::SetTextContentForElement(const nsAString& aElementId,
|
||||
const nsAString& aText,
|
||||
ErrorResult& aRv) {
|
||||
Element* element = GetElementById(aElementId);
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
element->SetTextContent(aText, aRv);
|
||||
}
|
||||
|
||||
void AnonymousContent::GetTextContentForElement(const nsAString& aElementId,
|
||||
DOMString& aText,
|
||||
ErrorResult& aRv) {
|
||||
Element* element = GetElementById(aElementId);
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
element->GetTextContent(aText, aRv);
|
||||
}
|
||||
|
||||
void AnonymousContent::SetAttributeForElement(const nsAString& aElementId,
|
||||
const nsAString& aName,
|
||||
const nsAString& aValue,
|
||||
nsIPrincipal* aSubjectPrincipal,
|
||||
ErrorResult& aRv) {
|
||||
Element* element = GetElementById(aElementId);
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
element->SetAttribute(aName, aValue, aSubjectPrincipal, aRv);
|
||||
}
|
||||
|
||||
void AnonymousContent::GetAttributeForElement(const nsAString& aElementId,
|
||||
const nsAString& aName,
|
||||
DOMString& aValue,
|
||||
ErrorResult& aRv) {
|
||||
Element* element = GetElementById(aElementId);
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
element->GetAttribute(aName, aValue);
|
||||
}
|
||||
|
||||
void AnonymousContent::RemoveAttributeForElement(const nsAString& aElementId,
|
||||
const nsAString& aName,
|
||||
ErrorResult& aRv) {
|
||||
Element* element = GetElementById(aElementId);
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
element->RemoveAttribute(aName, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<nsISupports> AnonymousContent::GetCanvasContext(
|
||||
const nsAString& aElementId, const nsAString& aContextId,
|
||||
ErrorResult& aRv) {
|
||||
Element* element = GetElementById(aElementId);
|
||||
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!element->IsHTMLElement(nsGkAtoms::canvas)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> context;
|
||||
|
||||
HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(element);
|
||||
canvas->GetContext(aContextId, getter_AddRefs(context));
|
||||
|
||||
return context.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Animation> AnonymousContent::SetAnimationForElement(
|
||||
JSContext* aContext, const nsAString& aElementId,
|
||||
JS::Handle<JSObject*> aKeyframes,
|
||||
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
|
||||
ErrorResult& aRv) {
|
||||
Element* element = GetElementById(aElementId);
|
||||
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return element->Animate(aContext, aKeyframes, aOptions, aRv);
|
||||
}
|
||||
|
||||
void AnonymousContent::SetCutoutRectsForElement(
|
||||
const nsAString& aElementId, const Sequence<OwningNonNull<DOMRect>>& aRects,
|
||||
ErrorResult& aRv) {
|
||||
Element* element = GetElementById(aElementId);
|
||||
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRegion cutOutRegion;
|
||||
for (const auto& r : aRects) {
|
||||
CSSRect rect(r->X(), r->Y(), r->Width(), r->Height());
|
||||
cutOutRegion.OrWith(CSSRect::ToAppUnits(rect));
|
||||
}
|
||||
|
||||
element->SetProperty(nsGkAtoms::cutoutregion, new nsRegion(cutOutRegion),
|
||||
nsINode::DeleteProperty<nsRegion>);
|
||||
|
||||
nsIFrame* frame = element->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
frame->SchedulePaint();
|
||||
}
|
||||
}
|
||||
|
||||
Element* AnonymousContent::GetElementById(const nsAString& aElementId) {
|
||||
// This can be made faster in the future if needed.
|
||||
RefPtr<nsAtom> elementId = NS_Atomize(aElementId);
|
||||
for (nsIContent* node = mContentNode; node;
|
||||
node = node->GetNextNode(mContentNode)) {
|
||||
if (!node->IsElement()) {
|
||||
continue;
|
||||
}
|
||||
nsAtom* id = node->AsElement()->GetID();
|
||||
if (id && id == elementId) {
|
||||
return node->AsElement();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool AnonymousContent::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aReflector) {
|
||||
return AnonymousContent_Binding::Wrap(aCx, this, aGivenProto, aReflector);
|
||||
}
|
||||
|
||||
void AnonymousContent::GetComputedStylePropertyValue(
|
||||
const nsAString& aElementId, const nsACString& aPropertyName,
|
||||
nsACString& aResult, ErrorResult& aRv) {
|
||||
Element* element = GetElementById(aElementId);
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!element->OwnerDoc()->GetPresShell()) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<nsComputedDOMStyle> cs = new nsComputedDOMStyle(
|
||||
element, PseudoStyleType::NotPseudo, element->OwnerDoc(),
|
||||
nsComputedDOMStyle::StyleType::All);
|
||||
cs->GetPropertyValue(aPropertyName, aResult);
|
||||
}
|
||||
|
||||
void AnonymousContent::GetTargetIdForEvent(Event& aEvent, DOMString& aResult) {
|
||||
nsCOMPtr<Element> el = do_QueryInterface(aEvent.GetOriginalTarget());
|
||||
if (el && el->IsInNativeAnonymousSubtree() && mContentNode->Contains(el)) {
|
||||
aResult.SetKnownLiveAtom(el->GetID(), DOMString::eTreatNullAsNull);
|
||||
return;
|
||||
}
|
||||
|
||||
aResult.SetNull();
|
||||
}
|
||||
|
||||
void AnonymousContent::SetStyle(const nsACString& aProperty,
|
||||
const nsACString& aValue, ErrorResult& aRv) {
|
||||
if (!mContentNode->IsHTMLElement()) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsGenericHTMLElement* element = nsGenericHTMLElement::FromNode(mContentNode);
|
||||
nsCOMPtr<nsICSSDeclaration> declaration = element->Style();
|
||||
declaration->SetProperty(aProperty, aValue, ""_ns, IgnoreErrors());
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -7,25 +7,15 @@
|
|||
#ifndef mozilla_dom_AnonymousContent_h
|
||||
#define mozilla_dom_AnonymousContent_h
|
||||
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
namespace mozilla::dom {
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class Animation;
|
||||
class DOMRect;
|
||||
class DOMString;
|
||||
class Element;
|
||||
class Event;
|
||||
template <typename T>
|
||||
class Sequence;
|
||||
class UnrestrictedDoubleOrAnonymousKeyframeAnimationOptions;
|
||||
class UnrestrictedDoubleOrKeyframeAnimationOptions;
|
||||
class Document;
|
||||
class ShadowRoot;
|
||||
|
||||
class AnonymousContent final {
|
||||
public:
|
||||
|
@ -33,61 +23,23 @@ class AnonymousContent final {
|
|||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnonymousContent)
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AnonymousContent)
|
||||
|
||||
explicit AnonymousContent(already_AddRefed<Element> aContentNode);
|
||||
Element& ContentNode() { return *mContentNode; }
|
||||
static already_AddRefed<AnonymousContent> Create(Document&);
|
||||
|
||||
Element* Host() const { return mHost.get(); }
|
||||
ShadowRoot* Root() const { return mRoot.get(); }
|
||||
|
||||
Element* GetElementById(const nsAString& aElementId);
|
||||
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aReflector);
|
||||
|
||||
// WebIDL methods
|
||||
void SetTextContentForElement(const nsAString& aElementId,
|
||||
const nsAString& aText, ErrorResult& aRv);
|
||||
|
||||
void GetTextContentForElement(const nsAString& aElementId, DOMString& aText,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void SetAttributeForElement(const nsAString& aElementId,
|
||||
const nsAString& aName, const nsAString& aValue,
|
||||
nsIPrincipal* aSubjectPrincipal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void GetAttributeForElement(const nsAString& aElementId,
|
||||
const nsAString& aName, DOMString& aValue,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void RemoveAttributeForElement(const nsAString& aElementId,
|
||||
const nsAString& aName, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<nsISupports> GetCanvasContext(const nsAString& aElementId,
|
||||
const nsAString& aContextId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Animation> SetAnimationForElement(
|
||||
JSContext* aContext, const nsAString& aElementId,
|
||||
JS::Handle<JSObject*> aKeyframes,
|
||||
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
|
||||
ErrorResult& aError);
|
||||
|
||||
void SetCutoutRectsForElement(const nsAString& aElementId,
|
||||
const Sequence<OwningNonNull<DOMRect>>& aRects,
|
||||
ErrorResult& aError);
|
||||
|
||||
void GetComputedStylePropertyValue(const nsAString& aElementId,
|
||||
const nsACString& aPropertyName,
|
||||
nsACString& aResult, ErrorResult& aRv);
|
||||
|
||||
void GetTargetIdForEvent(Event& aEvent, DOMString& aResult);
|
||||
|
||||
void SetStyle(const nsACString& aProperty, const nsACString& aValue,
|
||||
ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
~AnonymousContent();
|
||||
RefPtr<Element> mContentNode;
|
||||
|
||||
explicit AnonymousContent(already_AddRefed<Element> aHost,
|
||||
already_AddRefed<ShadowRoot> aRoot);
|
||||
RefPtr<Element> mHost;
|
||||
RefPtr<ShadowRoot> mRoot;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif // mozilla_dom_AnonymousContent_h
|
||||
|
|
|
@ -8293,14 +8293,8 @@ static Element* GetCustomContentContainer(PresShell* aPresShell) {
|
|||
}
|
||||
|
||||
already_AddRefed<AnonymousContent> Document::InsertAnonymousContent(
|
||||
Element& aElement, bool aForce, ErrorResult& aRv) {
|
||||
// Clone the node to avoid returning a direct reference.
|
||||
nsCOMPtr<nsINode> clone = aElement.CloneNode(true, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PresShell* shell = GetPresShell();
|
||||
bool aForce, ErrorResult& aRv) {
|
||||
RefPtr<PresShell> shell = GetPresShell();
|
||||
if (aForce && !GetCustomContentContainer(shell)) {
|
||||
FlushPendingNotifications(FlushType::Layout);
|
||||
shell = GetPresShell();
|
||||
|
@ -8308,14 +8302,23 @@ already_AddRefed<AnonymousContent> Document::InsertAnonymousContent(
|
|||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
auto anonContent =
|
||||
MakeRefPtr<AnonymousContent>(clone.forget().downcast<Element>());
|
||||
RefPtr<AnonymousContent> anonContent = AnonymousContent::Create(*this);
|
||||
if (!anonContent) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mAnonymousContents.AppendElement(anonContent);
|
||||
|
||||
if (Element* container = GetCustomContentContainer(shell)) {
|
||||
container->AppendChildTo(&anonContent->ContentNode(), true, IgnoreErrors());
|
||||
shell->GetCanvasFrame()->ShowCustomContentContainer();
|
||||
if (RefPtr<Element> container = GetCustomContentContainer(shell)) {
|
||||
// If the container is empty and we have other anon content we should be
|
||||
// about to show all the other anonymous content nodes.
|
||||
if (container->HasChildren() || mAnonymousContents.Length() == 1) {
|
||||
container->AppendChildTo(anonContent->Host(), true, IgnoreErrors());
|
||||
if (auto* canvasFrame = shell->GetCanvasFrame()) {
|
||||
canvasFrame->ShowCustomContentContainer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return anonContent.forget();
|
||||
|
@ -8327,7 +8330,7 @@ static void RemoveAnonContentFromCanvas(AnonymousContent& aAnonContent,
|
|||
if (!container) {
|
||||
return;
|
||||
}
|
||||
container->RemoveChild(aAnonContent.ContentNode(), IgnoreErrors());
|
||||
container->RemoveChild(*aAnonContent.Host(), IgnoreErrors());
|
||||
}
|
||||
|
||||
void Document::RemoveAnonymousContent(AnonymousContent& aContent) {
|
||||
|
|
|
@ -1345,9 +1345,9 @@ class Document : public nsINode,
|
|||
*/
|
||||
nsresult GetSrcdocData(nsAString& aSrcdocData);
|
||||
|
||||
already_AddRefed<AnonymousContent> InsertAnonymousContent(
|
||||
Element& aElement, bool aForce, ErrorResult& aError);
|
||||
void RemoveAnonymousContent(AnonymousContent& aContent);
|
||||
already_AddRefed<AnonymousContent> InsertAnonymousContent(bool aForce,
|
||||
ErrorResult&);
|
||||
void RemoveAnonymousContent(AnonymousContent&);
|
||||
/**
|
||||
* If aNode is a descendant of anonymous content inserted by
|
||||
* InsertAnonymousContent, this method returns the root element of the
|
||||
|
|
|
@ -267,7 +267,6 @@ skip-if =
|
|||
skip-if = headless # Bug 1405867
|
||||
[test_anonymousContent_insert.html]
|
||||
[test_anonymousContent_manipulate_content.html]
|
||||
[test_anonymousContent_set_style.html]
|
||||
[test_anonymousContent_style_csp.html]
|
||||
[test_appname_override.html]
|
||||
[test_async_setTimeout_stack.html]
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1020244
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1020244 - Test the chrome-only AnonymousContent API</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1020244 - Test the chrome-only AnonymousContent API</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1020244">Mozilla Bug 1020244</a>
|
||||
<script type="application/javascript">
|
||||
|
||||
<script>
|
||||
// Testing the presence of the chrome-only API
|
||||
ok(!document.insertAnonymousContent,
|
||||
"Content document shouldn't have access to insertAnonymousContent");
|
||||
|
@ -25,32 +20,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1020244
|
|||
ok(chromeDocument.removeAnonymousContent,
|
||||
"Chrome document should have access to removeAnonymousContent");
|
||||
|
||||
// Testing invalid inputs
|
||||
let invalidNodes = [null, undefined, false, 1, "string"];
|
||||
for (let node of invalidNodes) {
|
||||
let didThrow = false;
|
||||
try {
|
||||
chromeDocument.insertAnonymousContent(node);
|
||||
} catch (e) {
|
||||
didThrow = true;
|
||||
}
|
||||
ok(didThrow, "Passing an invalid node to insertAnonymousContent should throw");
|
||||
}
|
||||
|
||||
// Testing the API of the returned object
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent();
|
||||
ok(anonymousContent, "AnonymousContent object returned");
|
||||
let div = document.createElement("div");
|
||||
div.textContent = "this is a test element";
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent(div);
|
||||
ok(anonymousContent, "AnonymousContent object returned");
|
||||
|
||||
let members = ["getTextContentForElement", "setTextContentForElement",
|
||||
"getAttributeForElement", "setAttributeForElement",
|
||||
"removeAttributeForElement", "getCanvasContext",
|
||||
"setAnimationForElement", "setStyle"];
|
||||
for (let member of members) {
|
||||
ok(member in anonymousContent, "AnonymousContent object defines " + member);
|
||||
}
|
||||
anonymousContent.root.appendChild(div);
|
||||
chromeDocument.removeAnonymousContent(anonymousContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</script>
|
||||
|
|
|
@ -1,25 +1,22 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=1020244 -->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1020244 - Make sure anonymous content still works after a reflow (after the canvasframe has been reconstructed)</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1020244 - Make sure anonymous content still works after a reflow (after the canvasframe has been reconstructed)</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<div>
|
||||
<div id="test-element" style="color:red;">text content</div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
<script>
|
||||
info("Inserting anonymous content into the document frame");
|
||||
let chromeDocument = SpecialPowers.wrap(document);
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent();
|
||||
let testElement = document.querySelector("div");
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent(testElement);
|
||||
anonymousContent.root.appendChild(testElement.cloneNode(true));
|
||||
|
||||
info("Modifying the style of an element in the anonymous content");
|
||||
let style = anonymousContent.setAttributeForElement("test-element",
|
||||
"style", "color:green;");
|
||||
anonymousContent.root.getElementById("test-element").style.color = "green";
|
||||
|
||||
info("Toggling the display style on the document element to force reframing");
|
||||
// Note that we force sync reflows to make sure the canvasframe is recreated
|
||||
|
@ -30,11 +27,9 @@
|
|||
forceFlush = document.documentElement.offsetHeight;
|
||||
|
||||
info("Checking that the anonymous content can be retrieved still");
|
||||
style = anonymousContent.getAttributeForElement("test-element", "style");
|
||||
is(style, "color:green;", "The anonymous content still exists after reflow");
|
||||
let color = anonymousContent.root.getElementById("test-element").style.color;
|
||||
is(color, "green", "The anonymous content still exists after reflow");
|
||||
|
||||
info("Removing the anonymous content");
|
||||
chromeDocument.removeAnonymousContent(anonymousContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -3,57 +3,46 @@
|
|||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1212477
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1212477 - Needs a way to access to <canvas>'s context (2d, webgl) from Anonymous Content API</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1212477">Mozilla Bug 1212477</a>
|
||||
<div>
|
||||
<div id="id" class="test">text content</div>
|
||||
<canvas id="canvas2d"></canvas>
|
||||
<canvas id="canvas-webgl"></canvas>
|
||||
<canvas id="canvas-foo"></canvas>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
let chromeDocument = SpecialPowers.wrap(document);
|
||||
let testElement = document.querySelector("div");
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1212477 - Needs a way to access to <canvas>'s context (2d, webgl) from Anonymous Content API</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1212477">Mozilla Bug 1212477</a>
|
||||
<div>
|
||||
<div id="id" class="test">text content</div>
|
||||
<canvas id="canvas2d"></canvas>
|
||||
<canvas id="canvas-webgl"></canvas>
|
||||
<canvas id="canvas-foo"></canvas>
|
||||
</div>
|
||||
<script>
|
||||
let chromeDocument = SpecialPowers.wrap(document);
|
||||
let testElement = document.querySelector("div");
|
||||
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent(testElement);
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent();
|
||||
anonymousContent.root.appendChild(testElement.cloneNode(true));
|
||||
|
||||
is(anonymousContent.getCanvasContext("id", "2d"), null,
|
||||
"Context is null for non-canvas elements");
|
||||
let canvas2d = anonymousContent.root.getElementById("canvas2d");
|
||||
let context2d = canvas2d.getContext("2d");
|
||||
|
||||
let context2d = anonymousContent.getCanvasContext("canvas2d", "2d");
|
||||
is(context2d.toString(), "[object CanvasRenderingContext2D]",
|
||||
"2D Context is returned properly");
|
||||
|
||||
is(context2d.toString(), "[object CanvasRenderingContext2D]",
|
||||
"2D Context is returned properly");
|
||||
is(context2d.canvas, null, "context's canvas property");
|
||||
|
||||
is(context2d.canvas, null,
|
||||
"context's canvas property is null in anonymous content");
|
||||
is(anonymousContent.root.getElementById("canvas-foo").getContext("foo"),
|
||||
null,
|
||||
"Context is null for unknown context type");
|
||||
|
||||
is (anonymousContent.getCanvasContext("canvas-foo", "foo"), null,
|
||||
"Context is null for unknown context type");
|
||||
const normalWebGL = document.createElement('canvas').getContext('webgl');
|
||||
if (normalWebGL) {
|
||||
let canvasWebGL = anonymousContent.root.getElementById("canvas-webgl");
|
||||
let webgl = canvasWebGL.getContext("webgl");
|
||||
|
||||
SimpleTest.doesThrow(
|
||||
() => anonymousContent.getCanvasContext("foo", "2d"),
|
||||
"NS_ERROR_NOT_AVAILABLE",
|
||||
"Get a context using unexisting id should throw"
|
||||
);
|
||||
is(webgl.toString(), "[object WebGLRenderingContext]",
|
||||
"WebGL Context is returned properly");
|
||||
|
||||
const normalWebGL = document.createElement('canvas').getContext('webgl');
|
||||
if (normalWebGL) {
|
||||
let webgl = anonymousContent.getCanvasContext("canvas-webgl", "webgl");
|
||||
|
||||
is(webgl.toString(), "[object WebGLRenderingContext]",
|
||||
"WebGL Context is returned properly");
|
||||
|
||||
is(webgl.canvas, null,
|
||||
"WebGL context's canvas property is null in anonymous content");
|
||||
}
|
||||
chromeDocument.removeAnonymousContent(anonymousContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
is(webgl.canvas, null,
|
||||
"WebGL context's canvas property is null in anonymous content");
|
||||
}
|
||||
chromeDocument.removeAnonymousContent(anonymousContent);
|
||||
</script>
|
||||
|
|
|
@ -3,18 +3,15 @@
|
|||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1020244
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1020244 - Insert content using the AnonymousContent API, several times, and don't remove it</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1020244 - Insert content using the AnonymousContent API, several times, and don't remove it</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1020244">Mozilla Bug 1020244</a>
|
||||
<div>
|
||||
<div id="id" class="test">text content</div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
<script>
|
||||
const INSERTED_NB = 5;
|
||||
|
||||
// Insert the same content several times
|
||||
|
@ -23,7 +20,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1020244
|
|||
|
||||
let anonymousContents = [];
|
||||
for (let i = 0; i < INSERTED_NB; i ++) {
|
||||
let content = chromeDocument.insertAnonymousContent(testElement);
|
||||
let content = chromeDocument.insertAnonymousContent();
|
||||
content.root.appendChild(testElement.cloneNode(true));
|
||||
// Adding an expando pointing to the document to make sure this doesn't
|
||||
// cause leaks.
|
||||
content.dummyExpando = testElement.ownerDocument;
|
||||
|
@ -32,14 +30,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1020244
|
|||
|
||||
// Make sure that modifying one of the inserted elements does not modify the
|
||||
// other ones.
|
||||
anonymousContents[0].setAttributeForElement("id", "class", "updated");
|
||||
anonymousContents[0].root.getElementById("id").className = "updated";
|
||||
for (let i = 1; i < INSERTED_NB; i ++) {
|
||||
is(anonymousContents[i].getAttributeForElement("id", "class"),
|
||||
"test",
|
||||
"Element " + i + " didn't change when element 0 was changed");
|
||||
is(
|
||||
anonymousContents[i].root.getElementById("id").className,
|
||||
"test",
|
||||
"Element " + i + " didn't change when element 0 was changed"
|
||||
);
|
||||
}
|
||||
|
||||
// Do not remove inserted elements on purpose to test for potential leaks too.
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</script>
|
||||
|
|
|
@ -3,64 +3,33 @@
|
|||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1020244
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1020244 - Manipulate content created with the AnonymousContent API</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1020244 - Manipulate content created with the AnonymousContent API</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1020244">Mozilla Bug 1020244</a>
|
||||
<div>
|
||||
<div id="test-element" class="test-class" test="test">text content</div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
|
||||
<script>
|
||||
// Insert content
|
||||
let chromeDocument = SpecialPowers.wrap(document);
|
||||
let testElement = document.querySelector("div");
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent(testElement);
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent();
|
||||
anonymousContent.root.appendChild(testElement.cloneNode(true));
|
||||
|
||||
// Test getting/setting text content.
|
||||
is(anonymousContent.getTextContentForElement("test-element"),
|
||||
is(anonymousContent.root.getElementById("test-element").textContent,
|
||||
"text content", "Textcontent for the test element is correct");
|
||||
|
||||
anonymousContent.setTextContentForElement("test-element",
|
||||
"updated text content");
|
||||
is(anonymousContent.getTextContentForElement("test-element"),
|
||||
let anonTestElement = anonymousContent.root.getElementById("test-element");
|
||||
anonTestElement.textContent =
|
||||
"updated text content";
|
||||
is(anonTestElement.textContent,
|
||||
"updated text content",
|
||||
"Textcontent for the test element is correct after update");
|
||||
|
||||
// Test that modifying the original DOM element doesn't change the inserted
|
||||
// element.
|
||||
testElement.removeAttribute("test");
|
||||
is(anonymousContent.getAttributeForElement("test-element", "test"),
|
||||
"test",
|
||||
"Removing attributes on the original DOM node does not change the inserted node");
|
||||
|
||||
testElement.setAttribute("test", "test-updated");
|
||||
is(anonymousContent.getAttributeForElement("test-element", "test"),
|
||||
"test",
|
||||
"Setting attributes on the original DOM node does not change the inserted node");
|
||||
|
||||
// Test getting/setting/removing attributes on the inserted element and test
|
||||
// that this doesn't change the original DOM element.
|
||||
is(anonymousContent.getAttributeForElement("test-element", "class"),
|
||||
"test-class", "Class attribute for the test element is correct");
|
||||
|
||||
anonymousContent.setAttributeForElement("test-element", "class",
|
||||
"updated-test-class");
|
||||
is(anonymousContent.getAttributeForElement("test-element", "class"),
|
||||
"updated-test-class",
|
||||
"Class attribute for the test element is correct after update");
|
||||
ok(testElement.getAttribute("class") !== "updated-test-class",
|
||||
"Class attribute change on the inserted node does not change the original DOM node");
|
||||
|
||||
anonymousContent.removeAttributeForElement("test-element", "class");
|
||||
is(anonymousContent.getAttributeForElement("test-element", "class"), null,
|
||||
"Class attribute for the test element was removed");
|
||||
|
||||
let anim = anonymousContent.setAnimationForElement("test-element", [
|
||||
let anim = anonTestElement.animate([
|
||||
{ transform: 'translateY(0px)' },
|
||||
{ transform: 'translateY(-300px)' }
|
||||
], 2000);
|
||||
|
@ -69,6 +38,4 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1020244
|
|||
is(anim.playState, "idle", "Animation should have stopped immediately");
|
||||
|
||||
chromeDocument.removeAnonymousContent(anonymousContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</script>
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1571650
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1571650 - Test AnonymousContent.setStyle() API</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1571650">Mozilla Bug 1571650</a>
|
||||
<script type="application/javascript">
|
||||
const chromeDocument = SpecialPowers.wrap(document);
|
||||
|
||||
info("Set z-index to anonymous content");
|
||||
const div = document.createElement("div");
|
||||
div.setAttribute("class", "set-style-test");
|
||||
const anonymousContent = chromeDocument.insertAnonymousContent(div);
|
||||
anonymousContent.setStyle("z-index", 3);
|
||||
|
||||
info("Test the element which became to anonymous");
|
||||
const mozCustomContentContainerEl =
|
||||
[...SpecialPowers.InspectorUtils.getChildrenForNode(document.documentElement, true, false)]
|
||||
.find(n => n.classList && n.classList.contains("moz-custom-content-container"));
|
||||
|
||||
const targetEl = mozCustomContentContainerEl.querySelector(".set-style-test");
|
||||
ok(targetEl, "Element which became to anonymous is found");
|
||||
is(targetEl.style.zIndex, "3", "z-index is correct");
|
||||
|
||||
chromeDocument.removeAnonymousContent(anonymousContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,28 +1,23 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=1020244 -->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1185351 - Make sure that we don't enforce CSP on styles for AnonymousContent</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1185351 - Make sure that we don't enforce CSP on styles for AnonymousContent</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<div>
|
||||
<div id="test-element" style="color:red;">text content</div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
<script>
|
||||
let chromeDocument = SpecialPowers.wrap(document);
|
||||
let testElement = document.querySelector("div");
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent(testElement);
|
||||
let anonymousContent = chromeDocument.insertAnonymousContent();
|
||||
anonymousContent.root.appendChild(testElement.cloneNode(true));
|
||||
|
||||
let style = anonymousContent.setAttributeForElement("test-element",
|
||||
"style", "color:green;");
|
||||
|
||||
style = anonymousContent.getAttributeForElement("test-element", "style");
|
||||
is(style, "color:green;", "The anonymous content exists with CSP");
|
||||
let el = anonymousContent.root.getElementById("test-element");
|
||||
el.style = `color: green;`;
|
||||
let style = el.getAttribute("style");
|
||||
is(style, "color: green;", "The anonymous content exists with CSP");
|
||||
|
||||
chromeDocument.removeAnonymousContent(anonymousContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,94 +7,11 @@
|
|||
/*
|
||||
* This file declares the AnonymousContent interface which is used to
|
||||
* manipulate content that has been inserted into the document's canvasFrame
|
||||
* anonymous container.
|
||||
* See Document.insertAnonymousContent.
|
||||
*
|
||||
* This API never returns a reference to the actual inserted DOM node on
|
||||
* purpose. This is to make sure the content cannot be randomly changed and the
|
||||
* DOM cannot be traversed from the node, so that Gecko can remain in control of
|
||||
* the inserted content.
|
||||
* anonymous container. See Document.insertAnonymousContent.
|
||||
* Users of this API must never remove the host of the shadow root.
|
||||
*/
|
||||
|
||||
[ChromeOnly, Exposed=Window]
|
||||
interface AnonymousContent {
|
||||
/**
|
||||
* Get the text content of an element inside this custom anonymous content.
|
||||
*/
|
||||
[Throws]
|
||||
DOMString getTextContentForElement(DOMString elementId);
|
||||
|
||||
/**
|
||||
* Set the text content of an element inside this custom anonymous content.
|
||||
*/
|
||||
[Throws]
|
||||
undefined setTextContentForElement(DOMString elementId, DOMString text);
|
||||
|
||||
/**
|
||||
* Get the value of an attribute of an element inside this custom anonymous
|
||||
* content.
|
||||
*/
|
||||
[Throws]
|
||||
DOMString? getAttributeForElement(DOMString elementId,
|
||||
DOMString attributeName);
|
||||
|
||||
/**
|
||||
* Set the value of an attribute of an element inside this custom anonymous
|
||||
* content.
|
||||
*/
|
||||
[NeedsSubjectPrincipal=NonSystem, Throws]
|
||||
undefined setAttributeForElement(DOMString elementId,
|
||||
DOMString attributeName,
|
||||
DOMString value);
|
||||
|
||||
/**
|
||||
* Remove an attribute from an element inside this custom anonymous content.
|
||||
*/
|
||||
[Throws]
|
||||
undefined removeAttributeForElement(DOMString elementId,
|
||||
DOMString attributeName);
|
||||
|
||||
/**
|
||||
* Get the canvas' context for the element specified if it's a <canvas>
|
||||
* node, `null` otherwise.
|
||||
*/
|
||||
[Throws]
|
||||
nsISupports? getCanvasContext(DOMString elementId,
|
||||
DOMString contextId);
|
||||
|
||||
[Throws]
|
||||
Animation setAnimationForElement(DOMString elementId,
|
||||
object? keyframes,
|
||||
optional UnrestrictedDoubleOrKeyframeAnimationOptions
|
||||
options = {});
|
||||
|
||||
/**
|
||||
* Accepts a list of (possibly overlapping) DOMRects which describe a shape
|
||||
* in CSS pixels relative to the element's border box. This shape will be
|
||||
* excluded from the element's background color rendering. The element will
|
||||
* not render any background images once this method has been called.
|
||||
*/
|
||||
[Throws]
|
||||
undefined setCutoutRectsForElement(DOMString elementId,
|
||||
sequence<DOMRect> rects);
|
||||
|
||||
/**
|
||||
* Get the computed value of a property on an element inside this custom
|
||||
* anonymous content.
|
||||
*/
|
||||
[Throws]
|
||||
UTF8String? getComputedStylePropertyValue(DOMString elementId,
|
||||
UTF8String propertyName);
|
||||
|
||||
/**
|
||||
* If event's original target is in the anonymous content, this returns the id
|
||||
* attribute value of the target.
|
||||
*/
|
||||
DOMString? getTargetIdForEvent(Event event);
|
||||
|
||||
/**
|
||||
* Set given style to this AnonymousContent.
|
||||
*/
|
||||
[Throws]
|
||||
undefined setStyle(UTF8String property, UTF8String value);
|
||||
readonly attribute ShadowRoot root;
|
||||
};
|
||||
|
|
|
@ -506,20 +506,14 @@ partial interface Document {
|
|||
* Chrome document anonymous content management.
|
||||
* This is a Chrome-only API that allows inserting fixed positioned anonymous
|
||||
* content on top of the current page displayed in the document.
|
||||
* The supplied content is cloned and inserted into the document's CanvasFrame.
|
||||
* Note that this only works for HTML documents.
|
||||
*/
|
||||
partial interface Document {
|
||||
/**
|
||||
* Deep-clones the provided element and inserts it into the CanvasFrame.
|
||||
* Returns an AnonymousContent instance that can be used to manipulate the
|
||||
* inserted element.
|
||||
*
|
||||
* If aForce is true, tries to update layout to be able to insert the element
|
||||
* synchronously.
|
||||
*/
|
||||
[ChromeOnly, NewObject, Throws]
|
||||
AnonymousContent insertAnonymousContent(Element aElement, optional boolean aForce = false);
|
||||
AnonymousContent insertAnonymousContent(optional boolean aForce = false);
|
||||
|
||||
/**
|
||||
* Removes the element inserted into the CanvasFrame given an AnonymousContent
|
||||
|
|
|
@ -7,15 +7,19 @@
|
|||
#include "AccessibleCaret.h"
|
||||
|
||||
#include "AccessibleCaretLogger.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/ToString.h"
|
||||
#include "nsCanvasFrame.h"
|
||||
#include "nsCaret.h"
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
|
@ -33,9 +37,8 @@ using namespace dom;
|
|||
|
||||
NS_IMPL_ISUPPORTS(AccessibleCaret::DummyTouchListener, nsIDOMEventListener)
|
||||
|
||||
const nsLiteralString AccessibleCaret::sTextOverlayElementId =
|
||||
u"text-overlay"_ns;
|
||||
const nsLiteralString AccessibleCaret::sCaretImageElementId = u"image"_ns;
|
||||
static constexpr auto kTextOverlayElementId = u"text-overlay"_ns;
|
||||
static constexpr auto kCaretImageElementId = u"image"_ns;
|
||||
|
||||
#define AC_PROCESS_ENUM_TO_STREAM(e) \
|
||||
case (e): \
|
||||
|
@ -75,7 +78,6 @@ AccessibleCaret::AccessibleCaret(PresShell* aPresShell)
|
|||
: mPresShell(aPresShell) {
|
||||
// Check all resources required.
|
||||
if (mPresShell) {
|
||||
MOZ_ASSERT(RootFrame());
|
||||
MOZ_ASSERT(mPresShell->GetDocument());
|
||||
InjectCaretElement(mPresShell->GetDocument());
|
||||
}
|
||||
|
@ -87,12 +89,20 @@ AccessibleCaret::~AccessibleCaret() {
|
|||
}
|
||||
}
|
||||
|
||||
dom::Element* AccessibleCaret::TextOverlayElement() const {
|
||||
return mCaretElementHolder->Root()->GetElementById(kTextOverlayElementId);
|
||||
}
|
||||
|
||||
dom::Element* AccessibleCaret::CaretImageElement() const {
|
||||
return mCaretElementHolder->Root()->GetElementById(kCaretImageElementId);
|
||||
}
|
||||
|
||||
void AccessibleCaret::SetAppearance(Appearance aAppearance) {
|
||||
if (mAppearance == aAppearance) {
|
||||
return;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
IgnoredErrorResult rv;
|
||||
CaretElement().ClassList()->Remove(AppearanceString(mAppearance), rv);
|
||||
MOZ_ASSERT(!rv.Failed(), "Remove old appearance failed!");
|
||||
|
||||
|
@ -171,7 +181,6 @@ void AccessibleCaret::EnsureApzAware() {
|
|||
// if that's the case we register a dummy listener if there isn't one on
|
||||
// the element already.
|
||||
if (!CaretElement().IsApzAware()) {
|
||||
// FIXME(emilio): Is this needed anymore?
|
||||
CaretElement().AddEventListener(u"touchstart"_ns, mDummyTouchListener,
|
||||
false);
|
||||
}
|
||||
|
@ -183,43 +192,53 @@ bool AccessibleCaret::IsInPositionFixedSubtree() const {
|
|||
}
|
||||
|
||||
void AccessibleCaret::InjectCaretElement(Document* aDocument) {
|
||||
IgnoredErrorResult rv;
|
||||
RefPtr<Element> element = CreateCaretElement(aDocument);
|
||||
mCaretElementHolder =
|
||||
aDocument->InsertAnonymousContent(*element, /* aForce = */ false, rv);
|
||||
aDocument->InsertAnonymousContent(/* aForce = */ false, IgnoreErrors());
|
||||
MOZ_RELEASE_ASSERT(mCaretElementHolder, "We must have anonymous content!");
|
||||
|
||||
MOZ_ASSERT(!rv.Failed(), "Insert anonymous content should not fail!");
|
||||
MOZ_ASSERT(mCaretElementHolder, "We must have anonymous content!");
|
||||
|
||||
// InsertAnonymousContent will clone the element to make an AnonymousContent.
|
||||
// Since event listeners are not being cloned when cloning a node, we need to
|
||||
// add the listener here.
|
||||
CreateCaretElement();
|
||||
EnsureApzAware();
|
||||
}
|
||||
|
||||
already_AddRefed<Element> AccessibleCaret::CreateCaretElement(
|
||||
Document* aDocument) const {
|
||||
void AccessibleCaret::CreateCaretElement() const {
|
||||
// Content structure of AccessibleCaret
|
||||
// <div class="moz-accessiblecaret"> <- CaretElement()
|
||||
// <div id="text-overlay"> <- TextOverlayElement()
|
||||
// <div id="image"> <- CaretImageElement()
|
||||
// <#shadow-root>
|
||||
// <link rel="stylesheet" href="accessiblecaret.css">
|
||||
// <div id="text-overlay"> <- TextOverlayElement()
|
||||
// <div id="image"> <- CaretImageElement()
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<Element> parent = aDocument->CreateHTMLElement(nsGkAtoms::div);
|
||||
parent->ClassList()->Add(u"moz-accessiblecaret"_ns, rv);
|
||||
parent->ClassList()->Add(u"none"_ns, rv);
|
||||
constexpr bool kNotify = false;
|
||||
|
||||
auto CreateAndAppendChildElement =
|
||||
[aDocument, &parent](const nsLiteralString& aElementId) {
|
||||
RefPtr<Element> child = aDocument->CreateHTMLElement(nsGkAtoms::div);
|
||||
child->SetAttr(kNameSpaceID_None, nsGkAtoms::id, aElementId, true);
|
||||
parent->AppendChildTo(child, false, IgnoreErrors());
|
||||
};
|
||||
Element& host = CaretElement();
|
||||
host.SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
||||
u"moz-accessiblecaret none"_ns, kNotify);
|
||||
|
||||
CreateAndAppendChildElement(sTextOverlayElementId);
|
||||
CreateAndAppendChildElement(sCaretImageElementId);
|
||||
ShadowRoot* root = mCaretElementHolder->Root();
|
||||
Document* doc = host.OwnerDoc();
|
||||
{
|
||||
RefPtr<NodeInfo> linkNodeInfo = doc->NodeInfoManager()->GetNodeInfo(
|
||||
nsGkAtoms::link, nullptr, kNameSpaceID_XHTML, nsINode::ELEMENT_NODE);
|
||||
RefPtr<nsGenericHTMLElement> link =
|
||||
NS_NewHTMLLinkElement(linkNodeInfo.forget());
|
||||
if (NS_WARN_IF(!link)) {
|
||||
return;
|
||||
}
|
||||
link->SetAttr(nsGkAtoms::rel, u"stylesheet"_ns, IgnoreErrors());
|
||||
link->SetAttr(nsGkAtoms::href,
|
||||
u"resource://content-accessible/accessiblecaret.css"_ns,
|
||||
IgnoreErrors());
|
||||
root->AppendChildTo(link, kNotify, IgnoreErrors());
|
||||
}
|
||||
|
||||
return parent.forget();
|
||||
auto CreateAndAppendChildElement = [&](const nsLiteralString& aElementId) {
|
||||
RefPtr<Element> child = doc->CreateHTMLElement(nsGkAtoms::div);
|
||||
child->SetAttr(kNameSpaceID_None, nsGkAtoms::id, aElementId, kNotify);
|
||||
mCaretElementHolder->Root()->AppendChildTo(child, kNotify, IgnoreErrors());
|
||||
};
|
||||
|
||||
CreateAndAppendChildElement(kTextOverlayElementId);
|
||||
CreateAndAppendChildElement(kCaretImageElementId);
|
||||
}
|
||||
|
||||
void AccessibleCaret::RemoveCaretElement(Document* aDocument) {
|
||||
|
|
|
@ -130,9 +130,7 @@ class AccessibleCaret {
|
|||
// Element for 'Intersects' test. This is the container of the caret image
|
||||
// and text-overlay elements. See CreateCaretElement() for the content
|
||||
// structure.
|
||||
dom::Element& CaretElement() const {
|
||||
return mCaretElementHolder->ContentNode();
|
||||
}
|
||||
dom::Element& CaretElement() const { return *mCaretElementHolder->Host(); }
|
||||
|
||||
// Ensures that the caret element is made "APZ aware" so that the APZ code
|
||||
// doesn't scroll the page when the user is trying to drag the caret.
|
||||
|
@ -150,14 +148,10 @@ class AccessibleCaret {
|
|||
float GetZoomLevel();
|
||||
|
||||
// Element which contains the text overly for the 'Contains' test.
|
||||
dom::Element* TextOverlayElement() const {
|
||||
return mCaretElementHolder->GetElementById(sTextOverlayElementId);
|
||||
}
|
||||
dom::Element* TextOverlayElement() const;
|
||||
|
||||
// Element which contains the caret image for 'Contains' test.
|
||||
dom::Element* CaretImageElement() const {
|
||||
return mCaretElementHolder->GetElementById(sCaretImageElementId);
|
||||
}
|
||||
dom::Element* CaretImageElement() const;
|
||||
|
||||
nsIFrame* RootFrame() const;
|
||||
|
||||
|
@ -166,7 +160,7 @@ class AccessibleCaret {
|
|||
// Transform Appearance to CSS id used in ua.css.
|
||||
static nsAutoString AppearanceString(Appearance aAppearance);
|
||||
|
||||
already_AddRefed<dom::Element> CreateCaretElement(dom::Document*) const;
|
||||
void CreateCaretElement() const;
|
||||
|
||||
// Inject caret element into custom content container.
|
||||
void InjectCaretElement(dom::Document*);
|
||||
|
@ -223,11 +217,6 @@ class AccessibleCaret {
|
|||
// A no-op touch-start listener which prevents APZ from panning when dragging
|
||||
// the caret.
|
||||
RefPtr<DummyTouchListener> mDummyTouchListener{new DummyTouchListener()};
|
||||
|
||||
// Static class variables
|
||||
static const nsLiteralString sTextOverlayElementId;
|
||||
static const nsLiteralString sCaretImageElementId;
|
||||
|
||||
}; // class AccessibleCaret
|
||||
|
||||
std::ostream& operator<<(std::ostream& aStream,
|
||||
|
|
|
@ -332,11 +332,7 @@ AccessibleCaretEventHub::AccessibleCaretEventHub(PresShell* aPresShell)
|
|||
: mPresShell(aPresShell) {}
|
||||
|
||||
void AccessibleCaretEventHub::Init() {
|
||||
if (mInitialized && mManager) {
|
||||
mManager->OnFrameReconstruction();
|
||||
}
|
||||
|
||||
if (mInitialized || !mPresShell || !mPresShell->GetCanvasFrame()) {
|
||||
if (mInitialized || !mPresShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -798,11 +798,6 @@ void AccessibleCaretManager::OnKeyboardEvent() {
|
|||
}
|
||||
}
|
||||
|
||||
void AccessibleCaretManager::OnFrameReconstruction() {
|
||||
mCarets.GetFirst()->EnsureApzAware();
|
||||
mCarets.GetSecond()->EnsureApzAware();
|
||||
}
|
||||
|
||||
void AccessibleCaretManager::SetLastInputSource(uint16_t aInputSource) {
|
||||
mLastInputSource = aInputSource;
|
||||
}
|
||||
|
|
|
@ -115,10 +115,6 @@ class AccessibleCaretManager {
|
|||
MOZ_CAN_RUN_SCRIPT
|
||||
virtual void OnKeyboardEvent();
|
||||
|
||||
// The canvas frame holding the accessible caret anonymous content elements
|
||||
// was reconstructed, resulting in the content elements getting cloned.
|
||||
virtual void OnFrameReconstruction();
|
||||
|
||||
// Update the manager with the last input source that was observed. This
|
||||
// is used in part to determine if the carets should be shown or hidden.
|
||||
void SetLastInputSource(uint16_t aInputSource);
|
||||
|
|
|
@ -903,11 +903,12 @@ void PresShell::Init(nsPresContext* aPresContext, nsViewManager* aViewManager) {
|
|||
// Add the preference style sheet.
|
||||
UpdatePreferenceStyles();
|
||||
|
||||
bool accessibleCaretEnabled =
|
||||
const bool accessibleCaretEnabled =
|
||||
AccessibleCaretEnabled(mDocument->GetDocShell());
|
||||
if (accessibleCaretEnabled) {
|
||||
// Need to happen before nsFrameSelection has been set up.
|
||||
mAccessibleCaretEventHub = new AccessibleCaretEventHub(this);
|
||||
mAccessibleCaretEventHub->Init();
|
||||
}
|
||||
|
||||
mSelection = new nsFrameSelection(this, nullptr, accessibleCaretEnabled);
|
||||
|
|
|
@ -731,7 +731,7 @@ static bool HasVisibleAnonymousContents(Document* aDoc) {
|
|||
// For now we assume that if it has a frame, it is visible. We might be able
|
||||
// to refine this further by adding complexity if it turns out this
|
||||
// condition results in a lot of false positives.
|
||||
if (ac->ContentNode().GetPrimaryFrame()) {
|
||||
if (ac->Host()->GetPrimaryFrame()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,39 @@ void nsCanvasFrame::HideCustomContentContainer() {
|
|||
}
|
||||
}
|
||||
|
||||
// Do this off a script-runner because some anon content might load CSS which we
|
||||
// don't want to deal with while doing frame construction.
|
||||
void InsertAnonymousContentInContainer(Document& aDoc, Element& aContainer) {
|
||||
if (!aContainer.IsInComposedDoc() || aDoc.GetAnonymousContents().IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (RefPtr<AnonymousContent>& anonContent : aDoc.GetAnonymousContents()) {
|
||||
if (nsCOMPtr<nsINode> parent = anonContent->Host()->GetParentNode()) {
|
||||
// Parent had better be an old custom content container already
|
||||
// removed from a reframe. Forget about it since we're about to get
|
||||
// inserted in a new one.
|
||||
//
|
||||
// TODO(emilio): Maybe we should extend PostDestroyData and do this
|
||||
// stuff there instead, or something...
|
||||
MOZ_ASSERT(parent != &aContainer);
|
||||
MOZ_ASSERT(parent->IsElement());
|
||||
MOZ_ASSERT(parent->AsElement()->IsRootOfNativeAnonymousSubtree());
|
||||
MOZ_ASSERT(!parent->IsInComposedDoc());
|
||||
MOZ_ASSERT(!parent->GetParentNode());
|
||||
|
||||
parent->RemoveChildNode(anonContent->Host(), true);
|
||||
}
|
||||
aContainer.AppendChildTo(anonContent->Host(), true, IgnoreErrors());
|
||||
}
|
||||
// Flush frames now. This is really sadly needed, but otherwise stylesheets
|
||||
// inserted by the above DOM changes might not be processed in time for layout
|
||||
// to run.
|
||||
// FIXME(emilio): This is because we have a script-running checkpoint just
|
||||
// after ProcessPendingRestyles but before DoReflow. That seems wrong! Ideally
|
||||
// the whole layout / styling pass should be atomic.
|
||||
aDoc.FlushPendingNotifications(FlushType::Frames);
|
||||
}
|
||||
|
||||
nsresult nsCanvasFrame::CreateAnonymousContent(
|
||||
nsTArray<ContentInfo>& aElements) {
|
||||
MOZ_ASSERT(!mCustomContentContainer);
|
||||
|
@ -82,19 +115,7 @@ nsresult nsCanvasFrame::CreateAnonymousContent(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<Document> doc = mContent->OwnerDoc();
|
||||
|
||||
RefPtr<AccessibleCaretEventHub> eventHub =
|
||||
PresShell()->GetAccessibleCaretEventHub();
|
||||
|
||||
// This will go through InsertAnonymousContent and such, and we don't really
|
||||
// want it to end up inserting into our content container.
|
||||
//
|
||||
// FIXME(emilio): The fact that this enters into InsertAnonymousContent is a
|
||||
// bit nasty, can we avoid it, maybe doing this off a scriptrunner?
|
||||
if (eventHub) {
|
||||
eventHub->Init();
|
||||
}
|
||||
Document* doc = mContent->OwnerDoc();
|
||||
|
||||
// Create the custom content container.
|
||||
mCustomContentContainer = doc->CreateHTMLElement(nsGkAtoms::div);
|
||||
|
@ -129,27 +150,12 @@ nsresult nsCanvasFrame::CreateAnonymousContent(
|
|||
// Only create a frame for mCustomContentContainer if it has some children.
|
||||
if (doc->GetAnonymousContents().IsEmpty()) {
|
||||
HideCustomContentContainer();
|
||||
}
|
||||
|
||||
for (RefPtr<AnonymousContent>& anonContent : doc->GetAnonymousContents()) {
|
||||
if (nsCOMPtr<nsINode> parent = anonContent->ContentNode().GetParentNode()) {
|
||||
// Parent had better be an old custom content container already removed
|
||||
// from a reframe. Forget about it since we're about to get inserted in a
|
||||
// new one.
|
||||
//
|
||||
// TODO(emilio): Maybe we should extend PostDestroyData and do this stuff
|
||||
// there instead, or something...
|
||||
MOZ_ASSERT(parent != mCustomContentContainer);
|
||||
MOZ_ASSERT(parent->IsElement());
|
||||
MOZ_ASSERT(parent->AsElement()->IsRootOfNativeAnonymousSubtree());
|
||||
MOZ_ASSERT(!parent->IsInComposedDoc());
|
||||
MOZ_ASSERT(!parent->GetParentNode());
|
||||
|
||||
parent->RemoveChildNode(&anonContent->ContentNode(), false);
|
||||
}
|
||||
|
||||
mCustomContentContainer->AppendChildTo(&anonContent->ContentNode(), false,
|
||||
IgnoreErrors());
|
||||
} else {
|
||||
nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
|
||||
"InsertAnonymousContentInContainer",
|
||||
[doc = RefPtr{doc}, container = RefPtr{mCustomContentContainer.get()}] {
|
||||
InsertAnonymousContentInContainer(*doc, *container);
|
||||
}));
|
||||
}
|
||||
|
||||
// Create a popupgroup element for system privileged non-XUL documents to
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "mozilla/ViewportUtils.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsCSSRenderingGradients.h"
|
||||
#include "nsCaseTreatment.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "nsRegion.h"
|
||||
#include "nsStyleStructInlines.h"
|
||||
|
@ -1383,8 +1384,9 @@ void nsDisplayListBuilder::MarkFramesForDisplayList(
|
|||
nsIContent* content = e->GetContent();
|
||||
if (content && content->IsInNativeAnonymousSubtree() &&
|
||||
content->IsElement()) {
|
||||
auto* classList = content->AsElement()->ClassList();
|
||||
if (classList->Contains(u"moz-accessiblecaret"_ns)) {
|
||||
const nsAttrValue* classes = content->AsElement()->GetClasses();
|
||||
if (classes &&
|
||||
classes->Contains(nsGkAtoms::mozAccessiblecaret, eCaseMatters)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -904,15 +904,22 @@ nsresult Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
|
|||
}
|
||||
|
||||
static void RecordUseCountersIfNeeded(Document* aDoc,
|
||||
const StyleUseCounters* aCounters) {
|
||||
if (!aDoc || !aCounters) {
|
||||
const StyleSheet& aSheet) {
|
||||
if (!aDoc) {
|
||||
return;
|
||||
}
|
||||
const StyleUseCounters* docCounters = aDoc->GetStyleUseCounters();
|
||||
if (!docCounters) {
|
||||
return;
|
||||
}
|
||||
Servo_UseCounters_Merge(docCounters, aCounters);
|
||||
if (aSheet.URLData()->ChromeRulesEnabled()) {
|
||||
return;
|
||||
}
|
||||
auto* sheetCounters = aSheet.GetStyleUseCounters();
|
||||
if (!sheetCounters) {
|
||||
return;
|
||||
}
|
||||
Servo_UseCounters_Merge(docCounters, sheetCounters);
|
||||
aDoc->MaybeWarnAboutZoom();
|
||||
}
|
||||
|
||||
|
@ -959,7 +966,7 @@ std::tuple<RefPtr<StyleSheet>, Loader::SheetState> Loader::CreateSheet(
|
|||
if (cacheResult.mCompleteValue) {
|
||||
sheet = cacheResult.mCompleteValue->Clone(nullptr, nullptr);
|
||||
mDocument->SetDidHitCompleteSheetCache();
|
||||
RecordUseCountersIfNeeded(mDocument, sheet->GetStyleUseCounters());
|
||||
RecordUseCountersIfNeeded(mDocument, *sheet);
|
||||
mLoadsPerformed.PutEntry(key);
|
||||
} else {
|
||||
MOZ_ASSERT(cacheResult.mLoadingOrPendingValue);
|
||||
|
@ -1555,7 +1562,7 @@ Loader::Completed Loader::ParseSheet(const nsACString& aBytes,
|
|||
}
|
||||
|
||||
void Loader::NotifyObservers(SheetLoadData& aData, nsresult aStatus) {
|
||||
RecordUseCountersIfNeeded(mDocument, aData.mSheet->GetStyleUseCounters());
|
||||
RecordUseCountersIfNeeded(mDocument, *aData.mSheet);
|
||||
RefPtr loadDispatcher = aData.PrepareLoadEventIfNeeded();
|
||||
if (aData.mURI) {
|
||||
mLoadsPerformed.PutEntry(SheetLoadDataHashKey(aData));
|
||||
|
|
|
@ -764,7 +764,7 @@ void StyleSheet::ReplaceSync(const nsACString& aText, ErrorResult& aRv) {
|
|||
RefPtr<const StyleStylesheetContents> rawContent =
|
||||
Servo_StyleSheet_FromUTF8Bytes(
|
||||
loader, this,
|
||||
/* load_data = */ nullptr, &aText, mParsingMode, Inner().mURLData,
|
||||
/* load_data = */ nullptr, &aText, mParsingMode, URLData(),
|
||||
/* line_number_offset = */ 0,
|
||||
mConstructorDocument->GetCompatibilityMode(),
|
||||
/* reusable_sheets = */ nullptr,
|
||||
|
@ -1204,9 +1204,11 @@ RefPtr<StyleSheetParsePromise> StyleSheet::ParseSheet(
|
|||
auto allowImportRules = SelfOrAncestorIsConstructed()
|
||||
? StyleAllowImportRules::No
|
||||
: StyleAllowImportRules::Yes;
|
||||
URLExtraData* urlData = URLData();
|
||||
const bool shouldRecordCounters =
|
||||
aLoader.GetDocument() && aLoader.GetDocument()->GetStyleUseCounters();
|
||||
if (!AllowParallelParse(aLoader, Inner().mURLData)) {
|
||||
aLoader.GetDocument() && aLoader.GetDocument()->GetStyleUseCounters() &&
|
||||
!urlData->ChromeRulesEnabled();
|
||||
if (!AllowParallelParse(aLoader, urlData)) {
|
||||
UniquePtr<StyleUseCounters> counters;
|
||||
if (shouldRecordCounters) {
|
||||
counters.reset(Servo_UseCounters_Create());
|
||||
|
@ -1214,7 +1216,7 @@ RefPtr<StyleSheetParsePromise> StyleSheet::ParseSheet(
|
|||
|
||||
RefPtr<StyleStylesheetContents> contents =
|
||||
Servo_StyleSheet_FromUTF8Bytes(
|
||||
&aLoader, this, &aLoadData, &aBytes, mParsingMode, Inner().mURLData,
|
||||
&aLoader, this, &aLoadData, &aBytes, mParsingMode, urlData,
|
||||
aLoadData.mLineNumber, aLoadData.mCompatMode,
|
||||
/* reusable_sheets = */ nullptr, counters.get(), allowImportRules,
|
||||
StyleSanitizationKind::None,
|
||||
|
@ -1224,7 +1226,7 @@ RefPtr<StyleSheetParsePromise> StyleSheet::ParseSheet(
|
|||
} else {
|
||||
auto holder = MakeRefPtr<css::SheetLoadDataHolder>(__func__, &aLoadData);
|
||||
Servo_StyleSheet_FromUTF8BytesAsync(
|
||||
holder, Inner().mURLData, &aBytes, mParsingMode, aLoadData.mLineNumber,
|
||||
holder, urlData, &aBytes, mParsingMode, aLoadData.mLineNumber,
|
||||
aLoadData.mCompatMode, shouldRecordCounters, allowImportRules);
|
||||
}
|
||||
|
||||
|
@ -1256,8 +1258,11 @@ void StyleSheet::ParseSheetSync(
|
|||
return eCompatibility_FullStandards;
|
||||
}();
|
||||
|
||||
SetURLExtraData();
|
||||
|
||||
URLExtraData* urlData = URLData();
|
||||
const StyleUseCounters* useCounters =
|
||||
aLoader && aLoader->GetDocument()
|
||||
aLoader && aLoader->GetDocument() && !urlData->ChromeRulesEnabled()
|
||||
? aLoader->GetDocument()->GetStyleUseCounters()
|
||||
: nullptr;
|
||||
|
||||
|
@ -1265,12 +1270,11 @@ void StyleSheet::ParseSheetSync(
|
|||
? StyleAllowImportRules::No
|
||||
: StyleAllowImportRules::Yes;
|
||||
|
||||
SetURLExtraData();
|
||||
Inner().mContents =
|
||||
Servo_StyleSheet_FromUTF8Bytes(
|
||||
aLoader, this, aLoadData, &aBytes, mParsingMode, Inner().mURLData,
|
||||
aLineNumber, compatMode, aReusableSheets, useCounters,
|
||||
allowImportRules, StyleSanitizationKind::None,
|
||||
aLoader, this, aLoadData, &aBytes, mParsingMode, urlData, aLineNumber,
|
||||
compatMode, aReusableSheets, useCounters, allowImportRules,
|
||||
StyleSanitizationKind::None,
|
||||
/* sanitized_output = */ nullptr)
|
||||
.Consume();
|
||||
|
||||
|
@ -1481,7 +1485,7 @@ void StyleSheet::SetSharedContents(const StyleLockedCssRules* aSharedRules) {
|
|||
SetURLExtraData();
|
||||
|
||||
Inner().mContents =
|
||||
Servo_StyleSheet_FromSharedData(Inner().mURLData, aSharedRules).Consume();
|
||||
Servo_StyleSheet_FromSharedData(URLData(), aSharedRules).Consume();
|
||||
|
||||
// Don't call FinishParse(), since that tries to set source map URLs,
|
||||
// which we don't have.
|
||||
|
|
|
@ -274,6 +274,7 @@ RESOURCE_FILES += [
|
|||
|
||||
CONTENT_ACCESSIBLE_FILES += [
|
||||
"ImageDocument.css",
|
||||
"res/accessiblecaret.css",
|
||||
"res/details.css",
|
||||
"res/plaintext.css",
|
||||
"res/searchfield-cancel.svg",
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/* 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/. */
|
||||
|
||||
:host {
|
||||
/* Add transition effect to make caret size changing smoother. */
|
||||
transition-property: width, height, margin-left;
|
||||
|
||||
position: absolute;
|
||||
z-index: 2147483647;
|
||||
}
|
||||
|
||||
#image,
|
||||
#text-overlay {
|
||||
width: 100%;
|
||||
|
||||
/* Override this property in moz-custom-content-container to make dummy touch
|
||||
* listener work. */
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#image {
|
||||
background-position: center top;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-origin: content-box;
|
||||
}
|
||||
|
||||
:host(.normal) #image {
|
||||
background-image: image-set(
|
||||
url("resource://gre-resources/accessiblecaret-normal@1x.png"),
|
||||
url("resource://gre-resources/accessiblecaret-normal@1.5x.png") 1.5x,
|
||||
url("resource://gre-resources/accessiblecaret-normal@2x.png") 2x,
|
||||
url("resource://gre-resources/accessiblecaret-normal@2.25x.png") 2.25x
|
||||
);
|
||||
}
|
||||
|
||||
:host(.left) #image,
|
||||
:host(.left) #text-overlay {
|
||||
margin-left: -39%;
|
||||
}
|
||||
|
||||
:host(.left) > #image {
|
||||
background-image: image-set(
|
||||
url("resource://gre-resources/accessiblecaret-tilt-left@1x.png"),
|
||||
url("resource://gre-resources/accessiblecaret-tilt-left@1.5x.png") 1.5x,
|
||||
url("resource://gre-resources/accessiblecaret-tilt-left@2x.png") 2x,
|
||||
url("resource://gre-resources/accessiblecaret-tilt-left@2.25x.png") 2.25x
|
||||
);
|
||||
}
|
||||
|
||||
:host(.right) #image,
|
||||
:host(.right) #text-overlay {
|
||||
margin-left: 41%;
|
||||
}
|
||||
|
||||
:host(.right) #image {
|
||||
background-image: image-set(
|
||||
url("resource://gre-resources/accessiblecaret-tilt-right@1x.png"),
|
||||
url("resource://gre-resources/accessiblecaret-tilt-right@1.5x.png") 1.5x,
|
||||
url("resource://gre-resources/accessiblecaret-tilt-right@2x.png") 2x,
|
||||
url("resource://gre-resources/accessiblecaret-tilt-right@2.25x.png") 2.25x
|
||||
);
|
||||
}
|
||||
|
||||
:host(.none) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:host(.hidden) {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
@media (-moz-platform: android) {
|
||||
#image,
|
||||
#text-overlay {
|
||||
/* border: 0.1px solid red; */ /* Uncomment border to see the touch target. */
|
||||
padding-left: 59%; /* Enlarge the touch area. ((48-22)/2)px / 22px ~= 59% */
|
||||
padding-right: 59%; /* Enlarge the touch area. */
|
||||
margin-left: -59%;
|
||||
}
|
||||
|
||||
#image {
|
||||
padding-bottom: 59%; /* Enlarge the touch area. */
|
||||
}
|
||||
|
||||
:host(.normal) #image {
|
||||
background-image: url("chrome://geckoview/skin/images/accessiblecaret-normal.svg");
|
||||
}
|
||||
|
||||
:host(.left) #image,
|
||||
:host(.left) #text-overlay {
|
||||
margin-left: -109%;
|
||||
}
|
||||
|
||||
:host(.left) #image {
|
||||
background-image: url("chrome://geckoview/skin/images/accessiblecaret-tilt-left.svg");
|
||||
}
|
||||
|
||||
:host(.right) #image,
|
||||
:host(.right) #text-overlay {
|
||||
margin-left: -12%;
|
||||
}
|
||||
|
||||
:host(.right) #image {
|
||||
background-image: url("chrome://geckoview/skin/images/accessiblecaret-tilt-right.svg");
|
||||
}
|
||||
}
|
|
@ -443,108 +443,9 @@ parsererror|sourcetext {
|
|||
font-size: 12pt;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret {
|
||||
/* Add transition effect to make caret size changing smoother. */
|
||||
transition-property: width, height, margin-left;
|
||||
|
||||
position: absolute;
|
||||
z-index: 2147483647;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret > :is(#text-overlay, #image) {
|
||||
width: 100%;
|
||||
|
||||
/* Override this property in moz-custom-content-container to make dummy touch
|
||||
* listener work. */
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret > #image {
|
||||
background-position: center top;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-origin: content-box;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.normal > #image {
|
||||
background-image: image-set(
|
||||
url("resource://gre-resources/accessiblecaret-normal@1x.png"),
|
||||
url("resource://gre-resources/accessiblecaret-normal@1.5x.png") 1.5x,
|
||||
url("resource://gre-resources/accessiblecaret-normal@2x.png") 2x,
|
||||
url("resource://gre-resources/accessiblecaret-normal@2.25x.png") 2.25x
|
||||
);
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.left > :is(#text-overlay, #image) {
|
||||
margin-left: -39%;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.left > #image {
|
||||
background-image: image-set(
|
||||
url("resource://gre-resources/accessiblecaret-tilt-left@1x.png"),
|
||||
url("resource://gre-resources/accessiblecaret-tilt-left@1.5x.png") 1.5x,
|
||||
url("resource://gre-resources/accessiblecaret-tilt-left@2x.png") 2x,
|
||||
url("resource://gre-resources/accessiblecaret-tilt-left@2.25x.png") 2.25x
|
||||
);
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.right > :is(#text-overlay, #image) {
|
||||
margin-left: 41%;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.right > #image {
|
||||
background-image: image-set(
|
||||
url("resource://gre-resources/accessiblecaret-tilt-right@1x.png"),
|
||||
url("resource://gre-resources/accessiblecaret-tilt-right@1.5x.png") 1.5x,
|
||||
url("resource://gre-resources/accessiblecaret-tilt-right@2x.png") 2x,
|
||||
url("resource://gre-resources/accessiblecaret-tilt-right@2.25x.png") 2.25x
|
||||
);
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
@media (-moz-platform: android) {
|
||||
div:-moz-native-anonymous.moz-accessiblecaret > :is(#text-overlay, #image) {
|
||||
/* border: 0.1px solid red; */ /* Uncomment border to see the touch target. */
|
||||
padding-left: 59%; /* Enlarge the touch area. ((48-22)/2)px / 22px ~= 59% */
|
||||
padding-right: 59%; /* Enlarge the touch area. */
|
||||
margin-left: -59%;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret > #image {
|
||||
padding-bottom: 59%; /* Enlarge the touch area. */
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.normal > #image {
|
||||
background-image: url("chrome://geckoview/skin/images/accessiblecaret-normal.svg");
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.left > :is(#text-overlay, #image) {
|
||||
margin-left: -109%;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.left > #image {
|
||||
background-image: url("chrome://geckoview/skin/images/accessiblecaret-tilt-left.svg");
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.right > :is(#text-overlay, #image) {
|
||||
margin-left: -12%;
|
||||
}
|
||||
|
||||
div:-moz-native-anonymous.moz-accessiblecaret.right > #image {
|
||||
background-image: url("chrome://geckoview/skin/images/accessiblecaret-tilt-right.svg");
|
||||
}
|
||||
}
|
||||
|
||||
/* Custom content container in the CanvasFrame, positioned on top of everything
|
||||
everything else, not reacting to pointer events. */
|
||||
div:-moz-native-anonymous.moz-custom-content-container {
|
||||
.moz-custom-content-container:-moz-native-anonymous {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
-moz-top-layer: top;
|
||||
|
@ -553,4 +454,6 @@ div:-moz-native-anonymous.moz-custom-content-container {
|
|||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* Initial direction depends on the document, make sure to reset it */
|
||||
direction: ltr;
|
||||
}
|
||||
|
|
|
@ -33,10 +33,11 @@ function startTest() {
|
|||
div.id = "ac-child";
|
||||
div.textContent = " This div text should be green.";
|
||||
bq.appendChild(div);
|
||||
var ac = document.insertAnonymousContent(bq);
|
||||
var ac = document.insertAnonymousContent();
|
||||
ac.root.appendChild(bq);
|
||||
document.body.offsetWidth;
|
||||
|
||||
is(ac.getComputedStylePropertyValue("ac-child", "color"), "rgb(0, 128, 0)",
|
||||
is(getComputedStyle(div).color, "rgb(0, 128, 0)",
|
||||
"color before reframing");
|
||||
|
||||
// reframe the root
|
||||
|
@ -44,10 +45,10 @@ function startTest() {
|
|||
document.body.offsetWidth;
|
||||
|
||||
// restyle the div
|
||||
ac.setAttributeForElement("ac-child", "class", "abc");
|
||||
div.className = "abc";
|
||||
document.body.offsetWidth;
|
||||
|
||||
is(ac.getComputedStylePropertyValue("ac-child", "color"), "rgb(0, 128, 0)",
|
||||
is(getComputedStyle(div).color, "rgb(0, 128, 0)",
|
||||
"color after reframing");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
|
|
@ -6,20 +6,18 @@
|
|||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script>
|
||||
onload = function() {
|
||||
try {
|
||||
let doc = SpecialPowers.wrap(document);
|
||||
let div = doc.createElement('div');
|
||||
div.id = "test-id";
|
||||
ok(!!doc.insertAnonymousContent,
|
||||
"Must have the insertAnonymousContent API");
|
||||
let content = doc.insertAnonymousContent(div);
|
||||
ok(!!content, "Must have anon content");
|
||||
isnot(content.getComputedStylePropertyValue("test-id", "color"),
|
||||
getComputedStyle(document.documentElement).color,
|
||||
"Custom anon content shouldn't inherit from the root element");
|
||||
} catch(e) {
|
||||
ok(false, "Threw: " + e);
|
||||
}
|
||||
let doc = SpecialPowers.wrap(document);
|
||||
let div = doc.createElement('div');
|
||||
div.id = "test-id";
|
||||
ok(!!doc.insertAnonymousContent,
|
||||
"Must have the insertAnonymousContent API");
|
||||
let content = doc.insertAnonymousContent();
|
||||
ok(!!content, "Must have anon content");
|
||||
content.root.appendChild(div);
|
||||
let color = SpecialPowers.wrap(window).getComputedStyle(div).color;
|
||||
ok(!!color, "Should be able to get a color");
|
||||
isnot(color, getComputedStyle(document.documentElement).color,
|
||||
"Custom anon content shouldn't inherit from the root element");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
|
Загрузка…
Ссылка в новой задаче