forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			267 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			267 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* Any copyright is dedicated to the Public Domain.
 | 
						|
 * http://creativecommons.org/publicdomain/zero/1.0/ */
 | 
						|
 | 
						|
"use strict";
 | 
						|
 | 
						|
const ORIGIN = "https://example.com";
 | 
						|
const CROSS_SUBFRAME_PAGE =
 | 
						|
  getRootDirectory(gTestPath).replace("chrome://mochitests/content", ORIGIN) +
 | 
						|
  "temporary_permissions_subframe.html";
 | 
						|
 | 
						|
const CROSS_FRAME_PAGE =
 | 
						|
  getRootDirectory(gTestPath).replace("chrome://mochitests/content", ORIGIN) +
 | 
						|
  "temporary_permissions_frame.html";
 | 
						|
 | 
						|
const PromptResult = {
 | 
						|
  ALLOW: "allow",
 | 
						|
  DENY: "deny",
 | 
						|
  PROMPT: "prompt",
 | 
						|
};
 | 
						|
 | 
						|
var Perms = Services.perms;
 | 
						|
var uri = NetUtil.newURI(ORIGIN);
 | 
						|
var principal = Services.scriptSecurityManager.createContentPrincipal(uri, {});
 | 
						|
 | 
						|
async function checkNotificationBothOrigins(
 | 
						|
  firstPartyOrigin,
 | 
						|
  thirdPartyOrigin
 | 
						|
) {
 | 
						|
  // Notification is shown, check label and deny to clean
 | 
						|
  let popuphidden = BrowserTestUtils.waitForEvent(
 | 
						|
    PopupNotifications.panel,
 | 
						|
    "popuphidden"
 | 
						|
  );
 | 
						|
 | 
						|
  let notification = PopupNotifications.panel.firstElementChild;
 | 
						|
  // Check the label of the notificaiton should be the first party
 | 
						|
  is(
 | 
						|
    PopupNotifications.getNotification("geolocation").options.name,
 | 
						|
    firstPartyOrigin,
 | 
						|
    "Use first party's origin"
 | 
						|
  );
 | 
						|
 | 
						|
  // Check the second name of the notificaiton should be the third party
 | 
						|
  is(
 | 
						|
    PopupNotifications.getNotification("geolocation").options.secondName,
 | 
						|
    thirdPartyOrigin,
 | 
						|
    "Use third party's origin"
 | 
						|
  );
 | 
						|
 | 
						|
  // Check remember checkbox is hidden
 | 
						|
  let checkbox = notification.checkbox;
 | 
						|
  ok(!!checkbox, "checkbox is present");
 | 
						|
  ok(checkbox.hidden, "checkbox is not visible");
 | 
						|
  ok(!checkbox.checked, "checkbox not checked");
 | 
						|
 | 
						|
  EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
 | 
						|
  await popuphidden;
 | 
						|
}
 | 
						|
 | 
						|
