[tbb-commits] [tor-browser/tor-browser-38.4.0esr-5.5-1] fixup! Bug #6253: Add canvas image extraction prompt.

gk at torproject.org gk at torproject.org
Mon Nov 16 13:32:38 UTC 2015


commit 57ff8d65a2ec29f778b5654b6b8284d2b20feb68
Author: Arthur Edelstein <arthuredelstein at gmail.com>
Date:   Fri Nov 6 16:41:29 2015 -0800

    fixup! Bug #6253: Add canvas image extraction prompt.
    
    Ensure that third parties are never able to extract canvas
    image data, even if the same domain has been given
    permission previously as a first party.
    
    Also, refactor slightly to clarify logic of IsImageExtractionAllowed.
---
 dom/canvas/CanvasUtils.cpp |  179 +++++++++++++++++++++++---------------------
 1 file changed, 95 insertions(+), 84 deletions(-)

diff --git a/dom/canvas/CanvasUtils.cpp b/dom/canvas/CanvasUtils.cpp
index 9883a52..b3c83f6 100644
--- a/dom/canvas/CanvasUtils.cpp
+++ b/dom/canvas/CanvasUtils.cpp
@@ -46,99 +46,110 @@ namespace CanvasUtils {
 // Check site-specific permission and display prompt if appropriate.
 bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx)
 {
-  if (!aDocument || !aCx)
-    return false;
+    // Don't proceed if we don't have a document or JavaScript context.
+    if (!aDocument || !aCx) {
+        return false;
+    }
 
-  nsPIDOMWindow *win = aDocument->GetWindow();
-  nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
-  if (sop && nsContentUtils::IsSystemPrincipal(sop->GetPrincipal()))
-    return true;
+    // Documents with system principal can always extract canvas data.
+    nsPIDOMWindow *win = aDocument->GetWindow();
+    nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
+    if (sop && nsContentUtils::IsSystemPrincipal(sop->GetPrincipal())) {
+        return true;
+    }
 
-  // Don't show canvas prompt for chrome scripts (e.g. Page Inspector)
-  if (nsContentUtils::ThreadsafeIsCallerChrome())
-    return true;
+    // Always give permission to chrome scripts (e.g. Page Inspector).
+    if (nsContentUtils::ThreadsafeIsCallerChrome()) {
+        return true;
+    }
 
-  JS::AutoFilename scriptFile;
-  unsigned scriptLine = 0;
-  bool isScriptKnown = false;
-  if (JS::DescribeScriptedCaller(aCx, &scriptFile, &scriptLine)) {
-    isScriptKnown = true;
-    // Don't show canvas prompt for PDF.js
-    if (scriptFile.get() &&
-        strcmp(scriptFile.get(), "resource://pdf.js/build/pdf.js") == 0)
-      return true;
-  }
-  bool isAllowed = false;
-  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
-                                do_GetService(THIRDPARTYUTIL_CONTRACTID);
-  nsCOMPtr<nsIPermissionManager> permissionManager =
-                          do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
-  if (thirdPartyUtil && permissionManager) {
-    nsCOMPtr<nsIURI> uri;
-    nsresult rv = thirdPartyUtil->GetFirstPartyURI(NULL, aDocument,
-                                                   getter_AddRefs(uri));
-    uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
-    if (NS_SUCCEEDED(rv)) {
-      // Allow local files to access canvas data; check content permissions
-      // for remote pages.
-      bool isFileURL = false;
-      (void)uri->SchemeIs("file", &isFileURL);
-      if (isFileURL)
-        permission = nsIPermissionManager::ALLOW_ACTION;
-      else {
-        rv = permissionManager->TestPermission(uri,
-                                PERMISSION_CANVAS_EXTRACT_DATA, &permission);
-      }
+    // Get the document URI and its spec.
+    nsIURI *docURI = aDocument->GetDocumentURI();
+    nsCString docURISpec;
+    docURI->GetSpec(docURISpec);
+
+    // Allow local files to extract canvas data.
+    bool isFileURL;
+    (void) docURI->SchemeIs("file", &isFileURL);
+    if (isFileURL) {
+        return true;
     }
 
-    if (NS_SUCCEEDED(rv)) {
-      isAllowed = (permission == nsIPermissionManager::ALLOW_ACTION);
-
-      if (!isAllowed && (permission != nsIPermissionManager::DENY_ACTION)) {
-        // Log all attempted canvas access and block access by third parties.
-        bool isThirdParty = true;
-        nsIURI *docURI = aDocument->GetDocumentURI();
-        rv = thirdPartyUtil->IsThirdPartyURI(uri, docURI, &isThirdParty);
-        NS_ENSURE_SUCCESS(rv, false);
-
-        nsCString firstPartySpec;
-        rv = uri->GetSpec(firstPartySpec);
-        nsCString docSpec;
-        docURI->GetSpec(docSpec);
-        nsPrintfCString msg("On %s: blocked access to canvas image data"
-                            " from document %s, ",  // L10n
-                            firstPartySpec.get(), docSpec.get());
-        if (isScriptKnown && scriptFile.get()) {
-          msg += nsPrintfCString("script from %s:%u",  // L10n
-                                 scriptFile.get(), scriptLine);
-        } else {
-          msg += nsPrintfCString("unknown script");  // L10n
+    // Get calling script file and line for logging.
+    JS::AutoFilename scriptFile;
+    unsigned scriptLine = 0;
+    bool isScriptKnown = false;
+    if (JS::DescribeScriptedCaller(aCx, &scriptFile, &scriptLine)) {
+        isScriptKnown = true;
+        // Don't show canvas prompt for PDF.js
+        if (scriptFile.get() &&
+            strcmp(scriptFile.get(), "resource://pdf.js/build/pdf.js") == 0) {
+            return true;
         }
-        nsCOMPtr<nsIConsoleService> console
-                              (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
-        if (console)
-          console->LogStringMessage(NS_ConvertUTF8toUTF16(msg).get());
-
-        // Log every canvas access attempt to stdout if debugging:
-#ifdef DEBUG
-        printf("%s\n", msg.get());
-#endif
-        // Ensure URI is valid after logging, but before trying to notify the
-        // user:
-        NS_ENSURE_SUCCESS(rv, false);
-
-        if (!isThirdParty) {
-          // Send notification so that a prompt is displayed.
-          nsCOMPtr<nsIObserverService> obs =
-                                       mozilla::services::GetObserverService();
-          obs->NotifyObservers(win, TOPIC_CANVAS_PERMISSIONS_PROMPT,
-                               NS_ConvertUTF8toUTF16(firstPartySpec).get());
+    }
+
+    // Load Third Party Util service.
+    nsresult rv;
+    nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
+        do_GetService(THIRDPARTYUTIL_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, false);
+
+    // Get the First Party URI and its spec.
+    nsCOMPtr<nsIURI> firstPartyURI;
+    rv = thirdPartyUtil->GetFirstPartyURI(NULL, aDocument,
+                                                   getter_AddRefs(firstPartyURI));
+    NS_ENSURE_SUCCESS(rv, false);
+    nsCString firstPartySpec;
+    firstPartyURI->GetSpec(firstPartySpec);
+
+    // Block all third-party attempts to extract canvas.
+    bool isThirdParty = true;
+    rv = thirdPartyUtil->IsThirdPartyURI(firstPartyURI, docURI, &isThirdParty);
+    NS_ENSURE_SUCCESS(rv, false);
+    if (isThirdParty) {
+        nsAutoCString message;
+        message.AppendPrintf("Blocked third party %s in page %s from extracting canvas data.",
+                             docURISpec.get(), firstPartySpec.get());
+        if (isScriptKnown) {
+          message.AppendPrintf(" %s:%u.", scriptFile.get(), scriptLine);
         }
-      }
+        nsContentUtils::LogMessageToConsole(message.get());
+        return false;
+    }
+
+    // Load Permission Manager service.
+    nsCOMPtr<nsIPermissionManager> permissionManager =
+        do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+    NS_ENSURE_SUCCESS(rv, false);
+
+    // 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(firstPartyURI,
+                                           PERMISSION_CANVAS_EXTRACT_DATA, &permission);
+    NS_ENSURE_SUCCESS(rv, false);
+    if (permission == nsIPermissionManager::ALLOW_ACTION) {
+      return true;
+    } else if (permission == nsIPermissionManager::DENY_ACTION) {
+      return false;
     }
-  }
 
-  return isAllowed;
+    // At this point, permission is unknown (nsIPermissionManager::UNKNOWN_ACTION).
+    nsAutoCString message;
+    message.AppendPrintf("Blocked %s in page %s from extracting canvas data.",
+                         docURISpec.get(), firstPartySpec.get());
+    if (isScriptKnown) {
+      message.AppendPrintf(" %s:%u.", scriptFile.get(), scriptLine);
+    }
+    nsContentUtils::LogMessageToConsole(message.get());
+
+    // Prompt the user (asynchronous).
+    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+    obs->NotifyObservers(win, TOPIC_CANVAS_PERMISSIONS_PROMPT,
+                         NS_ConvertUTF8toUTF16(firstPartySpec).get());
+
+    // We don't extract the image for now -- user may override at prompt.
+    return false;
 }
 
 void





More information about the tbb-commits mailing list