|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 'use strict'; |
|
5 |
|
6 const { Cc, Ci } = require('chrome'); |
|
7 const { setTimeout } = require('sdk/timers'); |
|
8 const { Loader } = require('sdk/test/loader'); |
|
9 const { onFocus, getMostRecentWindow, windows, isBrowser, getWindowTitle } = require('sdk/window/utils'); |
|
10 const { open, close, focus } = require('sdk/window/helpers'); |
|
11 const { browserWindows } = require("sdk/windows"); |
|
12 const tabs = require("sdk/tabs"); |
|
13 const winUtils = require("sdk/deprecated/window-utils"); |
|
14 const { WindowTracker } = winUtils; |
|
15 const { isPrivate } = require('sdk/private-browsing'); |
|
16 const { isWindowPBSupported } = require('sdk/private-browsing/utils'); |
|
17 const { viewFor } = require("sdk/view/core"); |
|
18 const { defer } = require("sdk/lang/functional"); |
|
19 |
|
20 // TEST: open & close window |
|
21 exports.testOpenAndCloseWindow = function(assert, done) { |
|
22 assert.equal(browserWindows.length, 1, "Only one window open"); |
|
23 let title = 'testOpenAndCloseWindow'; |
|
24 |
|
25 browserWindows.open({ |
|
26 url: "data:text/html;charset=utf-8,<title>" + title + "</title>", |
|
27 onOpen: function(window) { |
|
28 assert.equal(this, browserWindows, "The 'this' object is the windows object."); |
|
29 assert.equal(window.tabs.length, 1, "Only one tab open"); |
|
30 assert.equal(browserWindows.length, 2, "Two windows open"); |
|
31 |
|
32 window.tabs.activeTab.once('ready', function onReady(tab) { |
|
33 assert.pass(RegExp(title).test(window.title), "URL correctly loaded"); |
|
34 window.close(); |
|
35 }); |
|
36 }, |
|
37 onClose: function(window) { |
|
38 assert.equal(window.tabs.length, 0, "Tabs were cleared"); |
|
39 assert.equal(browserWindows.length, 1, "Only one window open"); |
|
40 done(); |
|
41 } |
|
42 }); |
|
43 }; |
|
44 |
|
45 exports.testAutomaticDestroy = function(assert, done) { |
|
46 let windows = browserWindows; |
|
47 |
|
48 // Create a second windows instance that we will unload |
|
49 let called = false; |
|
50 let loader = Loader(module); |
|
51 let windows2 = loader.require("sdk/windows").browserWindows; |
|
52 |
|
53 windows2.on("open", function() { |
|
54 called = true; |
|
55 }); |
|
56 |
|
57 loader.unload(); |
|
58 |
|
59 // Fire a windows event and check that this unloaded instance is inactive |
|
60 windows.open({ |
|
61 url: "data:text/html;charset=utf-8,foo", |
|
62 onOpen: function(window) { |
|
63 setTimeout(function () { |
|
64 assert.ok(!called, "Unloaded windows instance is destroyed and inactive"); |
|
65 |
|
66 window.close(done); |
|
67 }); |
|
68 } |
|
69 }); |
|
70 }; |
|
71 |
|
72 exports.testWindowTabsObject = function(assert, done) { |
|
73 let window, count = 0; |
|
74 function runTest() { |
|
75 if (++count != 2) |
|
76 return; |
|
77 |
|
78 assert.equal(window.tabs.length, 1, "Only 1 tab open"); |
|
79 assert.equal(window.tabs.activeTab.title, "tab 1", "Correct active tab"); |
|
80 |
|
81 window.tabs.open({ |
|
82 url: "data:text/html;charset=utf-8,<title>tab 2</title>", |
|
83 inBackground: true, |
|
84 onReady: function onReady(newTab) { |
|
85 assert.equal(window.tabs.length, 2, "New tab open"); |
|
86 assert.equal(newTab.title, "tab 2", "Correct new tab title"); |
|
87 assert.equal(window.tabs.activeTab.title, "tab 1", "Correct active tab"); |
|
88 |
|
89 let i = 1; |
|
90 for (let tab of window.tabs) |
|
91 assert.equal(tab.title, "tab " + i++, "Correct title"); |
|
92 |
|
93 window.close(); |
|
94 } |
|
95 }); |
|
96 } |
|
97 |
|
98 tabs.once("ready", runTest); |
|
99 |
|
100 browserWindows.open({ |
|
101 url: "data:text/html;charset=utf-8,<title>tab 1</title>", |
|
102 onActivate: function onActivate(win) { |
|
103 window = win; |
|
104 runTest(); |
|
105 }, |
|
106 onClose: function onClose(window) { |
|
107 assert.equal(window.tabs.length, 0, "No more tabs on closed window"); |
|
108 done(); |
|
109 } |
|
110 }); |
|
111 }; |
|
112 |
|
113 exports.testOnOpenOnCloseListeners = function(assert, done) { |
|
114 let windows = browserWindows; |
|
115 |
|
116 assert.equal(browserWindows.length, 1, "Only one window open"); |
|
117 |
|
118 let received = { |
|
119 listener1: false, |
|
120 listener2: false, |
|
121 listener3: false, |
|
122 listener4: false |
|
123 } |
|
124 |
|
125 function listener1() { |
|
126 assert.equal(this, windows, "The 'this' object is the windows object."); |
|
127 |
|
128 if (received.listener1) |
|
129 assert.fail("Event received twice"); |
|
130 received.listener1 = true; |
|
131 } |
|
132 |
|
133 function listener2() { |
|
134 if (received.listener2) |
|
135 assert.fail("Event received twice"); |
|
136 received.listener2 = true; |
|
137 } |
|
138 |
|
139 function listener3() { |
|
140 assert.equal(this, windows, "The 'this' object is the windows object."); |
|
141 if (received.listener3) |
|
142 assert.fail("Event received twice"); |
|
143 received.listener3 = true; |
|
144 } |
|
145 |
|
146 function listener4() { |
|
147 if (received.listener4) |
|
148 assert.fail("Event received twice"); |
|
149 received.listener4 = true; |
|
150 } |
|
151 |
|
152 windows.on('open', listener1); |
|
153 windows.on('open', listener2); |
|
154 windows.on('close', listener3); |
|
155 windows.on('close', listener4); |
|
156 |
|
157 windows.open({ |
|
158 url: "data:text/html;charset=utf-8,foo", |
|
159 onOpen: function(window) { |
|
160 window.close(function() { |
|
161 assert.ok(received.listener1, "onOpen handler called"); |
|
162 assert.ok(received.listener2, "onOpen handler called"); |
|
163 assert.ok(received.listener3, "onClose handler called"); |
|
164 assert.ok(received.listener4, "onClose handler called"); |
|
165 |
|
166 windows.removeListener('open', listener1); |
|
167 windows.removeListener('open', listener2); |
|
168 windows.removeListener('close', listener3); |
|
169 windows.removeListener('close', listener4); |
|
170 |
|
171 done(); |
|
172 }); |
|
173 } |
|
174 }); |
|
175 }; |
|
176 |
|
177 exports.testActiveWindow = function(assert, done) { |
|
178 let windows = browserWindows; |
|
179 |
|
180 // API window objects |
|
181 let window2, window3; |
|
182 |
|
183 // Raw window objects |
|
184 let rawWindow2, rawWindow3; |
|
185 |
|
186 let testSteps = [ |
|
187 function() { |
|
188 assert.equal(windows.length, 3, "Correct number of browser windows"); |
|
189 |
|
190 let count = 0; |
|
191 for (let window in windows) |
|
192 count++; |
|
193 assert.equal(count, 3, "Correct number of windows returned by iterator"); |
|
194 |
|
195 assert.equal(windows.activeWindow.title, window3.title, "Correct active window - 3"); |
|
196 |
|
197 continueAfterFocus(rawWindow2); |
|
198 rawWindow2.focus(); |
|
199 }, |
|
200 function() { |
|
201 assert.equal(windows.activeWindow.title, window2.title, "Correct active window - 2"); |
|
202 |
|
203 continueAfterFocus(rawWindow2); |
|
204 window2.activate(); |
|
205 }, |
|
206 function() { |
|
207 assert.equal(windows.activeWindow.title, window2.title, "Correct active window - 2"); |
|
208 |
|
209 continueAfterFocus(rawWindow3); |
|
210 window3.activate(); |
|
211 }, |
|
212 function() { |
|
213 assert.equal(windows.activeWindow.title, window3.title, "Correct active window - 3"); |
|
214 finishTest(); |
|
215 } |
|
216 ]; |
|
217 |
|
218 let newWindow = null; |
|
219 let tracker = new WindowTracker({ |
|
220 onTrack: function(window) { |
|
221 newWindow = window; |
|
222 } |
|
223 }); |
|
224 |
|
225 windows.open({ |
|
226 url: "data:text/html;charset=utf-8,<title>window 2</title>", |
|
227 onOpen: function(window) { |
|
228 assert.pass('window 2 open'); |
|
229 |
|
230 window.tabs.activeTab.on('ready', function() { |
|
231 assert.pass('window 2 tab activated'); |
|
232 |
|
233 window2 = window; |
|
234 assert.ok(newWindow, "A new window was opened"); |
|
235 rawWindow2 = newWindow; |
|
236 newWindow = null; |
|
237 |
|
238 assert.equal(rawWindow2.content.document.title, "window 2", "Got correct raw window 2"); |
|
239 assert.equal(rawWindow2.document.title, window2.title, "Saw correct title on window 2"); |
|
240 |
|
241 windows.open({ |
|
242 url: "data:text/html;charset=utf-8,<title>window 3</title>", |
|
243 onOpen: function(window) { |
|
244 assert.pass('window 3 open'); |
|
245 |
|
246 window.tabs.activeTab.on('ready', function onReady() { |
|
247 assert.pass('window 3 tab activated'); |
|
248 |
|
249 window3 = window; |
|
250 assert.ok(newWindow, "A new window was opened"); |
|
251 rawWindow3 = newWindow; |
|
252 tracker.unload(); |
|
253 |
|
254 assert.equal(rawWindow3.content.document.title, "window 3", "Got correct raw window 3"); |
|
255 assert.equal(rawWindow3.document.title, window3.title, "Saw correct title on window 3"); |
|
256 |
|
257 continueAfterFocus(rawWindow3); |
|
258 rawWindow3.focus(); |
|
259 }); |
|
260 } |
|
261 }); |
|
262 }); |
|
263 } |
|
264 }); |
|
265 |
|
266 function nextStep() { |
|
267 if (testSteps.length) { |
|
268 setTimeout(testSteps.shift()) |
|
269 } |
|
270 } |
|
271 |
|
272 let continueAfterFocus = function(w) onFocus(w).then(nextStep); |
|
273 |
|
274 function finishTest() { |
|
275 // close unactive window first to avoid unnecessary focus changing |
|
276 window2.close(function() { |
|
277 window3.close(function() { |
|
278 assert.equal(rawWindow2.closed, true, 'window 2 is closed'); |
|
279 assert.equal(rawWindow3.closed, true, 'window 3 is closed'); |
|
280 |
|
281 done(); |
|
282 }); |
|
283 }); |
|
284 } |
|
285 }; |
|
286 |
|
287 exports.testTrackWindows = function(assert, done) { |
|
288 let windows = []; |
|
289 let actions = []; |
|
290 |
|
291 let expects = [ |
|
292 "activate 0", "global activate 0", "deactivate 0", "global deactivate 0", |
|
293 "activate 1", "global activate 1", "deactivate 1", "global deactivate 1", |
|
294 "activate 2", "global activate 2" |
|
295 ]; |
|
296 |
|
297 function windowsActivation(window) { |
|
298 let index = windows.indexOf(window); |
|
299 // only concerned with windows opened for this test |
|
300 if (index < 0) |
|
301 return; |
|
302 |
|
303 assert.equal(actions.join(), expects.slice(0, index*4 + 1).join(), expects[index*4 + 1]); |
|
304 actions.push("global activate " + index) |
|
305 } |
|
306 |
|
307 function windowsDeactivation(window) { |
|
308 let index = windows.indexOf(window); |
|
309 // only concerned with windows opened for this test |
|
310 if (index < 0) |
|
311 return; |
|
312 |
|
313 assert.equal(actions.join(), expects.slice(0, index*4 + 3).join(), expects[index*4 + 3]); |
|
314 actions.push("global deactivate " + index) |
|
315 } |
|
316 |
|
317 // listen to global activate events |
|
318 browserWindows.on("activate", windowsActivation); |
|
319 |
|
320 // listen to global deactivate events |
|
321 browserWindows.on("deactivate", windowsDeactivation); |
|
322 |
|
323 |
|
324 function openWindow() { |
|
325 windows.push(browserWindows.open({ |
|
326 url: "data:text/html;charset=utf-8,<i>testTrackWindows</i>", |
|
327 onActivate: function(window) { |
|
328 let index = windows.indexOf(window); |
|
329 |
|
330 // Guard against windows that have already been removed. |
|
331 // See bug 874502 comment 32. |
|
332 if (index == -1) |
|
333 return; |
|
334 |
|
335 assert.equal(actions.join(), |
|
336 expects.slice(0, index*4).join(), |
|
337 "expecting " + expects[index*4]); |
|
338 actions.push("activate " + index); |
|
339 |
|
340 if (windows.length < 3) { |
|
341 openWindow() |
|
342 } |
|
343 else { |
|
344 (function closeWindows(windows) { |
|
345 if (!windows.length) { |
|
346 browserWindows.removeListener("activate", windowsActivation); |
|
347 browserWindows.removeListener("deactivate", windowsDeactivation); |
|
348 return done(); |
|
349 } |
|
350 |
|
351 return windows.pop().close(function() { |
|
352 assert.pass('window was closed'); |
|
353 closeWindows(windows); |
|
354 }); |
|
355 })(windows) |
|
356 } |
|
357 }, |
|
358 onDeactivate: function(window) { |
|
359 let index = windows.indexOf(window); |
|
360 |
|
361 // Guard against windows that have already been removed. |
|
362 // See bug 874502 comment 32. |
|
363 if (index == -1) |
|
364 return; |
|
365 |
|
366 assert.equal(actions.join(), |
|
367 expects.slice(0, index*4 + 2).join(), |
|
368 "expecting " + expects[index*4 + 2]); |
|
369 actions.push("deactivate " + index) |
|
370 } |
|
371 })); |
|
372 } |
|
373 openWindow(); |
|
374 } |
|
375 |
|
376 // test that it is not possible to open a private window by default |
|
377 exports.testWindowOpenPrivateDefault = function(assert, done) { |
|
378 browserWindows.open({ |
|
379 url: 'about:mozilla', |
|
380 isPrivate: true, |
|
381 onOpen: function(window) { |
|
382 let tab = window.tabs[0]; |
|
383 |
|
384 tab.once('ready', function() { |
|
385 assert.equal(tab.url, 'about:mozilla', 'opened correct tab'); |
|
386 assert.equal(isPrivate(tab), false, 'tab is not private'); |
|
387 |
|
388 window.close(done); |
|
389 }); |
|
390 } |
|
391 }); |
|
392 } |
|
393 |
|
394 // test that it is not possible to find a private window in |
|
395 // windows module's iterator |
|
396 exports.testWindowIteratorPrivateDefault = function(assert, done) { |
|
397 assert.equal(browserWindows.length, 1, 'only one window open'); |
|
398 |
|
399 open('chrome://browser/content/browser.xul', { |
|
400 features: { |
|
401 private: true, |
|
402 chrome: true |
|
403 } |
|
404 }).then(focus).then(function(window) { |
|
405 // test that there is a private window opened |
|
406 assert.equal(isPrivate(window), isWindowPBSupported, 'there is a private window open'); |
|
407 assert.strictEqual(window, winUtils.activeWindow); |
|
408 assert.strictEqual(window, getMostRecentWindow()); |
|
409 |
|
410 assert.ok(!isPrivate(browserWindows.activeWindow)); |
|
411 |
|
412 assert.equal(browserWindows.length, 1, 'only one window in browserWindows'); |
|
413 assert.equal(windows().length, 1, 'only one window in windows()'); |
|
414 |
|
415 assert.equal(windows(null, { includePrivate: true }).length, 2); |
|
416 |
|
417 // test that all windows in iterator are not private |
|
418 for (let window of browserWindows) |
|
419 assert.ok(!isPrivate(window), 'no window in browserWindows is private'); |
|
420 |
|
421 close(window).then(done); |
|
422 }); |
|
423 }; |
|
424 |
|
425 exports["test getView(window)"] = function(assert, done) { |
|
426 browserWindows.once("open", window => { |
|
427 const view = viewFor(window); |
|
428 |
|
429 assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window"); |
|
430 assert.ok(isBrowser(view), "view is a browser window"); |
|
431 assert.equal(getWindowTitle(view), window.title, |
|
432 "window has a right title"); |
|
433 |
|
434 window.close(); |
|
435 // Defer handler cause window is destroyed after event is dispatched. |
|
436 browserWindows.once("close", defer(_ => { |
|
437 assert.equal(viewFor(window), null, "window view is gone"); |
|
438 done(); |
|
439 })); |
|
440 }); |
|
441 |
|
442 browserWindows.open({ url: "data:text/html,<title>yo</title>" }); |
|
443 }; |
|
444 |
|
445 require('sdk/test').run(exports); |