Bug 1193593 - Test fingerprinting resistance for media queries in picture elements. r=heycam
authorArthur Edelstein <arthuredelstein@gmail.com>
Tue, 01 Sep 2015 08:51:00 -0400
changeset 260435 ca8973360b9d13e1cc2803ed15be12ae16414020
parent 260434 e2bef4367e192bac7bfd947ca9126452ec54ee30
child 260436 1d96862c8a6ae52231f0f5578707af61ecbd035c
push id64498
push userryanvm@gmail.com
push dateWed, 02 Sep 2015 02:21:12 +0000
treeherdermozilla-inbound@1d96862c8a6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1193593, 16315
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1193593 - Test fingerprinting resistance for media queries in picture elements. r=heycam Based on Tor Browser #16315 https://trac.torproject.org/projects/tor/ticket/16315
layout/style/test/chrome/bug418986-2.js
layout/style/test/chrome/chrome.ini
layout/style/test/chrome/match.png
layout/style/test/chrome/mismatch.png
layout/style/test/chrome/test_bug418986-2.xul
layout/style/test/mochitest.ini
layout/style/test/test_bug418986-2.html
--- a/layout/style/test/chrome/bug418986-2.js
+++ b/layout/style/test/chrome/bug418986-2.js
@@ -1,16 +1,14 @@
 // # Bug 418986, part 2.
 
 /* jshint esnext:true */
 /* jshint loopfunc:true */
 /* global window, screen, ok, SpecialPowers, matchMedia */
 
