Bug 1631358 - remove traces of CPOWs from devtools, r=jdescottes,loganfsmyth

Differential Revision: https://phabricator.services.mozilla.com/D71509
This commit is contained in:
Gijs Kruitbosch 2020-04-21 14:04:58 +00:00
Родитель 0c15aaa999
Коммит 11836f7641
15 изменённых файлов: 13 добавлений и 218 удалений

Просмотреть файл

@ -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|.
*/