Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* Any copyright is dedicated to the Public Domain. |
michael@0 | 2 | http://creativecommons.org/publicdomain/zero/1.0/ */ |
michael@0 | 3 | |
michael@0 | 4 | "use strict"; |
michael@0 | 5 | |
michael@0 | 6 | const EXPECTED_REFLOWS = [ |
michael@0 | 7 | // handleEvent flushes layout to get the tabstrip width after a resize. |
michael@0 | 8 | "handleEvent@chrome://browser/content/tabbrowser.xml|", |
michael@0 | 9 | |
michael@0 | 10 | // Loading a tab causes a reflow. |
michael@0 | 11 | "loadTabs@chrome://browser/content/tabbrowser.xml|" + |
michael@0 | 12 | "loadOneOrMoreURIs@chrome://browser/content/browser.js|" + |
michael@0 | 13 | "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|", |
michael@0 | 14 | |
michael@0 | 15 | // Selecting the address bar causes a reflow. |
michael@0 | 16 | "select@chrome://global/content/bindings/textbox.xml|" + |
michael@0 | 17 | "focusAndSelectUrlBar@chrome://browser/content/browser.js|" + |
michael@0 | 18 | "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|", |
michael@0 | 19 | |
michael@0 | 20 | // Focusing the content area causes a reflow. |
michael@0 | 21 | "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|", |
michael@0 | 22 | |
michael@0 | 23 | // Sometimes sessionstore collects data during this test, which causes a sync reflow |
michael@0 | 24 | // (https://bugzilla.mozilla.org/show_bug.cgi?id=892154 will fix this) |
michael@0 | 25 | "ssi_getWindowDimension@resource:///modules/sessionstore/SessionStore.jsm", |
michael@0 | 26 | ]; |
michael@0 | 27 | |
michael@0 | 28 | if (Services.appinfo.OS == "WINNT" || Services.appinfo.OS == "Darwin") { |
michael@0 | 29 | // TabsInTitlebar._update causes a reflow on OS X and Windows trying to do calculations |
michael@0 | 30 | // since layout info is already dirty. This doesn't seem to happen before |
michael@0 | 31 | // MozAfterPaint on Linux. |
michael@0 | 32 | EXPECTED_REFLOWS.push("rect@chrome://browser/content/browser.js|" + |
michael@0 | 33 | "TabsInTitlebar._update@chrome://browser/content/browser.js|" + |
michael@0 | 34 | "updateAppearance@chrome://browser/content/browser.js|" + |
michael@0 | 35 | "handleEvent@chrome://browser/content/tabbrowser.xml|"); |
michael@0 | 36 | } |
michael@0 | 37 | |
michael@0 | 38 | if (Services.appinfo.OS == "Darwin") { |
michael@0 | 39 | // _onOverflow causes a reflow getting widths. |
michael@0 | 40 | EXPECTED_REFLOWS.push("OverflowableToolbar.prototype._onOverflow@resource:///modules/CustomizableUI.jsm|" + |
michael@0 | 41 | "OverflowableToolbar.prototype.init@resource:///modules/CustomizableUI.jsm|" + |
michael@0 | 42 | "OverflowableToolbar.prototype.observe@resource:///modules/CustomizableUI.jsm|" + |
michael@0 | 43 | "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|"); |
michael@0 | 44 | // Same as above since in packaged builds there are no function names and the resource URI includes "app" |
michael@0 | 45 | EXPECTED_REFLOWS.push("@resource://app/modules/CustomizableUI.jsm|" + |
michael@0 | 46 | "@resource://app/modules/CustomizableUI.jsm|" + |
michael@0 | 47 | "@resource://app/modules/CustomizableUI.jsm|" + |
michael@0 | 48 | "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|"); |
michael@0 | 49 | } |
michael@0 | 50 | |
michael@0 | 51 | /* |
michael@0 | 52 | * This test ensures that there are no unexpected |
michael@0 | 53 | * uninterruptible reflows when opening new windows. |
michael@0 | 54 | */ |
michael@0 | 55 | function test() { |
michael@0 | 56 | waitForExplicitFinish(); |
michael@0 | 57 | |
michael@0 | 58 | // Add a reflow observer and open a new window |
michael@0 | 59 | let win = OpenBrowserWindow(); |
michael@0 | 60 | let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor) |
michael@0 | 61 | .getInterface(Ci.nsIWebNavigation) |
michael@0 | 62 | .QueryInterface(Ci.nsIDocShell); |
michael@0 | 63 | docShell.addWeakReflowObserver(observer); |
michael@0 | 64 | |
michael@0 | 65 | // Wait until the mozafterpaint event occurs. |
michael@0 | 66 | waitForMozAfterPaint(win, function paintListener() { |
michael@0 | 67 | // Remove reflow observer and clean up. |
michael@0 | 68 | docShell.removeWeakReflowObserver(observer); |
michael@0 | 69 | win.close(); |
michael@0 | 70 | |
michael@0 | 71 | finish(); |
michael@0 | 72 | }); |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | let observer = { |
michael@0 | 76 | reflow: function (start, end) { |
michael@0 | 77 | // Gather information about the current code path. |
michael@0 | 78 | let stack = new Error().stack; |
michael@0 | 79 | let path = stack.split("\n").slice(1).map(line => { |
michael@0 | 80 | return line.replace(/:\d+:\d+$/, ""); |
michael@0 | 81 | }).join("|"); |
michael@0 | 82 | let pathWithLineNumbers = (new Error().stack).split("\n").slice(1).join("|"); |
michael@0 | 83 | |
michael@0 | 84 | // Stack trace is empty. Reflow was triggered by native code. |
michael@0 | 85 | if (path === "") { |
michael@0 | 86 | return; |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | // Check if this is an expected reflow. |
michael@0 | 90 | for (let expectedStack of EXPECTED_REFLOWS) { |
michael@0 | 91 | if (path.startsWith(expectedStack) || |
michael@0 | 92 | // Accept an empty function name for gBrowserInit._delayedStartup or TabsInTitlebar._update to workaround bug 906578. |
michael@0 | 93 | path.startsWith(expectedStack.replace(/(^|\|)(gBrowserInit\._delayedStartup|TabsInTitlebar\._update)@/, "$1@"))) { |
michael@0 | 94 | ok(true, "expected uninterruptible reflow '" + expectedStack + "'"); |
michael@0 | 95 | return; |
michael@0 | 96 | } |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | ok(false, "unexpected uninterruptible reflow '" + pathWithLineNumbers + "'"); |
michael@0 | 100 | }, |
michael@0 | 101 | |
michael@0 | 102 | reflowInterruptible: function (start, end) { |
michael@0 | 103 | // We're not interested in interruptible reflows. |
michael@0 | 104 | }, |
michael@0 | 105 | |
michael@0 | 106 | QueryInterface: XPCOMUtils.generateQI([Ci.nsIReflowObserver, |
michael@0 | 107 | Ci.nsISupportsWeakReference]) |
michael@0 | 108 | }; |
michael@0 | 109 | |
michael@0 | 110 | function waitForMozAfterPaint(win, callback) { |
michael@0 | 111 | win.addEventListener("MozAfterPaint", function onEnd(event) { |
michael@0 | 112 | if (event.target != win) |
michael@0 | 113 | return; |
michael@0 | 114 | win.removeEventListener("MozAfterPaint", onEnd); |
michael@0 | 115 | executeSoon(callback); |
michael@0 | 116 | }); |
michael@0 | 117 | } |