merge landing; a=...
authorEhsan Akhgari <ehsan@mozilla.com>
Sun, 23 Jan 2011 23:31:52 -0500
changeset 61164 4e57b18dd908c3537f1497fe6f7d0c28e8f7a6c6
parent 61163 6149b3a93e1b2f436601bb3375ff8620137eaa0f (current diff)
parent 61157 bc2fda9a8b321ac4880275c1a2ec21d1c0e18978 (diff)
child 61166 a186a082a084c97b997d007e17f326e8e1b55ebc
push id18252
push usereakhgari@mozilla.com
push dateMon, 24 Jan 2011 04:32:05 +0000
treeherdermozilla-central@4e57b18dd908 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0b10pre
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
merge landing; a=...
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -334,16 +334,17 @@ class Automation(object):
     part = """\
 user_pref("browser.console.showInPanel", true);
 user_pref("browser.dom.window.dump.enabled", true);
 user_pref("dom.allow_scripts_to_close_windows", true);
 user_pref("dom.disable_open_during_load", false);
 user_pref("dom.max_script_run_time", 0); // no slow script dialogs
 user_pref("dom.max_chrome_script_run_time", 0);
 user_pref("dom.popup_maximum", -1);
+user_pref("dom.send_after_paint_to_content", true);
 user_pref("dom.successive_dialog_time_limit", 0);
 user_pref("signed.applets.codebase_principal_support", true);
 user_pref("security.warn_submit_insecure", false);
 user_pref("browser.shell.checkDefaultBrowser", false);
 user_pref("shell.checkDefaultClient", false);
 user_pref("browser.warnOnQuit", false);
 user_pref("accessibility.typeaheadfind.autostart", false);
 user_pref("javascript.options.showInConsole", true);
--- a/js/src/xpconnect/src/xpcwrappednativescope.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp
@@ -774,22 +774,18 @@ void DEBUG_CheckForComponentsInScope(JSC
 
     // This is pretty much always bad. It usually means that native code is
     // making a callback to an interface implemented in JavaScript, but the
     // document where the JS object was created has already been cleared and the
     // global properties of that document's window are *gone*. Generally this
     // indicates a problem that should be addressed in the design and use of the
     // callback code.
     NS_ERROR("XPConnect is being called on a scope without a 'Components' property!  (stack and details follow)");
-    // Dumping the JS stack causes fatal JS asserts in some cases, so
-    // comment it out for now.
-#if 0
     printf("The current JS stack is:\n");
     xpc_DumpJSStack(cx, JS_TRUE, JS_TRUE, JS_TRUE);
-#endif
 
     printf("And the object whose scope lacks a 'Components' property is:\n");
     js_DumpObject(startingObj);
 
     JSObject *p = startingObj;
     while(p->isWrapper())
     {
         p = p->getProxyPrivate().toObjectOrNull();
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -224,16 +224,17 @@ nsPresContext::nsPresContext(nsIDocument
   mUseDocumentFonts = PR_TRUE;
 
   // the minimum font-size is unconstrained by default
 
   mLinkColor = NS_RGB(0x00, 0x00, 0xEE);
   mActiveLinkColor = NS_RGB(0xEE, 0x00, 0x00);
   mVisitedLinkColor = NS_RGB(0x55, 0x1A, 0x8B);
   mUnderlineLinks = PR_TRUE;
+  mSendAfterPaintToContent = PR_FALSE;
 
   mFocusTextColor = mDefaultColor;
   mFocusBackgroundColor = mBackgroundColor;
   mFocusRingWidth = 1;
 
   if (aType == eContext_Galley) {
     mMedium = nsGkAtoms::screen;
   } else {
@@ -298,16 +299,19 @@ nsPresContext::~nsPresContext()
                                          nsPresContext::PrefChangedCallback,
                                          this);
   nsContentUtils::UnregisterPrefCallback("image.animation_mode",
                                          nsPresContext::PrefChangedCallback,
                                          this);
 #ifdef IBMBIDI
   nsContentUtils::UnregisterPrefCallback("bidi.", PrefChangedCallback, this);
 #endif // IBMBIDI
+  nsContentUtils::UnregisterPrefCallback("dom.send_after_paint_to_content",
+                                         nsPresContext::PrefChangedCallback,
+                                         this);
   nsContentUtils::UnregisterPrefCallback("gfx.font_rendering.",
                                          nsPresContext::PrefChangedCallback,
                                          this);
   nsContentUtils::UnregisterPrefCallback("layout.css.dpi",
                                          nsPresContext::PrefChangedCallback,
                                          this);
   nsContentUtils::UnregisterPrefCallback("layout.css.devPixelsPerPx",
                                          nsPresContext::PrefChangedCallback,
@@ -644,16 +648,20 @@ nsPresContext::GetUserPreferences()
 
 
   mAutoQualityMinFontSizePixelsPref =
     nsContentUtils::GetIntPref("browser.display.auto_quality_min_font_size");
 
   // * document colors
   GetDocumentColorPreferences();
 
+  mSendAfterPaintToContent =
+    nsContentUtils::GetBoolPref("dom.send_after_paint_to_content",
+                                mSendAfterPaintToContent);
+
   // * link colors
   mUnderlineLinks =
     nsContentUtils::GetBoolPref("browser.underline_anchors", mUnderlineLinks);
 
   nsAdoptingCString colorStr =
     nsContentUtils::GetCharPref("browser.anchor_color");
 
   if (!colorStr.IsEmpty()) {
@@ -951,16 +959,19 @@ nsPresContext::Init(nsIDeviceContext* aD
                                        this);
   nsContentUtils::RegisterPrefCallback("image.animation_mode",
                                        nsPresContext::PrefChangedCallback,
                                        this);
 #ifdef IBMBIDI
   nsContentUtils::RegisterPrefCallback("bidi.", PrefChangedCallback,
                                        this);
 #endif
+  nsContentUtils::RegisterPrefCallback("dom.send_after_paint_to_content",
+                                       nsPresContext::PrefChangedCallback,
+                                       this);
   nsContentUtils::RegisterPrefCallback("gfx.font_rendering.", PrefChangedCallback,
                                        this);
   nsContentUtils::RegisterPrefCallback("layout.css.dpi",
                                        nsPresContext::PrefChangedCallback,
                                        this);
   nsContentUtils::RegisterPrefCallback("layout.css.devPixelsPerPx",
                                        nsPresContext::PrefChangedCallback,
                                        this);
@@ -2087,23 +2098,30 @@ nsPresContext::FireDOMPaintEvent()
 {
   nsPIDOMWindow* ourWindow = mDocument->GetWindow();
   if (!ourWindow)
     return;
 
   nsCOMPtr<nsIDOMEventTarget> dispatchTarget = do_QueryInterface(ourWindow);
   nsCOMPtr<nsIDOMEventTarget> eventTarget = dispatchTarget;
   if (!IsChrome()) {
-    PRBool isCrossDocOnly = PR_TRUE;
-    for (PRUint32 i = 0; i < mInvalidateRequests.mRequests.Length(); ++i) {
-      if (!(mInvalidateRequests.mRequests[i].mFlags & nsIFrame::INVALIDATE_CROSS_DOC)) {
-        isCrossDocOnly = PR_FALSE;
+    PRBool notifyContent = mSendAfterPaintToContent;
+
+    if (notifyContent) {
+      // If the pref is set, we still don't post events when they're
+      // entirely cross-doc.
+      notifyContent = PR_FALSE;
+      for (PRUint32 i = 0; i < mInvalidateRequests.mRequests.Length(); ++i) {
+        if (!(mInvalidateRequests.mRequests[i].mFlags &
+              nsIFrame::INVALIDATE_CROSS_DOC)) {
+          notifyContent = PR_TRUE;
+        }
       }
     }
-    if (isCrossDocOnly) {
+    if (!notifyContent) {
       // Don't tell the window about this event, it should not know that
       // something happened in a subdocument. Tell only the chrome event handler.
       // (Events sent to the window get propagated to the chrome event handler
       // automatically.)
       dispatchTarget = do_QueryInterface(ourWindow->GetParentTarget());
       if (!dispatchTarget) {
         return;
       }
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -1116,16 +1116,17 @@ protected:
 
   mozilla::TimeStamp    mReflowStartTime;
 
   unsigned              mHasPendingInterrupt : 1;
   unsigned              mInterruptsEnabled : 1;
   unsigned              mUseDocumentFonts : 1;
   unsigned              mUseDocumentColors : 1;
   unsigned              mUnderlineLinks : 1;
+  unsigned              mSendAfterPaintToContent : 1;
   unsigned              mUseFocusColors : 1;
   unsigned              mFocusRingOnAnything : 1;
   unsigned              mFocusRingStyle : 1;
   unsigned              mDrawImageBackground : 1;
   unsigned              mDrawColorBackground : 1;
   unsigned              mNeverAnimate : 1;
   unsigned              mIsRenderingOnlySelection : 1;
   unsigned              mPaginated : 1;
--- a/layout/base/tests/Makefile.in
+++ b/layout/base/tests/Makefile.in
@@ -61,16 +61,17 @@ include $(topsrcdir)/config/rules.mk
 
 DEFINES += -D_IMPL_NS_LAYOUT
 
 _TEST_FILES =	\
 		border_radius_hit_testing_iframe.html \
 		bug369950-subframe.xml \
 		bug495648.rdf \
 		decoration_line_rendering.js \
+		test_after_paint_pref.html \
 		test_border_radius_hit_testing.html \
 		test_bug66619.html \
 		test_bug114649.html \
 		$(warning test_bug369950.html disabled due to random orange; see bug 492575) \
 		test_bug370436.html \
 		test_bug386575.xhtml \
 		test_bug388019.html \
 		test_bug394057.html \
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/test_after_paint_pref.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=608030
+-->
+<head>
+  <title>Test for MozAfterPaint pref Bug 608030</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=608030">Mozilla Bug 608030</a>
+<div id="display" style="width: 10em; height: 5em; background-color: red"></div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 608030 **/
+
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var prefService = Components.classes["@mozilla.org/preferences-service;1"].
+                    getService(Components.interfaces.nsIPrefService);
+var domBranch = prefService.getBranch("dom.");
+
+function get_pref()
+{
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    return domBranch.getBoolPref("send_after_paint_to_content");
+}
+
+function set_pref(val)
+{
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    domBranch.setBoolPref("send_after_paint_to_content", val);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+window.addEventListener("load", step0, false);
+
+is(get_pref(), true, "pref defaults to true in mochitest harness");
+
+function print_rect(rect) {
+  return "(top=" + rect.top + ",left=" + rect.left + ",width=" + rect.width + ",height=" + rect.height + ")";
+}
+
+function print_event(event) {
+  var res = "boundingClientRect=" + print_rect(event.boundingClientRect);
+  var rects = event.clientRects;
+  for (var i = 0; i < rects.length; ++i) {
+    res += " clientRects[" + i + "]=" + print_rect(rects[i]);
+  }
+  return res;
+}
+
+function step0(event) {
+  // Wait until we get the MozAfterPaint following the load event
+  // before starting.
+  window.addEventListener("MozAfterPaint", step1, false);
+}
+
+var start;
+var div = document.getElementById("display");
+
+function step1(event)
+{
+  //ok(true, "step1 event: " + print_event(event));
+  window.removeEventListener("MozAfterPaint", step1, false);
+
+  start = Date.now();
+
+  window.addEventListener("MozAfterPaint", step2, false);
+
+  div.style.backgroundColor = "blue";
+}
+
+function step2(event)
+{
+  //ok(true, "step2 event: " + print_event(event));
+  window.removeEventListener("MozAfterPaint", step2, false);
+
+  var end = Date.now();
+  var timeout = 3 * Math.max(end - start, 300);
+
+  ok(true, "got MozAfterPaint (timeout for next step is " + timeout + "ms)");
+
+  // Set the pref for our second test
+  set_pref(false);
+
+  // When there was previously another page in our window, we seem to
+  // get duplicate events, simultaneously, so we need to register our
+  // next listener after a zero timeout.
+  setTimeout(step3, 0, timeout);
+}
+function step3(timeout) {
+
+  window.addEventListener("MozAfterPaint", failstep, false);
+
+  div.style.backgroundColor = "fuchsia";
+
+  setTimeout(step4, timeout);
+}
+
+function failstep(event)
+{
+  //ok(true, "failstep event: " + print_event(event));
+  ok(false, "got MozAfterPaint when we should not have");
+}
+
+function step4()
+{
+  window.removeEventListener("MozAfterPaint", failstep, false);
+
+  ok(true, "got final step"); // If we didn't get the failure in failstep,
+                              // then we passed.
+
+  // Set the pref back in its initial state.
+  set_pref(true);
+
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/tools/reftest/reftest-analyzer.xhtml
+++ b/layout/tools/reftest/reftest-analyzer.xhtml
@@ -48,317 +48,510 @@ Features to add:
 * ability to load multiple logs ?
 ** rename them by clicking on the name and editing
 ** turn the test list into a collapsing tree view
 ** move log loading into popup from viewer UI
 
 -->
 <html lang="en-US" xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>Reftest analyzer</title>
-	<style type="text/css"><![CDATA[
+  <title>Reftest analyzer</title>
+  <style type="text/css"><![CDATA[
+
+  #leftpane { width: 320px; }
+  #images { position: fixed; top: 10px; left: 340px; }
+
+  form#imgcontrols { margin: 0; display: block; }
 
-        #itemlist { width: 300px; }
-        #images { position: fixed; top: 10px; left: 310px; }
+  #itemlist > table { border-collapse: collapse; }
+  #itemlist > table > tbody > tr > td { border: 1px solid; padding: 1px; }
 
-	form#imgcontrols { margin: 0; display: block; }
+  /*
+  #itemlist > table > tbody > tr.pass > td.url { background: lime; }
+  #itemlist > table > tbody > tr.fail > td.url { background: red; }
+  */
 
-	#itemlist > table { border-collapse: collapse; }
-	#itemlist > table > tbody > tr > td { border: 1px solid; padding: 1px; }
+  #magnification { margin-top: 1em; }
+  #pixelinfo { font: small sans-serif; position: absolute; width: 200px; left: 100px; margin-top: 2px; }
+  #pixelinfo table { border-collapse: collapse; white-space: nowrap;}
+  #pixelinfo table td, #pixelinfo table th { padding: 0 6px 2px 0; text-align: left; }
+  #pixelinfo table td { font-family: monospace; }
 
-	/*
-	#itemlist > table > tbody > tr.pass > td.url { background: lime; }
-	#itemlist > table > tbody > tr.fail > td.url { background: red; }
-	*/
+  #pixelhint { display: inline; color: #88f; cursor: help; }
+  #pixelhint > * { display: none; position: absolute; margin: 8px 0 0 8px; padding: 4px; width: 400px; background: #ffa; color: black; box-shadow: 3px 3px 2px #888; z-index: 1; }
+  #pixelhint:hover { color: #000; }
+  #pixelhint:hover > * { display: block; }
+  #pixelhint p { margin: 0; }
+  #pixelhint p + p { margin-top: 1em; }
 
-	]]></style>
-	<script type="text/javascript"><![CDATA[
+  ]]></style>
+  <script type="text/javascript"><![CDATA[
 
 var XLINK_NS = "http://www.w3.org/1999/xlink";
 var SVG_NS = "http://www.w3.org/2000/svg";
 
 var gPhases = null;
 
 var gIDCache = {};
 
+var gMagPixPaths = [];     // 2D array of array-of-two <path> objects used in the pixel magnifier
+var gMagWidth = 5;         // number of zoomed in pixels to show horizontally
+var gMagHeight = 5;        // number of zoomed in pixels to show vertically
+var gMagZoom = 16;         // size of the zoomed in pixels
+var gImage1Data;           // ImageData object for the reference image
+var gImage2Data;           // ImageData object for the test output image
+var gFlashingPixels = [];  // array of <path> objects that should be flashed due to pixel color mismatch
+
 function ID(id) {
-	if (!(id in gIDCache))
-		gIDCache[id] = document.getElementById(id);
-	return gIDCache[id];
+  if (!(id in gIDCache))
+    gIDCache[id] = document.getElementById(id);
+  return gIDCache[id];
 }
 
 function load() {
-	gPhases = [ ID("entry"), ID("loading"), ID("viewer") ];
+  gPhases = [ ID("entry"), ID("loading"), ID("viewer") ];
+  build_mag();
+}
+
+function build_mag() {
+  var mag = ID("mag");
+
+  var r = document.createElementNS(SVG_NS, "rect");
+  r.setAttribute("x", gMagZoom * -gMagWidth / 2);
+  r.setAttribute("y", gMagZoom * -gMagHeight / 2);
+  r.setAttribute("width", gMagZoom * gMagWidth);
+  r.setAttribute("height", gMagZoom * gMagHeight);
+  mag.appendChild(r);
+
+  mag.setAttribute("transform", "translate(" + (gMagZoom * (gMagWidth / 2) + 1) + "," + (gMagZoom * (gMagHeight / 2) + 1) + ")");
+
+  for (var x = 0; x < gMagWidth; x++) {
+    gMagPixPaths[x] = [];
+    for (var y = 0; y < gMagHeight; y++) {
+      var p1 = document.createElementNS(SVG_NS, "path");
+      p1.setAttribute("d", "M" + ((x - gMagWidth / 2) + 1) * gMagZoom + "," + (y - gMagHeight / 2) * gMagZoom + "h" + -gMagZoom + "v" + gMagZoom);
+      p1.setAttribute("stroke", "black");
+      p1.setAttribute("stroke-width", "1px");
+      p1.setAttribute("fill", "#aaa");
+
+      var p2 = document.createElementNS(SVG_NS, "path");
+      p2.setAttribute("d", "M" + ((x - gMagWidth / 2) + 1) * gMagZoom + "," + (y - gMagHeight / 2) * gMagZoom + "v" + gMagZoom + "h" + -gMagZoom);
+      p2.setAttribute("stroke", "black");
+      p2.setAttribute("stroke-width", "1px");
+      p2.setAttribute("fill", "#888");
+
+      mag.appendChild(p1);
+      mag.appendChild(p2);
+      gMagPixPaths[x][y] = [p1, p2];
+    }
+  }
+
+  var flashedOn = false;
+  setInterval(function() {
+    flashedOn = !flashedOn;
+    flash_pixels(flashedOn);
+  }, 500);
 }
 
 function show_phase(phaseid) {
-	for (var i in gPhases) {
-		var phase = gPhases[i];
-		phase.style.display = (phase.id == phaseid) ? "" : "none";
-	}
+  for (var i in gPhases) {
+    var phase = gPhases[i];
+    phase.style.display = (phase.id == phaseid) ? "" : "none";
+  }
 
-	if (phase == "viewer")
-		ID("images").style.display = "none";
+  if (phase == "viewer")
+    ID("images").style.display = "none";
 }
 
 function fileentry_changed() {
-	show_phase("loading");
-	var input = ID("fileentry");
-	var files = input.files;
-	var log = null;
-	if (files.length > 0) {
-		// Only handle the first file; don't handle multiple selection.
-		// The parts of the log we care about are ASCII-only.  Since we
-		// can ignore lines we don't care about, best to read in as
-		// iso-8859-1, which guarantees we don't get decoding errors.
-		log = files[0].getAsText("iso-8859-1");
-	}
-	// So the user can process the same filename again (after
-	// overwriting the log), clear the value on the form input so we
-	// will always get an onchange event.
-	input.value = "";
+  show_phase("loading");
+  var input = ID("fileentry");
+  var files = input.files;
+  var log = null;
+  if (files.length > 0) {
+    // Only handle the first file; don't handle multiple selection.
+    // The parts of the log we care about are ASCII-only.  Since we
+    // can ignore lines we don't care about, best to read in as
+    // iso-8859-1, which guarantees we don't get decoding errors.
+    log = files[0].getAsText("iso-8859-1");
+  }
+  // So the user can process the same filename again (after
+  // overwriting the log), clear the value on the form input so we
+  // will always get an onchange event.
+  input.value = "";
 
-	if (log)
-		process_log(log);
-	else
-		show_phase("entry");
+  if (log)
+    process_log(log);
+  else
+    show_phase("entry");
 }
 
 function log_pasted() {
-	show_phase("loading");
-	var entry = ID("logentry");
-	var log = entry.value;
-	entry.value = "";
-	process_log(log);
+  show_phase("loading");
+  var entry = ID("logentry");
+  var log = entry.value;
+  entry.value = "";
+  process_log(log);
 }
 
 var gTestItems;
 
 function process_log(contents) {
-	var lines = contents.split(/[\r\n]+/);
-	gTestItems = [];
-	for (var j in lines) {
-		var line = lines[j];
-		var match = line.match(/^(?:NEXT ERROR )?REFTEST (.*)$/);
-		if (!match)
-			continue;
-		line = match[1];
-		match = line.match(/^(TEST-PASS|TEST-UNEXPECTED-PASS|TEST-KNOWN-FAIL|TEST-UNEXPECTED-FAIL)(\(EXPECTED RANDOM\)|) \| ([^\|]+) \|(.*)/);
-		if (match) {
-			var state = match[1];
-			var random = match[2];
-			var url = match[3];
+  var lines = contents.split(/[\r\n]+/);
+  gTestItems = [];
+  for (var j in lines) {
+    var line = lines[j];
+    var match = line.match(/^(?:NEXT ERROR )?REFTEST (.*)$/);
+    if (!match)
+      continue;
+    line = match[1];
+    match = line.match(/^(TEST-PASS|TEST-UNEXPECTED-PASS|TEST-KNOWN-FAIL|TEST-UNEXPECTED-FAIL)(\(EXPECTED RANDOM\)|) \| ([^\|]+) \|(.*)/);
+    if (match) {
+      var state = match[1];
+      var random = match[2];
+      var url = match[3];
                         var extra = match[4];
-			gTestItems.push(
-				{
-					pass: !state.match(/FAIL$/),
-					// only one of the following three should ever be true
-					unexpected: !!state.match(/^TEST-UNEXPECTED/),
-					random: (random == "(EXPECTED RANDOM)"),
-					skip: (extra == " (SKIP)"),
-					url: url,
-					images: []
-				});
-			continue;
-		}
-		match = line.match(/^  IMAGE[^:]*: (.*)$/);
-		if (match) {
-			var item = gTestItems[gTestItems.length - 1];
-			item.images.push(match[1]);
-		}
-	}
+      gTestItems.push(
+        {
+          pass: !state.match(/FAIL$/),
+          // only one of the following three should ever be true
+          unexpected: !!state.match(/^TEST-UNEXPECTED/),
+          random: (random == "(EXPECTED RANDOM)"),
+          skip: (extra == " (SKIP)"),
+          url: url,
+          images: []
+        });
+      continue;
+    }
+    match = line.match(/^  IMAGE[^:]*: (.*)$/);
+    if (match) {
+      var item = gTestItems[gTestItems.length - 1];
+      item.images.push(match[1]);
+    }
+  }
 
-	build_viewer();
+  build_viewer();
 }
 
 function build_viewer() {
-	if (gTestItems.length == 0) {
-		show_phase("entry");
-		return;
-	}
+  if (gTestItems.length == 0) {
+    show_phase("entry");
+    return;
+  }
 
-	var cell = ID("itemlist");
-	while (cell.childNodes.length > 0)
-		cell.removeChild(cell.childNodes[cell.childNodes.length - 1]);
+  var cell = ID("itemlist");
+  while (cell.childNodes.length > 0)
+    cell.removeChild(cell.childNodes[cell.childNodes.length - 1]);
+
+  var table = document.createElement("table");
+  var tbody = document.createElement("tbody");
+  table.appendChild(tbody);
+
+  for (var i in gTestItems) {
+    var item = gTestItems[i];
 
-	var table = document.createElement("table");
-	var tbody = document.createElement("tbody");
-	table.appendChild(tbody);
-
-	for (var i in gTestItems) {
-		var item = gTestItems[i];
+    // XXX skip expected pass items until we have filtering UI
+    if (item.pass && !item.unexpected)
+      continue;
 
-		// XXX skip expected pass items until we have filtering UI
-		if (item.pass && !item.unexpected)
-			continue;
+    var tr = document.createElement("tr");
+    var rowclass = item.pass ? "pass" : "fail";
+    var td;
+    var text;
 
-		var tr = document.createElement("tr");
-		var rowclass = item.pass ? "pass" : "fail";
-		var td;
-		var text;
+    td = document.createElement("td");
+    text = "";
+    if (item.unexpected) { text += "!"; rowclass += " unexpected"; }
+    if (item.random) { text += "R"; rowclass += " random"; }
+    if (item.skip) { text += "S"; rowclass += " skip"; }
+    td.appendChild(document.createTextNode(text));
+    tr.appendChild(td);
 
-		td = document.createElement("td");
-		text = "";
-		if (item.unexpected) { text += "!"; rowclass += " unexpected"; }
-		if (item.random) { text += "R"; rowclass += " random"; }
-		if (item.skip) { text += "S"; rowclass += " skip"; }
-		td.appendChild(document.createTextNode(text));
-		tr.appendChild(td);
+    td = document.createElement("td");
+    td.className = "url";
+    // Only display part of URL after "/mozilla/".
+    var match = item.url.match(/\/mozilla\/(.*)/);
+    text = document.createTextNode(match ? match[1] : item.url);
+    if (item.images.length > 0) {
+      var a = document.createElement("a");
+      a.href = "javascript:show_images(" + i + ")";
+      a.appendChild(text);
+      td.appendChild(a);
+    } else {
+      td.appendChild(text);
+    }
+    tr.appendChild(td);
+
+    tbody.appendChild(tr);
+  }
 
-		td = document.createElement("td");
-		td.className = "url";
-		// Only display part of URL after "/mozilla/".
-		var match = item.url.match(/\/mozilla\/(.*)/);
-		text = document.createTextNode(match ? match[1] : item.url);
-		if (item.images.length > 0) {
-			var a = document.createElement("a");
-			a.href = "javascript:show_images(" + i + ")";
-			a.appendChild(text);
-			td.appendChild(a);
-		} else {
-			td.appendChild(text);
-		}
-		tr.appendChild(td);
+  cell.appendChild(table);
+
+  show_phase("viewer");
+}
 
-		tbody.appendChild(tr);
-	}
+function get_image_data(src, whenReady) {
+  var img = new Image();
+  img.onload = function() {
+    var canvas = document.createElement("canvas");
+    canvas.width = 800;
+    canvas.height = 1000;
 
-	cell.appendChild(table);
+    var ctx = canvas.getContext("2d");
+    ctx.drawImage(img, 0, 0);
 
-	show_phase("viewer");
+    whenReady(ctx.getImageData(0, 0, 800, 1000));
+  };
+  img.src = src;
 }
 
 function show_images(i) {
-	var item = gTestItems[i];
-	var cell = ID("images");
+  var item = gTestItems[i];
+  var cell = ID("images");
 
-	ID("image1").style.display = "";
-	ID("image2").style.display = "none";
-	ID("diffrect").style.display = "none";
-	ID("imgcontrols").reset();
+  ID("image1").style.display = "";
+  ID("image2").style.display = "none";
+  ID("diffrect").style.display = "none";
+  ID("imgcontrols").reset();
 
-	ID("image1").setAttributeNS(XLINK_NS, "xlink:href", item.images[0]);
-	// Making the href be #image1 doesn't seem to work
-	ID("feimage1").setAttributeNS(XLINK_NS, "xlink:href", item.images[0]);
-	if (item.images.length == 1) {
-		ID("imgcontrols").style.display = "none";
-	} else {
-		ID("imgcontrols").style.display = "";
+  ID("image1").setAttributeNS(XLINK_NS, "xlink:href", item.images[0]);
+  // Making the href be #image1 doesn't seem to work
+  ID("feimage1").setAttributeNS(XLINK_NS, "xlink:href", item.images[0]);
+  if (item.images.length == 1) {
+    ID("imgcontrols").style.display = "none";
+  } else {
+    ID("imgcontrols").style.display = "";
 
-		ID("image2").setAttributeNS(XLINK_NS, "xlink:href", item.images[1]);
-		// Making the href be #image2 doesn't seem to work
-		ID("feimage2").setAttributeNS(XLINK_NS, "xlink:href", item.images[1]);
-	}
+    ID("image2").setAttributeNS(XLINK_NS, "xlink:href", item.images[1]);
+    // Making the href be #image2 doesn't seem to work
+    ID("feimage2").setAttributeNS(XLINK_NS, "xlink:href", item.images[1]);
+  }
 
-	cell.style.display = "";
+  cell.style.display = "";
+
+  get_image_data(item.images[0], function(data) { gImage1Data = data });
+  get_image_data(item.images[1], function(data) { gImage2Data = data });
 }
 
 function show_image(i) {
-	if (i == 1) {
-		ID("image1").style.display = "";
-		ID("image2").style.display = "none";
-	} else {
-		ID("image1").style.display = "none";
-		ID("image2").style.display = "";
-	}
+  if (i == 1) {
+    ID("image1").style.display = "";
+    ID("image2").style.display = "none";
+  } else {
+    ID("image1").style.display = "none";
+    ID("image2").style.display = "";
+  }
 }
 
 function show_differences(cb) {
-	ID("diffrect").style.display = cb.checked ? "" : "none";
+  ID("diffrect").style.display = cb.checked ? "" : "none";
+}
+
+function flash_pixels(on) {
+  var stroke = on ? "red" : "black";
+  var strokeWidth = on ? "2px" : "1px";
+  for (var i = 0; i < gFlashingPixels.length; i++) {
+    gFlashingPixels[i].setAttribute("stroke", stroke);
+    gFlashingPixels[i].setAttribute("stroke-width", strokeWidth);
+  }
+}
+
+function cursor_point(evt) {
+  var m = evt.target.getScreenCTM().inverse();
+  var p = ID("svg").createSVGPoint();
+  p.x = evt.clientX;
+  p.y = evt.clientY;
+  p = p.matrixTransform(m);
+  return { x: Math.floor(p.x), y: Math.floor(p.y) };
+}
+
+function hex2(i) {
+  return (i < 16 ? "0" : "") + i.toString(16);
+}
+
+function canvas_pixel_as_hex(data, x, y) {
+  var offset = (y * data.width + x) * 4;
+  var r = data.data[offset];
+  var g = data.data[offset + 1];
+  var b = data.data[offset + 2];
+  return "#" + hex2(r) + hex2(g) + hex2(b);
+}
+
+function hex_as_rgb(hex) {
+  return "rgb(" + [parseInt(hex.substring(1, 3), 16), parseInt(hex.substring(3, 5), 16), parseInt(hex.substring(5, 7), 16)] + ")";
 }
 
-	]]></script>
+function magnify(evt) {
+  var { x: x, y: y } = cursor_point(evt);
+  var centerPixelColor1, centerPixelColor2;
+
+  var dx_lo = -Math.floor(gMagWidth / 2);
+  var dx_hi = Math.floor(gMagWidth / 2);
+  var dy_lo = -Math.floor(gMagHeight / 2);
+  var dy_hi = Math.floor(gMagHeight / 2);
+
+  flash_pixels(false);
+  gFlashingPixels = [];
+  for (var j = dy_lo; j <= dy_hi; j++) {
+    for (var i = dx_lo; i <= dx_hi; i++) {
+      var px = x + i;
+      var py = y + j;
+      var p1 = gMagPixPaths[i + dx_hi][j + dy_hi][0];
+      var p2 = gMagPixPaths[i + dx_hi][j + dy_hi][1];
+      if (px < 0 || py < 0 || px >= 800 || py >= 1000) {
+        p1.setAttribute("fill", "#aaa");
+        p2.setAttribute("fill", "#888");
+      } else {
+        var color1 = canvas_pixel_as_hex(gImage1Data, x + i, y + j);
+        var color2 = canvas_pixel_as_hex(gImage2Data, x + i, y + j);
+        p1.setAttribute("fill", color1);
+        p2.setAttribute("fill", color2);
+        if (color1 != color2) {
+          gFlashingPixels.push(p1, p2);
+          p1.parentNode.appendChild(p1);
+          p2.parentNode.appendChild(p2);
+        }
+        if (i == 0 && j == 0) {
+          centerPixelColor1 = color1;
+          centerPixelColor2 = color2;
+        }
+      }
+    }
+  }
+  flash_pixels(true);
+  show_pixelinfo(x, y, centerPixelColor1, hex_as_rgb(centerPixelColor1), centerPixelColor2, hex_as_rgb(centerPixelColor2));
+}
+
+function show_pixelinfo(x, y, pix1rgb, pix1hex, pix2rgb, pix2hex) {
+  var pixelinfo = ID("pixelinfo");
+  ID("coords").textContent = [x, y];
+  ID("pix1hex").textContent = pix1hex;
+  ID("pix1rgb").textContent = pix1rgb;
+  ID("pix2hex").textContent = pix2hex;
+  ID("pix2rgb").textContent = pix2rgb;
+}
+
+  ]]></script>
 
 </head>
 <body onload="load()">
 
 <div id="entry">
 
 <h1>Reftest analyzer: load reftest log</h1>
 
 <p>Either paste your log into this textarea:<br />
-<textarea cols="80" rows="10" id="logentry" /><br/>
+<textarea cols="80" rows="10" id="logentry"/><br/>
 <input type="button" value="Process pasted log" onclick="log_pasted()" /></p>
 
 <p>... or load it from a file:<br/>
 <input type="file" id="fileentry" onchange="fileentry_changed()" />
 </p>
 </div>
 
 <div id="loading" style="display:none">Loading log...</div>
 
 <div id="viewer" style="display:none">
-  <div id="itemlist"></div>
+  <div id="leftpane">
+    <div id="pixelinfo">
+      <table>
+        <tbody>
+          <tr><th>Pixel at:</th><td colspan="2" id="coords"/></tr>
+          <tr><th>Image 1:</th><td id="pix1rgb"></td><td id="pix1hex"></td></tr>
+          <tr><th>Image 2:</th><td id="pix2rgb"></td><td id="pix2hex"></td></tr>
+        </tbody>
+      </table>
+      <div>
+        <div id="pixelhint">★
+          <div>
+            <p>Move the mouse over the reftest image on the right to show
+            magnified pixels on the left.  The color information above is for
+            the pixel centered in the magnified view.</p>
+            <p>Image 1 is shown in the upper triangle of each pixel and Image 2
+            is shown in the lower triangle.</p>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div id="magnification">
+      <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" shape-rendering="optimizeSpeed">
+        <g id="mag"/>
+      </svg>
+    </div>
+    <div id="itemlist"></div>
+  </div>
   <div id="images" style="display:none">
     <form id="imgcontrols">
     <label><input type="radio" name="which" value="0" onchange="show_image(1)" checked="checked" />Image 1</label>
     <label><input type="radio" name="which" value="1" onchange="show_image(2)" />Image 2</label>
     <label><input type="checkbox" onchange="show_differences(this)" />Circle differences</label>
     </form>
     <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800px" height="1000px" viewbox="0 0 800 1000" id="svg">
       <defs>
-	<!-- use sRGB to avoid loss of data -->
-	<filter id="showDifferences" x="0%" y="0%" width="100%" height="100%"
-	        style="color-interpolation-filters: sRGB">
-	  <feImage id="feimage1" result="img1" xlink:href="#image1" />
-	  <feImage id="feimage2" result="img2" xlink:href="#image2" />
-	  <!-- inv1 and inv2 are the images with RGB inverted -->
-	  <feComponentTransfer result="inv1" in="img1">
-	    <feFuncR type="linear" slope="-1" intercept="1" />
-	    <feFuncG type="linear" slope="-1" intercept="1" />
-	    <feFuncB type="linear" slope="-1" intercept="1" />
-	  </feComponentTransfer>
-	  <feComponentTransfer result="inv2" in="img2">
-	    <feFuncR type="linear" slope="-1" intercept="1" />
-	    <feFuncG type="linear" slope="-1" intercept="1" />
-	    <feFuncB type="linear" slope="-1" intercept="1" />
-	  </feComponentTransfer>
-	  <!-- w1 will have non-white pixels anywhere that img2
-	       is brighter than img1, and w2 for the reverse.
-	       It would be nice not to have to go through these
-	       intermediate states, but feComposite
-	       type="arithmetic" can't transform the RGB channels
-	       and leave the alpha channel untouched. -->
-	  <feComposite result="w1" in="img1" in2="inv2" operator="arithmetic" k2="1" k3="1" />
-	  <feComposite result="w2" in="img2" in2="inv1" operator="arithmetic" k2="1" k3="1" />
-	  <!-- c1 will have non-black pixels anywhere that img2
-	       is brighter than img1, and c2 for the reverse -->
-	  <feComponentTransfer result="c1" in="w1">
-	    <feFuncR type="linear" slope="-1" intercept="1" />
-	    <feFuncG type="linear" slope="-1" intercept="1" />
-	    <feFuncB type="linear" slope="-1" intercept="1" />
-	  </feComponentTransfer>
-	  <feComponentTransfer result="c2" in="w2">
-	    <feFuncR type="linear" slope="-1" intercept="1" />
-	    <feFuncG type="linear" slope="-1" intercept="1" />
-	    <feFuncB type="linear" slope="-1" intercept="1" />
-	  </feComponentTransfer>
-	  <!-- c will be nonblack (and fully on) for every pixel+component where there are differences -->
-	  <feComposite result="c" in="c1" in2="c2" operator="arithmetic" k2="255" k3="255" />
-	  <!-- a will be opaque for every pixel with differences and transparent for all others -->
-	  <feColorMatrix result="a" type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  1 1 1 0 0" />
-	  
-	  <!-- a, dilated by 4 pixels -->
-	  <feMorphology result="dila4" in="a" operator="dilate" radius="4" />
-	  <!-- a, dilated by 1 pixel -->
-	  <feMorphology result="dila1" in="a" operator="dilate" radius="1" />
-	  
-	  <!-- all the pixels in the 3-pixel dilation of a but not in the 1-pixel dilation of a, to highlight the diffs -->
-	  <feComposite result="highlight" in="dila4" in2="dila1" operator="out" />
+        <!-- use sRGB to avoid loss of data -->
+        <filter id="showDifferences" x="0%" y="0%" width="100%" height="100%"
+                style="color-interpolation-filters: sRGB">
+          <feImage id="feimage1" result="img1" xlink:href="#image1" />
+          <feImage id="feimage2" result="img2" xlink:href="#image2" />
+          <!-- inv1 and inv2 are the images with RGB inverted -->
+          <feComponentTransfer result="inv1" in="img1">
+            <feFuncR type="linear" slope="-1" intercept="1" />
+            <feFuncG type="linear" slope="-1" intercept="1" />
+            <feFuncB type="linear" slope="-1" intercept="1" />
+          </feComponentTransfer>
+          <feComponentTransfer result="inv2" in="img2">
+            <feFuncR type="linear" slope="-1" intercept="1" />
+            <feFuncG type="linear" slope="-1" intercept="1" />
+            <feFuncB type="linear" slope="-1" intercept="1" />
+          </feComponentTransfer>
+          <!-- w1 will have non-white pixels anywhere that img2
+               is brighter than img1, and w2 for the reverse.
+               It would be nice not to have to go through these
+               intermediate states, but feComposite
+               type="arithmetic" can't transform the RGB channels
+               and leave the alpha channel untouched. -->
+          <feComposite result="w1" in="img1" in2="inv2" operator="arithmetic" k2="1" k3="1" />
+          <feComposite result="w2" in="img2" in2="inv1" operator="arithmetic" k2="1" k3="1" />
+          <!-- c1 will have non-black pixels anywhere that img2
+               is brighter than img1, and c2 for the reverse -->
+          <feComponentTransfer result="c1" in="w1">
+            <feFuncR type="linear" slope="-1" intercept="1" />
+            <feFuncG type="linear" slope="-1" intercept="1" />
+            <feFuncB type="linear" slope="-1" intercept="1" />
+          </feComponentTransfer>
+          <feComponentTransfer result="c2" in="w2">
+            <feFuncR type="linear" slope="-1" intercept="1" />
+            <feFuncG type="linear" slope="-1" intercept="1" />
+            <feFuncB type="linear" slope="-1" intercept="1" />
+          </feComponentTransfer>
+          <!-- c will be nonblack (and fully on) for every pixel+component where there are differences -->
+          <feComposite result="c" in="c1" in2="c2" operator="arithmetic" k2="255" k3="255" />
+          <!-- a will be opaque for every pixel with differences and transparent for all others -->
+          <feColorMatrix result="a" type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  1 1 1 0 0" />
+          
+          <!-- a, dilated by 4 pixels -->
+          <feMorphology result="dila4" in="a" operator="dilate" radius="4" />
+          <!-- a, dilated by 1 pixel -->
+          <feMorphology result="dila1" in="a" operator="dilate" radius="1" />
+          
+          <!-- all the pixels in the 3-pixel dilation of a but not in the 1-pixel dilation of a, to highlight the diffs -->
+          <feComposite result="highlight" in="dila4" in2="dila1" operator="out" />
 
-	  <feFlood result="red" flood-color="red" />
-	  <feComposite result="redhighlight" in="red" in2="highlight" operator="in" />
-	  <feFlood result="black" flood-color="black" flood-opacity="0.5" />
-	  <feMerge>
-	    <feMergeNode in="black" />
-	    <feMergeNode in="redhighlight" />
-	  </feMerge>
-	</filter>
+          <feFlood result="red" flood-color="red" />
+          <feComposite result="redhighlight" in="red" in2="highlight" operator="in" />
+          <feFlood result="black" flood-color="black" flood-opacity="0.5" />
+          <feMerge>
+            <feMergeNode in="black" />
+            <feMergeNode in="redhighlight" />
+          </feMerge>
+        </filter>
       </defs>
-      <image x="0" y="0" width="100%" height="100%" id="image1" />
-      <image x="0" y="0" width="100%" height="100%" id="image2" />
-      <rect id="diffrect" filter="url(#showDifferences)" x="0" y="0" width="100%" height="100%" />
+      <g onmousemove="magnify(evt)">
+        <image x="0" y="0" width="100%" height="100%" id="image1" />
+        <image x="0" y="0" width="100%" height="100%" id="image2" />
+      </g>
+      <rect id="diffrect" filter="url(#showDifferences)" pointer-events="none" x="0" y="0" width="100%" height="100%" />
     </svg>
   </div>
 </div>
 
 </body>
 </html>
--- a/layout/tools/reftest/reftest-cmdline.js
+++ b/layout/tools/reftest/reftest-cmdline.js
@@ -87,21 +87,35 @@ RefTestCmdLineHandler.prototype =
     }
 
     /* Ignore the platform's online/offline status while running reftests. */
     var ios = Components.classes["@mozilla.org/network/io-service;1"]
               .getService(Components.interfaces.nsIIOService2);
     ios.manageOfflineStatus = false;
     ios.offline = false;
 
-    /* Force sRGB as an output profile for color management before we load a
-       window. */
+    /**
+     * Manipulate preferences by adding to the *default* branch.  Adding
+     * to the default branch means the changes we make won't get written
+     * back to user preferences.
+     *
+     * We want to do this here rather than in reftest.js because it's
+     * important to force sRGB as an output profile for color management
+     * before we load a window.
+     */
     var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-                getService(Components.interfaces.nsIPrefBranch2);
-    prefs.setBoolPref("gfx.color_management.force_srgb", true);
+                getService(Components.interfaces.nsIPrefService);
+    var branch = prefs.getDefaultBranch("");
+    branch.setBoolPref("gfx.color_management.force_srgb", true);
+    branch.setBoolPref("browser.dom.window.dump.enabled", true);
+    branch.setIntPref("ui.caretBlinkTime", -1);
+    branch.setBoolPref("dom.send_after_paint_to_content", true);
+    // no slow script dialogs
+    branch.setIntPref("dom.max_script_run_time", 0);
+    branch.setIntPref("dom.max_chrome_script_run_time", 0);
 
     var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
                            .getService(nsIWindowWatcher);
     wwatch.openWindow(null, "chrome://reftest/content/reftest.xul", "_blank",
                       "chrome,dialog=no,all", args);
     cmdLine.preventDefault = true;
   },
 
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.js
@@ -354,21 +354,16 @@ function StartTests()
         ++gTestResults.Exception;
         gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | | EXCEPTION: " + ex + "\n");
         DoneTests();
     }
 }
 
 function OnRefTestUnload()
 {
-    /* Clear the sRGB forcing pref to leave the profile as we found it. */
-    var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-                getService(Components.interfaces.nsIPrefBranch2);
-    prefs.clearUserPref("gfx.color_management.force_srgb");
-
     gBrowser.removeEventListener("load", OnDocumentLoad, true);
     MozillaFileLogger.close();
 }
 
 // Read all available data from an input stream and return it
 // as a string.
 function getStreamContent(inputStream)
 {
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -66,40 +66,36 @@ class RefTest(object):
     return self.getFullPath(path)
 
   def createReftestProfile(self, options, profileDir):
     "Sets up a profile for reftest."
 
     self.automation.setupPermissionsDatabase(profileDir,
       {'allowXULXBL': [('localhost', True), ('<file>', True)]})
 
-    # Set preferences.
+    # Set preferences for communication between our command line arguments
+    # and the reftest harness.  Preferences that are required for reftest
+    # to work should instead be set in reftest-cmdline.js .
     prefsFile = open(os.path.join(profileDir, "user.js"), "w")
-    prefsFile.write("""user_pref("browser.dom.window.dump.enabled", true);
-    """)
     prefsFile.write('user_pref("reftest.timeout", %d);\n' % (options.timeout * 1000))
-    prefsFile.write('user_pref("ui.caretBlinkTime", -1);\n')
 
     if options.totalChunks != None:
       prefsFile.write('user_pref("reftest.totalChunks", %d);\n' % options.totalChunks)
     if options.thisChunk != None:
       prefsFile.write('user_pref("reftest.thisChunk", %d);\n' % options.thisChunk)
     if options.logFile != None:
       prefsFile.write('user_pref("reftest.logFile", "%s");\n' % options.logFile)
 
     for v in options.extraPrefs:
       thispref = v.split("=")
       if len(thispref) < 2:
         print "Error: syntax error in --setpref=" + v
         sys.exit(1)
       part = 'user_pref("%s", %s);\n' % (thispref[0], thispref[1])
       prefsFile.write(part)
-    # no slow script dialogs
-    prefsFile.write('user_pref("dom.max_script_run_time", 0);')
-    prefsFile.write('user_pref("dom.max_chrome_script_run_time", 0);')
     prefsFile.close()
 
     # install the reftest extension bits into the profile
     self.automation.installExtension(os.path.join(SCRIPT_DIRECTORY, "reftest"),
                                                   profileDir,
                                                   "reftest@mozilla.org")
 
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -565,16 +565,18 @@ pref("dom.allow_scripts_to_close_windows
 pref("dom.disable_open_during_load",                false);
 pref("dom.popup_maximum",                           20);
 pref("dom.popup_allowed_events", "change click dblclick mouseup reset submit");
 pref("dom.disable_open_click_delay", 1000);
 
 pref("dom.storage.enabled", true);
 pref("dom.storage.default_quota",      5120);
 
+pref("dom.send_after_paint_to_content", false);
+
 // Timeout clamp in ms for timeouts we clamp
 pref("dom.min_timeout_value", 10);
 
 // Parsing perf prefs. For now just mimic what the old code did.
 #ifndef XP_WIN
 pref("content.sink.pending_event_mode", 0);
 #endif