зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1631358 - remove traces of CPOWs from devtools, r=jdescottes,loganfsmyth
Differential Revision: https://phabricator.services.mozilla.com/D71509
This commit is contained in:
Родитель
0c15aaa999
Коммит
11836f7641
|
@ -85,7 +85,7 @@ function toggleServiceWorkersTestingCheckbox() {
|
|||
function reload() {
|
||||
const promise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
|
||||
executeInContent("devtools:test:reload", {}, {}, false);
|
||||
executeInContent("devtools:test:reload", {}, false);
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,22 +76,16 @@ function waitForContentMessage(name) {
|
|||
* @param {String} name The message name. Should be one of the messages defined
|
||||
* in doc_frame_script.js
|
||||
* @param {Object} data Optional data to send along
|
||||
* @param {Object} objects Optional CPOW objects to send along
|
||||
* @param {Boolean} expectResponse If set to false, don't wait for a response
|
||||
* with the same name from the content script. Defaults to true.
|
||||
* @return {Promise} Resolves to the response data if a response is expected,
|
||||
* immediately resolves otherwise
|
||||
*/
|
||||
function executeInContent(
|
||||
name,
|
||||
data = {},
|
||||
objects = {},
|
||||
expectResponse = true
|
||||
) {
|
||||
function executeInContent(name, data = {}, expectResponse = true) {
|
||||
info("Sending message " + name + " to content");
|
||||
const mm = gBrowser.selectedBrowser.messageManager;
|
||||
|
||||
mm.sendAsyncMessage(name, data, objects);
|
||||
mm.sendAsyncMessage(name, data);
|
||||
if (expectResponse) {
|
||||
return waitForContentMessage(name);
|
||||
}
|
||||
|
|
|
@ -314,24 +314,17 @@ function waitForContentMessage(name) {
|
|||
* in doc_frame_script.js
|
||||
* @param {Object} data
|
||||
* Optional data to send along
|
||||
* @param {Object} objects
|
||||
* Optional CPOW objects to send along
|
||||
* @param {Boolean} expectResponse
|
||||
* If set to false, don't wait for a response with the same name
|
||||
* from the content script. Defaults to true.
|
||||
* @return {Promise} Resolves to the response data if a response is expected,
|
||||
* immediately resolves otherwise
|
||||
*/
|
||||
function executeInContent(
|
||||
name,
|
||||
data = {},
|
||||
objects = {},
|
||||
expectResponse = true
|
||||
) {
|
||||
function executeInContent(name, data = {}, expectResponse = true) {
|
||||
info("Sending message " + name + " to content");
|
||||
const mm = gBrowser.selectedBrowser.messageManager;
|
||||
|
||||
mm.sendAsyncMessage(name, data, objects);
|
||||
mm.sendAsyncMessage(name, data);
|
||||
if (expectResponse) {
|
||||
return waitForContentMessage(name);
|
||||
}
|
||||
|
|
|
@ -862,8 +862,6 @@ function performRequestsInContent(requests) {
|
|||
* shared/test/frame-script-utils.js
|
||||
* @param Object data
|
||||
* Optional data to send along
|
||||
* @param Object objects
|
||||
* Optional CPOW objects to send along
|
||||
* @param Boolean expectResponse
|
||||
* If set to false, don't wait for a response with the same name from the
|
||||
* content script. Defaults to true.
|
||||
|
@ -872,15 +870,10 @@ function performRequestsInContent(requests) {
|
|||
* Resolves to the response data if a response is expected, immediately
|
||||
* resolves otherwise
|
||||
*/
|
||||
function executeInContent(
|
||||
name,
|
||||
data = {},
|
||||
objects = {},
|
||||
expectResponse = true
|
||||
) {
|
||||
function executeInContent(name, data = {}, expectResponse = true) {
|
||||
const mm = gBrowser.selectedBrowser.messageManager;
|
||||
|
||||
mm.sendAsyncMessage(name, data, objects);
|
||||
mm.sendAsyncMessage(name, data);
|
||||
if (expectResponse) {
|
||||
return waitForContentMessage(name);
|
||||
}
|
||||
|
|
|
@ -678,9 +678,9 @@ MessageManagerTunnel.prototype = {
|
|||
|
||||
debug(`${name} inner -> outer, sync: ${sync}`);
|
||||
if (sync) {
|
||||
return this.outerChildMM.sendSyncMessage(name, data, objects, principal);
|
||||
return this.outerChildMM.sendSyncMessage(name, data);
|
||||
}
|
||||
this.outerChildMM.sendAsyncMessage(name, data, objects, principal);
|
||||
this.outerChildMM.sendAsyncMessage(name, data);
|
||||
return undefined;
|
||||
},
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ support-files =
|
|||
|
||||
[browser_console.js]
|
||||
[browser_console_chrome_context_message.js]
|
||||
[browser_console_cpow.js]
|
||||
skip-if = !e10s # This test is only valid in e10s
|
||||
[browser_console_clear_cache.js]
|
||||
[browser_console_clear_closed_tab.js]
|
||||
[browser_console_clear_method.js]
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test the basic features of the Browser Console.
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
gDevToolsBrowser,
|
||||
} = require("devtools/client/framework/devtools-browser");
|
||||
|
||||
add_task(async function() {
|
||||
// Needed for the execute() function below
|
||||
await pushPref("security.allow_parent_unrestricted_js_loads", true);
|
||||
|
||||
await addTab("about:blank");
|
||||
|
||||
const hud = await BrowserConsoleManager.openBrowserConsoleOrFocus();
|
||||
|
||||
const { message, objectFront } = await obtainObjectWithCPOW(hud);
|
||||
await testFrontEnd(message);
|
||||
await testBackEnd(objectFront);
|
||||
await clearOutput(hud, true);
|
||||
});
|
||||
|
||||
async function obtainObjectWithCPOW(hud) {
|
||||
info("Add a message listener, it will receive an object with a CPOW");
|
||||
await hud.evaluateJSAsync(`
|
||||
Services.ppmm.addMessageListener("cpow", function listener(message) {
|
||||
Services.ppmm.removeMessageListener("cpow", listener);
|
||||
console.log(message.objects);
|
||||
globalThis.result = message.objects;
|
||||
});
|
||||
`);
|
||||
|
||||
info("Open the browser content toolbox and send a message");
|
||||
const toolbox = await gDevToolsBrowser.openContentProcessToolbox(gBrowser);
|
||||
const webConsoleFront = await toolbox.target.getFront("console");
|
||||
await webConsoleFront.evaluateJSAsync(`
|
||||
let {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
Services.cpmm.sendAsyncMessage("cpow", null, {cpow: {a:1}});
|
||||
`);
|
||||
|
||||
info("Obtain the object with CPOW");
|
||||
const message = await waitFor(() => findMessage(hud, "cpow"));
|
||||
const result = await hud.evaluateJSAsync("result");
|
||||
const objectFront = result.result;
|
||||
|
||||
info("Cleanup");
|
||||
await hud.evaluateJSAsync("delete globalThis.result;");
|
||||
const onToolboxDestroyed = toolbox.once("destroyed");
|
||||
toolbox.topWindow.close();
|
||||
await onToolboxDestroyed;
|
||||
|
||||
return { message, objectFront };
|
||||
}
|
||||
|
||||
async function testFrontEnd(message) {
|
||||
const oi = message.querySelector(".tree");
|
||||
const node = oi.querySelector(".tree-node");
|
||||
is(node.textContent, "Object { cpow: CPOW }", "Got an object with a CPOW");
|
||||
|
||||
expandObjectInspectorNode(node);
|
||||
await waitFor(() => getObjectInspectorChildrenNodes(node).length > 0);
|
||||
|
||||
const cpow = findObjectInspectorNodeChild(node, "cpow");
|
||||
const cpowObject = cpow.querySelector(".objectBox-object");
|
||||
is(cpowObject.textContent, "CPOW { }", "Got the CPOW");
|
||||
|
||||
expandObjectInspectorNode(cpow);
|
||||
is(getObjectInspectorChildrenNodes(cpow).length, 0, "CPOW has no children");
|
||||
}
|
||||
|
||||
async function testBackEnd(objectFront) {
|
||||
// Check that inspecting an object with CPOW doesn't throw in the server.
|
||||
// This would be done in a mochitest-chrome suite, but that doesn't run in
|
||||
// e10s, so it's harder to get ahold of a CPOW.
|
||||
|
||||
// Before the fix for Bug 1382833, this wouldn't resolve due to a CPOW error
|
||||
// in the ObjectActor.
|
||||
const prototypeAndProperties = await objectFront.getPrototypeAndProperties();
|
||||
|
||||
// The CPOW is in the "cpow" property.
|
||||
const cpowFront = prototypeAndProperties.ownProperties.cpow.value;
|
||||
|
||||
is(cpowFront.getGrip().class, "CPOW", "The CPOW grip has the right class.");
|
||||
|
||||
// Check that various protocol request methods work for the CPOW.
|
||||
let response = await cpowFront.getPrototypeAndProperties();
|
||||
is(
|
||||
Reflect.ownKeys(response.ownProperties).length,
|
||||
0,
|
||||
"No property was retrieved."
|
||||
);
|
||||
is(response.ownSymbols.length, 0, "No symbol property was retrieved.");
|
||||
is(response.prototype.type, "null", "The prototype is null.");
|
||||
|
||||
response = await cpowFront.enumProperties({ ignoreIndexedProperties: true });
|
||||
let slice = await response.slice(0, response.count);
|
||||
is(
|
||||
Reflect.ownKeys(slice.ownProperties).length,
|
||||
0,
|
||||
"No property was retrieved."
|
||||
);
|
||||
|
||||
response = await cpowFront.enumProperties({});
|
||||
slice = await response.slice(0, response.count);
|
||||
is(
|
||||
Reflect.ownKeys(slice.ownProperties).length,
|
||||
0,
|
||||
"No property was retrieved."
|
||||
);
|
||||
|
||||
response = await cpowFront.getOwnPropertyNames();
|
||||
is(response.ownPropertyNames.length, 0, "No property was retrieved.");
|
||||
|
||||
response = await cpowFront.getProperty("x");
|
||||
is(response.descriptor, undefined, "The property does not exist.");
|
||||
|
||||
response = await cpowFront.enumSymbols();
|
||||
slice = await response.slice(0, response.count);
|
||||
is(slice.ownSymbols.length, 0, "No symbol property was retrieved.");
|
||||
|
||||
response = await cpowFront.getPrototype();
|
||||
is(response.prototype.type, "null", "The prototype is null.");
|
||||
|
||||
response = await cpowFront.getDisplayString();
|
||||
is(response.displayString, "<cpow>", "The CPOW stringifies to <cpow>");
|
||||
}
|
||||
|
||||
function findObjectInspectorNodeChild(node, nodeLabel) {
|
||||
return getObjectInspectorChildrenNodes(node).find(child => {
|
||||
const label = child.querySelector(".object-label");
|
||||
return label && label.textContent === nodeLabel;
|
||||
});
|
||||
}
|
|
@ -40,7 +40,7 @@ It can also be useful for patch authors: if the changes comply with these guidel
|
|||
* Test changes:
|
||||
* The feature or bug is [tested by new tests, or a modification of existing tests](../tests/writing-tests.md).
|
||||
* [Test logging](../tests/writing-tests.md#logs-and-comments) is sufficient to help investigating test failures/timeouts.
|
||||
* [Test is e10s compliant](../tests/writing-tests.md#e10s-electrolysis) (no CPOWs, no content, etc…).
|
||||
* [Test is e10s compliant](../tests/writing-tests.md#e10s-electrolysis) (doesn't try to access web content from the parent process, etc…).
|
||||
* Tests are [clean and maintainable](../tests/writing-tests.md#writing-clean-maintainable-test-code).
|
||||
* A try push has started (or even better, is green already).
|
||||
* User facing changes:
|
||||
|
|
|
@ -120,10 +120,6 @@ You can learn more about E10S [from this blog post](https://timtaubert.de/blog/2
|
|||
|
||||
One of the direct consequences of E10S on tests is that you cannot retrieve and manipulate objects from the content page as you'd do without E10S.
|
||||
|
||||
Well this isn't entirely true, because with [cross-process object wrappers](https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Cross_Process_Object_Wrappers CPOWs) you can somehow access the page, get to DOM nodes, and read their attributes for instance, but a lot of other things you'd expect to work without E10S won't work exactly the same or at all.
|
||||
|
||||
Using CPOWs is discouraged; they are only temporarily allowed in mochitests, and their use is forbidden in browser code.
|
||||
|
||||
So when creating a new test, if this test needs to access the content page in any way, you can use [the message manager](https://developer.mozilla.org/en-US/docs/The_message_manager) to communicate with a script loaded in the content process to do things for you instead of accessing objects in the page directly.
|
||||
|
||||
You can use the helper `ContentTask.spawn()` for this. See [this list of DevTools tests that use that helper for examples](https://dxr.mozilla.org/mozilla-central/search?q=ContentTask.spawn%28+path%3Adevtools%2Fclient&redirect=false&case=false).
|
||||
|
|
|
@ -135,13 +135,6 @@ const proto = {
|
|||
actor: this.actorID,
|
||||
};
|
||||
|
||||
// Unsafe objects must be treated carefully.
|
||||
if (DevToolsUtils.isCPOW(this.obj)) {
|
||||
// Cross-process object wrappers can't be accessed.
|
||||
g.class = "CPOW";
|
||||
return g;
|
||||
}
|
||||
|
||||
const unwrapped = DevToolsUtils.unwrap(this.obj);
|
||||
if (unwrapped === undefined) {
|
||||
// Objects belonging to an invisible-to-debugger compartment might be proxies,
|
||||
|
|
|
@ -22,9 +22,6 @@ loader.lazyRequireGetter(
|
|||
*/
|
||||
function stringify(obj) {
|
||||
if (!DevToolsUtils.isSafeDebuggerObject(obj)) {
|
||||
if (DevToolsUtils.isCPOW(obj)) {
|
||||
return "<cpow>";
|
||||
}
|
||||
const unwrapped = DevToolsUtils.unwrap(obj);
|
||||
if (unwrapped === undefined) {
|
||||
return "<invisibleToDebugger>";
|
||||
|
|
|
@ -37,8 +37,7 @@ waitForExplicitFinish();
|
|||
* @param {String} url The url to be loaded in the new tab
|
||||
* @return a promise that resolves to the new browser that the document
|
||||
* is loaded in. Note that we cannot return the document
|
||||
* directly, since this would be a CPOW in the e10s case,
|
||||
* and Promises cannot be resolved with CPOWs (see bug 1233497).
|
||||
* directly, as we aren't able to access that in the parent.
|
||||
*/
|
||||
var addTab = async function(url) {
|
||||
info(`Adding a new tab with URL: ${url}`);
|
||||
|
|
|
@ -56,9 +56,6 @@ const defaults = {
|
|||
afterTest: "true == true",
|
||||
};
|
||||
|
||||
// Obtaining a CPOW here does not seem possible, so the CPOW test is in
|
||||
// devtools/client/webconsole/test/browser/browser_console.js
|
||||
|
||||
// The following tests use a system principal debuggee.
|
||||
const systemPrincipalTests = [
|
||||
{
|
||||
|
|
|
@ -33,21 +33,6 @@ for (const key of Object.keys(ThreadSafeDevToolsUtils)) {
|
|||
exports[key] = ThreadSafeDevToolsUtils[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for Cu.isCrossProcessWrapper that works with Debugger.Objects.
|
||||
* This will always return false in workers (see the implementation in
|
||||
* ThreadSafeDevToolsUtils.js).
|
||||
*
|
||||
* @param Debugger.Object debuggerObject
|
||||
* @return bool
|
||||
*/
|
||||
exports.isCPOW = function(debuggerObject) {
|
||||
try {
|
||||
return Cu.isCrossProcessWrapper(debuggerObject.unsafeDereference());
|
||||
} catch (e) {}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits for the next tick in the event loop to execute a callback.
|
||||
*/
|
||||
|
@ -182,7 +167,7 @@ exports.getProperty = function(object, key, invokeUnsafeGetters = false) {
|
|||
* objects belong to this case.
|
||||
* - Otherwise, if the debuggee doesn't subsume object's compartment, returns `null`.
|
||||
* - Otherwise, if the object belongs to an invisible-to-debugger compartment,
|
||||
* returns `undefined`. Note CPOW objects belong to this case.
|
||||
* returns `undefined`.
|
||||
* - Otherwise, returns the unwrapped object.
|
||||
*/
|
||||
exports.unwrap = function unwrap(obj) {
|
||||
|
@ -194,7 +179,6 @@ exports.unwrap = function unwrap(obj) {
|
|||
// Attempt to unwrap via `obj.unwrap()`. Note that:
|
||||
// - This will return `null` if the debuggee does not subsume object's compartment.
|
||||
// - This will throw if the object belongs to an invisible-to-debugger compartment.
|
||||
// This case includes CPOWs (see bug 1391449).
|
||||
// - This will return `obj` if there is no wrapper.
|
||||
let unwrapped;
|
||||
try {
|
||||
|
@ -216,18 +200,13 @@ exports.unwrap = function unwrap(obj) {
|
|||
* Checks whether a debuggee object is safe. Unsafe objects may run proxy traps or throw
|
||||
* when using `proto`, `isExtensible`, `isFrozen` or `isSealed`. Note that safe objects
|
||||
* may still throw when calling `getOwnPropertyNames`, `getOwnPropertyDescriptor`, etc.
|
||||
* Also note CPOW objects are considered to be unsafe, and DeadObject objects to be safe.
|
||||
* Also note DeadObject objects are considered safe.
|
||||
*
|
||||
* @param obj Debugger.Object
|
||||
* The debuggee object to be checked.
|
||||
* @return boolean
|
||||
*/
|
||||
exports.isSafeDebuggerObject = function(obj) {
|
||||
// CPOW usage is forbidden outside tests (bug 1465911)
|
||||
if (exports.isCPOW(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const unwrapped = exports.unwrap(obj);
|
||||
|
||||
// Objects belonging to an invisible-to-debugger compartment might be proxies,
|
||||
|
|
|
@ -69,14 +69,6 @@ exports.values = function values(object) {
|
|||
return Object.keys(object).map(k => object[k]);
|
||||
};
|
||||
|
||||
/**
|
||||
* This is overridden in DevToolsUtils for the main thread, where we have the
|
||||
* Cu object available.
|
||||
*/
|
||||
exports.isCPOW = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Report that |who| threw an exception, |exception|.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче