| // META: script=/resources/testdriver.js |
| // META: script=/resources/testdriver-vendor.js |
| // META: script=/common/utils.js |
| // META: script=resources/fledge-util.sub.js |
| // META: script=/common/subset-tests.js |
| // META: timeout=long |
| // META: variant=?1-last |
| |
| "use strict"; |
| |
| const SERVICE_WORKER_SCRIPT = "resources/service-worker-helper.js"; |
| |
| // List of URL fragments that uniquely identify private requests. |
| // These are used to detect if a service worker has inadvertently |
| // accessed any of these private requests, which should not be visible to it. |
| const PRIVATE_REQUEST_FILE_NAMES = [ |
| 'trusted-bidding-signals.py', |
| 'update-url.py', // This requires another test, since it takes a while, |
| // see TODO file for more info. |
| 'wasm-helper.py', |
| 'bidding-logic.py', |
| 'decision-logic.py', |
| 'trusted-scoring-signals.py', |
| 'trusted-bidding-signals.py', |
| 'bidder_report', |
| 'seller_report' |
| ]; |
| |
| // List of URL fragments that uniquely identify public requests. |
| // These are used to verify that a service worker can correctly |
| // access and intercept these public requests as expected. |
| const PUBLIC_REQUEST_FILE_NAMES = [ |
| 'direct-from-seller-signals.py', |
| ]; |
| |
| const COMPLETE_TEST_URL = 'complete-test' |
| |
| const CURRENT_SCOPE = "/fledge/tentative/" |
| |
| async function registerAndActivateServiceWorker(test) { |
| // Unregister existing service worker (if any) |
| const existingRegistration = await navigator.serviceWorker.getRegistration(CURRENT_SCOPE); |
| if (existingRegistration) { |
| await existingRegistration.unregister(); |
| } |
| |
| // Register new service worker |
| var newRegistration = await navigator.serviceWorker.register(`./${SERVICE_WORKER_SCRIPT}`, { scope: CURRENT_SCOPE }); |
| |
| test.add_cleanup(async () => { |
| await newRegistration.unregister(); |
| }); |
| |
| await navigator.serviceWorker.ready; |
| |
| // Wait for the page to be controlled by the service worker. |
| // This is needed as navigator.serviceWorker.ready does not |
| // guarantee that the page is being controlled. |
| // See https://github.com/slightlyoff/ServiceWorker/issues/799. |
| await new Promise(resolve => { |
| if (navigator.serviceWorker.controller) { |
| resolve(); |
| } else { |
| navigator.serviceWorker.addEventListener('controllerchange', resolve); |
| } |
| }); |
| |
| // Validate the service worker |
| if (!navigator.serviceWorker.controller.scriptURL.includes(SERVICE_WORKER_SCRIPT)) { |
| throw new Error('Failed to register service worker'); |
| } |
| } |
| |
| async function setUpServiceWorkerAndGetBroadcastChannel(test) { |
| await registerAndActivateServiceWorker(test); |
| return new BroadcastChannel("requests-test"); |
| } |
| |
| // Waits for a service worker to observe specific URL filenames via a BroadcastChannel. |
| // Resolves when all expected URL filenames are seen. |
| function awaitServiceWorkerURLPromise(broadcastChannel, expectedURLFileNames, |
| unexpectedURLFileNames) { |
| const seenURLs = new Set(); |
| return new Promise((resolve, reject) => { |
| broadcastChannel.addEventListener('message', (event) => { |
| var url = event.data.url; |
| var fileName = url.substring(url.lastIndexOf('/') + 1); |
| if (expectedURLFileNames.includes(fileName)) { |
| seenURLs.add(fileName); |
| } |
| if (unexpectedURLFileNames.includes(fileName)) { |
| reject(`unexpected result: ${fileName}`); |
| } |
| // Resolve when all `expectedURLs` have been seen. |
| if (seenURLs.size === expectedURLFileNames.length) { |
| resolve(); |
| } |
| }); |
| }); |
| } |
| |
| // Tests that public requests are seen by the service worker. |
| // Specifically anything that contains: |
| // - 'direct-from-seller-signals.py' |
| |
| // This test works by having the service worker send a message over |
| // the broadcastChannel, if it sees a request that contains any of |
| // the following strings above, it will send a 'passed' result and |
| // also change the variable 'finish_test', to true, so that guarantees |
| // that the request was seen before we complete the test. |
| subsetTest(promise_test, async test => { |
| const broadcastChannel = await setUpServiceWorkerAndGetBroadcastChannel(test); |
| let finishTest = awaitServiceWorkerURLPromise( |
| broadcastChannel, |
| PUBLIC_REQUEST_FILE_NAMES, |
| PRIVATE_REQUEST_FILE_NAMES); |
| |
| await fetchDirectFromSellerSignals({ 'Buyer-Origin': window.location.origin }); |
| await finishTest; |
| }, "Make sure service workers do see public requests."); |
| |
| // Tests that private requests are not seen by the service worker. |
| // Specifically anything that contains: |
| // - 'resources/trusted-bidding-signals.py' |
| // - 'resources/trusted-scoring-signals.py' |
| // - 'wasm-helper.py' |
| // - 'bidding-logic.py' |
| // - 'decision-logic.py' |
| // - 'seller_report' |
| // - 'bidder_report' |
| |
| // This test works by having the service worker send a message |
| // over the broadcastChannel, if it sees a request that contains |
| // any of the following strings above, it will send a 'failed' |
| // result which will cause assert_false case to fail. |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| const broadcastChannel = await setUpServiceWorkerAndGetBroadcastChannel(test); |
| |
| let finishTest = awaitServiceWorkerURLPromise( |
| broadcastChannel, |
| /*expectedURLFileNames=*/[COMPLETE_TEST_URL], |
| PRIVATE_REQUEST_FILE_NAMES) |
| |
| let interestGroupOverrides = { |
| biddingWasmHelperURL: `${RESOURCE_PATH}wasm-helper.py`, |
| trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL, |
| trustedScoringSignalsURL: TRUSTED_SCORING_SIGNALS_URL, |
| }; |
| |
| await joinInterestGroup(test, uuid, interestGroupOverrides); |
| await runBasicFledgeAuctionAndNavigate(test, uuid); |
| // By verifying that these requests are observed we can assume |
| // none of the other requests were seen by the service-worker. |
| await waitForObservedRequests( |
| uuid, |
| [createBidderReportURL(uuid), createSellerReportURL(uuid)]); |
| |
| // We use this fetch to complete the test. |
| await fetch(COMPLETE_TEST_URL); |
| await finishTest; |
| }, "Make sure service workers do not see private requests"); |