| <!DOCTYPE html> |
| <meta charset='utf-8'> |
| <title>protocol handlers</title> |
| |
| <script src='/resources/testharness.js'></script> |
| <script src='/resources/testharnessreport.js'></script> |
| |
| <noscript><p>Enable JavaScript and reload.</p></noscript> |
| |
| <p><strong>Note:</strong> If your browser limits the number of handler |
| registration requests on a page, you might need to disable or significantly |
| increase that limit for the tests below to run.</p> |
| |
| <script> |
| test(() => { |
| assert_idl_attribute(navigator, 'registerProtocolHandler'); |
| }, 'the registerProtocolHandler method should exist on the navigator object'); |
| |
| test(() => { |
| assert_idl_attribute(navigator, 'unregisterProtocolHandler'); |
| }, 'the unregisterProtocolHandler method should exist on the navigator object'); |
| |
| /* URL argument */ |
| [ |
| '%s', |
| 'foo/%s', |
| location.href + '/%s', |
| location.href + '#%s', |
| location.href + '?foo=%s', |
| location.href + '?foo=%s&bar', |
| location.href + '/%s/bar/baz/', |
| location.href + '/%s/bar/baz/?foo=1337&bar#baz', |
| location.href + '/%s/foo/%s/', |
| ].forEach(url => { |
| test(() => { |
| navigator.registerProtocolHandler('tel', url, 'foo'); |
| }, 'registerProtocolHandler: Valid URL "' + url + '" should work.'); |
| |
| test(() => { |
| navigator.unregisterProtocolHandler('tel', url); |
| }, 'unregisterProtocolHandler: Valid URL "' + url + '" should work.'); |
| }); |
| |
| /* Invalid URLs */ |
| [ |
| '', |
| '%S', |
| location.href + '', |
| location.href + '/%', |
| location.href + '/%a', |
| 'http://example.com', |
| 'http://[v8.:::]//url=%s', |
| 'https://test:test/', |
| ].forEach(url => { |
| test(() => { |
| assert_throws_dom('SYNTAX_ERR', () => { navigator.registerProtocolHandler('mailto', url, 'foo'); }); |
| assert_throws_dom('SECURITY_ERR', () => { navigator.registerProtocolHandler('x', url, 'foo'); }); |
| }, `registerProtocolHandler: Invalid URL "${url}" should throw (but after scheme)`); |
| |
| test(() => { |
| assert_throws_dom('SYNTAX_ERR', () => { navigator.unregisterProtocolHandler('mailto', url); }); |
| assert_throws_dom('SECURITY_ERR', () => { navigator.unregisterProtocolHandler('x', url, 'foo'); }); |
| }, `unregisterProtocolHandler: Invalid URL "${url}" should throw (but after scheme)`); |
| }); |
| |
| [ |
| 'http://%s.com', |
| 'http://%s.example.com', |
| 'http://example.com/%s', |
| 'https://example.com/%s', |
| 'http://foobar.example.com/%s', |
| 'mailto:%s@example.com', |
| 'mailto:%s', |
| `ftp://${location.host}/%s`, |
| `chrome://${location.host}/%s`, |
| `foo://${location.host}/%s`, |
| URL.createObjectURL(new Blob()) + "#%s", |
| ].forEach(url => { |
| const title = url.startsWith("blob:") ? "blob: URL" : url; |
| test(() => { |
| assert_throws_dom('SECURITY_ERR', () => { navigator.registerProtocolHandler('mailto', url, 'foo'); }); |
| }, `registerProtocolHandler: Invalid URL "${title}" should throw SECURITY_ERR.`); |
| |
| test(() => { |
| assert_throws_dom('SECURITY_ERR', () => { navigator.unregisterProtocolHandler('mailto', url); }); |
| }, `unregisterProtocolHandler: Invalid URL "${title}" should throw SECURITY_ERR.`); |
| }); |
| |
| /* Protocol argument */ |
| |
| /* Overriding any of the following protocols must never be allowed. That would |
| * break the browser. */ |
| [ |
| 'about', |
| 'attachment', |
| 'blob', |
| 'chrome', |
| 'cid', |
| 'data', |
| 'file', |
| 'ftp', |
| 'http', |
| 'https', |
| 'javascript', |
| 'livescript', |
| 'mid', |
| 'mocha', |
| 'moz-icon', |
| 'opera', |
| 'operamail', |
| 'res', |
| 'resource', |
| 'shttp', |
| 'tcl', |
| 'vbscript', |
| 'view-source', |
| 'ws', |
| 'wss', |
| 'wyciwyg', |
| /* other invalid schemes */ |
| 'unrecognized', |
| 'mаilto', /* a cyrillic "а" */ |
| 'mailto:', |
| 'mailto://', |
| 'mailto' + String.fromCharCode(0), |
| 'mailtoo' + String.fromCharCode(8), |
| 'mailto' + String.fromCharCode(10), |
| 'http://', |
| 'ssh:/', |
| 'magnet:+', |
| 'tel:sip', |
| 'foo', |
| 'fweb+oo', |
| /* web+ prefixed schemes must be followed by 1+ ascii alphas */ |
| 'web+', |
| 'web+1', |
| 'web+dots.are.forbidden', |
| 'web+dashes-are-forbidden', |
| 'web+digits123areforbidden', |
| ].forEach(scheme => { |
| test(() => { |
| // https://test:test/ does not parse and does not contain %s, but the scheme check happens first |
| assert_throws_dom('SECURITY_ERR', () => { navigator.registerProtocolHandler(scheme, 'https://test:test/', 'foo'); }); |
| }, 'registerProtocolHandler: Attempting to override the "' + scheme + '" protocol should throw SECURITY_ERR.'); |
| |
| test(() => { |
| assert_throws_dom('SECURITY_ERR', () => { navigator.unregisterProtocolHandler(scheme, 'https://test:test/'); }); |
| }, 'unregisterProtocolHandler: Attempting to override the "' + scheme + '" protocol should throw SECURITY_ERR.'); |
| }); |
| |
| /* The following protocols must be possible to override. |
| * We're just testing that the call goes through here. Whether or not they |
| * actually work as handlers is covered by the interactive tests. */ |
| |
| [ |
| /* safelisted schemes listed in |
| * https://html.spec.whatwg.org/multipage/system-state.html#safelisted-scheme */ |
| 'bitcoin', |
| 'geo', |
| 'im', |
| 'irc', |
| 'ircs', |
| 'magnet', |
| 'mailto', |
| 'mms', |
| 'news', |
| 'nntp', |
| 'openpgp4fpr', |
| 'sip', |
| 'sms', |
| 'smsto', |
| 'ssh', |
| 'tel', |
| 'urn', |
| 'webcal', |
| 'wtai', |
| 'xmpp', |
| /* other valid schemes */ |
| 'BitcoIn', |
| 'Irc', |
| 'MagneT', |
| 'SmsTo', |
| 'TEL', |
| 'teL', |
| 'WebCAL', |
| 'WTAI', |
| 'web+myprotocol', |
| 'web+UpperCasedIsLowercased', |
| 'WEB+seeabove', |
| 'WeB+SeEaBoVe' |
| ].forEach(scheme => { |
| test(() => { |
| navigator.registerProtocolHandler(scheme, location.href + '/%s', "foo"); |
| }, 'registerProtocolHandler: overriding the "' + scheme + '" protocol should work'); |
| |
| test(() => { |
| navigator.unregisterProtocolHandler(scheme, location.href + '/%s'); |
| }, 'unregisterProtocolHandler: overriding the "' + scheme + '" protocol should work'); |
| }); |
| </script> |