Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* globals Components: true, Promise: true, gBrowser: true, Test: true, |
michael@0 | 2 | info: true, is: true, window: true, waitForExplicitFinish: true, |
michael@0 | 3 | finish: true, ok: true*/ |
michael@0 | 4 | |
michael@0 | 5 | "use strict"; |
michael@0 | 6 | |
michael@0 | 7 | const { interfaces: Ci, classes: Cc, utils: Cu } = Components; |
michael@0 | 8 | const { addObserver, removeObserver } = Cc["@mozilla.org/observer-service;1"]. |
michael@0 | 9 | getService(Ci.nsIObserverService); |
michael@0 | 10 | const { openWindow } = Cc["@mozilla.org/embedcomp/window-watcher;1"]. |
michael@0 | 11 | getService(Ci.nsIWindowWatcher); |
michael@0 | 12 | |
michael@0 | 13 | const Test = routine => () => { |
michael@0 | 14 | waitForExplicitFinish(); |
michael@0 | 15 | Task.spawn(routine) |
michael@0 | 16 | .then(finish, error => { |
michael@0 | 17 | ok(false, error); |
michael@0 | 18 | finish(); |
michael@0 | 19 | }); |
michael@0 | 20 | }; |
michael@0 | 21 | |
michael@0 | 22 | // Returns promise for the observer notification subject for |
michael@0 | 23 | // the given topic. If `receive("foo")` is called `n` times |
michael@0 | 24 | // nth promise is resolved on an `nth` "foo" notification. |
michael@0 | 25 | const receive = (topic, p, syncCallback) => { |
michael@0 | 26 | const { promise, resolve, reject } = Promise.defer(); |
michael@0 | 27 | const { queue } = receive; |
michael@0 | 28 | const timeout = () => { |
michael@0 | 29 | queue.splice(queue.indexOf(resolve) - 1, 2); |
michael@0 | 30 | reject(new Error("Timeout")); |
michael@0 | 31 | }; |
michael@0 | 32 | |
michael@0 | 33 | const observer = { |
michael@0 | 34 | observe: subject => { |
michael@0 | 35 | // Browser loads bunch of other documents that we don't care |
michael@0 | 36 | // about so we let allow filtering notifications via `p` function. |
michael@0 | 37 | if (p && !p(subject)) return; |
michael@0 | 38 | // If observer is a first one with a given `topic` |
michael@0 | 39 | // in a queue resolve promise and take it off the queue |
michael@0 | 40 | // otherwise keep waiting. |
michael@0 | 41 | const index = queue.indexOf(topic); |
michael@0 | 42 | if (queue.indexOf(resolve) === index + 1) { |
michael@0 | 43 | removeObserver(observer, topic); |
michael@0 | 44 | clearTimeout(id, reject); |
michael@0 | 45 | queue.splice(index, 2); |
michael@0 | 46 | // Some tests need to be executed synchronously when the event is fired. |
michael@0 | 47 | if (syncCallback) { |
michael@0 | 48 | syncCallback(subject); |
michael@0 | 49 | } |
michael@0 | 50 | resolve(subject); |
michael@0 | 51 | } |
michael@0 | 52 | } |
michael@0 | 53 | }; |
michael@0 | 54 | const id = setTimeout(timeout, 90000); |
michael@0 | 55 | addObserver(observer, topic, false); |
michael@0 | 56 | queue.push(topic, resolve); |
michael@0 | 57 | |
michael@0 | 58 | return promise; |
michael@0 | 59 | }; |
michael@0 | 60 | receive.queue = []; |
michael@0 | 61 | |
michael@0 | 62 | const openTab = uri => gBrowser.selectedTab = gBrowser.addTab(uri); |
michael@0 | 63 | |
michael@0 | 64 | const sleep = ms => { |
michael@0 | 65 | const { promise, resolve } = Promise.defer(); |
michael@0 | 66 | setTimeout(resolve, ms); |
michael@0 | 67 | return promise; |
michael@0 | 68 | }; |
michael@0 | 69 | |
michael@0 | 70 | const isData = document => document.URL.startsWith("data:"); |
michael@0 | 71 | |
michael@0 | 72 | const uri1 = "data:text/html;charset=utf-8,<h1>1</h1>"; |
michael@0 | 73 | // For whatever reason going back on load event doesn't work so timeout it is :( |
michael@0 | 74 | const uri2 = "data:text/html;charset=utf-8,<h1>2</h1><script>setTimeout(back,100)</script>"; |
michael@0 | 75 | const uri3 = "data:text/html;charset=utf-8,<h1>3</h1>"; |
michael@0 | 76 | |
michael@0 | 77 | const uri4 = "chrome://browser/content/license.html"; |
michael@0 | 78 | |
michael@0 | 79 | const test = Test(function*() { |
michael@0 | 80 | let documentInteractive = receive("content-document-interactive", isData, d => { |
michael@0 | 81 | // This test is executed synchronously when the event is received. |
michael@0 | 82 | is(d.readyState, "interactive", "document is interactive"); |
michael@0 | 83 | is(d.URL, uri1, "document.URL matches tab url"); |
michael@0 | 84 | }); |
michael@0 | 85 | let documentLoaded = receive("content-document-loaded", isData); |
michael@0 | 86 | let pageShown = receive("content-page-shown", isData); |
michael@0 | 87 | |
michael@0 | 88 | info("open: uri#1"); |
michael@0 | 89 | const tab1 = openTab(uri1); |
michael@0 | 90 | const browser1 = gBrowser.getBrowserForTab(tab1); |
michael@0 | 91 | |
michael@0 | 92 | let interactiveDocument1 = yield documentInteractive; |
michael@0 | 93 | |
michael@0 | 94 | let loadedDocument1 = yield documentLoaded; |
michael@0 | 95 | is(loadedDocument1.readyState, "complete", "document is loaded"); |
michael@0 | 96 | is(interactiveDocument1, loadedDocument1, "interactive document is loaded"); |
michael@0 | 97 | |
michael@0 | 98 | let shownPage = yield pageShown; |
michael@0 | 99 | is(interactiveDocument1, shownPage, "loaded document is shown"); |
michael@0 | 100 | |
michael@0 | 101 | // Wait until history entry is created before loading new uri. |
michael@0 | 102 | yield receive("sessionstore-state-write-complete"); |
michael@0 | 103 | |
michael@0 | 104 | info("load uri#2"); |
michael@0 | 105 | |
michael@0 | 106 | documentInteractive = receive("content-document-interactive", isData, d => { |
michael@0 | 107 | // This test is executed synchronously when the event is received. |
michael@0 | 108 | is(d.readyState, "interactive", "document is interactive"); |
michael@0 | 109 | is(d.URL, uri2, "document.URL matches URL loaded"); |
michael@0 | 110 | }); |
michael@0 | 111 | documentLoaded = receive("content-document-loaded", isData); |
michael@0 | 112 | pageShown = receive("content-page-shown", isData); |
michael@0 | 113 | let pageHidden = receive("content-page-hidden", isData); |
michael@0 | 114 | |
michael@0 | 115 | browser1.loadURI(uri2); |
michael@0 | 116 | |
michael@0 | 117 | let hiddenPage = yield pageHidden; |
michael@0 | 118 | is(interactiveDocument1, hiddenPage, "loaded document is hidden"); |
michael@0 | 119 | |
michael@0 | 120 | let interactiveDocument2 = yield documentInteractive; |
michael@0 | 121 | |
michael@0 | 122 | let loadedDocument2 = yield documentLoaded; |
michael@0 | 123 | is(loadedDocument2.readyState, "complete", "document is loaded"); |
michael@0 | 124 | is(interactiveDocument2, loadedDocument2, "interactive document is loaded"); |
michael@0 | 125 | |
michael@0 | 126 | shownPage = yield pageShown; |
michael@0 | 127 | is(interactiveDocument2, shownPage, "loaded document is shown"); |
michael@0 | 128 | |
michael@0 | 129 | info("go back to uri#1"); |
michael@0 | 130 | |
michael@0 | 131 | |
michael@0 | 132 | documentInteractive = receive("content-document-interactive", isData, d => { |
michael@0 | 133 | // This test is executed synchronously when the event is received. |
michael@0 | 134 | is(d.readyState, "interactive", "document is interactive"); |
michael@0 | 135 | is(d.URL, uri3, "document.URL matches URL loaded"); |
michael@0 | 136 | }); |
michael@0 | 137 | documentLoaded = receive("content-document-loaded", isData); |
michael@0 | 138 | pageShown = receive("content-page-shown", isData); |
michael@0 | 139 | pageHidden = receive("content-page-hidden", isData); |
michael@0 | 140 | |
michael@0 | 141 | hiddenPage = yield pageHidden; |
michael@0 | 142 | is(interactiveDocument2, hiddenPage, "new document is hidden"); |
michael@0 | 143 | |
michael@0 | 144 | shownPage = yield pageShown; |
michael@0 | 145 | is(interactiveDocument1, shownPage, "previous document is shown"); |
michael@0 | 146 | |
michael@0 | 147 | info("load uri#3"); |
michael@0 | 148 | |
michael@0 | 149 | browser1.loadURI(uri3); |
michael@0 | 150 | |
michael@0 | 151 | pageShown = receive("content-page-shown", isData); |
michael@0 | 152 | |
michael@0 | 153 | let interactiveDocument3 = yield documentInteractive; |
michael@0 | 154 | |
michael@0 | 155 | let loadedDocument3 = yield documentLoaded; |
michael@0 | 156 | is(loadedDocument3.readyState, "complete", "document is loaded"); |
michael@0 | 157 | is(interactiveDocument3, loadedDocument3, "interactive document is loaded"); |
michael@0 | 158 | |
michael@0 | 159 | shownPage = yield pageShown; |
michael@0 | 160 | is(interactiveDocument3, shownPage, "previous document is shown"); |
michael@0 | 161 | |
michael@0 | 162 | gBrowser.removeTab(tab1); |
michael@0 | 163 | |
michael@0 | 164 | info("load chrome uri"); |
michael@0 | 165 | |
michael@0 | 166 | const tab2 = openTab(uri4); |
michael@0 | 167 | documentInteractive = receive("chrome-document-interactive", null, d => { |
michael@0 | 168 | // This test is executed synchronously when the event is received. |
michael@0 | 169 | is(d.readyState, "interactive", "document is interactive"); |
michael@0 | 170 | is(d.URL, uri4, "document.URL matches URL loaded"); |
michael@0 | 171 | }); |
michael@0 | 172 | documentLoaded = receive("chrome-document-loaded"); |
michael@0 | 173 | pageShown = receive("chrome-page-shown"); |
michael@0 | 174 | |
michael@0 | 175 | const interactiveDocument4 = yield documentInteractive; |
michael@0 | 176 | |
michael@0 | 177 | let loadedDocument4 = yield documentLoaded; |
michael@0 | 178 | is(loadedDocument4.readyState, "complete", "document is loaded"); |
michael@0 | 179 | is(interactiveDocument4, loadedDocument4, "interactive document is loaded"); |
michael@0 | 180 | |
michael@0 | 181 | shownPage = yield pageShown; |
michael@0 | 182 | is(interactiveDocument4, shownPage, "loaded chrome document is shown"); |
michael@0 | 183 | |
michael@0 | 184 | pageHidden = receive("chrome-page-hidden"); |
michael@0 | 185 | gBrowser.removeTab(tab2); |
michael@0 | 186 | |
michael@0 | 187 | hiddenPage = yield pageHidden; |
michael@0 | 188 | is(interactiveDocument4, hiddenPage, "chrome document hidden"); |
michael@0 | 189 | }); |