-SimpleTest.waitForExplicitFinish();
-
 // Expected values. Format: [name, pref_off_value, pref_on_value]
 // If pref_*_value is an array with two values, then we will match
 // any value in between those two values. If a value is null, then
 // we skip the media query.
 let expected_values = [
   ["color", null, 8],
   ["color-index", null, 0],
   ["aspect-ratio", null, window.innerWidth + "/" + window.innerHeight],
@@ -161,29 +159,32 @@ let generateHtmlLines = function (resist
 // __cssLine__.
 // Creates a line of css that looks something like
 // `@media (resolution: 1ppx) { .spoof#resolution { background-color: green; } }`.
 let cssLine = function (query, clazz, id, color) {
   return "@media " + query + " { ." + clazz +  "#" + id +
          " { background-color: " + color + "; } }\n";
 };
 
+// __constructQuery(key, val)__.
+// Creates a CSS media query from key and val. If key is an array of
+// two elements, constructs a range query (using min- and max-).
+let constructQuery = function (key, val) {
+  return Array.isArray(val) ?
+    "(min-" + key + ": " + val[0] + ") and (max-" +  key + ": " + val[1] + ")" :
+    "(" + key + ": " + val + ")";
+};
+
 // __mediaQueryCSSLine(key, val, color)__.
 // Creates a line containing a CSS media query and a CSS expression.
 let mediaQueryCSSLine = function (key, val, color) {
   if (val === null) {
     return "";
   }
-  let query;
-  if (Array.isArray(val)) {
-    query = "(min-" + key + ": " + val[0] + ") and (max-" +  key + ": " + val[1] + ")";
-  } else {
-    query = "(" + key + ": " + val + ")";
-  }
-  return cssLine(query, "spoof", key, color);
+  return cssLine(constructQuery(key, val), "spoof", key, color);
 };
 
 // __suppressedMediaQueryCSSLine(key, color)__.
 // Creates a CSS line that matches the existence of a
 // media query that is supposed to be suppressed.
 let suppressedMediaQueryCSSLine = function (key, color, suppressed) {
   let query = "(" + key + ": 0), (" + key + ": 1)";
   return cssLine(query, "suppress", key, color);
@@ -243,38 +244,72 @@ let testOSXFontSmoothing = function (res
   let div = document.createElement("div");
   div.style.MozOsxFontSmoothing = "unset";
   let readBack = window.getComputedStyle(div).MozOsxFontSmoothing;
   let smoothingPref = SpecialPowers.getBoolPref("layout.css.osx-font-smoothing.enabled", false);
   is(readBack, resisting ? "" : (smoothingPref ? "auto" : ""),
                "-moz-osx-font-smoothing");
 };
 
-// An iterator yielding pref values for two consecutive tests.
-let prefVals = (for (prefVal of [false, true]) prefVal);
+// __sleep(timeoutMs)__.
+// Returns a promise that resolves after the given timeout.
+let sleep = function (timeoutMs) {
+  return new Promise(function(resolve, reject) {
+    window.setTimeout(resolve);
+  });
+};
+
+// __testMediaQueriesInPictureElements(resisting)__.
+// Test to see if media queries are properly spoofed in picture elements
+// when we are resisting fingerprinting. A generator function
+// to be used with SpawnTask.js.
+let testMediaQueriesInPictureElements = function* (resisting) {
+  let lines = "";
+  for (let [key, offVal, onVal] of expected_values) {
+    let expected = resisting ? onVal : offVal;
+    if (expected) {
+      let query = constructQuery(key, expected);
+      lines += "<picture>\n";
+      lines += " <source srcset='/tests/layout/style/test/chrome/match.png' media='" + query + "' />\n";
+      lines += " <img title='" + key + ":" + expected + "' class='testImage' src='/tests/layout/style/test/chrome/mismatch.png' alt='" + key + "' />\n";
+      lines += "</picture><br/>\n";
+    }
+  }
+  document.getElementById("pictures").innerHTML = lines;
+  var testImages = document.getElementsByClassName("testImage");
+  yield sleep(0);
+  for (let testImage of testImages) {
+    ok(testImage.currentSrc.endsWith("/match.png"), "Media query '" + testImage.title + "' in picture should match.");
+  }
+};
+
+// __pushPref(key, value)__.
+// Set a pref value asynchronously, returning a promise that resolves
+// when it succeeds.
+let pushPref = function (key, value) {
+  return new Promise(function(resolve, reject) {
+    SpecialPowers.pushPrefEnv({"set": [[key, value]]}, resolve);
+  });
+};
 
 // __test(isContent)__.
-// Run all tests.
-let test = function(isContent) {
-  let {value: prefValue, done} = prefVals.next();
-  if (done) {
-    SimpleTest.finish();
-    return;
+// Run all tests. A generator function to be used
+// with SpawnTask.js.
+let test = function* (isContent) {
+  for (prefValue of [false, true]) {
+    yield pushPref("privacy.resistFingerprinting", prefValue);
+    let resisting = prefValue && isContent;
+    expected_values.forEach(
+      function ([key, offVal, onVal]) {
+        testMatch(key, resisting ? onVal : offVal);
+      });
+    testToggles(resisting);
+    if (OS === "WINNT") {
+      testWindowsSpecific(resisting, "-moz-os-version", windows_versions);
+      testWindowsSpecific(resisting, "-moz-windows-theme", windows_themes);
+    }
+    testCSS(resisting);
+    if (OS === "Darwin") {
+      testOSXFontSmoothing(resisting);
+    }
+    yield testMediaQueriesInPictureElements(resisting);
   }
-  SpecialPowers.pushPrefEnv({set: [["privacy.resistFingerprinting", prefValue]]},
-    function () {
-      let resisting = prefValue && isContent;
-      expected_values.forEach(
-        function ([key, offVal, onVal]) {
-          testMatch(key, resisting ? onVal : offVal);
-        });
-      testToggles(resisting);
-      if (OS === "WINNT") {
-        testWindowsSpecific(resisting, "-moz-os-version", windows_versions);
-        testWindowsSpecific(resisting, "-moz-windows-theme", windows_themes);
-      }
-      testCSS(resisting);
-      if (OS === "Darwin") {
-        testOSXFontSmoothing(resisting);
-      }
-      test(isContent);
-    });
 };
--- a/layout/style/test/chrome/chrome.ini
+++ b/layout/style/test/chrome/chrome.ini
@@ -1,16 +1,18 @@
 [DEFAULT]
 skip-if = buildapp == 'b2g' || os == 'android'
 support-files =
   bug418986-2.js
   bug535806-css.css
   bug535806-html.html
   bug535806-xul.xul
   hover_helper.html
+  match.png
+  mismatch.png
 
 [test_addSheet.html]
 [test_additional_sheets.html]
 [test_author_specified_style.html]
 [test_bug418986-2.xul]
 [test_bug1157097.html]
 [test_bug1160724.xul]
 [test_bug535806.xul]
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d3f299bf58248c86158c94facf3bdb305cbdd795
GIT binary patch
literal 1210
zc$@*c1V#IaP)<h;3K|Lk000e1NJLTq002Ay001lq1^@s6IV#)f000DmNkl<ZXhZE-
zeN2>f9RHj&B8d_NL<Fu024dd9@p5Rm(I}U=a)70#kPrl3EM8=70^z~I98n=QLn;F~
z%FujiLye-6;z~JD|A<6Q3JwGXUpU_H#q0U~+TC&m^J(?mc0SMT{`u{@@Avz8`F-x$
z2^3!znV2u`mq)+@wsEO>g>775@Cx$^+ZY49rEN^mzro=Z<`uRv26#)`n4o-Uv9k1`
zSB@fF7>@IO=kZ*1%w6m$6F)_iUli0mYQ%lCW=5kpJ?I2^Oflrg3o$Y^GHvatt!ii|
zwOF}3`ad%sE5L2J?GP^r!i0VTVdWBB9=t>sApkBFcEM$~3x2=x8~jWBW?Zl(vlU@J
z;Rq=Y!i9lf{;`(y>@M!Z(C8o@SNK{7@b_6NNQDtFnM_bL6`{0AK^IAXatkWrcVU)b
z7A{`zglNZ-85dM#pMq$C7y%`V(099cTEJcM9`tLk(te9Q0;eU14I8W!{xRn?LcBvM
z;4>OEA}f~BSxvHLMEb6P&Y+_U2A29GRvd?l*h<WQ)RWds8K%&1_A`v@#*iK<qi2RY
z2Bhv!M$4})II*P({_X+ve2`JKg!$WPJ7ar?2OMBD8L5j%{l3$+kR3>4gYm9f)_?=%
zEvBk?JNr;u4`}<T^*XOzfDdy<?ws`PP+XCB(<STGN{ldP8^aRdXzz%OgEADaR>19H
zcPQ0$C_1qn&98lng|5D6zW6n|Z+2s|Gznu2F~&PaIL~&by;WT*tPj~hUG&%M#1=Vg
zz=0l17?x|OO8Jf3=wdtLcA=m#54q8A;KtYxRe0}9wYW8Y6S+rokQ9-OZO`Px-Dw_O
zwsupU#nK{A5l9%G?QOR>=EDsiL+B!e#5)9&`bl`b=|OQFPWb|>0%NdtZ!C^=G_u7?
z>sbR{$}G72T`7LbX=7M#h0dr$)S{=bP%cDAekTnX0=R132iU}@YHw$6S<D=E`x2BO
zeI#XK___H}AjIyQ>k}-s#2w@g4~|}^{m4UzB}8W*$wbu;ySW2Q!lp6pIDB3IOyhRV
z89ZOT+Opu*BiR&0|L|2*w(LaZ$qJDBPuxKiHUlPoA|8uCed2zcy!;(jRjs7`%GQ+Q
z#o%?A^N_P86UcdG{Ch}a0y6VZ2C7wixB)Ek6eGAygp}o}$coCL0Y(_FZ>yt#iNXcP
z@+gRo{-2TF@G4$r?qtfcRJ!2$nio*;Y$2YQzm%#<u7@)56Sz9MVNdJ((A?J0-)Ox-
z4-@mbHZovQ*bJCch0Q9B>&MZN*NM@oQApnjg?3_?0@mE>f#fYQ$V)@8mxO{Or1TB<
z!fTE<Rolto5hO{IArJ_Vb@+934P8Oa#yZS(oJ;FTqL+VD2HA=XngeD_n*oz#CxQ2G
z9#(gl?SN?ir)hG3e(vCmZ&c>K@j+{0C$PhTa}8`q-E;l_3izJ4;INPf%puuU8O1AX
z71}u*$}7wv*;X0FD{K|oIULF>%puuU8O1AX71}u*$}7wv*;W~Ke=5A=t5U15ZH=LS
Y0NTcg$=Xm)tpET307*qoM6N<$g6-QvZ2$lO
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8f9da3f00ff947f14075b37bac24269a27d6b202
GIT binary patch
literal 1573
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
XKlOUk;hZpA00000NkvXXu0mjfI)mQa
--- a/layout/style/test/chrome/test_bug418986-2.xul
+++ b/layout/style/test/chrome/test_bug418986-2.xul
@@ -2,26 +2,29 @@
 <?xml-stylesheet type="text/css" href="chrome://global/skin"?>
 <?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=418986
 -->
 <window title="Mozilla Bug 418986"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"/>
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml">
   <style id="test-css" scoped="true"></style>
   <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=418986"
      target="_blank">Mozilla Bug 418986</a>
   <p id="display"></p>
-
+  <p id="pictures"></p>
   </body>
 
   <script type="text/javascript;version=1.7" src="bug418986-2.js"></script>
   <!-- test code goes here -->
   <script type="text/javascript;version=1.7">
     // Run all tests now.
     window.onload = function () {
-      test(false);
+      add_task(function* () {
+        yield test(false);
+      });
     };
   </script>
 </window>
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -1,16 +1,18 @@
 [DEFAULT]
 support-files =
   animation_utils.js
   ccd-quirks.html
   ccd.sjs
   ccd-standards.html
   css_properties.js
   chrome/bug418986-2.js
+  chrome/match.png
+  chrome/mismatch.png
   descriptor_database.js
   empty.html
   media_queries_dynamic_xbl_binding.xml
   media_queries_dynamic_xbl_iframe.html
   media_queries_dynamic_xbl_style.css
   media_queries_iframe.html
   neverending_font_load.sjs
   neverending_stylesheet_load.sjs
--- a/layout/style/test/test_bug418986-2.html
+++ b/layout/style/test/test_bug418986-2.html
@@ -2,28 +2,32 @@
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=418986
 -->
 <head>
   <meta charset="utf-8">
   <title>Test 2/3 for Bug #418986: Resist fingerprinting by preventing exposure of screen and system info</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <style id="test-css"></style>
   <script type="text/javascript;version=1.7" src="chrome/bug418986-2.js"></script>
   <script type="text/javascript;version=1.7">
     // Run all tests now.
     window.onload = function () {
-      test(true);
+      add_task(function* () {
+        yield test(true);
+      });
     };
   </script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418986">Bug 418986</a>
 <p id="display">TEST</p>
 <div id="content" style="display: none">
 
 </div>
+<p id="pictures"></p>
 <pre id="test">
 </pre>
 </body>
 </html>