Bug 1365075 - waiting until the document is loaded if CustomContentContainer is not available; r=pbro
MozReview-Commit-ID: Cuv6diP08RT
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -63,16 +63,17 @@ skip-if = os == "mac" # Full keyboard na
[browser_inspector_destroy-after-navigation.js]
[browser_inspector_destroy-before-ready.js]
[browser_inspector_expand-collapse.js]
[browser_inspector_gcli-inspect-command.js]
[browser_inspector_highlighter-01.js]
[browser_inspector_highlighter-02.js]
[browser_inspector_highlighter-03.js]
[browser_inspector_highlighter-04.js]
+[browser_inspector_highlighter-05.js]
[browser_inspector_highlighter-by-type.js]
[browser_inspector_highlighter-cancel.js]
[browser_inspector_highlighter-comments.js]
[browser_inspector_highlighter-cssgrid_01.js]
[browser_inspector_highlighter-cssgrid_02.js]
[browser_inspector_highlighter-csstransform_01.js]
[browser_inspector_highlighter-csstransform_02.js]
[browser_inspector_highlighter-embed.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-05.js
@@ -0,0 +1,69 @@
+/* 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";
+
+// This is testing that the Anonymous Content is properly inserted into the document.
+// Usually that is happening during the "interactive" state of the document, to have them
+// ready as soon as possible.
+// However, in some conditions, that's not possible since we don't have access yet to
+// the `CustomContentContainer`, that is used to add the Anonymous Content.
+// That can happen if the page has some external resource, as <link>, that takes time
+// to load and / or returns the wrong content. This is not happening, for instance, with
+// images.
+//
+// In those case, we want to be sure that if we're not able to insert the Anonymous
+// Content at the "interactive" state, we're doing so when the document is loaded.
+//
+// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1365075
+
+const server = createTestHTTPServer();
+const filepath = "/slow.css";
+const cssuri = `http://localhost:${server.identity.primaryPort}${filepath}`;
+
+// Register a slow css file handler so we can simulate a long loading time.
+server.registerContentType("css", "text/css");
+server.registerPathHandler(filepath, (metadata, response) => {
+ info("CSS has been requested");
+ response.processAsync();
+ setTimeout(() => {
+ info("CSS is responding");
+ response.finish();
+ }, 2000);
+});
+
+const TEST_URL = "data:text/html," + encodeURIComponent(`
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <link href="${cssuri}" rel="stylesheet" />
+ </head>
+ <body>
+ <p>Slow page</p>
+ </body>
+ </html>
+`);
+
+add_task(function* () {
+ info("Open the inspector to a blank page.");
+ let { inspector, tab, testActor } = yield openInspectorForURL("about:blank");
+
+ let pageLoaded = waitForPageLoad(tab);
+
+ info("Navigate to the test url and waiting for the page to be loaded.");
+ yield navigateTo(inspector, TEST_URL);
+ yield pageLoaded;
+
+ info("Shows the box model highligher for the <p> node.");
+ let divFront = yield getNodeFront("p", inspector);
+ yield inspector.highlighter.showBoxModel(divFront);
+
+ info("Check the node is highlighted.");
+ is(yield testActor.isHighlighting(), true,
+ "Box Model highlighter is working as expected.");
+});
+
+const waitForPageLoad = (tab) => new Promise(resolve => {
+ tab.linkedBrowser.addEventListener("load", resolve, {capture: true, once: true});
+});
--- a/devtools/server/actors/highlighters/utils/markup.js
+++ b/devtools/server/actors/highlighters/utils/markup.js
@@ -1,15 +1,15 @@
/* 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 { Cc, Ci, Cu, Cr } = require("chrome");
const { getCurrentZoom, getWindowDimensions, getViewportDimensions,
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);
@@ -265,17 +265,33 @@ CanvasFrameAnonymousContentHelper.protot
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)
- this._content = doc.insertAnonymousContent(node);
+ try {
+ this._content = doc.insertAnonymousContent(node);
+ } catch (e) {
+ // If the `insertAnonymousContent` fails throwing a `NS_ERROR_UNEXPECTED`, it means
+ // we don't have access to a `CustomContentContainer` yet (see bug 1365075).
+ // At this point, it could only happen on document's interactive state, and we
+ // need to wait until the `complete` state before inserting the anonymous content
+ // again.
+ if (e.result === Cr.NS_ERROR_UNEXPECTED && doc.readyState === "interactive") {
+ // The next state change will be "complete" since the current is "interactive"
+ doc.addEventListener("readystatechange", () => {
+ this._content = doc.insertAnonymousContent(node);
+ }, { once: true });
+ } else {
+ throw e;
+ }
+ }
},
_remove() {
try {
let doc = this.anonymousContentDocument;
doc.removeAnonymousContent(this._content);
} catch (e) {
// If the current window isn't the one the content was inserted into, this