tor-browser

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

browser_permission_delegate_geo.js (9004B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const ORIGIN = "https://example.com";
      7 const CROSS_SUBFRAME_PAGE =
      8  getRootDirectory(gTestPath).replace("chrome://mochitests/content", ORIGIN) +
      9  "temporary_permissions_subframe.html";
     10 
     11 const CROSS_FRAME_PAGE =
     12  getRootDirectory(gTestPath).replace("chrome://mochitests/content", ORIGIN) +
     13  "temporary_permissions_frame.html";
     14 
     15 const PromptResult = {
     16  ALLOW: "allow",
     17  DENY: "deny",
     18  PROMPT: "prompt",
     19 };
     20 
     21 var Perms = Services.perms;
     22 var uri = NetUtil.newURI(ORIGIN);
     23 var principal = Services.scriptSecurityManager.createContentPrincipal(uri, {});
     24 
     25 async function checkNotificationBothOrigins(
     26  firstPartyOrigin,
     27  thirdPartyOrigin
     28 ) {
     29  // Notification is shown, check label and deny to clean
     30  let popuphidden = BrowserTestUtils.waitForEvent(
     31    PopupNotifications.panel,
     32    "popuphidden"
     33  );
     34 
     35  let notification = PopupNotifications.panel.firstElementChild;
     36  // Check the label of the notificaiton should be the first party
     37  is(
     38    PopupNotifications.getNotification("geolocation").options.name,
     39    firstPartyOrigin,
     40    "Use first party's origin"
     41  );
     42 
     43  // Check the second name of the notificaiton should be the third party
     44  is(
     45    PopupNotifications.getNotification("geolocation").options.secondName,
     46    thirdPartyOrigin,
     47    "Use third party's origin"
     48  );
     49 
     50  // Check remember checkbox is hidden
     51  let checkbox = notification.checkbox;
     52  ok(!!checkbox, "checkbox is present");
     53  ok(checkbox.hidden, "checkbox is not visible");
     54  ok(!checkbox.checked, "checkbox not checked");
     55 
     56  EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
     57  await popuphidden;
     58 }
     59 
     60 async function checkGeolocation(browser, frameId, expect) {
     61  let isPrompt = expect == PromptResult.PROMPT;
     62  let waitForPrompt;
     63  if (isPrompt) {
     64    waitForPrompt = BrowserTestUtils.waitForEvent(
     65      PopupNotifications.panel,
     66      "popupshown"
     67    );
     68  }
     69 
     70  await SpecialPowers.spawn(
     71    browser,
     72    [{ frameId, expect, isPrompt }],
     73    async args => {
     74      let frame = content.document.getElementById(args.frameId);
     75 
     76      let waitForNoPrompt = new Promise(resolve => {
     77        function onMessage(event) {
     78          // Check the result right here because there's no notification
     79          Assert.equal(
     80            event.data,
     81            args.expect,
     82            "Correct expectation for third party"
     83          );
     84          content.window.removeEventListener("message", onMessage);
     85          resolve();
     86        }
     87 
     88        if (!args.isPrompt) {
     89          content.window.addEventListener("message", onMessage);
     90        }
     91      });
     92 
     93      await content.SpecialPowers.spawn(frame, [], async () => {
     94        const { E10SUtils } = ChromeUtils.importESModule(
     95          "resource://gre/modules/E10SUtils.sys.mjs"
     96        );
     97 
     98        E10SUtils.wrapHandlingUserInput(this.content, true, function () {
     99          let frameDoc = this.content.document;
    100          frameDoc.getElementById("geo").click();
    101        });
    102      });
    103 
    104      if (!args.isPrompt) {
    105        await waitForNoPrompt;
    106      }
    107    }
    108  );
    109 
    110  if (isPrompt) {
    111    await waitForPrompt;
    112  }
    113 }
    114 
    115 add_setup(async function () {
    116  await new Promise(r => {
    117    SpecialPowers.pushPrefEnv(
    118      {
    119        set: [
    120          ["test.wait300msAfterTabSwitch", true],
    121          ["dom.security.featurePolicy.header.enabled", true],
    122          ["dom.security.featurePolicy.webidl.enabled", true],
    123          // This is the amount of time before the repeating
    124          // NetworkGeolocationProvider timer is stopped.
    125          // It needs to be less than 5000ms, or the timer will be
    126          // reported as left behind by the test.
    127          ["geo.timeout", 4000],
    128        ],
    129      },
    130      r
    131    );
    132  });
    133 });
    134 
    135 // Test that temp blocked permissions in first party affect the third party
    136 // iframe.
    137 add_task(async function testUseTempPermissionsFirstParty() {
    138  await BrowserTestUtils.withNewTab(
    139    CROSS_SUBFRAME_PAGE,
    140    async function (browser) {
    141      SitePermissions.setForPrincipal(
    142        principal,
    143        "geo",
    144        SitePermissions.BLOCK,
    145        SitePermissions.SCOPE_TEMPORARY,
    146        browser
    147      );
    148 
    149      await checkGeolocation(browser, "frame", PromptResult.DENY);
    150 
    151      SitePermissions.removeFromPrincipal(principal, "geo", browser);
    152    }
    153  );
    154 });
    155 
    156 // Test that persistent permissions in first party affect the third party
    157 // iframe.
    158 add_task(async function testUsePersistentPermissionsFirstParty() {
    159  await BrowserTestUtils.withNewTab(
    160    CROSS_SUBFRAME_PAGE,
    161    async function (browser) {
    162      async function checkPermission(aPermission, aExpect) {
    163        PermissionTestUtils.add(uri, "geo", aPermission);
    164        await checkGeolocation(browser, "frame", aExpect);
    165 
    166        if (aExpect == PromptResult.PROMPT) {
    167          // Notification is shown, check label and deny to clean
    168          let popuphidden = BrowserTestUtils.waitForEvent(
    169            PopupNotifications.panel,
    170            "popuphidden"
    171          );
    172 
    173          let notification = PopupNotifications.panel.firstElementChild;
    174          // Check the label of the notificaiton should be the first party
    175          is(
    176            PopupNotifications.getNotification("geolocation").options.name,
    177            uri.host,
    178            "Use first party's origin"
    179          );
    180 
    181          EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
    182 
    183          await popuphidden;
    184          SitePermissions.removeFromPrincipal(null, "geo", browser);
    185        }
    186 
    187        PermissionTestUtils.remove(uri, "geo");
    188      }
    189 
    190      await checkPermission(Perms.PROMPT_ACTION, PromptResult.PROMPT);
    191      await checkPermission(Perms.DENY_ACTION, PromptResult.DENY);
    192      await checkPermission(Perms.ALLOW_ACTION, PromptResult.ALLOW);
    193    }
    194  );
    195 });
    196 
    197 // Test that we do not prompt for maybe unsafe permission delegation if the
    198 // origin of the page is the original src origin.
    199 add_task(async function testPromptInMaybeUnsafePermissionDelegation() {
    200  await BrowserTestUtils.withNewTab(
    201    CROSS_SUBFRAME_PAGE,
    202    async function (browser) {
    203      // Persistent allow top level origin
    204      PermissionTestUtils.add(uri, "geo", Perms.ALLOW_ACTION);
    205 
    206      await checkGeolocation(browser, "frameAllowsAll", PromptResult.ALLOW);
    207 
    208      SitePermissions.removeFromPrincipal(null, "geo", browser);
    209      PermissionTestUtils.remove(uri, "geo");
    210    }
    211  );
    212 });
    213 
    214 // Test that we should prompt if we are in unsafe permission delegation and
    215 // change location to origin which is not explicitly trusted. The prompt popup
    216 // should include both first and third party origin.
    217 add_task(async function testPromptChangeLocationUnsafePermissionDelegation() {
    218  await BrowserTestUtils.withNewTab(
    219    CROSS_SUBFRAME_PAGE,
    220    async function (browser) {
    221      // Persistent allow top level origin
    222      PermissionTestUtils.add(uri, "geo", Perms.ALLOW_ACTION);
    223 
    224      let iframe = await SpecialPowers.spawn(browser, [], () => {
    225        return content.document.getElementById("frameAllowsAll")
    226          .browsingContext;
    227      });
    228 
    229      let otherURI =
    230        "https://test1.example.com/browser/browser/base/content/test/permissions/permissions.html";
    231      let loaded = BrowserTestUtils.browserLoaded(browser, true, otherURI);
    232      await SpecialPowers.spawn(iframe, [otherURI], async function (_otherURI) {
    233        content.location = _otherURI;
    234      });
    235      await loaded;
    236 
    237      await checkGeolocation(browser, "frameAllowsAll", PromptResult.PROMPT);
    238      await checkNotificationBothOrigins(uri.host, "test1.example.com");
    239 
    240      SitePermissions.removeFromPrincipal(null, "geo", browser);
    241      PermissionTestUtils.remove(uri, "geo");
    242    }
    243  );
    244 });
    245 
    246 // If we are in unsafe permission delegation and the origin is explicitly
    247 // trusted in ancestor chain. Do not need prompt
    248 add_task(async function testExplicitlyAllowedInChain() {
    249  await BrowserTestUtils.withNewTab(CROSS_FRAME_PAGE, async function (browser) {
    250    // Persistent allow top level origin
    251    PermissionTestUtils.add(uri, "geo", Perms.ALLOW_ACTION);
    252 
    253    let iframeAncestor = await SpecialPowers.spawn(browser, [], () => {
    254      return content.document.getElementById("frameAncestor").browsingContext;
    255    });
    256 
    257    let iframe = await SpecialPowers.spawn(iframeAncestor, [], () => {
    258      return content.document.getElementById("frameAllowsAll").browsingContext;
    259    });
    260 
    261    // Change location to check that we actually look at the ancestor chain
    262    // instead of just considering the "same origin as src" rule.
    263    let otherURI =
    264      "https://test2.example.com/browser/browser/base/content/test/permissions/permissions.html";
    265    let loaded = BrowserTestUtils.browserLoaded(browser, true, otherURI);
    266    await SpecialPowers.spawn(iframe, [otherURI], async function (_otherURI) {
    267      content.location = _otherURI;
    268    });
    269    await loaded;
    270 
    271    await checkGeolocation(
    272      iframeAncestor,
    273      "frameAllowsAll",
    274      PromptResult.ALLOW
    275    );
    276 
    277    PermissionTestUtils.remove(uri, "geo");
    278  });
    279 });