summaryrefslogtreecommitdiffstats
path: root/devtools/client/aboutdebugging/components/workers/service-worker-target.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/aboutdebugging/components/workers/service-worker-target.js')
-rw-r--r--devtools/client/aboutdebugging/components/workers/service-worker-target.js231
1 files changed, 231 insertions, 0 deletions
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()
+ );
+ }
+});