async function checkGeolocation(browser, frameId, expect) {
 | 
						|
  let waitForPrompt = BrowserTestUtils.waitForEvent(
 | 
						|
    PopupNotifications.panel,
 | 
						|
    "popupshown"
 | 
						|
  );
 | 
						|
 | 
						|
  let isPrompt = expect == PromptResult.PROMPT;
 | 
						|
  await SpecialPowers.spawn(
 | 
						|
    browser,
 | 
						|
    [{ frameId, expect, isPrompt }],
 | 
						|
    async args => {
 | 
						|
      let frame = content.document.getElementById(args.frameId);
 | 
						|
 | 
						|
      let waitForNoPrompt = new Promise(resolve => {
 | 
						|
        function onMessage(event) {
 | 
						|
          // Check the result right here because there's no notification
 | 
						|
          Assert.equal(
 | 
						|
            event.data,
 | 
						|
            args.expect,
 | 
						|
            "Correct expectation for third party"
 | 
						|
          );
 | 
						|
          content.window.removeEventListener("message", onMessage);
 | 
						|
          resolve();
 | 
						|
        }
 | 
						|
 | 
						|
        if (!args.isPrompt) {
 | 
						|
          content.window.addEventListener("message", onMessage);
 | 
						|
        }
 | 
						|
      });
 | 
						|
 | 
						|
      await content.SpecialPowers.spawn(frame, [], async () => {
 | 
						|
        const { E10SUtils } = ChromeUtils.import(
 | 
						|
          "resource://gre/modules/E10SUtils.jsm"
 | 
						|
        );
 | 
						|
 | 
						|
        E10SUtils.wrapHandlingUserInput(this.content, true, function() {
 | 
						|
          let frameDoc = this.content.document;
 | 
						|
          frameDoc.getElementById("geo").click();
 | 
						|
        });
 | 
						|
      });
 | 
						|
 | 
						|
      if (!args.isPrompt) {
 | 
						|
        await waitForNoPrompt;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  );
 | 
						|
 | 
						|
  if (isPrompt) {
 | 
						|
    await waitForPrompt;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
add_task(async function setup() {
 | 
						|
  await new Promise(r => {
 | 
						|
    SpecialPowers.pushPrefEnv(
 | 
						|
      {
 | 
						|
        set: [
 | 
						|
          ["dom.security.featurePolicy.enabled", true],
 | 
						|
          ["dom.security.featurePolicy.header.enabled", true],
 | 
						|
          ["dom.security.featurePolicy.webidl.enabled", true],
 | 
						|
          ["permissions.delegation.enabled", true],
 | 
						|
        ],
 | 
						|
      },
 | 
						|
      r
 | 
						|
    );
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
// Test that temp blocked permissions in first party affect the third party
 | 
						|
// iframe.
 | 
						|
add_task(async function testUseTempPermissionsFirstParty() {
 | 
						|
  await BrowserTestUtils.withNewTab(CROSS_SUBFRAME_PAGE, async function(
 | 
						|
    browser
 | 
						|
  ) {
 | 
						|
    SitePermissions.setForPrincipal(
 | 
						|
      principal,
 | 
						|
      "geo",
 | 
						|
      SitePermissions.BLOCK,
 | 
						|
      SitePermissions.SCOPE_TEMPORARY,
 | 
						|
      browser
 | 
						|
    );
 | 
						|
 | 
						|
    await checkGeolocation(browser, "frame", PromptResult.DENY);
 | 
						|
 | 
						|
    SitePermissions.removeFromPrincipal(principal, "geo", browser);
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
// Test that persistent permissions in first party affect the third party
 | 
						|
// iframe.
 | 
						|
add_task(async function testUsePersistentPermissionsFirstParty() {
 | 
						|
  await BrowserTestUtils.withNewTab(CROSS_SUBFRAME_PAGE, async function(
 | 
						|
    browser
 | 
						|
  ) {
 | 
						|
    async function checkPermission(aPermission, aExpect) {
 | 
						|
      PermissionTestUtils.add(uri, "geo", aPermission);
 | 
						|
      await checkGeolocation(browser, "frame", aExpect);
 | 
						|
 | 
						|
      if (aExpect == PromptResult.PROMPT) {
 | 
						|
        // Notification is shown, check label and deny to clean
 | 
						|
        let popuphidden = BrowserTestUtils.waitForEvent(
 | 
						|
          PopupNotifications.panel,
 | 
						|
          "popuphidden"
 | 
						|
        );
 | 
						|
 | 
						|
        let notification = PopupNotifications.panel.firstElementChild;
 | 
						|
        // Check the label of the notificaiton should be the first party
 | 
						|
        is(
 | 
						|
          PopupNotifications.getNotification("geolocation").options.name,
 | 
						|
          uri.host,
 | 
						|
          "Use first party's origin"
 | 
						|
        );
 | 
						|
 | 
						|
        EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
 | 
						|
 | 
						|
        await popuphidden;
 | 
						|
        SitePermissions.removeFromPrincipal(null, "geo", browser);
 | 
						|
      }
 | 
						|
 | 
						|
      PermissionTestUtils.remove(uri, "geo");
 | 
						|
    }
 | 
						|
 | 
						|
    await checkPermission(Perms.PROMPT_ACTION, PromptResult.PROMPT);
 | 
						|
    await checkPermission(Perms.DENY_ACTION, PromptResult.DENY);
 | 
						|
    await checkPermission(Perms.ALLOW_ACTION, PromptResult.ALLOW);
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
// Test that we do not prompt for maybe unsafe permission delegation if the
 | 
						|
// origin of the page is the original src origin.
 | 
						|
add_task(async function testPromptInMaybeUnsafePermissionDelegation() {
 | 
						|
  await BrowserTestUtils.withNewTab(CROSS_SUBFRAME_PAGE, async function(
 | 
						|
    browser
 | 
						|
  ) {
 | 
						|
    // Persistent allow top level origin
 | 
						|
    PermissionTestUtils.add(uri, "geo", Perms.ALLOW_ACTION);
 | 
						|
 | 
						|
    await checkGeolocation(browser, "frameAllowsAll", PromptResult.ALLOW);
 | 
						|
 | 
						|
    SitePermissions.removeFromPrincipal(null, "geo", browser);
 | 
						|
    PermissionTestUtils.remove(uri, "geo");
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
// Test that we should prompt if we are in unsafe permission delegation and
 | 
						|
// change location to origin which is not explicitly trusted. The prompt popup
 | 
						|
// should include both first and third party origin.
 | 
						|
add_task(async function testPromptChangeLocationUnsafePermissionDelegation() {
 | 
						|
  await BrowserTestUtils.withNewTab(CROSS_SUBFRAME_PAGE, async function(
 | 
						|
    browser
 | 
						|
  ) {
 | 
						|
    // Persistent allow top level origin
 | 
						|
    PermissionTestUtils.add(uri, "geo", Perms.ALLOW_ACTION);
 | 
						|
 | 
						|
    let iframe = await SpecialPowers.spawn(browser, [], () => {
 | 
						|
      return content.document.getElementById("frameAllowsAll").browsingContext;
 | 
						|
    });
 | 
						|
 | 
						|
    let otherURI =
 | 
						|
      "https://test1.example.com/browser/browser/base/content/test/permissions/permissions.html";
 | 
						|
    let loaded = BrowserTestUtils.browserLoaded(browser, true, otherURI);
 | 
						|
    await SpecialPowers.spawn(iframe, [otherURI], async function(_otherURI) {
 | 
						|
      content.location = _otherURI;
 | 
						|
    });
 | 
						|
    await loaded;
 | 
						|
 | 
						|
    await checkGeolocation(browser, "frameAllowsAll", PromptResult.PROMPT);
 | 
						|
    await checkNotificationBothOrigins(uri.host, "test1.example.com");
 | 
						|
 | 
						|
    SitePermissions.removeFromPrincipal(null, "geo", browser);
 | 
						|
    PermissionTestUtils.remove(uri, "geo");
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
// If we are in unsafe permission delegation and the origin is explicitly
 | 
						|
// trusted in ancestor chain. Do not need prompt
 | 
						|
add_task(async function testExplicitlyAllowedInChain() {
 | 
						|
  await BrowserTestUtils.withNewTab(CROSS_FRAME_PAGE, async function(browser) {
 | 
						|
    // Persistent allow top level origin
 | 
						|
    PermissionTestUtils.add(uri, "geo", Perms.ALLOW_ACTION);
 | 
						|
 | 
						|
    let iframeAncestor = await SpecialPowers.spawn(browser, [], () => {
 | 
						|
      return content.document.getElementById("frameAncestor").browsingContext;
 | 
						|
    });
 | 
						|
 | 
						|
    let iframe = await SpecialPowers.spawn(iframeAncestor, [], () => {
 | 
						|
      return content.document.getElementById("frameAllowsAll").browsingContext;
 | 
						|
    });
 | 
						|
 | 
						|
    // Change location to check that we actually look at the ancestor chain
 | 
						|
    // instead of just considering the "same origin as src" rule.
 | 
						|
    let otherURI =
 | 
						|
      "https://test2.example.com/browser/browser/base/content/test/permissions/permissions.html";
 | 
						|
    let loaded = BrowserTestUtils.browserLoaded(browser, true, otherURI);
 | 
						|
    await SpecialPowers.spawn(iframe, [otherURI], async function(_otherURI) {
 | 
						|
      content.location = _otherURI;
 | 
						|
    });
 | 
						|
    await loaded;
 | 
						|
 | 
						|
    await checkGeolocation(
 | 
						|
      iframeAncestor,
 | 
						|
      "frameAllowsAll",
 | 
						|
      PromptResult.ALLOW
 | 
						|
    );
 | 
						|
 | 
						|
    PermissionTestUtils.remove(uri, "geo");
 | 
						|
  });
 | 
						|
});
 |