commit 79db24856a23ec7ae1f6d8cf46919a499ae5bb9f Author: Arthur Edelstein arthuredelstein@gmail.com Date: Wed Aug 29 09:56:57 2018 -0700
Bug 26670: Make canvas permission respect FPI --- browser/base/content/browser.js | 21 ++++++++++++--------- dom/canvas/CanvasUtils.cpp | 23 ++++++++++++++++------- dom/ipc/PBrowser.ipdl | 4 ++-- dom/ipc/TabParent.cpp | 4 ++-- dom/ipc/TabParent.h | 2 +- 5 files changed, 33 insertions(+), 21 deletions(-)
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index fbfbf3e809ca..443619533567 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -6824,7 +6824,7 @@ var CanvasPermissionPromptHelper = { },
// aSubject is an nsIBrowser (e10s) or an nsIDOMWindow (non-e10s). - // aData is an URL string. + // aData is an Origin string. observe(aSubject, aTopic, aData) { if (aTopic != this._permissionsPrompt) { return; @@ -6838,7 +6838,6 @@ var CanvasPermissionPromptHelper = { browser = aSubject.QueryInterface(Ci.nsIBrowser); }
- let uri = Services.io.newURI(aData); if (gBrowser.selectedBrowser !== browser) { // Must belong to some other window. return; @@ -6846,17 +6845,21 @@ var CanvasPermissionPromptHelper = {
let message = gNavigatorBundle.getFormattedString("canvas.siteprompt", ["<>"], 1);
- function setCanvasPermission(aURI, aPerm, aPersistent) { - Services.perms.add(aURI, "canvas", aPerm, - aPersistent ? Ci.nsIPermissionManager.EXPIRE_NEVER - : Ci.nsIPermissionManager.EXPIRE_SESSION); + let principal = Services.scriptSecurityManager + .createCodebasePrincipalFromOrigin(aData); + + function setCanvasPermission(aPerm, aPersistent) { + Services.perms.addFromPrincipal( + principal, "canvas", aPerm, + aPersistent ? Ci.nsIPermissionManager.EXPIRE_NEVER + : Ci.nsIPermissionManager.EXPIRE_SESSION); }
let mainAction = { label: gNavigatorBundle.getString("canvas.allow"), accessKey: gNavigatorBundle.getString("canvas.allow.accesskey"), callback(state) { - setCanvasPermission(uri, Ci.nsIPermissionManager.ALLOW_ACTION, + setCanvasPermission(Ci.nsIPermissionManager.ALLOW_ACTION, state && state.checkboxChecked); } }; @@ -6865,7 +6868,7 @@ var CanvasPermissionPromptHelper = { label: gNavigatorBundle.getString("canvas.notAllow"), accessKey: gNavigatorBundle.getString("canvas.notAllow.accesskey"), callback(state) { - setCanvasPermission(uri, Ci.nsIPermissionManager.DENY_ACTION, + setCanvasPermission(Ci.nsIPermissionManager.DENY_ACTION, state && state.checkboxChecked); } }]; @@ -6881,7 +6884,7 @@ var CanvasPermissionPromptHelper = {
let options = { checkbox, - name: uri.asciiHost, + name: principal.URI.host, learnMoreURL: Services.urlFormatter.formatURLPref("app.support.baseURL") + "fingerprint-permission", }; PopupNotifications.show(browser, aTopic, message, this._notificationIcon, diff --git a/dom/canvas/CanvasUtils.cpp b/dom/canvas/CanvasUtils.cpp index 0a8d7f0e2e59..ca8d91d92181 100644 --- a/dom/canvas/CanvasUtils.cpp +++ b/dom/canvas/CanvasUtils.cpp @@ -58,8 +58,13 @@ bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx) // Documents with system principal can always extract canvas data. nsPIDOMWindowOuter *win = aDocument->GetWindow(); nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win)); - if (sop && nsContentUtils::IsSystemPrincipal(sop->GetPrincipal())) { - return true; + if (!sop) { + return false; + } + + nsCOMPtr<nsIPrincipal> principal(sop->GetPrincipal()); + if (principal && nsContentUtils::IsSystemPrincipal(principal)) { + return true; }
// Always give permission to chrome scripts (e.g. Page Inspector). @@ -127,9 +132,9 @@ bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx) // Check if the site has permission to extract canvas data. // Either permit or block extraction if a stored permission setting exists. uint32_t permission; - rv = permissionManager->TestPermission(topLevelDocURI, - PERMISSION_CANVAS_EXTRACT_DATA, - &permission); + rv = permissionManager->TestPermissionFromPrincipal(principal, + PERMISSION_CANVAS_EXTRACT_DATA, + &permission); NS_ENSURE_SUCCESS(rv, false); switch (permission) { case nsIPermissionManager::ALLOW_ACTION: @@ -165,16 +170,20 @@ bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx) nsContentUtils::LogMessageToConsole(message.get());
// Prompt the user (asynchronous). + nsAutoCString origin; + rv = principal->GetOrigin(origin); + NS_ENSURE_SUCCESS(rv, false); + if (XRE_IsContentProcess()) { TabChild* tabChild = TabChild::GetFrom(win); if (tabChild) { - tabChild->SendShowCanvasPermissionPrompt(topLevelDocURISpec); + tabChild->SendShowCanvasPermissionPrompt(origin); } } else { nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->NotifyObservers(win, TOPIC_CANVAS_PERMISSIONS_PROMPT, - NS_ConvertUTF8toUTF16(topLevelDocURISpec).get()); + NS_ConvertUTF8toUTF16(origin).get()); } }
diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 024ebc5b6cf7..118eaf15af1f 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -579,9 +579,9 @@ parent: * This function is used to notify the parent that it should display a * canvas permission prompt. * - * @param aFirstPartyURI first party of the tab that is requesting access. + * @param aOrigin origin string of the document that is requesting access. */ - async ShowCanvasPermissionPrompt(nsCString aFirstPartyURI); + async ShowCanvasPermissionPrompt(nsCString aOrigin);
child: /** diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 86bb854962be..d8f4567626e1 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -3567,7 +3567,7 @@ TabParent::RecvLookUpDictionary(const nsString& aText, }
mozilla::ipc::IPCResult -TabParent::RecvShowCanvasPermissionPrompt(const nsCString& aFirstPartyURI) +TabParent::RecvShowCanvasPermissionPrompt(const nsCString& aOrigin) { nsCOMPtr<nsIBrowser> browser = do_QueryInterface(mFrameElement); if (!browser) { @@ -3580,7 +3580,7 @@ TabParent::RecvShowCanvasPermissionPrompt(const nsCString& aFirstPartyURI) return IPC_FAIL_NO_REASON(this); } nsresult rv = os->NotifyObservers(browser, "canvas-permissions-prompt", - NS_ConvertUTF8toUTF16(aFirstPartyURI).get()); + NS_ConvertUTF8toUTF16(aOrigin).get()); if (NS_FAILED(rv)) { return IPC_FAIL_NO_REASON(this); } diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 7d62663835d7..6f3d6de10c10 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -631,7 +631,7 @@ protected:
virtual mozilla::ipc::IPCResult RecvGetTabCount(uint32_t* aValue) override;
- virtual mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(const nsCString& aFirstPartyURI) override; + virtual mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(const nsCString& aOrigin) override;
ContentCacheInParent mContentCache;