summaryrefslogtreecommitdiffstats
path: root/uriloader/exthandler/tests/mochitest/browser_web_protocol_handlers.js
blob: 828d02d24b44b2fc96b6106c98c2300e8456804e (plain)
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
ChromeUtils.defineESModuleGetters(this, {
  UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.sys.mjs",
});

let testURL =
  "https://example.com/browser/" +
  "uriloader/exthandler/tests/mochitest/protocolHandler.html";

add_task(async function () {
  await SpecialPowers.pushPrefEnv({
    set: [["security.external_protocol_requires_permission", false]],
  });

  // Load a page registering a protocol handler.
  let browser = gBrowser.selectedBrowser;
  BrowserTestUtils.startLoadingURIString(browser, testURL);
  await BrowserTestUtils.browserLoaded(browser, false, testURL);

  // Register the protocol handler by clicking the notificationbar button.
  let notificationValue = "Protocol Registration: web+testprotocol";
  let getNotification = () =>
    gBrowser.getNotificationBox().getNotificationWithValue(notificationValue);
  await BrowserTestUtils.waitForCondition(getNotification);
  let notification = getNotification();
  let button = notification.buttonContainer.querySelector("button");
  ok(button, "got registration button");
  button.click();

  // Set the new handler as default.
  const protoSvc = Cc[
    "@mozilla.org/uriloader/external-protocol-service;1"
  ].getService(Ci.nsIExternalProtocolService);
  let protoInfo = protoSvc.getProtocolHandlerInfo("web+testprotocol");
  is(
    protoInfo.preferredAction,
    protoInfo.useHelperApp,
    "using a helper application is the preferred action"
  );
  ok(!protoInfo.preferredApplicationHandler, "no preferred handler is set");
  let handlers = protoInfo.possibleApplicationHandlers;
  is(1, handlers.length, "only one handler registered for web+testprotocol");
  let handler = handlers.queryElementAt(0, Ci.nsIHandlerApp);
  ok(handler instanceof Ci.nsIWebHandlerApp, "the handler is a web handler");
  is(
    handler.uriTemplate,
    "https://example.com/foobar?uri=%s",
    "correct url template"
  );
  protoInfo.preferredApplicationHandler = handler;
  protoInfo.alwaysAskBeforeHandling = false;
  const handlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].getService(
    Ci.nsIHandlerService
  );
  handlerSvc.store(protoInfo);

  const expectedURL =
    "https://example.com/foobar?uri=web%2Btestprotocol%3Atest";

  // Create a framed link:
  await SpecialPowers.spawn(browser, [], async function () {
    let iframe = content.document.createElement("iframe");
    iframe.src = `data:text/html,<a href="web+testprotocol:test">Click me</a>`;
    content.document.body.append(iframe);
    // Can't return this promise because it resolves to the event object.
    await ContentTaskUtils.waitForEvent(iframe, "load");
    iframe.contentDocument.querySelector("a").click();
  });
  let kidContext = browser.browsingContext.children[0];
  await TestUtils.waitForCondition(() => {
    let spec = kidContext.currentWindowGlobal?.documentURI?.spec || "";
    return spec == expectedURL;
  });
  is(
    kidContext.currentWindowGlobal.documentURI.spec,
    expectedURL,
    "Should load in frame."
  );

  // Middle-click a testprotocol link and check the new tab is correct
  let link = "#link";

  let promiseTabOpened = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL);
  await BrowserTestUtils.synthesizeMouseAtCenter(link, { button: 1 }, browser);
  let tab = await promiseTabOpened;
  gBrowser.selectedTab = tab;
  is(
    gURLBar.value,
    UrlbarTestUtils.trimURL(expectedURL),
    "the expected URL is displayed in the location bar"
  );
  BrowserTestUtils.removeTab(tab);

  // Shift-click the testprotocol link and check the new window.
  let newWindowPromise = BrowserTestUtils.waitForNewWindow({
    url: expectedURL,
  });
  await BrowserTestUtils.synthesizeMouseAtCenter(
    link,
    { shiftKey: true },
    browser
  );
  let win = await newWindowPromise;
  await BrowserTestUtils.waitForCondition(
    () => win.gBrowser.currentURI.spec == expectedURL
  );
  is(
    win.gURLBar.value,
    UrlbarTestUtils.trimURL(expectedURL),
    "the expected URL is displayed in the location bar"
  );
  await BrowserTestUtils.closeWindow(win);

  // Click the testprotocol link and check the url in the current tab.
  let loadPromise = BrowserTestUtils.browserLoaded(browser);
  await BrowserTestUtils.synthesizeMouseAtCenter(link, {}, browser);
  await loadPromise;
  await BrowserTestUtils.waitForCondition(
    () => gURLBar.value != UrlbarTestUtils.trimURL(testURL)
  );
  is(
    gURLBar.value,
    UrlbarTestUtils.trimURL(expectedURL),
    "the expected URL is displayed in the location bar"
  );

  // Cleanup.
  protoInfo.preferredApplicationHandler = null;
  handlers.removeElementAt(0);
  handlerSvc.store(protoInfo);
});