зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1164077 - Implement WorkerActor.attach;r=jlong
This commit is contained in:
Родитель
ec4d34ba60
Коммит
3479bf68cf
|
@ -43,6 +43,8 @@ support-files =
|
|||
code_ugly-7.js
|
||||
code_ugly-8
|
||||
code_ugly-8^headers^
|
||||
code_WorkerActor.attach-worker1.js
|
||||
code_WorkerActor.attach-worker2.js
|
||||
doc_auto-pretty-print-01.html
|
||||
doc_auto-pretty-print-02.html
|
||||
doc_binary_search.html
|
||||
|
@ -103,6 +105,8 @@ support-files =
|
|||
doc_watch-expressions.html
|
||||
doc_watch-expression-button.html
|
||||
doc_with-frame.html
|
||||
doc_WorkerActor.attach-tab1.html
|
||||
doc_WorkerActor.attach-tab2.html
|
||||
head.js
|
||||
sjs_random-javascript.sjs
|
||||
testactors.js
|
||||
|
@ -556,3 +560,5 @@ skip-if = e10s && debug
|
|||
skip-if = e10s && debug
|
||||
[browser_dbg_watch-expressions-02.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_WorkerActor.attach.js]
|
||||
skip-if = e10s && debug
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
let MAX_TOTAL_VIEWERS = "browser.sessionhistory.max_total_viewers";
|
||||
|
||||
let TAB1_URL = EXAMPLE_URL + "doc_WorkerActor.attach-tab1.html";
|
||||
let TAB2_URL = EXAMPLE_URL + "doc_WorkerActor.attach-tab2.html";
|
||||
let WORKER1_URL = "code_WorkerActor.attach-worker1.js";
|
||||
let WORKER2_URL = "code_WorkerActor.attach-worker2.js";
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
let oldMaxTotalViewers = SpecialPowers.getIntPref(MAX_TOTAL_VIEWERS);
|
||||
SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, 10);
|
||||
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
yield connect(client);
|
||||
|
||||
let tab = yield addTab(TAB1_URL);
|
||||
let { tabs } = yield listTabs(client);
|
||||
let [, tabClient] = yield attachTab(client, findTab(tabs, TAB1_URL));
|
||||
yield listWorkers(tabClient);
|
||||
|
||||
// If a page still has pending network requests, it will not be moved into
|
||||
// the bfcache. Consequently, we cannot use waitForWorkerListChanged here,
|
||||
// because the worker is not guaranteed to have finished loading when it is
|
||||
// registered. Instead, we have to wait for the promise returned by
|
||||
// createWorker in the tab to be resolved.
|
||||
yield createWorkerInTab(tab, WORKER1_URL);
|
||||
|
||||
let { workers } = yield listWorkers(tabClient);
|
||||
let [, workerClient1] = yield attachWorker(tabClient,
|
||||
findWorker(workers, WORKER1_URL));
|
||||
is(workerClient1.isFrozen, false);
|
||||
|
||||
executeSoon(() => {
|
||||
tab.linkedBrowser.loadURI(TAB2_URL);
|
||||
});
|
||||
yield waitForWorkerFreeze(workerClient1);
|
||||
is(workerClient1.isFrozen, true, "worker should be frozen");
|
||||
|
||||
yield createWorkerInTab(tab, WORKER2_URL);
|
||||
({ workers } = yield listWorkers(tabClient));
|
||||
let [, workerClient2] = yield attachWorker(tabClient,
|
||||
findWorker(workers, WORKER2_URL));
|
||||
is(workerClient2.isFrozen, false);
|
||||
|
||||
executeSoon(() => {
|
||||
tab.linkedBrowser.contentWindow.history.back();
|
||||
});
|
||||
yield Promise.all([
|
||||
waitForWorkerFreeze(workerClient2),
|
||||
waitForWorkerThaw(workerClient1)
|
||||
]);
|
||||
|
||||
terminateWorkerInTab(tab, WORKER1_URL);
|
||||
yield waitForWorkerClose(workerClient1);
|
||||
|
||||
yield close(client);
|
||||
SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, oldMaxTotalViewers);
|
||||
finish();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
self.onmessage = function () {};
|
||||
|
||||
postMessage("load");
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
self.onmessage = function () {};
|
||||
|
||||
postMessage("load");
|
|
@ -13,8 +13,14 @@ addMessageListener("test:call", function (message) {
|
|||
dump("Calling function with name " + message.data.name + ".\n");
|
||||
|
||||
let data = message.data;
|
||||
XPCNativeWrapper.unwrap(content)[data.name].apply(undefined, data.args);
|
||||
sendAsyncMessage("test:call");
|
||||
let result = XPCNativeWrapper.unwrap(content)[data.name].apply(undefined, data.args);
|
||||
if (result && result.then) {
|
||||
result.then(() => {
|
||||
sendAsyncMessage("test:call");
|
||||
});
|
||||
} else {
|
||||
sendAsyncMessage("test:call");
|
||||
}
|
||||
});
|
||||
|
||||
addMessageListener("test:click", function (message) {
|
||||
|
@ -28,6 +34,34 @@ addMessageListener("test:click", function (message) {
|
|||
addMessageListener("test:eval", function (message) {
|
||||
dump("Evalling string " + message.data.string + ".\n");
|
||||
|
||||
content.eval(message.data.string);
|
||||
sendAsyncMessage("test:eval");
|
||||
let result = content.eval(message.data.string);
|
||||
if (result.then) {
|
||||
result.then(() => {
|
||||
sendAsyncMessage("test:eval");
|
||||
});
|
||||
} else {
|
||||
sendAsyncMessage("test:eval");
|
||||
}
|
||||
});
|
||||
|
||||
let workers = {}
|
||||
|
||||
addMessageListener("test:createWorker", function (message) {
|
||||
dump("Creating worker with url '" + message.data.url + "'.\n");
|
||||
|
||||
let url = message.data.url;
|
||||
let worker = new content.Worker(message.data.url);
|
||||
worker.addEventListener("message", function listener() {
|
||||
worker.removeEventListener("message", listener);
|
||||
sendAsyncMessage("test:createWorker");
|
||||
});
|
||||
workers[url] = worker;
|
||||
});
|
||||
|
||||
addMessageListener("test:terminateWorker", function (message) {
|
||||
dump("Terminating worker with url '" + message.data.url + "'.\n");
|
||||
|
||||
let url = message.data.url;
|
||||
workers[url].terminate();
|
||||
delete workers[url];
|
||||
});
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
self.onmessage = function () {};
|
||||
|
||||
postMessage("load");
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -984,7 +984,7 @@ function callInTab(tab, name) {
|
|||
name: name,
|
||||
args: Array.prototype.slice.call(arguments, 2)
|
||||
});
|
||||
waitForMessageFromTab(tab, "test:call");
|
||||
return waitForMessageFromTab(tab, "test:call");
|
||||
}
|
||||
|
||||
function evalInTab(tab, string) {
|
||||
|
@ -993,7 +993,7 @@ function evalInTab(tab, string) {
|
|||
sendMessageToTab(tab, "test:eval", {
|
||||
string: string,
|
||||
});
|
||||
waitForMessageFromTab(tab, "test:eval");
|
||||
return waitForMessageFromTab(tab, "test:eval");
|
||||
}
|
||||
|
||||
function sendMouseClickToTab(tab, target) {
|
||||
|
@ -1026,6 +1026,24 @@ function getSourceForm(aSources, aURL) {
|
|||
return item.attachment.source;
|
||||
}
|
||||
|
||||
function createWorkerInTab(tab, url) {
|
||||
info("Creating worker with url '" + url + "' in tab.");
|
||||
|
||||
sendMessageToTab(tab, "test:createWorker", {
|
||||
url: url
|
||||
});
|
||||
return waitForMessageFromTab(tab, "test:createWorker");
|
||||
}
|
||||
|
||||
function terminateWorkerInTab(tab, url) {
|
||||
info("Terminating worker with url '" + url + "' in tab.");
|
||||
|
||||
sendMessageToTab(tab, "test:terminateWorker", {
|
||||
url: url
|
||||
});
|
||||
return waitForMessageFromTab(tab, "test:terminateWorker");
|
||||
}
|
||||
|
||||
function connect(client) {
|
||||
info("Connecting client.");
|
||||
return new Promise(function (resolve) {
|
||||
|
@ -1081,6 +1099,25 @@ function listWorkers(tabClient) {
|
|||
});
|
||||
}
|
||||
|
||||
function findWorker(workers, url) {
|
||||
info("Finding worker with url '" + url + "'.");
|
||||
for (let worker of workers) {
|
||||
if (worker.url === url) {
|
||||
return worker;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function attachWorker(tabClient, worker) {
|
||||
info("Attaching to worker with url '" + worker.url + "'.");
|
||||
return new Promise(function(resolve, reject) {
|
||||
tabClient.attachWorker(worker.actor, function (response, workerClient) {
|
||||
resolve([response, workerClient]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForWorkerListChanged(tabClient) {
|
||||
info("Waiting for worker list to change.");
|
||||
return new Promise(function (resolve) {
|
||||
|
@ -1090,3 +1127,31 @@ function waitForWorkerListChanged(tabClient) {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForWorkerClose(workerClient) {
|
||||
info("Waiting for worker to close.");
|
||||
return new Promise(function (resolve) {
|
||||
workerClient.addOneTimeListener("close", function () {
|
||||
info("Worker did close.");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForWorkerFreeze(workerClient) {
|
||||
info("Waiting for worker to freeze.");
|
||||
return new Promise(function (resolve) {
|
||||
workerClient.addOneTimeListener("freeze", function () {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForWorkerThaw(workerClient) {
|
||||
info("Waiting for worker to thaw.");
|
||||
return new Promise(function (resolve) {
|
||||
workerClient.addOneTimeListener("thaw", function () {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5541,6 +5541,20 @@
|
|||
"n_buckets": "1000",
|
||||
"description": "The time (in milliseconds) that it took a 'detach' request to go round trip."
|
||||
},
|
||||
"DEVTOOLS_DEBUGGER_RDP_LOCAL_WORKERDETACH_MS": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "10000",
|
||||
"n_buckets": "1000",
|
||||
"description": "The time (in milliseconds) that it took a 'detach' request to go round trip."
|
||||
},
|
||||
"DEVTOOLS_DEBUGGER_RDP_REMOTE_WORKERDETACH_MS": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "10000",
|
||||
"n_buckets": "1000",
|
||||
"description": "The time (in milliseconds) that it took a 'detach' request to go round trip."
|
||||
},
|
||||
"DEVTOOLS_DEBUGGER_DISPLAY_SOURCE_LOCAL_MS": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
|
|
|
@ -51,6 +51,7 @@ Object.defineProperty(this, "WebConsoleClient", {
|
|||
});
|
||||
|
||||
Components.utils.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
|
||||
this.executeSoon = DevToolsUtils.executeSoon;
|
||||
this.makeInfallible = DevToolsUtils.makeInfallible;
|
||||
this.values = DevToolsUtils.values;
|
||||
|
||||
|
@ -505,6 +506,29 @@ DebuggerClient.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
attachWorker: function DC_attachWorker(aWorkerActor, aOnResponse = noop) {
|
||||
let workerClient = this._clients.get(aWorkerActor);
|
||||
if (workerClient !== undefined) {
|
||||
executeSoon(() => aOnResponse({
|
||||
from: workerClient.actor,
|
||||
type: "attached",
|
||||
isFrozen: workerClient.isFrozen
|
||||
}, workerClient));
|
||||
return;
|
||||
}
|
||||
|
||||
this.request({ to: aWorkerActor, type: "attach" }, (aResponse) => {
|
||||
if (aResponse.error) {
|
||||
aOnResponse(aResponse, null);
|
||||
return;
|
||||
}
|
||||
|
||||
let workerClient = new WorkerClient(this, aResponse);
|
||||
this.registerClient(workerClient);
|
||||
aOnResponse(aResponse, workerClient);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach to an addon actor.
|
||||
*
|
||||
|
@ -1326,11 +1350,82 @@ TabClient.prototype = {
|
|||
type: "listWorkers"
|
||||
}, {
|
||||
telemetry: "LISTWORKERS"
|
||||
})
|
||||
}),
|
||||
|
||||
attachWorker: function (aWorkerActor, aOnResponse) {
|
||||
this.client.attachWorker(aWorkerActor, aOnResponse);
|
||||
}
|
||||
};
|
||||
|
||||
eventSource(TabClient.prototype);
|
||||
|
||||
function WorkerClient(aClient, aForm) {
|
||||
this._client = aClient;
|
||||
this._actor = aForm.from;
|
||||
this._isClosed = false;
|
||||
this._isFrozen = aForm.isFrozen;
|
||||
|
||||
this._onClose = this._onClose.bind(this);
|
||||
this._onFreeze = this._onFreeze.bind(this);
|
||||
this._onThaw = this._onThaw.bind(this);
|
||||
|
||||
this.addListener("close", this._onClose);
|
||||
this.addListener("freeze", this._onFreeze);
|
||||
this.addListener("thaw", this._onThaw);
|
||||
}
|
||||
|
||||
WorkerClient.prototype = {
|
||||
get _transport() {
|
||||
return this._client._transport;
|
||||
},
|
||||
|
||||
get request() {
|
||||
return this._client.request;
|
||||
},
|
||||
|
||||
get actor() {
|
||||
return this._actor;
|
||||
},
|
||||
|
||||
get isClosed() {
|
||||
return this._isClosed;
|
||||
},
|
||||
|
||||
get isFrozen() {
|
||||
return this._isFrozen;
|
||||
},
|
||||
|
||||
detach: DebuggerClient.requester({ type: "detach" }, {
|
||||
after: function (aResponse) {
|
||||
this._client.unregisterClient(this);
|
||||
return aResponse;
|
||||
},
|
||||
|
||||
telemetry: "WORKERDETACH"
|
||||
}),
|
||||
|
||||
_onClose: function () {
|
||||
this.removeListener("close", this._onClose);
|
||||
this.removeListener("freeze", this._onFreeze);
|
||||
this.removeListener("thaw", this._onThaw);
|
||||
|
||||
this._client.unregisterClient(this);
|
||||
this._closed = true;
|
||||
},
|
||||
|
||||
_onFreeze: function () {
|
||||
this._isFrozen = true;
|
||||
},
|
||||
|
||||
_onThaw: function () {
|
||||
this._isFrozen = false;
|
||||
},
|
||||
|
||||
events: ["close", "freeze", "thaw"]
|
||||
};
|
||||
|
||||
eventSource(WorkerClient.prototype);
|
||||
|
||||
function AddonClient(aClient, aActor) {
|
||||
this._client = aClient;
|
||||
this._actor = aActor;
|
||||
|
|
|
@ -27,6 +27,7 @@ function matchWorkerDebugger(dbg, options) {
|
|||
|
||||
function WorkerActor(dbg) {
|
||||
this._dbg = dbg;
|
||||
this._isAttached = false;
|
||||
}
|
||||
|
||||
WorkerActor.prototype = {
|
||||
|
@ -37,9 +38,61 @@ WorkerActor.prototype = {
|
|||
actor: this.actorID,
|
||||
url: this._dbg.url
|
||||
};
|
||||
},
|
||||
|
||||
onAttach: function () {
|
||||
if (this._dbg.isClosed) {
|
||||
return { error: "closed" };
|
||||
}
|
||||
|
||||
if (!this._isAttached) {
|
||||
this._dbg.addListener(this);
|
||||
this._isAttached = true;
|
||||
}
|
||||
|
||||
return {
|
||||
type: "attached",
|
||||
isFrozen: this._dbg.isFrozen
|
||||
};
|
||||
},
|
||||
|
||||
onDetach: function () {
|
||||
if (!this._isAttached) {
|
||||
return { error: "wrongState" };
|
||||
}
|
||||
|
||||
this._detach();
|
||||
|
||||
return { type: "detached" };
|
||||
},
|
||||
|
||||
onClose: function () {
|
||||
if (this._isAttached) {
|
||||
this._detach();
|
||||
}
|
||||
|
||||
this.conn.sendActorEvent(this.actorID, "close");
|
||||
},
|
||||
|
||||
onFreeze: function () {
|
||||
this.conn.sendActorEvent(this.actorID, "freeze");
|
||||
},
|
||||
|
||||
onThaw: function () {
|
||||
this.conn.sendActorEvent(this.actorID, "thaw");
|
||||
},
|
||||
|
||||
_detach: function () {
|
||||
this._dbg.removeListener(this);
|
||||
this._isAttached = false;
|
||||
}
|
||||
};
|
||||
|
||||
WorkerActor.prototype.requestTypes = {
|
||||
"attach": WorkerActor.prototype.onAttach,
|
||||
"detach": WorkerActor.prototype.onDetach
|
||||
};
|
||||
|
||||
exports.WorkerActor = WorkerActor;
|
||||
|
||||
function WorkerActorList(options) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче