tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

protocol.https.html (6423B)


      1 <!DOCTYPE html>
      2 <meta charset='utf-8'>
      3 <title>protocol handlers</title>
      4 
      5 <script src='/resources/testharness.js'></script>
      6 <script src='/resources/testharnessreport.js'></script>
      7 
      8 <noscript><p>Enable JavaScript and reload.</p></noscript>
      9 
     10 <p><strong>Note:</strong> If your browser limits the number of handler
     11 registration requests on a page, you might need to disable or significantly
     12 increase that limit for the tests below to run.</p>
     13 
     14 <script>
     15 test(() => {
     16  assert_idl_attribute(navigator, 'registerProtocolHandler');
     17 }, 'the registerProtocolHandler method should exist on the navigator object');
     18 
     19 test(() => {
     20  assert_idl_attribute(navigator, 'unregisterProtocolHandler');
     21 }, 'the unregisterProtocolHandler method should exist on the navigator object');
     22 
     23 /* URL argument */
     24 [
     25  '%s',
     26  'foo/%s',
     27  `%s${location.href}`,
     28  location.href.replace(location.protocol,
     29    `${location.protocol[0]}%s${location.protocol.substring(1)}`),
     30  location.href.replace(location.protocol, `${location.protocol}%s`),
     31  location.href + '/%s',
     32  location.href + '#%s',
     33  location.href + '?foo=%s',
     34  location.href + '?foo=%s&bar',
     35  location.href + '/%s/bar/baz/',
     36  location.href + '/%s/bar/baz/?foo=1337&bar#baz',
     37  location.href + '/%s/foo/%s/',
     38 ].forEach(url => {
     39  test(() => {
     40    navigator.registerProtocolHandler('tel', url, 'foo');
     41  }, 'registerProtocolHandler: Valid URL "' + url + '" should work.');
     42 
     43  test(() => {
     44    navigator.unregisterProtocolHandler('tel', url);
     45  }, 'unregisterProtocolHandler: Valid URL "' + url + '" should work.');
     46 });
     47 
     48 /* Invalid URLs */
     49 [
     50  '',
     51  '%S',
     52  'http://%s.com',
     53  'http://%s.example.com',
     54  location.href.replace(location.hostname, `%s${location.hostname}`),
     55  location.href.replace(location.port, `%s${location.port}`),
     56  location.href + '',
     57  location.href + '/%',
     58  location.href + '/%a',
     59  'http://example.com',
     60  'http://[v8.:::]//url=%s',
     61  'https://test:test/',
     62 ].forEach(url => {
     63  test(() => {
     64    assert_throws_dom('SYNTAX_ERR', () => { navigator.registerProtocolHandler('mailto', url, 'foo'); });
     65    assert_throws_dom('SECURITY_ERR', () => { navigator.registerProtocolHandler('x', url, 'foo'); });
     66  }, `registerProtocolHandler: Invalid URL "${url}" should throw (but after scheme)`);
     67 
     68  test(() => {
     69    assert_throws_dom('SYNTAX_ERR', () => { navigator.unregisterProtocolHandler('mailto', url); });
     70    assert_throws_dom('SECURITY_ERR', () => { navigator.unregisterProtocolHandler('x', url, 'foo'); });
     71  }, `unregisterProtocolHandler: Invalid URL "${url}" should throw (but after scheme)`);
     72 });
     73 
     74 [
     75  'http://example.com/%s',
     76  'https://example.com/%s',
     77  'http://foobar.example.com/%s',
     78  'mailto:%s@example.com',
     79  'mailto:%s',
     80  `chrome://${location.host}/%s`,
     81  `foo://${location.host}/%s`,
     82  URL.createObjectURL(new Blob()) + "#%s",
     83 ].forEach(url => {
     84  const title = url.startsWith("blob:") ? "blob: URL" : url;
     85  test(() => {
     86    assert_throws_dom('SECURITY_ERR', () => { navigator.registerProtocolHandler('mailto', url, 'foo'); });
     87  }, `registerProtocolHandler: Invalid URL "${title}" should throw SECURITY_ERR.`);
     88 
     89  test(() => {
     90    assert_throws_dom('SECURITY_ERR', () => { navigator.unregisterProtocolHandler('mailto', url); });
     91  }, `unregisterProtocolHandler: Invalid URL "${title}" should throw SECURITY_ERR.`);
     92 });
     93 
     94 /* Protocol argument */
     95 
     96 /* Overriding any of the following protocols must never be allowed. That would
     97 * break the browser. */
     98 [
     99  'about',
    100  'attachment',
    101  'blob',
    102  'chrome',
    103  'cid',
    104  'data',
    105  'file',
    106  'http',
    107  'https',
    108  'javascript',
    109  'livescript',
    110  'mid',
    111  'mocha',
    112  'moz-icon',
    113  'opera',
    114  'operamail',
    115  'res',
    116  'resource',
    117  'shttp',
    118  'tcl',
    119  'vbscript',
    120  'view-source',
    121  'ws',
    122  'wss',
    123  'wyciwyg',
    124  /* other invalid schemes */
    125  'unrecognized',
    126  'mаilto', /* a cyrillic "а" */
    127  'mailto:',
    128  'mailto://',
    129  'mailto' + String.fromCharCode(0),
    130  'mailtoo' + String.fromCharCode(8),
    131  'mailto' + String.fromCharCode(10),
    132  'http://',
    133  'ssh:/',
    134  'magnet:+',
    135  'tel:sip',
    136  'foo',
    137  'fweb+oo',
    138  /* web+ prefixed schemes must be followed by 1+ ascii alphas */
    139  'web+',
    140  'web+1',
    141  'web+namewithid123',
    142  'web+namewithtrailingspace ',
    143  'web+préfixewithaccent',     // é is not ascii alpha
    144  'web+Kelvinsign',            // ASCII-lower KELVIN SIGN is not k
    145  'web+latinsmallletterlongſ', // ASCII-lower LATIN SMALL LETTER LONG S is not s
    146  'web+dots.are.forbidden',
    147  'web+dashes-are-forbidden',
    148  'web+underscores_are_forbidden',
    149  'web+spaces are forbidden',
    150  'web+non*alpha*are*forbidden',
    151  'web+digits123areforbidden',
    152 ].forEach(scheme => {
    153  test(() => {
    154    // https://test:test/ does not parse and does not contain %s, but the scheme check happens first
    155    assert_throws_dom('SECURITY_ERR', () => { navigator.registerProtocolHandler(scheme, 'https://test:test/', 'foo'); });
    156  }, 'registerProtocolHandler: Attempting to override the "' + scheme + '" protocol should throw SECURITY_ERR.');
    157 
    158  test(() => {
    159    assert_throws_dom('SECURITY_ERR', () => { navigator.unregisterProtocolHandler(scheme, 'https://test:test/'); });
    160  }, 'unregisterProtocolHandler: Attempting to override the "' + scheme + '" protocol should throw SECURITY_ERR.');
    161 });
    162 
    163 /* The following protocols must be possible to override.
    164 * We're just testing that the call goes through here. Whether or not they
    165 * actually work as handlers is covered by the interactive tests. */
    166 
    167 [
    168  /* safelisted schemes listed in
    169   * https://html.spec.whatwg.org/multipage/system-state.html#safelisted-scheme */
    170  'bitcoin',
    171  'ftp',
    172  'ftps',
    173  'geo',
    174  'im',
    175  'irc',
    176  'ircs',
    177  'magnet',
    178  'mailto',
    179  'matrix',
    180  'mms',
    181  'news',
    182  'nntp',
    183  'openpgp4fpr',
    184  'sftp',
    185  'sip',
    186  'sms',
    187  'smsto',
    188  'ssh',
    189  'tel',
    190  'urn',
    191  'webcal',
    192  'wtai',
    193  'xmpp',
    194  /* other valid schemes */
    195  'BitcoIn',
    196  'Irc',
    197  'MagneT',
    198  'Matrix',
    199  'SmsTo',
    200  'TEL',
    201  'teL',
    202  'WebCAL',
    203  'WTAI',
    204  'web+myprotocol',
    205  'web+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', // all alphas
    206  'web+UpperCasedIsLowercased',
    207  'WEB+seeabove',
    208  'WeB+SeEaBoVe'
    209 ].forEach(scheme => {
    210  test(() => {
    211    navigator.registerProtocolHandler(scheme, location.href + '/%s', "foo");
    212  }, 'registerProtocolHandler: overriding the "' + scheme + '" protocol should work');
    213 
    214  test(() => {
    215    navigator.unregisterProtocolHandler(scheme, location.href + '/%s');
    216  }, 'unregisterProtocolHandler: overriding the "' + scheme + '" protocol should work');
    217 });
    218 </script>