From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../tests/browser_resources_network_events.js | 316 +++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 devtools/shared/commands/resource/tests/browser_resources_network_events.js (limited to 'devtools/shared/commands/resource/tests/browser_resources_network_events.js') diff --git a/devtools/shared/commands/resource/tests/browser_resources_network_events.js b/devtools/shared/commands/resource/tests/browser_resources_network_events.js new file mode 100644 index 0000000000..bd84b81e09 --- /dev/null +++ b/devtools/shared/commands/resource/tests/browser_resources_network_events.js @@ -0,0 +1,316 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test the ResourceCommand API around NETWORK_EVENT + +const ResourceCommand = require("resource://devtools/shared/commands/resource/resource-command.js"); + +// We are borrowing tests from the netmonitor frontend +const NETMONITOR_TEST_FOLDER = + "https://example.com/browser/devtools/client/netmonitor/test/"; +const CSP_URL = `${NETMONITOR_TEST_FOLDER}html_csp-test-page.html`; +const JS_CSP_URL = `${NETMONITOR_TEST_FOLDER}js_websocket-worker-test.js`; +const CSS_CSP_URL = `${NETMONITOR_TEST_FOLDER}internal-loaded.css`; + +const CSP_BLOCKED_REASON_CODE = 4000; + +add_task(async function testContentProcessRequests() { + info(`Tests for NETWORK_EVENT resources fired from the content process`); + + const expectedAvailable = [ + { + url: CSP_URL, + method: "GET", + isNavigationRequest: true, + chromeContext: false, + }, + { + url: JS_CSP_URL, + method: "GET", + blockedReason: CSP_BLOCKED_REASON_CODE, + isNavigationRequest: false, + chromeContext: false, + }, + { + url: CSS_CSP_URL, + method: "GET", + blockedReason: CSP_BLOCKED_REASON_CODE, + isNavigationRequest: false, + chromeContext: false, + }, + ]; + const expectedUpdated = [ + { + url: CSP_URL, + method: "GET", + isNavigationRequest: true, + chromeContext: false, + }, + { + url: JS_CSP_URL, + method: "GET", + blockedReason: CSP_BLOCKED_REASON_CODE, + isNavigationRequest: false, + chromeContext: false, + }, + { + url: CSS_CSP_URL, + method: "GET", + blockedReason: CSP_BLOCKED_REASON_CODE, + isNavigationRequest: false, + chromeContext: false, + }, + ]; + + await assertNetworkResourcesOnPage( + CSP_URL, + expectedAvailable, + expectedUpdated + ); +}); + +add_task(async function testCanceledRequest() { + info(`Tests for NETWORK_EVENT resources with a canceled request`); + + // Do a XHR request that we cancel against a slow loading page + const requestUrl = + "https://example.org/document-builder.sjs?delay=1000&html=foo"; + const html = + ""; + const pageUrl = + "https://example.org/document-builder.sjs?html=" + encodeURIComponent(html); + + const expectedAvailable = [ + { + url: pageUrl, + method: "GET", + isNavigationRequest: true, + chromeContext: false, + }, + { + url: requestUrl, + method: "GET", + isNavigationRequest: false, + blockedReason: "NS_BINDING_ABORTED", + chromeContext: false, + }, + ]; + const expectedUpdated = [ + { + url: pageUrl, + method: "GET", + isNavigationRequest: true, + chromeContext: false, + }, + { + url: requestUrl, + method: "GET", + isNavigationRequest: false, + blockedReason: "NS_BINDING_ABORTED", + chromeContext: false, + }, + ]; + + // Register a one-off listener to cancel the XHR request + // Using XMLHttpRequest's abort() method from the content process + // isn't reliable and would introduce many race condition in the test. + // Canceling the request via nsIRequest.cancel privileged method, + // from the parent process is much more reliable. + const observer = { + QueryInterface: ChromeUtils.generateQI(["nsIObserver"]), + observe(subject, topic, data) { + subject = subject.QueryInterface(Ci.nsIHttpChannel); + if (subject.URI.spec == requestUrl) { + subject.cancel(Cr.NS_BINDING_ABORTED); + Services.obs.removeObserver(observer, "http-on-modify-request"); + } + }, + }; + Services.obs.addObserver(observer, "http-on-modify-request"); + + await assertNetworkResourcesOnPage( + pageUrl, + expectedAvailable, + expectedUpdated + ); +}); + +add_task(async function testIframeRequest() { + info(`Tests for NETWORK_EVENT resources with an iframe`); + + // Do a XHR request that we cancel against a slow loading page + const iframeRequestUrl = + "https://example.org/document-builder.sjs?html=iframe-request"; + const iframeHtml = `iframe`; + const iframeUrl = + "https://example.org/document-builder.sjs?html=" + + encodeURIComponent(iframeHtml); + const html = `top-document`; + const pageUrl = + "https://example.org/document-builder.sjs?html=" + encodeURIComponent(html); + + const expectedAvailable = [ + { + url: pageUrl, + method: "GET", + chromeContext: false, + isNavigationRequest: true, + // The top level navigation request relates to the previous top level target. + // Unfortunately, it is hard to test because it is racy. + // The target front might be destroyed and `targetFront.url` will be null. + // Or not just yet and be equal to "about:blank". + }, + { + url: iframeUrl, + method: "GET", + isNavigationRequest: false, + targetFrontUrl: pageUrl, + chromeContext: false, + }, + { + url: iframeRequestUrl, + method: "GET", + isNavigationRequest: false, + targetFrontUrl: iframeUrl, + chromeContext: false, + }, + ]; + const expectedUpdated = [ + { + url: pageUrl, + method: "GET", + isNavigationRequest: true, + chromeContext: false, + }, + { + url: iframeUrl, + method: "GET", + isNavigationRequest: false, + chromeContext: false, + }, + { + url: iframeRequestUrl, + method: "GET", + isNavigationRequest: false, + chromeContext: false, + }, + ]; + + await assertNetworkResourcesOnPage( + pageUrl, + expectedAvailable, + expectedUpdated + ); +}); + +async function assertNetworkResourcesOnPage( + url, + expectedAvailable, + expectedUpdated +) { + // First open a blank document to avoid spawning any request + const tab = await addTab("about:blank"); + + const commands = await CommandsFactory.forTab(tab); + await commands.targetCommand.startListening(); + const { resourceCommand } = commands; + + const onAvailable = resources => { + for (const resource of resources) { + // Immediately assert the resource, as the same resource object + // will be notified to onUpdated and so if we assert it later + // we will not highlight attributes that aren't set yet from onAvailable. + const idx = expectedAvailable.findIndex(e => e.url === resource.url); + ok( + idx != -1, + "Found a matching available notification for: " + resource.url + ); + // Remove the match from the list in case there is many requests with the same url + const [expected] = expectedAvailable.splice(idx, 1); + + assertResources(resource, expected); + } + }; + const onUpdated = updates => { + for (const { resource } of updates) { + const idx = expectedUpdated.findIndex(e => e.url === resource.url); + ok( + idx != -1, + "Found a matching updated notification for: " + resource.url + ); + // Remove the match from the list in case there is many requests with the same url + const [expected] = expectedUpdated.splice(idx, 1); + + assertResources(resource, expected); + } + }; + + // Start observing for network events before loading the test page + await resourceCommand.watchResources([resourceCommand.TYPES.NETWORK_EVENT], { + onAvailable, + onUpdated, + }); + + // Load the test page that fires network requests + const onLoaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + BrowserTestUtils.loadURIString(gBrowser.selectedBrowser, url); + await onLoaded; + + // Make sure we processed all the expected request updates + await waitFor( + () => !expectedAvailable.length, + "Wait for all expected available notifications" + ); + await waitFor( + () => !expectedUpdated.length, + "Wait for all expected updated notifications" + ); + + resourceCommand.unwatchResources([resourceCommand.TYPES.NETWORK_EVENT], { + onAvailable, + onUpdated, + }); + + await commands.destroy(); + + BrowserTestUtils.removeTab(tab); +} + +function assertResources(actual, expected) { + is( + actual.resourceType, + ResourceCommand.TYPES.NETWORK_EVENT, + "The resource type is correct" + ); + is( + typeof actual.innerWindowId, + "number", + "All requests have an innerWindowId attribute" + ); + ok( + actual.targetFront.isTargetFront, + "All requests have a targetFront attribute" + ); + + for (const name in expected) { + if (name == "targetFrontUrl") { + is( + actual.targetFront.url, + expected[name], + "The request matches the right target front" + ); + } else { + is(actual[name], expected[name], `The '${name}' attribute is correct`); + } + } +} -- cgit v1.2.3