Bug 1471795 - Part 16: Add action buttons. r?jdescottes, r?ladybenko
MozReview-Commit-ID: JkPDyKtiF5j
--- a/devtools/client/aboutdebugging-new/src/components/DebugTargetsPane.js
+++ b/devtools/client/aboutdebugging-new/src/components/DebugTargetsPane.js
@@ -149,21 +149,23 @@ class DebugTargetsPane extends PureCompo
debugTargets: serviceWorkers,
runtime,
title: "Service Workers",
}),
DebugTargetList({
className: "debug-target-list--shared-workers",
debugTargetItemComponent: WorkerItem,
debugTargets: sharedWorkers,
+ runtime,
title: "Shared Workers",
}),
DebugTargetList({
className: "debug-target-list--other-workers",
debugTargetItemComponent: WorkerItem,
debugTargets: otherWorkers,
+ runtime,
title: "Other Workers",
})
);
}
}
module.exports = DebugTargetsPane;
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/ServiceWorkerItem.css
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/ServiceWorkerItem.css
@@ -12,16 +12,21 @@
}
.debug-target-item__info__detail__service-worker__info__content {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
+.debug-target-item__info__detail__service-worker__info__unregister {
+ cursor: pointer;
+ margin-inline-start: 1ch;
+}
+
.debug-target-item__info__detail__service-worker__status {
border-style: solid;
border-width: 1px;
box-sizing: border-box;
display: inline-block;
font-size: 10px;
margin-block-start: 6px;
min-width: 50px;
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/ServiceWorkerItem.js
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/ServiceWorkerItem.js
@@ -19,16 +19,62 @@ class ServiceWorkerItem extends WorkerIt
componentDidUpdate(prevProps) {
if (prevProps.runtime !== this.props.runtime ||
prevProps.debugTarget !== this.props.debugTarget) {
this.updateState(this.props);
}
}
+ doInspect() {
+ if (!this.isRunning()) {
+ // If the worker is not running, we can't debug it.
+ return;
+ }
+
+ const { debugTarget, runtime } = this.props;
+ runtime.inspectWorker(debugTarget);
+ }
+
+ doPush() {
+ 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;
+ }
+
+ const { debugTarget, runtime } = this.props;
+ runtime.sendRequest({
+ to: debugTarget.registrationActor,
+ type: "push"
+ });
+ }
+
+ doStart() {
+ if (!this.isActive() || this.isRunning()) {
+ // If the worker is not active or if it is already running, we can't start it.
+ return;
+ }
+
+ const { debugTarget, runtime } = this.props;
+ runtime.sendRequest({
+ to: debugTarget.registrationActor,
+ type: "start"
+ });
+ }
+
+ doUnregister() {
+ const { debugTarget, runtime } = this.props;
+ runtime.sendRequest({
+ to: debugTarget.registrationActor,
+ type: "unregister"
+ });
+ }
+
getStatus() {
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
@@ -43,17 +89,48 @@ class ServiceWorkerItem extends WorkerIt
}
isActive() {
const { debugTarget } = this.props;
return debugTarget.active;
}
renderActionComponents() {
- return null;
+ const inspectButton = dom.button(
+ {
+ className: "debug-target-item__actions__service-worker-inspect",
+ onClick: e => this.doInspect(),
+ },
+ "Inspect"
+ );
+
+ const pushButton = dom.button(
+ {
+ className: "debug-target-item__actions__service-worker-push",
+ onClick: e => this.doPush(),
+ },
+ "Push"
+ );
+
+ if (this.isRunning()) {
+ if (this.isActive()) {
+ return [pushButton, inspectButton];
+ }
+
+ // Only debug button is available if the service worker is not active.
+ return inspectButton;
+ }
+
+ return dom.button(
+ {
+ className: "debug-target-item__actions__service-worker-start",
+ onClick: e => this.doStart(),
+ },
+ "Start"
+ );
}
renderDetailComponents() {
return [
dom.div(
{
className: "debug-target-item__info__detail__service-worker__info",
},
@@ -120,33 +197,50 @@ class ServiceWorkerItem extends WorkerIt
},
"Scope"
),
dom.dd(
{
className: "debug-target-item__info__detail__service-worker__info__content",
title: debugTarget.scope,
},
- debugTarget.scope
+ debugTarget.scope,
+ this.renderUnregisterLink()
),
];
}
renderStatus() {
const status = this.getStatus();
return dom.div(
{
className: "debug-target-item__info__detail__service-worker__status " +
`debug-target-item__info__detail__service-worker__status--${ status }`,
},
status
);
}
+ renderUnregisterLink() {
+ if (!this.isActive()) {
+ // If not active, there might be no registrationActor available.
+ return null;
+ }
+
+ return dom.a(
+ {
+ className: "debug-target-item__info__detail__service-worker__info__unregister",
+ onClick: e => this.doUnregister(),
+ title: "",
+ },
+ "Unregister"
+ );
+ }
+
async updateState({ debugTarget, runtime }) {
if (!debugTarget) {
// A valid registrationActor is needed to retrieve the push subscription.
return;
}
const { subscription } = await runtime.sendRequest({
to: debugTarget.registrationActor,
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/WorkerItem.js
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/WorkerItem.js
@@ -1,28 +1,41 @@
/* 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";
+const dom = require("devtools/client/shared/vendor/react-dom-factories");
+
const DebugTargetItem = require("./DebugTargetItem");
class WorkerItem extends DebugTargetItem {
+ async inspect() {
+ const { debugTarget, runtime } = this.props;
+ runtime.inspectWorker(debugTarget);
+ }
+
getIcon() {
return "chrome://devtools/skin/images/debugging-workers.svg";
}
getName() {
const { debugTarget } = this.props;
return debugTarget.name;
}
renderActionComponents() {
- return null;
+ return dom.button(
+ {
+ className: "debug-target-item__actions__worker-inspect",
+ onClick: e => this.inspect(),
+ },
+ "Inspect"
+ );
}
renderDetailComponents() {
return null;
}
}
module.exports = WorkerItem;
--- a/devtools/client/aboutdebugging-new/src/runtimes/runtime.js
+++ b/devtools/client/aboutdebugging-new/src/runtimes/runtime.js
@@ -108,16 +108,25 @@ class Runtime {
* Subclass should override this method.
* @param {Object} - debug target
*/
async inspectTab(_) {
throw new Error("Subclass of Runtime should override inspectTab()");
}
/**
+ * Inspect given debug target of worker which can get by getWorkers().
+ * Subclass should override this method.
+ * @param {Object} - debug target
+ */
+ async inspectWorker(_) {
+ throw new Error("Subclass of Runtime should override inspectWorker()");
+ }
+
+ /**
* Install temporary extension.
* Subclass should override this method.
*/
async installTemporaryExtension() {
throw new Error("Subclass of Runtime should override installTemporaryExtension()");
}
/**
--- a/devtools/client/aboutdebugging-new/src/runtimes/this-firefox.js
+++ b/devtools/client/aboutdebugging-new/src/runtimes/this-firefox.js
@@ -5,16 +5,17 @@
"use strict";
const { Cc, Ci } = require("chrome");
const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
const { BrowserToolboxProcess } =
require("resource://devtools/client/framework/ToolboxProcess.jsm");
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
const { DebuggerServer } = require("devtools/server/main");
+const { gDevToolsBrowser } = require("devtools/client/framework/devtools-browser");
const Services = require("Services");
const Runtime = require("./runtime");
/**
* This class represents the Firefox instance which runs in the same environment that
* opened about:debugging.
*/
@@ -89,16 +90,20 @@ class ThisFirefox extends Runtime {
}
});
}
async inspectTab(debugTarget) {
window.open(`about:devtools-toolbox?type=tab&id=${ debugTarget.outerWindowID }`);
}
+ async inspectWorker(debugTarget) {
+ gDevToolsBrowser.openWorkerToolbox(this.client, debugTarget.workerTargetActor);
+ }
+
async installTemporaryExtension() {
return new Promise((resolve, reject) => {
const fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window,
"Select Manifest File or Package (.xpi)",
Ci.nsIFilePicker.modeOpen);
fp.open(async res => {
if (res == Ci.nsIFilePicker.returnCancel || !fp.file) {