summaryrefslogtreecommitdiffstats
path: root/devtools/shared/commands/network
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/shared/commands/network/moz.build10
-rw-r--r--devtools/shared/commands/network/network-command.js96
-rw-r--r--devtools/shared/commands/network/tests/browser.ini11
-rw-r--r--devtools/shared/commands/network/tests/browser_network_command_request_blocking.js61
-rw-r--r--devtools/shared/commands/network/tests/browser_network_command_sendHTTPRequest.js78
-rw-r--r--devtools/shared/commands/network/tests/head.js12
6 files changed, 268 insertions, 0 deletions
diff --git a/devtools/shared/commands/network/moz.build b/devtools/shared/commands/network/moz.build
new file mode 100644
index 0000000000..e765e5ac76
--- /dev/null
+++ b/devtools/shared/commands/network/moz.build
@@ -0,0 +1,10 @@
+# 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(
+ "network-command.js",
+)
+
+if CONFIG["MOZ_BUILD_APP"] != "mobile/android":
+ BROWSER_CHROME_MANIFESTS += ["tests/browser.ini"]
diff --git a/devtools/shared/commands/network/network-command.js b/devtools/shared/commands/network/network-command.js
new file mode 100644
index 0000000000..44cdf4e759
--- /dev/null
+++ b/devtools/shared/commands/network/network-command.js
@@ -0,0 +1,96 @@
+/* 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";
+
+class NetworkCommand {
+ /**
+ * This class helps listen, inspect and control network requests.
+ *
+ * @param {DescriptorFront} descriptorFront
+ * The context to inspect identified by this descriptor.
+ * @param {WatcherFront} watcherFront
+ * If available, a reference to the related Watcher Front.
+ * @param {Object} commands
+ * The commands object with all interfaces defined from devtools/shared/commands/
+ */
+ constructor({ descriptorFront, watcherFront, commands }) {
+ this.commands = commands;
+ this.descriptorFront = descriptorFront;
+ this.watcherFront = watcherFront;
+ }
+
+ /**
+ * Send a HTTP request data payload
+ *
+ * @param {object} data data payload would like to sent to backend
+ */
+ async sendHTTPRequest(data) {
+ // By default use the top-level target, but we might at some point
+ // allow using another target.
+ const networkContentFront =
+ await this.commands.targetCommand.targetFront.getFront("networkContent");
+ const { channelId } = await networkContentFront.sendHTTPRequest(data);
+ return { channelId };
+ }
+
+ /*
+ * Get the list of blocked URL filters.
+ *
+ * A URL filter is a RegExp string so that one filter can match many URLs.
+ * It can be an absolute URL to match only one precise request:
+ * http://mozilla.org/index.html
+ * Or just a string which would match all URL containing this string:
+ * mozilla
+ * Or a RegExp to match various types of URLs:
+ * http://*mozilla.org/*.css
+ *
+ * @return {Array}
+ * List of all currently blocked URL filters.
+ */
+ async getBlockedUrls() {
+ const networkParentFront = await this.watcherFront.getNetworkParentActor();
+ return networkParentFront.getBlockedUrls();
+ }
+
+ /**
+ * Updates the list of blocked URL filters.
+ *
+ * @param {Array} urls
+ * An array of URL filter strings.
+ * See getBlockedUrls for definition of URL filters.
+ */
+ async setBlockedUrls(urls) {
+ const networkParentFront = await this.watcherFront.getNetworkParentActor();
+ return networkParentFront.setBlockedUrls(urls);
+ }
+
+ /**
+ * Block only one additional URL filter
+ *
+ * @param {String} url
+ * URL filter to block.
+ * See getBlockedUrls for definition of URL filters.
+ */
+ async blockRequestForUrl(url) {
+ const networkParentFront = await this.watcherFront.getNetworkParentActor();
+ return networkParentFront.blockRequest({ url });
+ }
+
+ /**
+ * Stop blocking only one specific URL filter
+ *
+ * @param {String} url
+ * URL filter to unblock.
+ * See getBlockedUrls for definition of URL filters.
+ */
+ async unblockRequestForUrl(url) {
+ const networkParentFront = await this.watcherFront.getNetworkParentActor();
+ return networkParentFront.unblockRequest({ url });
+ }
+
+ destroy() {}
+}
+
+module.exports = NetworkCommand;
diff --git a/devtools/shared/commands/network/tests/browser.ini b/devtools/shared/commands/network/tests/browser.ini
new file mode 100644
index 0000000000..ce1860f0f0
--- /dev/null
+++ b/devtools/shared/commands/network/tests/browser.ini
@@ -0,0 +1,11 @@
+[DEFAULT]
+tags = devtools
+subsuite = devtools
+support-files =
+ !/devtools/client/shared/test/shared-head.js
+ !/devtools/client/shared/test/telemetry-test-helpers.js
+ !/devtools/client/shared/test/highlighter-test-actor.js
+ head.js
+
+[browser_network_command_request_blocking.js]
+[browser_network_command_sendHTTPRequest.js]
diff --git a/devtools/shared/commands/network/tests/browser_network_command_request_blocking.js b/devtools/shared/commands/network/tests/browser_network_command_request_blocking.js
new file mode 100644
index 0000000000..dd1167fa9b
--- /dev/null
+++ b/devtools/shared/commands/network/tests/browser_network_command_request_blocking.js
@@ -0,0 +1,61 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test the NetworkCommand API around request blocking
+
+add_task(async function () {
+ info("Test NetworkCommand request blocking");
+ const tab = await addTab("data:text/html,foo");
+ const commands = await CommandsFactory.forTab(tab);
+ const networkCommand = commands.networkCommand;
+ const resourceCommand = commands.resourceCommand;
+
+ // Usage of request blocking APIs requires to listen to NETWORK_EVENT.
+ await resourceCommand.watchResources([resourceCommand.TYPES.NETWORK_EVENT], {
+ onAvailable: () => {},
+ });
+
+ let blockedUrls = await networkCommand.getBlockedUrls();
+ Assert.deepEqual(
+ blockedUrls,
+ [],
+ "The list of blocked URLs is originaly empty"
+ );
+
+ await networkCommand.blockRequestForUrl("https://foo.com");
+ blockedUrls = await networkCommand.getBlockedUrls();
+ Assert.deepEqual(
+ blockedUrls,
+ ["https://foo.com"],
+ "The freshly added blocked URL is reported as blocked"
+ );
+
+ // We pass "url filters" which can be only part of a URL string
+ await networkCommand.blockRequestForUrl("bar");
+ blockedUrls = await networkCommand.getBlockedUrls();
+ Assert.deepEqual(
+ blockedUrls,
+ ["https://foo.com", "bar"],
+ "The second blocked URL is also reported as blocked"
+ );
+
+ await networkCommand.setBlockedUrls(["https://mozilla.org"]);
+ blockedUrls = await networkCommand.getBlockedUrls();
+ Assert.deepEqual(
+ blockedUrls,
+ ["https://mozilla.org"],
+ "setBlockedUrls replace the whole list of blocked URLs"
+ );
+
+ await networkCommand.unblockRequestForUrl("https://mozilla.org");
+ blockedUrls = await networkCommand.getBlockedUrls();
+ Assert.deepEqual(
+ blockedUrls,
+ [],
+ "The unblocked URL disappear from the list of blocked URLs"
+ );
+
+ await commands.destroy();
+});
diff --git a/devtools/shared/commands/network/tests/browser_network_command_sendHTTPRequest.js b/devtools/shared/commands/network/tests/browser_network_command_sendHTTPRequest.js
new file mode 100644
index 0000000000..1d84a8a668
--- /dev/null
+++ b/devtools/shared/commands/network/tests/browser_network_command_sendHTTPRequest.js
@@ -0,0 +1,78 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test the NetworkCommand's sendHTTPRequest
+
+add_task(async function () {
+ info("Test NetworkCommand.sendHTTPRequest");
+ const tab = await addTab("data:text/html,foo");
+ const commands = await CommandsFactory.forTab(tab);
+
+ // We have to ensure TargetCommand is initialized to have access to the top level target
+ // from NetworkCommand.sendHTTPRequest
+ await commands.targetCommand.startListening();
+
+ const { networkCommand } = commands;
+
+ const httpServer = createTestHTTPServer();
+ const onRequest = new Promise(resolve => {
+ httpServer.registerPathHandler(
+ "/http-request.html",
+ (request, response) => {
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.write("Response body");
+ resolve(request);
+ }
+ );
+ });
+ const url = `http://localhost:${httpServer.identity.primaryPort}/http-request.html`;
+
+ info("Call NetworkCommand.sendHTTPRequest");
+ const { resourceCommand } = commands;
+ const { onResource } = await resourceCommand.waitForNextResource(
+ resourceCommand.TYPES.NETWORK_EVENT
+ );
+ const { channelId } = await networkCommand.sendHTTPRequest({
+ url,
+ method: "POST",
+ headers: [{ name: "Request", value: "Header" }],
+ body: "Hello",
+ cause: {
+ loadingDocumentUri: "https://example.com",
+ stacktraceAvailable: true,
+ type: "xhr",
+ },
+ });
+ ok(channelId, "Received a channel id in response");
+ const resource = await onResource;
+ is(
+ resource.resourceId,
+ channelId,
+ "NETWORK_EVENT resource channelId is the same as the one returned by sendHTTPRequest"
+ );
+
+ const request = await onRequest;
+ is(request.method, "POST", "Request method is correct");
+ is(request.getHeader("Request"), "Header", "The custom header was passed");
+ is(fetchRequestBody(request), "Hello", "The request POST's body is correct");
+
+ await commands.destroy();
+});
+
+const BinaryInputStream = Components.Constructor(
+ "@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream"
+);
+
+function fetchRequestBody(request) {
+ let body = "";
+ const bodyStream = new BinaryInputStream(request.bodyInputStream);
+ let avail = 0;
+ while ((avail = bodyStream.available()) > 0) {
+ body += String.fromCharCode.apply(String, bodyStream.readByteArray(avail));
+ }
+ return body;
+}
diff --git a/devtools/shared/commands/network/tests/head.js b/devtools/shared/commands/network/tests/head.js
new file mode 100644
index 0000000000..ce65b3d827
--- /dev/null
+++ b/devtools/shared/commands/network/tests/head.js
@@ -0,0 +1,12 @@
+/* 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";
+
+/* eslint no-unused-vars: [2, {"vars": "local"}] */
+
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js",
+ this
+);