1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is MozMill Test code.
16 * The Initial Developer of the Original Code is Mozilla Foundation.
17 * Portions created by the Initial Developer are Copyright (C) 2009
18 * the Initial Developer. All Rights Reserved.
21 * Clint Talbert <ctalbert@mozilla.com>
22 * Henrik Skupin <hskupin@mozilla.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 // Include required modules
39 var domUtils = require("dom-utils");
41 const TIMEOUT_MODAL_DIALOG = 5000;
42 const DELAY_CHECK = 100;
45 * Observer object to find the modal dialog spawned by a controller
48 * @class Observer used to find a modal dialog
50 * @param {object} aOpener
51 * Window which is the opener of the modal dialog
52 * @param {function} aCallback
53 * The callback handler to use to interact with the modal dialog
55 function mdObserver(aOpener, aCallback) {
56 this._opener = aOpener;
57 this._callback = aCallback;
58 this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
61 mdObserver.prototype = {
64 * Set our default values for our internal properties
73 * Check if the modal dialog has been opened
75 * @returns {object} The modal dialog window found, or null.
77 findWindow : function mdObserver_findWindow() {
78 // If a window has been opened from content, it has to be unwrapped.
79 var window = domUtils.unwrapNode(mozmill.wm.getMostRecentWindow(''));
81 // Get the WebBrowserChrome and check if it's a modal window
82 var chrome = window.QueryInterface(Ci.nsIInterfaceRequestor).
83 getInterface(Ci.nsIWebNavigation).
84 QueryInterface(Ci.nsIDocShellTreeItem).
86 QueryInterface(Ci.nsIInterfaceRequestor).
87 getInterface(Ci.nsIWebBrowserChrome);
88 if (!chrome.isWindowModal()) {
92 // Opening a modal dialog from a modal dialog would fail, if we wouldn't
93 // check for the opener of the modal dialog
96 // XXX Bug 614757 - an already unwrapped node returns a wrapped node
97 var opener = domUtils.unwrapNode(window.opener);
98 found = (mozmill.utils.getChromeWindow(opener) == this._opener);
101 // Also note that it could happen that dialogs don't have an opener
102 // (i.e. clear recent history). In such a case make sure that the most
103 // recent window is not the passed in reference opener
104 found = (window != this._opener);
107 return (found ? window : null);
111 * Called by the timer in the given interval to check if the modal dialog has
112 * been opened. Once it has been found the callback gets executed
114 * @param {object} aSubject Not used.
115 * @param {string} aTopic Not used.
116 * @param {string} aData Not used.
118 observe : function mdObserver_observe(aSubject, aTopic, aData) {
119 // Once the window has been found and loaded we can execute the callback
120 var window = this.findWindow();
121 if (window && ("documentLoaded" in window)) {
123 this._callback(new mozmill.controller.MozMillController(window));
126 // Store the exception, so it can be forwarded if a modal dialog has
127 // been opened by another modal dialog
135 this.finished = true;
139 // otherwise try again in a bit
140 this._timer.init(this, DELAY_CHECK, Ci.nsITimer.TYPE_ONE_SHOT);
145 * Stop the timer which checks for new modal dialogs
147 stop : function mdObserver_stop() {
154 * Creates a new instance of modalDialog.
157 * @class Handler for modal dialogs
159 * @param {object} aWindow [optional - default: null]
160 * Window which is the opener of the modal dialog
162 function modalDialog(aWindow) {
163 this._window = aWindow || null;
166 modalDialog.prototype = {
169 * Simply checks if the modal dialog has been processed
171 * @returns {boolean} True, if the dialog has been processed
174 return (!this._observer || this._observer.finished);
178 * Start timer to wait for the modal dialog.
180 * @param {function} aCallback
181 * The callback handler to use to interact with the modal dialog
183 start : function modalDialog_start(aCallback) {
185 throw new Error(arguments.callee.name + ": Callback not specified.");
187 this._observer = new mdObserver(this._window, aCallback);
189 this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
190 this._timer.init(this._observer, DELAY_CHECK, Ci.nsITimer.TYPE_ONE_SHOT);
194 * Stop the timer which checks for new modal dialogs
196 stop : function modalDialog_stop() {
199 if (this._observer) {
200 this._observer.stop();
201 this._observer = null;
206 * Wait until the modal dialog has been processed.
208 * @param {Number} aTimeout (optional - default 5s)
211 waitForDialog : function modalDialog_waitForDialog(aTimeout) {
212 var timeout = aTimeout || TIMEOUT_MODAL_DIALOG;
214 if (!this._observer) {
219 mozmill.utils.waitFor(function () {
220 return this.finished;
221 }, "Modal dialog has been found and processed", timeout, undefined, this);
223 // Forward the raised exception so we can detect failures in modal dialogs
224 if (this._observer.exception) {
225 throw this._observer.exception;
236 exports.modalDialog = modalDialog;