Bug 1445197 - part 3: Move about:debugging worker module to a shared module;r=ochameau

Extract all the logic that will be shared between about debugging and the application
panel to a dedicated client module.

MozReview-Commit-ID: Ccnmp3dCZpW

--HG--
extra : rebase_source : ce2f5ec4e0af884a99a91ab4bfc1048f893416a8
This commit is contained in:
Julian Descottes 2018-04-05 21:45:15 +02:00
Родитель fabe2dcb6f
Коммит 488d086724
7 изменённых файлов: 164 добавлений и 144 удалений

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

@ -11,7 +11,6 @@ const { Ci } = require("chrome");
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { getWorkerForms } = require("../../modules/worker");
const Services = require("Services");
const PanelHeader = createFactory(require("../PanelHeader"));
@ -48,7 +47,6 @@ class WorkersPanel extends Component {
this.updateMultiE10S = this.updateMultiE10S.bind(this);
this.updateWorkers = this.updateWorkers.bind(this);
this.getRegistrationForWorker = this.getRegistrationForWorker.bind(this);
this.isE10S = this.isE10S.bind(this);
this.renderServiceWorkersError = this.renderServiceWorkersError.bind(this);
@ -110,74 +108,31 @@ class WorkersPanel extends Component {
this.setState({ processCount });
}
updateWorkers() {
async updateWorkers() {
let workers = this.initialState.workers;
getWorkerForms(this.props.client).then(forms => {
forms.registrations.forEach(form => {
workers.service.push({
icon: WorkerIcon,
name: form.url,
url: form.url,
scope: form.scope,
fetch: form.fetch,
registrationActor: form.actor,
active: form.active
});
});
let forms = await this.props.client.mainRoot.listAllWorkers();
forms.workers.forEach(form => {
let worker = {
icon: WorkerIcon,
name: form.url,
url: form.url,
workerActor: form.actor
};
switch (form.type) {
case Ci.nsIWorkerDebugger.TYPE_SERVICE:
let registration = this.getRegistrationForWorker(form, workers.service);
if (registration) {
// XXX: Race, sometimes a ServiceWorkerRegistrationInfo doesn't
// have a scriptSpec, but its associated WorkerDebugger does.
if (!registration.url) {
registration.name = registration.url = form.url;
}
registration.workerActor = form.actor;
} else {
worker.fetch = form.fetch;
workers.service = forms.serviceWorkers
.map(form => Object.assign({ icon: WorkerIcon, name: form.url }, form));
// If a service worker registration could not be found, this means we are in
// e10s, and registrations are not forwarded to other processes until they
// reach the activated state. Augment the worker as a registration worker to
// display it in aboutdebugging.
worker.scope = form.scope;
worker.active = false;
workers.service.push(worker);
}
break;
case Ci.nsIWorkerDebugger.TYPE_SHARED:
workers.shared.push(worker);
break;
default:
workers.other.push(worker);
}
});
// Lookup shared and regular workers in forms.workers.
forms.workers.forEach(form => {
let worker = {
icon: WorkerIcon,
name: form.url,
url: form.url,
workerActor: form.actor
};
// XXX: Filter out the service worker registrations for which we couldn't
// find the scriptSpec.
workers.service = workers.service.filter(reg => !!reg.url);
this.setState({ workers });
});
}
getRegistrationForWorker(form, registrations) {
for (let registration of registrations) {
if (registration.scope === form.scope) {
return registration;
if (form.type === Ci.nsIWorkerDebugger.TYPE_DEDICATED) {
workers.other.push(worker);
} else if (form.type === Ci.nsIWorkerDebugger.TYPE_SHARED) {
workers.shared.push(worker);
}
}
return null;
});
this.setState({ workers });
}
isE10S() {

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

@ -9,11 +9,12 @@
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { debugWorker } = require("../../modules/worker");
const Services = require("Services");
loader.lazyRequireGetter(this, "DebuggerClient",
"devtools/shared/client/debugger-client", true);
loader.lazyRequireGetter(this, "gDevToolsBrowser",
"devtools/client/framework/devtools-browser", true);
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
@ -85,7 +86,7 @@ class ServiceWorkerTarget extends Component {
}
let { client, target } = this.props;
debugWorker(client, target.workerActor);
gDevToolsBrowser.openWorkerToolbox(client, target.workerActor);
}
push() {

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

@ -9,11 +9,12 @@
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { debugWorker } = require("../../modules/worker");
const Services = require("Services");
loader.lazyRequireGetter(this, "DebuggerClient",
"devtools/shared/client/debugger-client", true);
loader.lazyRequireGetter(this, "gDevToolsBrowser",
"devtools/client/framework/devtools-browser", true);
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
@ -38,7 +39,7 @@ class WorkerTarget extends Component {
debug() {
let { client, target } = this.props;
debugWorker(client, target.workerActor);
gDevToolsBrowser.openWorkerToolbox(client, target.workerActor);
}
render() {

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

@ -5,5 +5,4 @@
DevToolsModules(
'addon.js',
'connect.js',
'worker.js',
)

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

@ -1,75 +0,0 @@
/* 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";
loader.lazyRequireGetter(this, "gDevTools",
"devtools/client/framework/devtools", true);
loader.lazyRequireGetter(this, "TargetFactory",
"devtools/client/framework/target", true);
loader.lazyRequireGetter(this, "Toolbox",
"devtools/client/framework/toolbox", true);
/**
* Open a window-hosted toolbox to debug the worker associated to the provided
* worker actor.
*
* @param {DebuggerClient} client
* @param {Object} workerActor
* worker actor form to debug
*/
exports.debugWorker = function(client, workerActor) {
client.attachWorker(workerActor, (response, workerClient) => {
let workerTarget = TargetFactory.forWorker(workerClient);
gDevTools.showToolbox(workerTarget, "jsdebugger", Toolbox.HostType.WINDOW)
.then(toolbox => {
toolbox.once("destroy", () => workerClient.detach());
});
});
};
/**
* Retrieve all service worker registrations as well as workers from the parent
* and child processes.
*
* @param {DebuggerClient} client
* @return {Object}
* - {Array} registrations
* Array of ServiceWorkerRegistrationActor forms
* - {Array} workers
* Array of WorkerActor forms
*/
exports.getWorkerForms = async function(client) {
let registrations = [];
let workers = [];
try {
// List service worker registrations
({ registrations } =
await client.mainRoot.listServiceWorkerRegistrations());
// List workers from the Parent process
({ workers } = await client.mainRoot.listWorkers());
// And then from the Child processes
let { processes } = await client.mainRoot.listProcesses();
for (let process of processes) {
// Ignore parent process
if (process.parent) {
continue;
}
let { form } = await client.getProcess(process.id);
let processActor = form.actor;
let response = await client.request({
to: processActor,
type: "listWorkers"
});
workers = workers.concat(response.workers);
}
} catch (e) {
// Something went wrong, maybe our client is disconnected?
}
return { registrations, workers };
};

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

@ -388,6 +388,24 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
return Promise.reject(msg);
},
/**
* Open a window-hosted toolbox to debug the worker associated to the provided
* worker actor.
*
* @param {DebuggerClient} client
* @param {Object} workerActor
* worker actor form to debug
*/
openWorkerToolbox(client, workerActor) {
client.attachWorker(workerActor, (response, workerClient) => {
let workerTarget = TargetFactory.forWorker(workerClient);
gDevTools.showToolbox(workerTarget, null, Toolbox.HostType.WINDOW)
.then(toolbox => {
toolbox.once("destroy", () => workerClient.detach());
});
});
},
/**
* Install WebIDE widget
*/

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

@ -7,6 +7,8 @@
const { Ci } = require("chrome");
const { arg, DebuggerClient } = require("devtools/shared/client/debugger-client");
const TYPE_SERVICE = Ci.nsIWorkerDebugger.TYPE_SERVICE;
/**
* A RootClient object represents a root actor on the server. Each
* DebuggerClient keeps a RootClient instance representing the root actor
@ -159,6 +161,125 @@ RootClient.prototype = {
return this.request(packet);
},
/**
* Retrieve the service worker registrations currently available for the this client.
*
* @param {Form} forms
* All available worker forms
* @return {Array} array of form-like objects dedicated to service workers:
* - {String} url: url of the worker
* - {String} scope: scope controlled by this worker
* - {String} fetch: fetch url if available
* - {Boolean} active: is the service worker active
* - {String} registrationActor: id of the registration actor, needed to start,
* unregister and get push information for the registation. Available on
* active service workers only in e10s.
* - {String} workerActor: id of the worker actor, needed to debug and send push
* notifications.
*/
_mergeServiceWorkerForms: async function(workers) {
// List service worker registrations
let { registrations } = await this.listServiceWorkerRegistrations();
// registrations contain only service worker registrations, add each registration
// to the workers array.
let fromRegistrations = registrations.map(form => {
return {
url: form.url,
scope: form.scope,
fetch: form.fetch,
active: form.active,
registrationActor: form.actor,
};
});
// Loop on workers to retrieve the worker actor corresponding to the current
// instance of the service worker if available.
let fromWorkers = [];
workers
.filter(form => form.type === TYPE_SERVICE)
.forEach(form => {
let registration = fromRegistrations.find(w => w.scope === form.scope);
if (registration) {
if (!registration.url) {
// XXX: Race, sometimes a ServiceWorkerRegistrationInfo doesn't
// have a scriptSpec, but its associated WorkerDebugger does.
registration.url = form.url;
}
// Add the worker actor as "workerActor" on the registration.
registration.workerActor = form.actor;
} else {
// If a service worker registration could not be found, this means we are in
// e10s, and registrations are not forwarded to other processes until they
// reach the activated state.
fromWorkers.push({
url: form.url,
scope: form.scope,
fetch: form.fetch,
// Infer active=false since the service worker is not supposed to be
// registered yet in this edge case.
active: false,
workerActor: form.actor,
});
}
});
// Concatenate service workers found in forms.registrations and forms.workers.
let combined = [...fromRegistrations, ...fromWorkers];
// Filter out service workers missing a url.
return combined.filter(form => !!form.url);
},
/**
* Retrieve all service worker registrations as well as workers from the parent
* and child processes. Listing service workers involves merging information coming from
* registrations and workers, this method will combine this information to present a
* unified array of serviceWorkers. If you are only interested in other workers, use
* listWorkers.
*
* @return {Object}
* - {Array} serviceWorkers
* array of form-like objects for serviceworkers (cf _mergeServiceWorkerForms)
* - {Array} workers
* Array of WorkerActor forms, containing all possible workers.
*/
listAllWorkers: async function() {
let workers = [];
try {
// List workers from the Parent process
({ workers } = await this.listWorkers());
// And then from the Child processes
let { processes } = await this.listProcesses();
for (let process of processes) {
// Ignore parent process
if (process.parent) {
continue;
}
let { form } = await this._client.getProcess(process.id);
let processActor = form.actor;
let response = await this._client.request({
to: processActor,
type: "listWorkers"
});
workers = workers.concat(response.workers);
}
} catch (e) {
console.warn("Error while listing all workers, is the client disconnected?", e);
}
// Combine information from registrations and workers to create a usable list of
// workers for consumer code.
let serviceWorkers = await this._mergeServiceWorkerForms(workers);
return {
serviceWorkers,
workers
};
},
/**
* Description of protocol's actors and methods.
*