content/canvas/src/CanvasUtils.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include <stdlib.h>
     7 #include <stdarg.h>
     9 #include "prprf.h"
    11 #include "nsIServiceManager.h"
    13 #include "nsIConsoleService.h"
    14 #include "nsIDOMCanvasRenderingContext2D.h"
    15 #include "nsICanvasRenderingContextInternal.h"
    16 #include "nsIHTMLCollection.h"
    17 #include "mozilla/dom/HTMLCanvasElement.h"
    18 #include "nsIPrincipal.h"
    20 #include "nsGfxCIID.h"
    22 #include "nsTArray.h"
    24 #include "CanvasUtils.h"
    25 #include "mozilla/gfx/Matrix.h"
    27 using namespace mozilla::gfx;
    29 #include "nsIScriptObjectPrincipal.h"
    30 #include "nsIPermissionManager.h"
    31 #include "nsIObserverService.h"
    32 #include "mozilla/Services.h"
    33 #include "mozIThirdPartyUtil.h"
    34 #include "nsContentUtils.h"
    35 #include "nsUnicharUtils.h"
    36 #include "nsPrintfCString.h"
    37 #include "nsIConsoleService.h"
    38 #include "jsapi.h"
    40 #define TOPIC_CANVAS_PERMISSIONS_PROMPT "canvas-permissions-prompt"
    41 #define PERMISSION_CANVAS_EXTRACT_DATA "canvas/extractData"
    43 namespace mozilla {
    44 namespace CanvasUtils {
    46 // Check site-specific permission and display prompt if appropriate.
    47 bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx)
    48 {
    49   if (!aDocument || !aCx)
    50     return false;
    52   nsPIDOMWindow *win = aDocument->GetWindow();
    53   nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
    54   if (sop && nsContentUtils::IsSystemPrincipal(sop->GetPrincipal()))
    55     return true;
    57   // Don't show canvas prompt for chrome scripts (e.g. Page Inspector)
    58   if (nsContentUtils::IsCallerChrome())
    59     return true;
    61   JS::AutoFilename scriptFile;
    62   unsigned scriptLine = 0;
    63   bool isScriptKnown = false;
    64   if (JS::DescribeScriptedCaller(aCx, &scriptFile, &scriptLine)) {
    65     isScriptKnown = true;
    66     // Don't show canvas prompt for PDF.js
    67     if (scriptFile.get() &&
    68         strcmp(scriptFile.get(), "resource://pdf.js/build/pdf.js") == 0)
    69       return true;
    70   }
    71   bool isAllowed = false;
    72   nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
    73                                 do_GetService(THIRDPARTYUTIL_CONTRACTID);
    74   nsCOMPtr<nsIPermissionManager> permissionManager =
    75                           do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
    76   if (thirdPartyUtil && permissionManager) {
    77     nsCOMPtr<nsIURI> uri;
    78     nsresult rv = thirdPartyUtil->GetFirstPartyURI(NULL, aDocument,
    79                                                    getter_AddRefs(uri));
    80     uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
    81     if (NS_SUCCEEDED(rv)) {
    82       // Allow local files to access canvas data; check content permissions
    83       // for remote pages.
    84       bool isFileURL = false;
    85       (void)uri->SchemeIs("file", &isFileURL);
    86       if (isFileURL)
    87         permission = nsIPermissionManager::ALLOW_ACTION;
    88       else {
    89         rv = permissionManager->TestPermission(uri,
    90                                 PERMISSION_CANVAS_EXTRACT_DATA, &permission);
    91       }
    92     }
    94     if (NS_SUCCEEDED(rv)) {
    95       isAllowed = (permission == nsIPermissionManager::ALLOW_ACTION);
    97       if (!isAllowed && (permission != nsIPermissionManager::DENY_ACTION)) {
    98         // Log all attempted canvas access and block access by third parties.
    99         bool isThirdParty = true;
   100         nsIURI *docURI = aDocument->GetDocumentURI();
   101         rv = thirdPartyUtil->IsThirdPartyURI(uri, docURI, &isThirdParty);
   102         NS_ENSURE_SUCCESS(rv, false);
   104         nsCString firstPartySpec;
   105         rv = uri->GetSpec(firstPartySpec);
   106         nsCString docSpec;
   107         docURI->GetSpec(docSpec);
   108         nsPrintfCString msg("On %s: blocked access to canvas image data"
   109                             " from document %s, ",  // L10n
   110                             firstPartySpec.get(), docSpec.get());
   111         if (isScriptKnown && scriptFile.get()) {
   112           msg += nsPrintfCString("script from %s:%u",  // L10n
   113                                  scriptFile.get(), scriptLine);
   114         } else {
   115           msg += nsPrintfCString("unknown script");  // L10n
   116         }
   117         nsCOMPtr<nsIConsoleService> console
   118                               (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   119         if (console)
   120           console->LogStringMessage(NS_ConvertUTF8toUTF16(msg).get());
   122         // Log every canvas access attempt to stdout if debugging:
   123 #ifdef DEBUG
   124         printf("%s\n", msg.get());
   125 #endif
   126         // Ensure URI is valid after logging, but before trying to notify the
   127         // user:
   128         NS_ENSURE_SUCCESS(rv, false);
   130         if (!isThirdParty) {
   131           // Send notification so that a prompt is displayed.
   132           nsCOMPtr<nsIObserverService> obs =
   133                                        mozilla::services::GetObserverService();
   134           obs->NotifyObservers(win, TOPIC_CANVAS_PERMISSIONS_PROMPT,
   135                                NS_ConvertUTF8toUTF16(firstPartySpec).get());
   136         }
   137       }
   138     }
   139   }
   141   return isAllowed;
   142 }
   144 void
   145 DoDrawImageSecurityCheck(dom::HTMLCanvasElement *aCanvasElement,
   146                          nsIPrincipal *aPrincipal,
   147                          bool forceWriteOnly,
   148                          bool CORSUsed)
   149 {
   150     NS_PRECONDITION(aPrincipal, "Must have a principal here");
   152     // Callers should ensure that mCanvasElement is non-null before calling this
   153     if (!aCanvasElement) {
   154         NS_WARNING("DoDrawImageSecurityCheck called without canvas element!");
   155         return;
   156     }
   158     if (aCanvasElement->IsWriteOnly())
   159         return;
   161     // If we explicitly set WriteOnly just do it and get out
   162     if (forceWriteOnly) {
   163         aCanvasElement->SetWriteOnly();
   164         return;
   165     }
   167     // No need to do a security check if the image used CORS for the load
   168     if (CORSUsed)
   169         return;
   171     if (aCanvasElement->NodePrincipal()->Subsumes(aPrincipal)) {
   172         // This canvas has access to that image anyway
   173         return;
   174     }
   176     aCanvasElement->SetWriteOnly();
   177 }
   179 bool
   180 CoerceDouble(JS::Value v, double* d)
   181 {
   182     if (JSVAL_IS_DOUBLE(v)) {
   183         *d = JSVAL_TO_DOUBLE(v);
   184     } else if (JSVAL_IS_INT(v)) {
   185         *d = double(JSVAL_TO_INT(v));
   186     } else if (JSVAL_IS_VOID(v)) {
   187         *d = 0.0;
   188     } else {
   189         return false;
   190     }
   191     return true;
   192 }
   194 } // namespace CanvasUtils
   195 } // namespace mozilla

mercurial