commit 79db24856a23ec7ae1f6d8cf46919a499ae5bb9f
Author: Arthur Edelstein <arthuredelstein(a)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;