File: protocol-handler-unregister.https.html

package info (click to toggle)
firefox-esr 140.6.0esr-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,552,424 kB
  • sloc: cpp: 7,430,808; javascript: 6,389,773; ansic: 3,712,263; python: 1,393,776; xml: 628,165; asm: 426,918; java: 184,004; sh: 65,744; makefile: 19,302; objc: 13,059; perl: 12,912; yacc: 4,583; cs: 3,846; pascal: 3,352; lex: 1,720; ruby: 1,226; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10
file content (140 lines) | stat: -rw-r--r-- 5,357 bytes parent folder | download | duplicates (13)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<!DOCTYPE html>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="../resources/utils.js"></script>
<script src="resources/utils.js"></script>
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>

<script>

function getNextWindowMessageFromFrame(frame) {
  return new Promise(resolve => {
    window.addEventListener('message', event => {
      if (event.source === frame.contentWindow) {
        resolve(event.data);
      }
    });
  });
}

function getNextMessageFromServiceWorker(serviceWorker) {
  return new Promise(resolve => {
    serviceWorker.addEventListener('message', event => {
      resolve(event.data);
    }, {once: true});
  });
}

promise_setup(async () => {
  assertSpeculationRulesIsSupported()
  await test_driver.set_rph_registration_mode('autoAccept');
  await test_driver.bless('handler registration');
});

// The overall idea for this test is:
// 1. Register a protocol handler for a custom URI scheme.
// 2. Create a prerendered page that unregisters the protocol handler.
// 3. Navigate an iframe to the custom URI scheme. It should navigate
// successfully.
// 4. Activate the prerendered page. This should run the deferred unregistration
// work.
// 5. Navigate the iframe to the custom URI scheme again. It should fail to
// navigate.
// To detect the navigation failure, we use a service worker to perform the
// navigation via client.navigate and report the result back to
// the test. This is because the service worker's client.navigate method
// actually reports if the navigation failed, unlike other mechanisms which
// tell us nothing in this case.
promise_test(async t => {
  const customUrlScheme = 'web+wptrphtest';
  function getProtocolHandlerUrlTemplate(id) {
    return new URL(
        `resources/protocol-handler.html?id=${id}&s=%s`, location.href).href;
  }

  const urlTemplate = getProtocolHandlerUrlTemplate('unregister');

  t.add_cleanup(() => {
    navigator.unregisterProtocolHandler(
        customUrlScheme, urlTemplate);
  });
  navigator.registerProtocolHandler(customUrlScheme, urlTemplate);

  const {exec, activate} = await create_prerendered_page(t);

  const result = await exec(
      (customUrlScheme, urlTemplate) => {
        try {
          navigator.unregisterProtocolHandler(
              customUrlScheme, urlTemplate);
        } catch (registerProtocolHandlerException) {
          return 'registerProtocolHandler failed with \'' +
              registerProtocolHandlerException.name + '\'';
        }
        return 'success';
  }, [customUrlScheme, urlTemplate]);
  assert_equals(result, 'success', 'unregisterProtocolHandler should succeed.');

  const frame1 = await with_iframe('about:blank');

  const frame1MessagePromise = getNextWindowMessageFromFrame(frame1);
  frame1.src = `${customUrlScheme}:1`;
  assert_equals((await frame1MessagePromise).id, 'unregister',
    'Until activation, the initial handler should be registered.');

  frame1.remove();

  // Activate the prerendered page.
  await activate();

  // At this point the deferred unregistration work has run during activation
  // and the protocol handler is no longer registered.
  // We use Service Worker client.navigate to detect the failed navigation since
  // it is well supported and reliably reports error for unknown URL schemes.
  const serviceWorkerScope =
      'resources/protocol-handler.html?service_worker_client';
  const frame2Url = serviceWorkerScope + '&id=communication';
  const frame3Url = serviceWorkerScope + '&id=nav_target';
  const serviceWorkerUrl = 'resources/protocol-handler-service-worker.js';
  const serviceWorkerRegistration =
      await service_worker_unregister_and_register(
          t, serviceWorkerUrl, serviceWorkerScope);

  t.add_cleanup(async () => {
    await serviceWorkerRegistration.unregister();
  });

  await wait_for_state(t, serviceWorkerRegistration.installing, 'activated');

  // We use frame2 to communicate with the service worker.
  const frame2 = await with_iframe(frame2Url);

  // Frame3 is used by the service worker to attempt navigation.
  const frame3 = await with_iframe(frame3Url);

  const serviceWorkerMessagePromise = getNextMessageFromServiceWorker(
      frame2.contentWindow.navigator.serviceWorker);

  // Post message via frame2 to the service worker to tell it to navigate frame3
  // to the custom URI.
  frame2.contentWindow.navigator.serviceWorker.controller.postMessage(
      {clientUrlMatch: new URL(frame3Url, location.href).href,
       navigationUrl: `${customUrlScheme}:3`});

  // The service worker will post message back the result of the navigation.
  const navigationResult = await serviceWorkerMessagePromise;

  frame2.remove();
  frame3.remove();

  assert_false(navigationResult.success, 'Navigation to unregistered URI should fail');
  assert_equals(navigationResult.message, 'navigate failure: TypeError',
      'unregisterProtocolHandler should have completed.');
}, 'prerendering page unregisterProtocolHandler call defers registration until activation.');

</script>