$OpenBSD$ index 1a38477..5a6e05e 100644 --- content/canvas/src/CanvasUtils.cpp.orig Fri Feb 20 15:40:36 2015 +++ content/canvas/src/CanvasUtils.cpp Fri Feb 20 15:40:36 2015 @@ -26,9 +26,121 @@ using namespace mozilla::gfx; +#include "nsIScriptObjectPrincipal.h" +#include "nsIPermissionManager.h" +#include "nsIObserverService.h" +#include "mozilla/Services.h" +#include "mozIThirdPartyUtil.h" +#include "nsContentUtils.h" +#include "nsUnicharUtils.h" +#include "nsPrintfCString.h" +#include "nsIConsoleService.h" +#include "jsapi.h" + +#define TOPIC_CANVAS_PERMISSIONS_PROMPT "canvas-permissions-prompt" +#define PERMISSION_CANVAS_EXTRACT_DATA "canvas/extractData" + namespace mozilla { namespace CanvasUtils { +// Check site-specific permission and display prompt if appropriate. +bool IsImageExtractionAllowed(nsIDocument *aDocument, JSContext *aCx) +{ + if (!aDocument || !aCx) + return false; + + nsPIDOMWindow *win = aDocument->GetWindow(); + nsCOMPtr 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::IsCallerChrome()) + 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 thirdPartyUtil = + do_GetService(THIRDPARTYUTIL_CONTRACTID); + nsCOMPtr permissionManager = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + if (thirdPartyUtil && permissionManager) { + nsCOMPtr 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); + } + } + + 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 + } + nsCOMPtr 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 obs = + mozilla::services::GetObserverService(); + obs->NotifyObservers(win, TOPIC_CANVAS_PERMISSIONS_PROMPT, + NS_ConvertUTF8toUTF16(firstPartySpec).get()); + } + } + } + } + + return isAllowed; +} + void DoDrawImageSecurityCheck(dom::HTMLCanvasElement *aCanvasElement, nsIPrincipal *aPrincipal,