michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: "use strict"; michael@0: michael@0: module.metadata = { michael@0: engines: { michael@0: 'Firefox': '*' michael@0: } michael@0: }; michael@0: michael@0: const windowUtils = require("sdk/deprecated/window-utils"); michael@0: const timer = require("sdk/timers"); michael@0: const { Cc, Ci } = require("chrome"); michael@0: const { Loader } = require("sdk/test/loader"); michael@0: const { open, getFrames, getWindowTitle, onFocus, windows } = require('sdk/window/utils'); michael@0: const { close } = require('sdk/window/helpers'); michael@0: const { fromIterator: toArray } = require('sdk/util/array'); michael@0: michael@0: const WM = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); michael@0: michael@0: function makeEmptyWindow(options) { michael@0: options = options || {}; michael@0: var xulNs = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; michael@0: var blankXul = ('' + michael@0: '' + michael@0: '' + michael@0: ''); michael@0: michael@0: return open("data:application/vnd.mozilla.xul+xml;charset=utf-8," + escape(blankXul), { michael@0: features: { michael@0: chrome: true, michael@0: width: 10, michael@0: height: 10 michael@0: } michael@0: }); michael@0: } michael@0: michael@0: exports['test close on unload'] = function(assert) { michael@0: var timesClosed = 0; michael@0: var fakeWindow = { michael@0: _listeners: [], michael@0: addEventListener: function(name, func, bool) { michael@0: this._listeners.push(func); michael@0: }, michael@0: removeEventListener: function(name, func, bool) { michael@0: var index = this._listeners.indexOf(func); michael@0: if (index == -1) michael@0: throw new Error("event listener not found"); michael@0: this._listeners.splice(index, 1); michael@0: }, michael@0: close: function() { michael@0: timesClosed++; michael@0: this._listeners.forEach( michael@0: function(func) { michael@0: func({target: fakeWindow.document}); michael@0: }); michael@0: }, michael@0: document: { michael@0: get defaultView() { return fakeWindow; } michael@0: } michael@0: }; michael@0: michael@0: let loader = Loader(module); michael@0: loader.require("sdk/deprecated/window-utils").closeOnUnload(fakeWindow); michael@0: assert.equal(fakeWindow._listeners.length, 1, michael@0: "unload listener added on closeOnUnload()"); michael@0: assert.equal(timesClosed, 0, michael@0: "window not closed when registered."); michael@0: loader.unload(); michael@0: assert.equal(timesClosed, 1, michael@0: "window closed on module unload."); michael@0: assert.equal(fakeWindow._listeners.length, 0, michael@0: "unload event listener removed on module unload"); michael@0: michael@0: timesClosed = 0; michael@0: loader = Loader(module); michael@0: loader.require("sdk/deprecated/window-utils").closeOnUnload(fakeWindow); michael@0: assert.equal(timesClosed, 0, michael@0: "window not closed when registered."); michael@0: fakeWindow.close(); michael@0: assert.equal(timesClosed, 1, michael@0: "window closed when close() called."); michael@0: assert.equal(fakeWindow._listeners.length, 0, michael@0: "unload event listener removed on window close"); michael@0: loader.unload(); michael@0: assert.equal(timesClosed, 1, michael@0: "window not closed again on module unload."); michael@0: }; michael@0: michael@0: exports.testWindowTracker = function(assert, done) { michael@0: var myWindow; michael@0: var finished = false; michael@0: michael@0: var delegate = { michael@0: onTrack: function(window) { michael@0: if (window == myWindow) { michael@0: assert.pass("onTrack() called with our test window"); michael@0: timer.setTimeout(function() myWindow.close()); michael@0: } michael@0: }, michael@0: onUntrack: function(window) { michael@0: if (window == myWindow) { michael@0: assert.pass("onUntrack() called with our test window"); michael@0: timer.setTimeout(function() { michael@0: if (!finished) { michael@0: finished = true; michael@0: myWindow = null; michael@0: wt.unload(); michael@0: done(); michael@0: } michael@0: else { michael@0: assert.fail("finishTest() called multiple times."); michael@0: } michael@0: }); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: // test bug 638007 (new is optional), using new michael@0: var wt = new windowUtils.WindowTracker(delegate); michael@0: myWindow = makeEmptyWindow(); michael@0: }; michael@0: michael@0: exports['test window watcher untracker'] = function(assert, done) { michael@0: var myWindow; michael@0: var tracks = 0; michael@0: var unloadCalled = false; michael@0: michael@0: var delegate = { michael@0: onTrack: function(window) { michael@0: tracks = tracks + 1; michael@0: if (window == myWindow) { michael@0: assert.pass("onTrack() called with our test window"); michael@0: timer.setTimeout(function() { michael@0: myWindow.close(); michael@0: }, 1); michael@0: } michael@0: }, michael@0: onUntrack: function(window) { michael@0: tracks = tracks - 1; michael@0: if (window == myWindow && !unloadCalled) { michael@0: unloadCalled = true; michael@0: timer.setTimeout(function() { michael@0: wt.unload(); michael@0: }, 1); michael@0: } michael@0: if (0 > tracks) { michael@0: assert.fail("WindowTracker onUntrack was called more times than onTrack.."); michael@0: } michael@0: else if (0 == tracks) { michael@0: timer.setTimeout(function() { michael@0: myWindow = null; michael@0: done(); michael@0: }, 1); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: // test bug 638007 (new is optional), not using new michael@0: var wt = windowUtils.WindowTracker(delegate); michael@0: myWindow = makeEmptyWindow(); michael@0: }; michael@0: michael@0: // test that _unregWindow calls _unregLoadingWindow michael@0: exports['test window watcher unregs 4 loading wins'] = function(assert, done) { michael@0: var myWindow; michael@0: var finished = false; michael@0: let browserWindow = WM.getMostRecentWindow("navigator:browser"); michael@0: var counter = 0; michael@0: michael@0: var delegate = { michael@0: onTrack: function(window) { michael@0: var type = window.document.documentElement.getAttribute("windowtype"); michael@0: if (type == "test:window") michael@0: assert.fail("onTrack shouldn't have been executed."); michael@0: } michael@0: }; michael@0: var wt = new windowUtils.WindowTracker(delegate); michael@0: michael@0: // make a new window michael@0: myWindow = makeEmptyWindow(); michael@0: michael@0: // make sure that the window hasn't loaded yet michael@0: assert.notEqual( michael@0: myWindow.document.readyState, michael@0: "complete", michael@0: "window hasn't loaded yet."); michael@0: michael@0: // unload WindowTracker michael@0: wt.unload(); michael@0: michael@0: // make sure that the window still hasn't loaded, which means that the onTrack michael@0: // would have been removed successfully assuming that it doesn't execute. michael@0: assert.notEqual( michael@0: myWindow.document.readyState, michael@0: "complete", michael@0: "window still hasn't loaded yet."); michael@0: michael@0: // wait for the window to load and then close it. onTrack wouldn't be called michael@0: // until the window loads, so we must let it load before closing it to be michael@0: // certain that onTrack was removed. michael@0: myWindow.addEventListener("load", function() { michael@0: // allow all of the load handles to execute before closing michael@0: myWindow.setTimeout(function() { michael@0: myWindow.addEventListener("unload", function() { michael@0: // once the window unloads test is done michael@0: done(); michael@0: }, false); michael@0: myWindow.close(); michael@0: }, 0); michael@0: }, false); michael@0: } michael@0: michael@0: exports['test window watcher without untracker'] = function(assert, done) { michael@0: let myWindow; michael@0: let wt = new windowUtils.WindowTracker({ michael@0: onTrack: function(window) { michael@0: if (window == myWindow) { michael@0: assert.pass("onTrack() called with our test window"); michael@0: michael@0: close(myWindow).then(function() { michael@0: wt.unload(); michael@0: done(); michael@0: }, assert.fail); michael@0: } michael@0: } michael@0: }); michael@0: michael@0: myWindow = makeEmptyWindow(); michael@0: }; michael@0: michael@0: exports['test active window'] = function(assert, done) { michael@0: let browserWindow = WM.getMostRecentWindow("navigator:browser"); michael@0: let continueAfterFocus = function(window) onFocus(window).then(nextTest); michael@0: michael@0: assert.equal(windowUtils.activeBrowserWindow, browserWindow, michael@0: "Browser window is the active browser window."); michael@0: michael@0: michael@0: let testSteps = [ michael@0: function() { michael@0: continueAfterFocus(windowUtils.activeWindow = browserWindow); michael@0: }, michael@0: function() { michael@0: assert.equal(windowUtils.activeWindow, browserWindow, michael@0: "Correct active window [1]"); michael@0: nextTest(); michael@0: }, michael@0: function() { michael@0: assert.equal(windowUtils.activeBrowserWindow, browserWindow, michael@0: "Correct active browser window [2]"); michael@0: continueAfterFocus(windowUtils.activeWindow = browserWindow); michael@0: }, michael@0: function() { michael@0: assert.equal(windowUtils.activeWindow, browserWindow, michael@0: "Correct active window [3]"); michael@0: nextTest(); michael@0: }, michael@0: function() { michael@0: assert.equal(windowUtils.activeBrowserWindow, browserWindow, michael@0: "Correct active browser window [4]"); michael@0: done(); michael@0: } michael@0: ]; michael@0: michael@0: function nextTest() { michael@0: if (testSteps.length) michael@0: testSteps.shift()(); michael@0: } michael@0: nextTest(); michael@0: }; michael@0: michael@0: exports.testWindowIterator = function(assert, done) { michael@0: // make a new window michael@0: let window = makeEmptyWindow(); michael@0: michael@0: // make sure that the window hasn't loaded yet michael@0: assert.notEqual( michael@0: window.document.readyState, michael@0: "complete", michael@0: "window hasn't loaded yet."); michael@0: michael@0: // this window should only appear in windowIterator() while its loading michael@0: assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) === -1, michael@0: "window isn't in windowIterator()"); michael@0: michael@0: // Then it should be in windowIterator() michael@0: window.addEventListener("load", function onload() { michael@0: window.addEventListener("load", onload, false); michael@0: assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) !== -1, michael@0: "window is now in windowIterator()"); michael@0: michael@0: // Wait for the window unload before ending test michael@0: close(window).then(done); michael@0: }, false); michael@0: }; michael@0: michael@0: exports.testIgnoreClosingWindow = function(assert, done) { michael@0: assert.equal(windows().length, 1, "Only one window open"); michael@0: michael@0: // make a new window michael@0: let window = makeEmptyWindow(); michael@0: michael@0: assert.equal(windows().length, 2, "Two windows open"); michael@0: michael@0: window.addEventListener("load", function onload() { michael@0: window.addEventListener("load", onload, false); michael@0: michael@0: assert.equal(windows().length, 2, "Two windows open"); michael@0: michael@0: // Wait for the window unload before ending test michael@0: let checked = false; michael@0: michael@0: close(window).then(function() { michael@0: assert.ok(checked, 'the test is finished'); michael@0: }).then(done, assert.fail) michael@0: michael@0: assert.equal(windows().length, 1, "Only one window open"); michael@0: checked = true; michael@0: }, false); michael@0: }; michael@0: michael@0: require("test").run(exports);