Bug 1376865 Automatically decline the canvas permission if it is not in response to user input r?baku
The canvas prompt is extremely annoying. It happens everyone, automatically. And in
99.9% (not scientific) of cases it is not triggered by user input, but my automatic
tracking scripts.
This commit will automatically decline the canvas read if it was not triggered by
user input.
Just in case this breaks something irrepairably, we have a cutoff pref.
We don't intend to keep this pref forever, and have asked anyone who sets it to
tell us why.
MozReview-Commit-ID: CxNkuraRWpV
--- a/dom/base/DOMPrefsInternal.h
+++ b/dom/base/DOMPrefsInternal.h
@@ -33,16 +33,17 @@ DOM_PREF(PromiseRejectionEventsEnabled,
DOM_PREF(PushEnabled, "dom.push.enabled")
DOM_PREF(StreamsEnabled, "dom.streams.enabled")
DOM_PREF(RequestContextEnabled, "dom.requestcontext.enabled")
DOM_PREF(OffscreenCanvasEnabled, "gfx.offscreencanvas.enabled")
DOM_PREF(WebkitBlinkDirectoryPickerEnabled, "dom.webkitBlink.dirPicker.enabled")
DOM_PREF(NetworkInformationEnabled, "dom.netinfo.enabled")
DOM_PREF(FetchObserverEnabled, "dom.fetchObserver.enabled")
DOM_PREF(ResistFingerprintingEnabled, "privacy.resistFingerprinting")
+DOM_PREF(EnableAutoDeclineCanvasPrompts, "privacy.resistFingerprinting.autoDeclineNoUserInputCanvasPrompts")
DOM_PREF(DevToolsEnabled, "devtools.enabled")
DOM_PREF(PerformanceObserverEnabled, "dom.enable_performance_observer")
DOM_WEBIDL_PREF(ImageBitmapExtensionsEnabled)
DOM_WEBIDL_PREF(DOMCachesEnabled)
DOM_WEBIDL_PREF(NotificationEnabledInServiceWorkers)
DOM_WEBIDL_PREF(NotificationRIEnabled)
DOM_WEBIDL_PREF(ServiceWorkersEnabled)
--- a/dom/canvas/CanvasUtils.cpp
+++ b/dom/canvas/CanvasUtils.cpp
@@ -9,16 +9,17 @@
#include "nsIServiceManager.h"
#include "nsIConsoleService.h"
#include "nsIDOMCanvasRenderingContext2D.h"
#include "nsICanvasRenderingContextInternal.h"
#include "nsIHTMLCollection.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/dom/TabChild.h"
+#include "mozilla/EventStateManager.h"
#include "nsIPrincipal.h"
#include "nsGfxCIID.h"
#include "nsTArray.h"
#include "CanvasUtils.h"
#include "mozilla/gfx/Matrix.h"
@@ -137,18 +138,33 @@ bool IsImageExtractionAllowed(nsIDocumen
return true;
case nsIPermissionManager::DENY_ACTION:
return false;
default:
break;
}
// At this point, permission is unknown (nsIPermissionManager::UNKNOWN_ACTION).
+
+ // Check if the request is in response to user input
+ if (DOMPrefs::EnableAutoDeclineCanvasPrompts() && !EventStateManager::IsHandlingUserInput()) {
+ nsAutoCString message;
+ message.AppendPrintf("Blocked %s in page %s from extracting canvas data because no user input was detected.",
+ docURISpec.get(), topLevelDocURISpec.get());
+ if (isScriptKnown) {
+ message.AppendPrintf(" %s:%u.", scriptFile.get(), scriptLine);
+ }
+ nsContentUtils::LogMessageToConsole(message.get());
+
+ return false;
+ }
+
+ // It was in response to user input, so log and display the prompt.
nsAutoCString message;
- message.AppendPrintf("Blocked %s in page %s from extracting canvas data.",
+ message.AppendPrintf("Blocked %s in page %s from extracting canvas data, but prompting the user.",
docURISpec.get(), topLevelDocURISpec.get());
if (isScriptKnown) {
message.AppendPrintf(" %s:%u.", scriptFile.get(), scriptLine);
}
nsContentUtils::LogMessageToConsole(message.get());
// Prompt the user (asynchronous).
if (XRE_IsContentProcess()) {
--- a/dom/ipc/ContentPrefs.cpp
+++ b/dom/ipc/ContentPrefs.cpp
@@ -283,16 +283,17 @@ const char* mozilla::dom::ContentPrefs::
"network.tcp.keepalive.retry_interval",
"network.tcp.sendbuffer",
"nglayout.debug.invalidation",
"privacy.donottrackheader.enabled",
"privacy.firstparty.isolate",
"privacy.firstparty.isolate.restrict_opener_access",
"privacy.reduceTimerPrecision",
"privacy.resistFingerprinting",
+ "privacy.resistFingerprinting.autoDeclineNoUserInputCanvasPrompts",
"privacy.resistFingerprinting.reduceTimerPrecision.microseconds",
"privacy.resistFingerprinting.target_video_res",
"privacy.resistFingerprinting.video_dropped_ratio",
"privacy.resistFingerprinting.video_frames_per_sec",
"privacy.trackingprotection.lower_network_priority",
"privacy.window.maxInnerHeight",
"privacy.window.maxInnerWidth",
"security.csp.enable",
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1395,16 +1395,22 @@ pref("privacy.trackingprotection.annotat
// First Party Isolation (double keying), disabled by default
pref("privacy.firstparty.isolate", false);
// If false, two windows in the same domain with different first party domains
// (top level URLs) can access resources through window.opener.
// This pref is effective only when "privacy.firstparty.isolate" is true.
pref("privacy.firstparty.isolate.restrict_opener_access", true);
// Anti-fingerprinting, disabled by default
pref("privacy.resistFingerprinting", false);
+// We automatically decline canvas permission requests if they are not initiated
+// from user input. Just in case that breaks something, we allow the user to revert
+// this behaior with this obscure pref. We do not intend to support this long term.
+// If you do set it, to work around some broken website, please file a bug with
+// information so we can understand why it is needed.
+pref("privacy.resistFingerprinting.autoDeclineNoUserInputCanvasPrompts", true);
// A subset of Resist Fingerprinting protections focused specifically on timers for testing
// This affects the Animation API, the performance APIs, Date.getTime, Event.timestamp,
// File.lastModified, audioContext.currentTime, canvas.captureStream.currentTime
pref("privacy.reduceTimerPrecision", true);
// Dynamically tune the resolution of the timer reduction for both of the two above prefs
pref("privacy.resistFingerprinting.reduceTimerPrecision.microseconds", 2000);
// Lower the priority of network loads for resources on the tracking protection list.
// Note that this requires the privacy.trackingprotection.annotate_channels pref to be on in order to have any effect.