diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /devtools/client/aboutdebugging/components/workers | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'devtools/client/aboutdebugging/components/workers')
4 files changed, 490 insertions, 0 deletions
diff --git a/devtools/client/aboutdebugging/components/workers/moz.build b/devtools/client/aboutdebugging/components/workers/moz.build new file mode 100644 index 000000000..ff33a5b28 --- /dev/null +++ b/devtools/client/aboutdebugging/components/workers/moz.build @@ -0,0 +1,9 @@ +# 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/. + +DevToolsModules( + 'panel.js', + 'service-worker-target.js', + 'target.js', +) diff --git a/devtools/client/aboutdebugging/components/workers/panel.js b/devtools/client/aboutdebugging/components/workers/panel.js new file mode 100644 index 000000000..b1bab2b99 --- /dev/null +++ b/devtools/client/aboutdebugging/components/workers/panel.js @@ -0,0 +1,193 @@ +/* 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/. */ +/* globals window */ +"use strict"; + +loader.lazyImporter(this, "PrivateBrowsingUtils", + "resource://gre/modules/PrivateBrowsingUtils.jsm"); + +const { Ci } = require("chrome"); +const { createClass, createFactory, DOM: dom, PropTypes } = + require("devtools/client/shared/vendor/react"); +const { getWorkerForms } = require("../../modules/worker"); +const Services = require("Services"); + +const PanelHeader = createFactory(require("../panel-header")); +const TargetList = createFactory(require("../target-list")); +const WorkerTarget = createFactory(require("./target")); +const ServiceWorkerTarget = createFactory(require("./service-worker-target")); + +loader.lazyImporter(this, "PrivateBrowsingUtils", + "resource://gre/modules/PrivateBrowsingUtils.jsm"); + +loader.lazyRequireGetter(this, "DebuggerClient", + "devtools/shared/client/main", true); + +const Strings = Services.strings.createBundle( + "chrome://devtools/locale/aboutdebugging.properties"); + +const WorkerIcon = "chrome://devtools/skin/images/debugging-workers.svg"; +const MORE_INFO_URL = "https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging"; + +module.exports = createClass({ + displayName: "WorkersPanel", + + propTypes: { + client: PropTypes.instanceOf(DebuggerClient).isRequired, + id: PropTypes.string.isRequired + }, + + getInitialState() { + return { + workers: { + service: [], + shared: [], + other: [] + } + }; + }, + + componentDidMount() { + let client = this.props.client; + client.addListener("workerListChanged", this.update); + client.addListener("serviceWorkerRegistrationListChanged", this.update); + client.addListener("processListChanged", this.update); + client.addListener("registration-changed", this.update); + + this.update(); + }, + + componentWillUnmount() { + let client = this.props.client; + client.removeListener("processListChanged", this.update); + client.removeListener("serviceWorkerRegistrationListChanged", this.update); + client.removeListener("workerListChanged", this.update); + client.removeListener("registration-changed", this.update); + }, + + update() { + let workers = this.getInitialState().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, + registrationActor: form.actor, + active: form.active + }); + }); + + 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 { + // 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); + } + }); + + // 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; + } + } + return null; + }, + + render() { + let { client, id } = this.props; + let { workers } = this.state; + + let isWindowPrivate = PrivateBrowsingUtils.isContentWindowPrivate(window); + let isPrivateBrowsingMode = PrivateBrowsingUtils.permanentPrivateBrowsing; + let isServiceWorkerDisabled = !Services.prefs + .getBoolPref("dom.serviceWorkers.enabled"); + let errorMsg = isWindowPrivate || isPrivateBrowsingMode || + isServiceWorkerDisabled ? + dom.p({ className: "service-worker-disabled" }, + dom.div({ className: "warning" }), + Strings.GetStringFromName("configurationIsNotCompatible"), + " (", + dom.a({ href: MORE_INFO_URL, target: "_blank" }, + Strings.GetStringFromName("moreInfo")), + ")" + ) : ""; + + return dom.div({ + id: id + "-panel", + className: "panel", + role: "tabpanel", + "aria-labelledby": id + "-header" + }, + PanelHeader({ + id: id + "-header", + name: Strings.GetStringFromName("workers") + }), + dom.div({ id: "workers", className: "inverted-icons" }, + TargetList({ + client, + error: errorMsg, + id: "service-workers", + name: Strings.GetStringFromName("serviceWorkers"), + sort: true, + targetClass: ServiceWorkerTarget, + targets: workers.service + }), + TargetList({ + client, + id: "shared-workers", + name: Strings.GetStringFromName("sharedWorkers"), + sort: true, + targetClass: WorkerTarget, + targets: workers.shared + }), + TargetList({ + client, + id: "other-workers", + name: Strings.GetStringFromName("otherWorkers"), + sort: true, + targetClass: WorkerTarget, + targets: workers.other + }) + )); + } +}); diff --git a/devtools/client/aboutdebugging/components/workers/service-worker-target.js b/devtools/client/aboutdebugging/components/workers/service-worker-target.js new file mode 100644 index 000000000..d46f6f20f --- /dev/null +++ b/devtools/client/aboutdebugging/components/workers/service-worker-target.js @@ -0,0 +1,231 @@ +/* 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/. */ + +/* eslint-env browser */ + +"use strict"; + +const { createClass, DOM: dom, PropTypes } = + require("devtools/client/shared/vendor/react"); +const { debugWorker } = require("../../modules/worker"); +const Services = require("Services"); + +loader.lazyRequireGetter(this, "DebuggerClient", + "devtools/shared/client/main", true); + +const Strings = Services.strings.createBundle( + "chrome://devtools/locale/aboutdebugging.properties"); + +module.exports = createClass({ + displayName: "ServiceWorkerTarget", + + propTypes: { + client: PropTypes.instanceOf(DebuggerClient).isRequired, + debugDisabled: PropTypes.bool, + target: PropTypes.shape({ + active: PropTypes.bool, + icon: PropTypes.string, + name: PropTypes.string.isRequired, + url: PropTypes.string, + scope: PropTypes.string.isRequired, + // registrationActor can be missing in e10s. + registrationActor: PropTypes.string, + workerActor: PropTypes.string + }).isRequired + }, + + getInitialState() { + return { + pushSubscription: null + }; + }, + + componentDidMount() { + let { client } = this.props; + client.addListener("push-subscription-modified", this.onPushSubscriptionModified); + this.updatePushSubscription(); + }, + + componentDidUpdate(oldProps, oldState) { + let wasActive = oldProps.target.active; + if (!wasActive && this.isActive()) { + // While the service worker isn't active, any calls to `updatePushSubscription` + // won't succeed. If we just became active, make sure we didn't miss a push + // subscription change by updating it now. + this.updatePushSubscription(); + } + }, + + componentWillUnmount() { + let { client } = this.props; + client.removeListener("push-subscription-modified", this.onPushSubscriptionModified); + }, + + debug() { + if (!this.isRunning()) { + // If the worker is not running, we can't debug it. + return; + } + + let { client, target } = this.props; + debugWorker(client, target.workerActor); + }, + + push() { + if (!this.isActive() || !this.isRunning()) { + // If the worker is not running, we can't push to it. + // If the worker is not active, the registration might be unavailable and the + // push will not succeed. + return; + } + + let { client, target } = this.props; + client.request({ + to: target.workerActor, + type: "push" + }); + }, + + start() { + if (!this.isActive() || this.isRunning()) { + // If the worker is not active or if it is already running, we can't start it. + return; + } + + let { client, target } = this.props; + client.request({ + to: target.registrationActor, + type: "start" + }); + }, + + unregister() { + let { client, target } = this.props; + client.request({ + to: target.registrationActor, + type: "unregister" + }); + }, + + onPushSubscriptionModified(type, data) { + let { target } = this.props; + if (data.from === target.registrationActor) { + this.updatePushSubscription(); + } + }, + + updatePushSubscription() { + if (!this.props.target.registrationActor) { + // A valid registrationActor is needed to retrieve the push subscription. + return; + } + + let { client, target } = this.props; + client.request({ + to: target.registrationActor, + type: "getPushSubscription" + }, ({ subscription }) => { + this.setState({ pushSubscription: subscription }); + }); + }, + + isRunning() { + // We know the target is running if it has a worker actor. + return !!this.props.target.workerActor; + }, + + isActive() { + return this.props.target.active; + }, + + getServiceWorkerStatus() { + if (this.isActive() && this.isRunning()) { + return "running"; + } else if (this.isActive()) { + return "stopped"; + } + // We cannot get service worker registrations unless the registration is in + // ACTIVE state. Unable to know the actual state ("installing", "waiting"), we + // display a custom state "registering" for now. See Bug 1153292. + return "registering"; + }, + + renderButtons() { + let pushButton = dom.button({ + className: "push-button", + onClick: this.push + }, Strings.GetStringFromName("push")); + + let debugButton = dom.button({ + className: "debug-button", + onClick: this.debug, + disabled: this.props.debugDisabled + }, Strings.GetStringFromName("debug")); + + let startButton = dom.button({ + className: "start-button", + onClick: this.start, + }, Strings.GetStringFromName("start")); + + if (this.isRunning()) { + if (this.isActive()) { + return [pushButton, debugButton]; + } + // Only debug button is available if the service worker is not active. + return debugButton; + } + return startButton; + }, + + renderUnregisterLink() { + if (!this.isActive()) { + // If not active, there might be no registrationActor available. + return null; + } + + return dom.a({ + onClick: this.unregister, + className: "unregister-link" + }, Strings.GetStringFromName("unregister")); + }, + + render() { + let { target } = this.props; + let { pushSubscription } = this.state; + let status = this.getServiceWorkerStatus(); + + return dom.div({ className: "target-container" }, + dom.img({ + className: "target-icon", + role: "presentation", + src: target.icon + }), + dom.span({ className: `target-status target-status-${status}` }, + Strings.GetStringFromName(status)), + dom.div({ className: "target" }, + dom.div({ className: "target-name", title: target.name }, target.name), + dom.ul({ className: "target-details" }, + (pushSubscription ? + dom.li({ className: "target-detail" }, + dom.strong(null, Strings.GetStringFromName("pushService")), + dom.span({ + className: "service-worker-push-url", + title: pushSubscription.endpoint + }, pushSubscription.endpoint)) : + null + ), + dom.li({ className: "target-detail" }, + dom.strong(null, Strings.GetStringFromName("scope")), + dom.span({ + className: "service-worker-scope", + title: target.scope + }, target.scope), + this.renderUnregisterLink() + ) + ) + ), + this.renderButtons() + ); + } +}); diff --git a/devtools/client/aboutdebugging/components/workers/target.js b/devtools/client/aboutdebugging/components/workers/target.js new file mode 100644 index 000000000..c1f6420ac --- /dev/null +++ b/devtools/client/aboutdebugging/components/workers/target.js @@ -0,0 +1,57 @@ +/* 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/. */ + +/* eslint-env browser */ + +"use strict"; + +const { createClass, DOM: dom, PropTypes } = + require("devtools/client/shared/vendor/react"); +const { debugWorker } = require("../../modules/worker"); +const Services = require("Services"); + +loader.lazyRequireGetter(this, "DebuggerClient", + "devtools/shared/client/main", true); + +const Strings = Services.strings.createBundle( + "chrome://devtools/locale/aboutdebugging.properties"); + +module.exports = createClass({ + displayName: "WorkerTarget", + + propTypes: { + client: PropTypes.instanceOf(DebuggerClient).isRequired, + debugDisabled: PropTypes.bool, + target: PropTypes.shape({ + icon: PropTypes.string, + name: PropTypes.string.isRequired, + workerActor: PropTypes.string + }).isRequired + }, + + debug() { + let { client, target } = this.props; + debugWorker(client, target.workerActor); + }, + + render() { + let { target, debugDisabled } = this.props; + + return dom.li({ className: "target-container" }, + dom.img({ + className: "target-icon", + role: "presentation", + src: target.icon + }), + dom.div({ className: "target" }, + dom.div({ className: "target-name", title: target.name }, target.name) + ), + dom.button({ + className: "debug-button", + onClick: this.debug, + disabled: debugDisabled + }, Strings.GetStringFromName("debug")) + ); + } +}); |