mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 07:48:00 +01:00
237 lines
7.1 KiB
JavaScript
237 lines
7.1 KiB
JavaScript
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is MozMill Test code.
|
|
*
|
|
* The Initial Developer of the Original Code is Mozilla Foundation.
|
|
* Portions created by the Initial Developer are Copyright (C) 2009
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Clint Talbert <ctalbert@mozilla.com>
|
|
* Henrik Skupin <hskupin@mozilla.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
// Include required modules
|
|
var domUtils = require("dom-utils");
|
|
|
|
const TIMEOUT_MODAL_DIALOG = 5000;
|
|
const DELAY_CHECK = 100;
|
|
|
|
/**
|
|
* Observer object to find the modal dialog spawned by a controller
|
|
*
|
|
* @constructor
|
|
* @class Observer used to find a modal dialog
|
|
*
|
|
* @param {object} aOpener
|
|
* Window which is the opener of the modal dialog
|
|
* @param {function} aCallback
|
|
* The callback handler to use to interact with the modal dialog
|
|
*/
|
|
function mdObserver(aOpener, aCallback) {
|
|
this._opener = aOpener;
|
|
this._callback = aCallback;
|
|
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
|
}
|
|
|
|
mdObserver.prototype = {
|
|
|
|
/**
|
|
* Set our default values for our internal properties
|
|
*/
|
|
_opener : null,
|
|
_callback: null,
|
|
_timer: null,
|
|
exception: null,
|
|
finished: false,
|
|
|
|
/**
|
|
* Check if the modal dialog has been opened
|
|
*
|
|
* @returns {object} The modal dialog window found, or null.
|
|
*/
|
|
findWindow : function mdObserver_findWindow() {
|
|
// If a window has been opened from content, it has to be unwrapped.
|
|
var window = domUtils.unwrapNode(mozmill.wm.getMostRecentWindow(''));
|
|
|
|
// Get the WebBrowserChrome and check if it's a modal window
|
|
var chrome = window.QueryInterface(Ci.nsIInterfaceRequestor).
|
|
getInterface(Ci.nsIWebNavigation).
|
|
QueryInterface(Ci.nsIDocShellTreeItem).
|
|
treeOwner.
|
|
QueryInterface(Ci.nsIInterfaceRequestor).
|
|
getInterface(Ci.nsIWebBrowserChrome);
|
|
if (!chrome.isWindowModal()) {
|
|
return null;
|
|
}
|
|
|
|
// Opening a modal dialog from a modal dialog would fail, if we wouldn't
|
|
// check for the opener of the modal dialog
|
|
var found = false;
|
|
if (window.opener) {
|
|
// XXX Bug 614757 - an already unwrapped node returns a wrapped node
|
|
var opener = domUtils.unwrapNode(window.opener);
|
|
found = (mozmill.utils.getChromeWindow(opener) == this._opener);
|
|
}
|
|
else {
|
|
// Also note that it could happen that dialogs don't have an opener
|
|
// (i.e. clear recent history). In such a case make sure that the most
|
|
// recent window is not the passed in reference opener
|
|
found = (window != this._opener);
|
|
}
|
|
|
|
return (found ? window : null);
|
|
},
|
|
|
|
/**
|
|
* Called by the timer in the given interval to check if the modal dialog has
|
|
* been opened. Once it has been found the callback gets executed
|
|
*
|
|
* @param {object} aSubject Not used.
|
|
* @param {string} aTopic Not used.
|
|
* @param {string} aData Not used.
|
|
*/
|
|
observe : function mdObserver_observe(aSubject, aTopic, aData) {
|
|
// Once the window has been found and loaded we can execute the callback
|
|
var window = this.findWindow();
|
|
if (window && ("documentLoaded" in window)) {
|
|
try {
|
|
this._callback(new mozmill.controller.MozMillController(window));
|
|
}
|
|
catch (ex) {
|
|
// Store the exception, so it can be forwarded if a modal dialog has
|
|
// been opened by another modal dialog
|
|
this.exception = ex;
|
|
}
|
|
|
|
if (window) {
|
|
window.close();
|
|
}
|
|
|
|
this.finished = true;
|
|
this.stop();
|
|
}
|
|
else {
|
|
// otherwise try again in a bit
|
|
this._timer.init(this, DELAY_CHECK, Ci.nsITimer.TYPE_ONE_SHOT);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Stop the timer which checks for new modal dialogs
|
|
*/
|
|
stop : function mdObserver_stop() {
|
|
delete this._timer;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates a new instance of modalDialog.
|
|
*
|
|
* @constructor
|
|
* @class Handler for modal dialogs
|
|
*
|
|
* @param {object} aWindow [optional - default: null]
|
|
* Window which is the opener of the modal dialog
|
|
*/
|
|
function modalDialog(aWindow) {
|
|
this._window = aWindow || null;
|
|
}
|
|
|
|
modalDialog.prototype = {
|
|
|
|
/**
|
|
* Simply checks if the modal dialog has been processed
|
|
*
|
|
* @returns {boolean} True, if the dialog has been processed
|
|
*/
|
|
get finished() {
|
|
return (!this._observer || this._observer.finished);
|
|
},
|
|
|
|
/**
|
|
* Start timer to wait for the modal dialog.
|
|
*
|
|
* @param {function} aCallback
|
|
* The callback handler to use to interact with the modal dialog
|
|
*/
|
|
start : function modalDialog_start(aCallback) {
|
|
if (!aCallback)
|
|
throw new Error(arguments.callee.name + ": Callback not specified.");
|
|
|
|
this._observer = new mdObserver(this._window, aCallback);
|
|
|
|
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
|
this._timer.init(this._observer, DELAY_CHECK, Ci.nsITimer.TYPE_ONE_SHOT);
|
|
},
|
|
|
|
/**
|
|
* Stop the timer which checks for new modal dialogs
|
|
*/
|
|
stop : function modalDialog_stop() {
|
|
delete this._timer;
|
|
|
|
if (this._observer) {
|
|
this._observer.stop();
|
|
this._observer = null;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Wait until the modal dialog has been processed.
|
|
*
|
|
* @param {Number} aTimeout (optional - default 5s)
|
|
* Duration to wait
|
|
*/
|
|
waitForDialog : function modalDialog_waitForDialog(aTimeout) {
|
|
var timeout = aTimeout || TIMEOUT_MODAL_DIALOG;
|
|
|
|
if (!this._observer) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
mozmill.utils.waitFor(function () {
|
|
return this.finished;
|
|
}, "Modal dialog has been found and processed", timeout, undefined, this);
|
|
|
|
// Forward the raised exception so we can detect failures in modal dialogs
|
|
if (this._observer.exception) {
|
|
throw this._observer.exception;
|
|
}
|
|
}
|
|
finally {
|
|
this.stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Export of classes
|
|
exports.modalDialog = modalDialog;
|