author | Chung-Sheng Fu <cfu@mozilla.com> |
Wed, 23 Aug 2017 16:32:41 +0800 | |
changeset 386119 | 11d5208791fed061fdeb0e0ecd031dbcf676bf12 |
parent 386118 | 1e1c64f987b708e95a62beb39313ff6c637287de |
child 386120 | e0f3918c6e30229d4c69d7288c943a3709a6a4f7 |
push id | 53266 |
push user | ryanvm@gmail.com |
push date | Fri, 13 Oct 2017 15:34:43 +0000 |
treeherder | autoland@11d5208791fe [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | johannh |
bugs | 967895 |
milestone | 58.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/base/content/test/permissions/browser.ini +++ b/browser/base/content/test/permissions/browser.ini @@ -1,13 +1,14 @@ [DEFAULT] support-files= head.js permissions.html +[browser_canvas_fingerprinting_resistance.js] [browser_permissions.js] [browser_temporary_permissions.js] support-files = temporary_permissions_subframe.html ../webrtc/get_user_media.html [browser_temporary_permissions_expiry.js] [browser_temporary_permissions_navigation.js] [browser_temporary_permissions_tabs.js]
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/permissions/browser_canvas_fingerprinting_resistance.js @@ -0,0 +1,122 @@ +/** + * When "privacy.resistFingerprinting" is set to true, user permission is + * required for canvas data extraction. + * This tests whether the site permission prompt for canvas data extraction + * works properly. + */ +"use strict"; + +const kUrl = "https://example.com/"; +const kPrincipal = Components.classes["@mozilla.org/scriptsecuritymanager;1"] + .getService(Ci.nsIScriptSecurityManager) + .createCodebasePrincipal(Services.io.newURI(kUrl), {}); +const kPermission = "canvas/extractData"; + +function initTab() { + let contentWindow = content.wrappedJSObject; + + let drawCanvas = (fillStyle, id) => { + let contentDocument = contentWindow.document; + let width = 64, height = 64; + let canvas = contentDocument.createElement("canvas"); + if (id) { + canvas.setAttribute("id", id); + } + canvas.setAttribute("width", width); + canvas.setAttribute("height", height); + contentDocument.body.appendChild(canvas); + + let context = canvas.getContext("2d"); + context.fillStyle = fillStyle; + context.fillRect(0, 0, width, height); + + return canvas; + }; + + let placeholder = drawCanvas("white"); + contentWindow.kPlaceholderData = placeholder.toDataURL(); + let canvas = drawCanvas("cyan", "canvas-id-canvas"); + isnot(canvas.toDataURL(), contentWindow.kPlaceholderData, + "privacy.resistFingerprinting = false, canvas data != placeholder data"); +} + +function enableResistFingerprinting() { + return SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.resistFingerprinting", true] + ] + }); +} + +function promisePopupShown() { + return BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown") +} + +function promisePopupHidden() { + return BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden") +} + +function extractCanvasData(grantPermission) { + let contentWindow = content.wrappedJSObject; + let canvas = contentWindow.document.getElementById("canvas-id-canvas"); + let canvasData = canvas.toDataURL(); + if (grantPermission) { + isnot(canvasData, contentWindow.kPlaceholderData, + "privacy.resistFingerprinting = true, permission granted, canvas data != placeholderdata"); + } else if (grantPermission === false) { + is(canvasData, contentWindow.kPlaceholderData, + "privacy.resistFingerprinting = true, permission denied, canvas data == placeholderdata"); + } else { + is(canvasData, contentWindow.kPlaceholderData, + "privacy.resistFingerprinting = true, requesting permission, canvas data == placeholderdata"); + } +} + +function triggerCommand(button) { + let notifications = PopupNotifications.panel.childNodes; + let notification = notifications[0]; + EventUtils.synthesizeMouseAtCenter(notification[button], {}); +} + +function triggerMainCommand() { + triggerCommand("button"); +} + +function triggerSecondaryCommand() { + triggerCommand("secondaryButton"); +} + +function testPermission() { + return Services.perms.testPermissionFromPrincipal(kPrincipal, kPermission); +} + +async function withNewTab(grantPermission, browser) { + await ContentTask.spawn(browser, null, initTab); + await enableResistFingerprinting(); + let popupShown = promisePopupShown(); + await ContentTask.spawn(browser, null, extractCanvasData); + await popupShown; + let popupHidden = promisePopupHidden(); + if (grantPermission) { + triggerMainCommand(); + await popupHidden; + is(testPermission(), Services.perms.ALLOW_ACTION, "permission granted"); + } else { + triggerSecondaryCommand(); + await popupHidden; + is(testPermission(), Services.perms.DENY_ACTION, "permission denied"); + } + await ContentTask.spawn(browser, grantPermission, extractCanvasData); + await SpecialPowers.popPrefEnv(); +} + +async function doTest(grantPermission) { + Services.perms.removeFromPrincipal(kPrincipal, kPermission); + await BrowserTestUtils.withNewTab(kUrl, withNewTab.bind(null, grantPermission)); +} + +// Tests clicking "Don't Allow" button of the permission prompt. +add_task(doTest.bind(null, false)); + +// Tests clicking "Allow" button of the permission prompt. +add_task(doTest.bind(null, true));