diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index a7d937fd3c..60078a8fcb 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -2094,7 +2094,10 @@ CanvasRenderingContext2D::GetInputStream(const char* aMimeType, bool PoisonData = Preferences::GetBool("canvas.poisondata",false); if (PoisonData) { - srand(time(NULL)); + int PoisonInterval = Preferences::GetInt("canvas.poisondata.interval", 300); + PoisonInterval = (PoisonInterval < 1) ? 1 : (PoisonInterval > 28800) ? 28800 : PoisonInterval; + unsigned int epoch = time(nullptr); + srand(epoch / PoisonInterval); // Image buffer is always a packed BGRA array (BGRX -> BGR[FF]) // so always 4-byte pixels. // GetImageBuffer => SurfaceToPackedBGRA [=> ConvertBGRXToBGRA] @@ -5775,9 +5778,13 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx, MOZ_ASSERT(aWidth && aHeight); - bool PoisonData = Preferences::GetBool("canvas.poisondata",false); - if (PoisonData) - srand(time(NULL)); + bool PoisonData = Preferences::GetBool("canvas.poisondata", false); + if (PoisonData) { + int PoisonInterval = Preferences::GetInt("canvas.poisondata.interval", 300); + PoisonInterval = (PoisonInterval < 1) ? 1 : (PoisonInterval > 28800) ? 28800 : PoisonInterval; + unsigned int epoch = time(nullptr); + srand(epoch / PoisonInterval); + } CheckedInt len = CheckedInt(aWidth) * aHeight * 4; if (!len.isValid()) { diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 682000aaf2..56c82aa1d9 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4305,6 +4305,9 @@ pref("canvas.image.cache.limit", 0); // Allow track-fobics to deliberately poison canvas data for // toDataURL() and getImageData() pref("canvas.poisondata", false); +// Rotate randomness of data poisoning every n seconds. Default 5 minutes. +// Valid range [1..28800] (1s-8h). +pref("canvas.poisondata.interval", 300); // WebGL prefs pref("gl.msaa-level", 2);