fune/devtools/client/aboutdebugging/components/workers/ServiceWorkerTarget.js
Andreea Pavel f970070b39 Backed out 4 changesets (bug 1445197) for failing mochitest devtools on multiple files e.g. devtools/client/aboutdebugging/test/browser_service_workers.js on a CLOSED TREE
Backed out changeset 4b6f77cfd686 (bug 1445197)
Backed out changeset ba9ffea6d216 (bug 1445197)
Backed out changeset a0345830e1cf (bug 1445197)
Backed out changeset 3e9acd2c8bd3 (bug 1445197)
2018-04-18 20:19:34 +03:00

260 lines
7.7 KiB
JavaScript

/* 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 { 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);
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
class ServiceWorkerTarget extends Component {
static get propTypes() {
return {
client: PropTypes.instanceOf(DebuggerClient).isRequired,
debugDisabled: PropTypes.bool,
target: PropTypes.shape({
active: PropTypes.bool,
fetch: PropTypes.bool.isRequired,
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
};
}
constructor(props) {
super(props);
this.state = {
pushSubscription: null
};
this.debug = this.debug.bind(this);
this.push = this.push.bind(this);
this.start = this.start.bind(this);
this.unregister = this.unregister.bind(this);
this.onPushSubscriptionModified = this.onPushSubscriptionModified.bind(this);
this.updatePushSubscription = this.updatePushSubscription.bind(this);
this.isRunning = this.isRunning.bind(this);
this.isActive = this.isActive.bind(this);
this.getServiceWorkerStatus = this.getServiceWorkerStatus.bind(this);
this.renderButtons = this.renderButtons.bind(this);
this.renderUnregisterLink = this.renderUnregisterLink.bind(this);
}
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,
disabled: this.props.debugDisabled
}, 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,
disabled: this.props.debugDisabled
}, 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();
let fetch = target.fetch ? Strings.GetStringFromName("listeningForFetchEvents") :
Strings.GetStringFromName("notListeningForFetchEvents");
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("fetch")),
dom.span({
className: "service-worker-fetch-flag",
title: fetch
}, fetch)),
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()
);
}
}
module.exports = ServiceWorkerTarget;