Bug 1353005 - removed sdk/content/mod and replaced with DOMWindowUtils calls; r=pbro
MozReview-Commit-ID: 7aj8C0zYr6C
--- a/devtools/server/actors/highlighters/simple-outline.js
+++ b/devtools/server/actors/highlighters/simple-outline.js
@@ -1,30 +1,32 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
- installHelperSheet,
isNodeValid,
addPseudoClassLock,
removePseudoClassLock
} = require("./utils/markup");
+const { loadSheet } = require("devtools/shared/layout/utils");
+
// SimpleOutlineHighlighter's stylesheet
const HIGHLIGHTED_PSEUDO_CLASS = ":-moz-devtools-highlighted";
-const SIMPLE_OUTLINE_SHEET = `.__fx-devtools-hide-shortcut__ {
- visibility: hidden !important
- }
- ${HIGHLIGHTED_PSEUDO_CLASS} {
- outline: 2px dashed #F06!important;
- outline-offset: -2px!important
- }`;
+const SIMPLE_OUTLINE_SHEET = `data:text/css;charset=utf-8,
+ __fx-devtools-hide-shortcut__ {
+ visibility: hidden !important
+ }
+ ${HIGHLIGHTED_PSEUDO_CLASS} {
+ outline: 2px dashed #F06!important;
+ outline-offset: -2px!important
+ }`;
/**
* The SimpleOutlineHighlighter is a class that has the same API than the
* BoxModelHighlighter, but adds a pseudo-class on the target element itself
* to draw a simple css outline around the element.
* It is used by the HighlighterActor when canvasframe-based highlighters can't
* be used. This is the case for XUL windows.
*/
function SimpleOutlineHighlighter(highlighterEnv) {
@@ -43,17 +45,17 @@ SimpleOutlineHighlighter.prototype = {
/**
* Show the highlighter on a given node
* @param {DOMNode} node
*/
show: function (node) {
if (isNodeValid(node) && (!this.currentNode || node !== this.currentNode)) {
this.hide();
this.currentNode = node;
- installHelperSheet(node.ownerGlobal, SIMPLE_OUTLINE_SHEET);
+ loadSheet(node.ownerGlobal, SIMPLE_OUTLINE_SHEET);
addPseudoClassLock(node, HIGHLIGHTED_PSEUDO_CLASS);
}
return true;
},
/**
* Hide the highlighter, the outline and the infobar.
*/
--- a/devtools/server/actors/highlighters/utils/markup.js
+++ b/devtools/server/actors/highlighters/utils/markup.js
@@ -1,17 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Cc, Ci, Cu } = require("chrome");
const { getCurrentZoom, getWindowDimensions, getViewportDimensions,
- getRootBindingParent } = require("devtools/shared/layout/utils");
+ getRootBindingParent, loadSheet } = require("devtools/shared/layout/utils");
const { on, emit } = require("sdk/event/core");
const lazyContainer = {};
loader.lazyRequireGetter(lazyContainer, "CssLogic",
"devtools/server/css-logic", true);
exports.getComputedStyle = (node) =>
lazyContainer.CssLogic.getComputedStyle(node);
@@ -97,33 +97,16 @@ ClassList.prototype = {
* @return {Boolean}
*/
function isXUL(window) {
return window.document.documentElement.namespaceURI === XUL_NS;
}
exports.isXUL = isXUL;
/**
- * Inject a helper stylesheet in the window.
- */
-var installedHelperSheets = new WeakMap();
-
-function installHelperSheet(win, source, type = "agent") {
- if (installedHelperSheets.has(win.document)) {
- return;
- }
- let {Style} = require("sdk/stylesheet/style");
- let {attach} = require("sdk/content/mod");
- let style = Style({source, type});
- attach(style, win);
- installedHelperSheets.set(win.document, style);
-}
-exports.installHelperSheet = installHelperSheet;
-
-/**
* Returns true if a DOM node is "valid", where "valid" means that the node isn't a dead
* object wrapper, is still attached to a document, and is of a given type.
* @param {DOMNode} node
* @param {Number} nodeType Optional, defaults to ELEMENT_NODE
* @return {Boolean}
*/
function isNodeValid(node, nodeType = Ci.nsIDOMNode.ELEMENT_NODE) {
// Is it still alive?
@@ -273,25 +256,17 @@ CanvasFrameAnonymousContentHelper.protot
if (isXUL(this.highlighterEnv.window)) {
return;
}
// For now highlighters.css is injected in content as a ua sheet because
// <style scoped> doesn't work inside anonymous content (see bug 1086532).
// If it did, highlighters.css would be injected as an anonymous content
// node using CanvasFrameAnonymousContentHelper instead.
- if (!installedHelperSheets.has(doc)) {
- installedHelperSheets.set(doc, true);
- let source = "@import url('" + STYLESHEET_URI + "');";
- let url = "data:text/css;charset=utf-8," + encodeURIComponent(source);
- let winUtils = this.highlighterEnv.window
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
- winUtils.loadSheetUsingURIString(url, winUtils.AGENT_SHEET);
- }
+ loadSheet(this.highlighterEnv.window, STYLESHEET_URI);
let 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
// that scenario, fixes when we're adding anonymous content in a tab that
// is not the active one (see bug 1260043 and bug 1260044)
--- a/devtools/server/actors/inspector.js
+++ b/devtools/server/actors/inspector.js
@@ -67,17 +67,18 @@ const {
HighlighterEnvironment
} = require("devtools/server/actors/highlighters");
const {EyeDropper} = require("devtools/server/actors/highlighters/eye-dropper");
const {
isAnonymous,
isNativeAnonymous,
isXBLAnonymous,
isShadowAnonymous,
- getFrameElement
+ getFrameElement,
+ loadSheet
} = require("devtools/shared/layout/utils");
const {getLayoutChangesObserver, releaseLayoutChangesObserver} = require("devtools/server/actors/reflow");
const nodeFilterConstants = require("devtools/shared/dom-node-filter-constants");
const {colorUtils} = require("devtools/shared/css/color");
const {EventParsers} = require("devtools/server/event-parsers");
const {nodeSpec, nodeListSpec, walkerSpec, inspectorSpec} = require("devtools/shared/specs/inspector");
@@ -122,17 +123,17 @@ const PSEUDO_SELECTORS = [
[":empty", 0],
[":target", 0],
[":enabled", 0],
[":disabled", 0],
[":checked", 1],
["::selection", 0]
];
-var HELPER_SHEET = `
+var HELPER_SHEET = `data:text/css;charset=utf-8,
.__fx-devtools-hide-shortcut__ {
visibility: hidden !important;
}
:-moz-devtools-highlighted {
outline: 2px dashed #F06!important;
outline-offset: -2px !important;
}
@@ -1858,36 +1859,22 @@ var WalkerActor = protocol.ActorClassWit
return false;
}
DOMUtils.addPseudoClassLock(node.rawNode, pseudo, enabled);
this._activePseudoClassLocks.add(node);
this._queuePseudoClassMutation(node);
return true;
},
- _installHelperSheet: function (node) {
- if (!this.installedHelpers) {
- this.installedHelpers = new WeakMap();
- }
- let win = node.rawNode.ownerGlobal;
- if (!this.installedHelpers.has(win)) {
- let { Style } = require("sdk/stylesheet/style");
- let { attach } = require("sdk/content/mod");
- let style = Style({source: HELPER_SHEET, type: "agent" });
- attach(style, win);
- this.installedHelpers.set(win, style);
- }
- },
-
hideNode: function (node) {
if (isNodeDead(node)) {
return;
}
- this._installHelperSheet(node);
+ loadSheet(node.rawNode.ownerGlobal, HELPER_SHEET);
node.rawNode.classList.add(HIDDEN_CLASS);
},
unhideNode: function (node) {
if (isNodeDead(node)) {
return;
}
--- a/devtools/server/actors/stylesheets.js
+++ b/devtools/server/actors/stylesheets.js
@@ -12,17 +12,17 @@ const {Task} = require("devtools/shared/
const events = require("sdk/event/core");
const protocol = require("devtools/shared/protocol");
const {LongStringActor} = require("devtools/server/actors/string");
const {fetch} = require("devtools/shared/DevToolsUtils");
const {listenOnce} = require("devtools/shared/async-utils");
const {originalSourceSpec, mediaRuleSpec, styleSheetSpec,
styleSheetsSpec} = require("devtools/shared/specs/stylesheets");
const {SourceMapConsumer} = require("source-map");
-const { installHelperSheet,
+const {
addPseudoClassLock, removePseudoClassLock } = require("devtools/server/actors/highlighters/utils/markup");
loader.lazyGetter(this, "CssLogic", () => require("devtools/shared/inspector/css-logic"));
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
});
--- a/devtools/shared/layout/utils.js
+++ b/devtools/shared/layout/utils.js
@@ -2,16 +2,22 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Ci, Cc } = require("chrome");
const nodeFilterConstants = require("devtools/shared/dom-node-filter-constants");
+const SHEET_TYPE = {
+ "agent": "AGENT_SHEET",
+ "user": "USER_SHEET",
+ "author": "AUTHOR_SHEET"
+};
+
loader.lazyRequireGetter(this, "setIgnoreLayoutChanges", "devtools/server/actors/reflow", true);
exports.setIgnoreLayoutChanges = (...args) =>
this.setIgnoreLayoutChanges(...args);
/**
* Returns the `DOMWindowUtils` for the window given.
*
* @param {DOMWindow} win
@@ -710,8 +716,54 @@ function getWindowFor(node) {
return node.defaultView;
}
return node.ownerDocument.defaultView;
} else if (node instanceof Ci.nsIDOMWindow) {
return node;
}
return null;
}
+
+/**
+ * Synchronously loads a style sheet from `uri` and adds it to the list of
+ * additional style sheets of the document.
+ * The sheets added takes effect immediately, and only on the document of the
+ * `window` given.
+ *
+ * @param {DOMWindow} window
+ * @param {String} url
+ * @param {String} [type="agent"]
+ */
+function loadSheet(window, url, type = "agent") {
+ if (!(type in SHEET_TYPE)) {
+ type = "agent";
+ }
+
+ let windowUtils = utilsFor(window);
+ try {
+ windowUtils.loadSheetUsingURIString(url, windowUtils[SHEET_TYPE[type]]);
+ } catch (e) {
+ // The method fails if the url is already loaded.
+ }
+}
+exports.loadSheet = loadSheet;
+
+/**
+ * Remove the document style sheet at `sheetURI` from the list of additional
+ * style sheets of the document. The removal takes effect immediately.
+ *
+ * @param {DOMWindow} window
+ * @param {String} url
+ * @param {String} [type="agent"]
+ */
+function removeSheet(window, url, type = "agent") {
+ if (!(type in SHEET_TYPE)) {
+ type = "agent";
+ }
+
+ let windowUtils = utilsFor(window);
+ try {
+ windowUtils.removeSheetUsingURIString(url, windowUtils[SHEET_TYPE[type]]);
+ } catch (e) {
+ // The method fails if the url is already removed.
+ }
+}
+exports.removeSheet = removeSheet;