mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 741587 - Part 1: Make alert/prompt/confirm work with <iframe mozbrowser>. r=smaug
--HG-- extra : rebase_source : f418da542453f8b0f5853a8da48bea1c8c95969e
This commit is contained in:
parent
43b3d9bcf3
commit
5fb435f5c4
@ -487,3 +487,9 @@ pref("ui.click_hold_context_menus.delay", 1000);
|
||||
pref("device.storage.enabled", true);
|
||||
|
||||
pref("media.plugins.enabled", true);
|
||||
|
||||
// Disable printing (particularly, window.print())
|
||||
pref("dom.disable_window_print", true);
|
||||
|
||||
// Disable window.showModalDialog
|
||||
pref("dom.disable_window_showModalDialog", true);
|
||||
|
@ -874,6 +874,9 @@ xpicleanup@BIN_SUFFIX@
|
||||
components/amContentHandler.js
|
||||
components/amWebInstallListener.js
|
||||
components/browser.xpt
|
||||
components/BrowserElementParent.js
|
||||
components/BrowserElementParent.manifest
|
||||
components/BrowserElementPromptService.jsm
|
||||
components/components.manifest
|
||||
components/contentAreaDropListener.js
|
||||
components/contentSecurityPolicy.js
|
||||
|
@ -7,7 +7,10 @@
|
||||
let Cu = Components.utils;
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
let Cr = Components.results;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||
|
||||
// Event whitelisted for bubbling.
|
||||
let whitelistedEvents = [
|
||||
@ -45,6 +48,9 @@ var global = this;
|
||||
|
||||
function BrowserElementChild() {
|
||||
this._init();
|
||||
|
||||
// Maps outer window id --> weak ref to window. Used by modal dialog code.
|
||||
this._windowIDDict = {};
|
||||
};
|
||||
|
||||
BrowserElementChild.prototype = {
|
||||
@ -52,6 +58,8 @@ BrowserElementChild.prototype = {
|
||||
debug("Starting up.");
|
||||
sendAsyncMsg("hello");
|
||||
|
||||
BrowserElementPromptService.mapWindowToBrowserElementChild(content, this);
|
||||
|
||||
docShell.QueryInterface(Ci.nsIWebProgress)
|
||||
.addProgressListener(this._progressListener,
|
||||
Ci.nsIWebProgress.NOTIFY_LOCATION |
|
||||
@ -87,11 +95,14 @@ BrowserElementChild.prototype = {
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
addMessageListener("browser-element-api:get-screenshot",
|
||||
this._recvGetScreenshot.bind(this));
|
||||
var self = this;
|
||||
function addMsgListener(msg, handler) {
|
||||
addMessageListener('browser-element-api:' + msg, handler.bind(self));
|
||||
}
|
||||
|
||||
addMessageListener("browser-element-api:set-visible",
|
||||
this._recvSetVisible.bind(this));
|
||||
addMsgListener("get-screenshot", this._recvGetScreenshot);
|
||||
addMsgListener("set-visible", this._recvSetVisible);
|
||||
addMsgListener("unblock-modal-prompt", this._recvStopWaiting);
|
||||
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
@ -109,6 +120,136 @@ BrowserElementChild.prototype = {
|
||||
/* useCapture = */ true);
|
||||
},
|
||||
|
||||
_tryGetInnerWindowID: function(win) {
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
try {
|
||||
return utils.currentInnerWindowID;
|
||||
}
|
||||
catch(e) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a modal prompt. Called by BrowserElementPromptService.
|
||||
*/
|
||||
showModalPrompt: function(win, args) {
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
args.windowID = { outer: utils.outerWindowID,
|
||||
inner: this._tryGetInnerWindowID(win) };
|
||||
sendAsyncMsg('showmodalprompt', args);
|
||||
|
||||
let returnValue = this._waitForResult(win);
|
||||
|
||||
if (args.promptType == 'prompt' ||
|
||||
args.promptType == 'confirm') {
|
||||
return returnValue;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Spin in a nested event loop until we receive a unblock-modal-prompt message for
|
||||
* this window.
|
||||
*/
|
||||
_waitForResult: function(win) {
|
||||
debug("_waitForResult(" + win + ")");
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let outerWindowID = utils.outerWindowID;
|
||||
let innerWindowID = this._tryGetInnerWindowID(win);
|
||||
if (innerWindowID === null) {
|
||||
// I have no idea what waiting for a result means when there's no inner
|
||||
// window, so let's just bail.
|
||||
debug("_waitForResult: No inner window. Bailing.");
|
||||
return;
|
||||
}
|
||||
|
||||
this._windowIDDict[outerWindowID] = Cu.getWeakReference(win);
|
||||
|
||||
debug("Entering modal state (outerWindowID=" + outerWindowID + ", " +
|
||||
"innerWindowID=" + innerWindowID + ")");
|
||||
|
||||
// In theory, we're supposed to pass |modalStateWin| back to
|
||||
// leaveModalStateWithWindow. But in practice, the window is always null,
|
||||
// because it's the window associated with this script context, which
|
||||
// doesn't have a window. But we'll play along anyway in case this
|
||||
// changes.
|
||||
var modalStateWin = utils.enterModalStateWithWindow();
|
||||
|
||||
// We'll decrement win.modalDepth when we receive a unblock-modal-prompt message
|
||||
// for the window.
|
||||
if (!win.modalDepth) {
|
||||
win.modalDepth = 0;
|
||||
}
|
||||
win.modalDepth++;
|
||||
let origModalDepth = win.modalDepth;
|
||||
|
||||
let thread = Services.tm.currentThread;
|
||||
debug("Nested event loop - begin");
|
||||
while (win.modalDepth == origModalDepth) {
|
||||
// Bail out of the loop if the inner window changed; that means the
|
||||
// window navigated.
|
||||
if (this._tryGetInnerWindowID(win) !== innerWindowID) {
|
||||
debug("_waitForResult: Inner window ID changed " +
|
||||
"while in nested event loop.");
|
||||
break;
|
||||
}
|
||||
|
||||
thread.processNextEvent(/* mayWait = */ true);
|
||||
}
|
||||
debug("Nested event loop - finish");
|
||||
|
||||
// If we exited the loop because the inner window changed, then bail on the
|
||||
// modal prompt.
|
||||
if (innerWindowID !== this._tryGetInnerWindowID(win)) {
|
||||
throw Components.Exception("Modal state aborted by navigation",
|
||||
Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
let returnValue = win.modalReturnValue;
|
||||
delete win.modalReturnValue;
|
||||
|
||||
utils.leaveModalStateWithWindow(modalStateWin);
|
||||
|
||||
debug("Leaving modal state (outerID=" + outerWindowID + ", " +
|
||||
"innerID=" + innerWindowID + ")");
|
||||
return returnValue;
|
||||
},
|
||||
|
||||
_recvStopWaiting: function(msg) {
|
||||
let outerID = msg.json.windowID.outer;
|
||||
let innerID = msg.json.windowID.inner;
|
||||
let returnValue = msg.json.returnValue;
|
||||
debug("recvStopWaiting(outer=" + outerID + ", inner=" + innerID +
|
||||
", returnValue=" + returnValue + ")");
|
||||
|
||||
if (!this._windowIDDict[outerID]) {
|
||||
debug("recvStopWaiting: No record of outer window ID " + outerID);
|
||||
return;
|
||||
}
|
||||
|
||||
let win = this._windowIDDict[outerID].get();
|
||||
delete this._windowIDDict[outerID];
|
||||
|
||||
if (!win) {
|
||||
debug("recvStopWaiting, but window is gone\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (innerID !== this._tryGetInnerWindowID(win)) {
|
||||
debug("recvStopWaiting, but inner ID has changed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("recvStopWaiting " + win);
|
||||
win.modalReturnValue = returnValue;
|
||||
win.modalDepth--;
|
||||
},
|
||||
|
||||
_titleChangedHandler: function(e) {
|
||||
debug("Got titlechanged: (" + e.target.title + ")");
|
||||
var win = e.target.defaultView;
|
||||
@ -179,8 +320,7 @@ BrowserElementChild.prototype = {
|
||||
// to keep a strong ref to it ourselves.
|
||||
_progressListener: {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsISupports]),
|
||||
Ci.nsISupportsWeakReference]),
|
||||
_seenLoadStart: false,
|
||||
|
||||
onLocationChange: function(webProgress, request, location, flags) {
|
||||
|
@ -18,6 +18,14 @@ function debug(msg) {
|
||||
//dump("BrowserElementParent - " + msg + "\n");
|
||||
}
|
||||
|
||||
function sendAsyncMsg(frameElement, msg, data) {
|
||||
let mm = frameElement.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader
|
||||
.messageManager;
|
||||
|
||||
mm.sendAsyncMessage('browser-element-api:' + msg, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The BrowserElementParent implements one half of <iframe mozbrowser>.
|
||||
* (The other half is, unsurprisingly, BrowserElementChild.)
|
||||
@ -38,8 +46,6 @@ BrowserElementParent.prototype = {
|
||||
* changed.
|
||||
*/
|
||||
_init: function() {
|
||||
debug("_init");
|
||||
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
@ -52,6 +58,7 @@ BrowserElementParent.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
debug("_init");
|
||||
this._initialized = true;
|
||||
|
||||
this._screenshotListeners = {};
|
||||
@ -107,6 +114,7 @@ BrowserElementParent.prototype = {
|
||||
addMessageListener("iconchange", this._fireEventFromMsg);
|
||||
addMessageListener("get-mozapp-manifest-url", this._sendMozAppManifestURL);
|
||||
addMessageListener("keyevent", this._fireKeyEvent);
|
||||
addMessageListener("showmodalprompt", this._handleShowModalPrompt);
|
||||
mm.addMessageListener('browser-element-api:got-screenshot',
|
||||
this._recvGotScreenshot.bind(this));
|
||||
|
||||
@ -129,24 +137,83 @@ BrowserElementParent.prototype = {
|
||||
* |data|.
|
||||
*/
|
||||
_fireEventFromMsg: function(frameElement, data) {
|
||||
let name = data.name;
|
||||
let name = data.name.substring('browser-element-api:'.length);
|
||||
let detail = data.json;
|
||||
|
||||
debug('fireEventFromMsg: ' + name + ' ' + detail);
|
||||
let evtName = name.substring('browser-element-api:'.length);
|
||||
debug('fireEventFromMsg: ' + name + ', ' + detail);
|
||||
let evt = this._createEvent(frameElement, name, detail,
|
||||
/* cancelable = */ false);
|
||||
frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_handleShowModalPrompt: function(frameElement, data) {
|
||||
// Fire a showmodalprmopt event on the iframe. When this method is called,
|
||||
// the child is spinning in a nested event loop waiting for an
|
||||
// unblock-modal-prompt message.
|
||||
//
|
||||
// If the embedder calls preventDefault() on the showmodalprompt event,
|
||||
// we'll block the child until event.detail.unblock() is called.
|
||||
//
|
||||
// Otherwise, if preventDefault() is not called, we'll send the
|
||||
// unblock-modal-prompt message to the child as soon as the event is done
|
||||
// dispatching.
|
||||
|
||||
let detail = data.json;
|
||||
debug('handleShowPrompt ' + JSON.stringify(detail));
|
||||
|
||||
// Strip off the windowID property from the object we send along in the
|
||||
// event.
|
||||
let windowID = detail.windowID;
|
||||
delete detail.windowID;
|
||||
debug("Event will have detail: " + JSON.stringify(detail));
|
||||
let evt = this._createEvent(frameElement, 'showmodalprompt', detail,
|
||||
/* cancelable = */ true);
|
||||
|
||||
let unblockMsgSent = false;
|
||||
function sendUnblockMsg() {
|
||||
if (unblockMsgSent) {
|
||||
return;
|
||||
}
|
||||
unblockMsgSent = true;
|
||||
|
||||
// We don't need to sanitize evt.detail.returnValue (e.g. converting the
|
||||
// return value of confirm() to a boolean); Gecko does that for us.
|
||||
|
||||
let data = { windowID: windowID,
|
||||
returnValue: evt.detail.returnValue };
|
||||
sendAsyncMsg(frameElement, 'unblock-modal-prompt', data);
|
||||
}
|
||||
|
||||
XPCNativeWrapper.unwrap(evt.detail).unblock = function() {
|
||||
sendUnblockMsg();
|
||||
};
|
||||
|
||||
frameElement.dispatchEvent(evt);
|
||||
|
||||
if (!evt.defaultPrevented) {
|
||||
// Unblock the inner frame immediately. Otherwise we'll unblock upon
|
||||
// evt.detail.unblock().
|
||||
sendUnblockMsg();
|
||||
}
|
||||
},
|
||||
|
||||
_createEvent: function(frameElement, evtName, detail, cancelable) {
|
||||
let win = frameElement.ownerDocument.defaultView;
|
||||
let evt;
|
||||
|
||||
// This will have to change if we ever want to send a CustomEvent with null
|
||||
// detail. For now, it's OK.
|
||||
if (detail !== undefined && detail !== null) {
|
||||
evt = new win.CustomEvent('mozbrowser' + evtName, {detail: detail});
|
||||
evt = new win.CustomEvent('mozbrowser' + evtName,
|
||||
{bubbles: true, cancelable: cancelable,
|
||||
detail: detail});
|
||||
}
|
||||
else {
|
||||
evt = new win.Event('mozbrowser' + evtName);
|
||||
evt = new win.Event('mozbrowser' + evtName,
|
||||
{bubbles: true, cancelable: cancelable});
|
||||
}
|
||||
|
||||
frameElement.dispatchEvent(evt);
|
||||
return evt;
|
||||
},
|
||||
|
||||
_sendMozAppManifestURL: function(frameElement, data) {
|
||||
|
189
dom/base/BrowserElementPromptService.jsm
Normal file
189
dom/base/BrowserElementPromptService.jsm
Normal file
@ -0,0 +1,189 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/* vim: set ft=javascript : */
|
||||
|
||||
"use strict";
|
||||
|
||||
let Cu = Components.utils;
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
let Cr = Components.results;
|
||||
let Cm = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
|
||||
let EXPORTED_SYMBOLS = ["BrowserElementPromptService"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function debug(msg) {
|
||||
//dump("BrowserElementPromptService - " + msg + "\n");
|
||||
}
|
||||
|
||||
function BrowserElementPrompt(win, browserElementChild) {
|
||||
this._win = win;
|
||||
this._browserElementChild = browserElementChild;
|
||||
}
|
||||
|
||||
BrowserElementPrompt.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrompt]),
|
||||
|
||||
alert: function(title, text) {
|
||||
this._browserElementChild.showModalPrompt(
|
||||
this._win, {promptType: "alert", title: title, message: text});
|
||||
},
|
||||
|
||||
alertCheck: function(title, text, checkMsg, checkState) {
|
||||
// Treat this like a normal alert() call, ignoring the checkState. The
|
||||
// front-end can do its own suppression of the alert() if it wants.
|
||||
this.alert(title, text);
|
||||
},
|
||||
|
||||
confirm: function(title, text) {
|
||||
return this._browserElementChild.showModalPrompt(
|
||||
this._win, {promptType: "confirm", title: title, message: text});
|
||||
},
|
||||
|
||||
confirmCheck: function(title, text, checkMsg, checkState) {
|
||||
return this.confirm(title, text);
|
||||
},
|
||||
|
||||
confirmEx: function(title, text, buttonFlags, button0Title, button1Title, button2Title, checkMsg, checkState) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
prompt: function(title, text, value, checkMsg, checkState) {
|
||||
let rv = this._browserElementChild.showModalPrompt(
|
||||
this._win,
|
||||
{ promptType: "prompt",
|
||||
title: title,
|
||||
message: text,
|
||||
initialValue: value.value,
|
||||
returnValue: null });
|
||||
|
||||
value.value = rv;
|
||||
|
||||
// nsIPrompt::Prompt returns true if the user pressed "OK" at the prompt,
|
||||
// and false if the user pressed "Cancel".
|
||||
//
|
||||
// BrowserElementChild returns null for "Cancel" and returns the string the
|
||||
// user entered otherwise.
|
||||
return rv !== null;
|
||||
},
|
||||
|
||||
promptUsernameAndPassword: function(title, text, username, password, checkMsg, checkState) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
promptPassword: function(title, text, password, checkMsg, checkState) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
select: function(title, text, aCount, aSelectList, aOutSelection) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
};
|
||||
|
||||
function BrowserElementPromptFactory(toWrap) {
|
||||
this._wrapped = toWrap;
|
||||
}
|
||||
|
||||
BrowserElementPromptFactory.prototype = {
|
||||
classID: Components.ID("{24f3d0cf-e417-4b85-9017-c9ecf8bb1299}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPromptFactory]),
|
||||
|
||||
getPrompt: function(win, iid) {
|
||||
// Try to find a browserelementchild for the window.
|
||||
if (iid.number != Ci.nsIPrompt.number) {
|
||||
debug("Falling back to wrapped prompt service because " +
|
||||
"we don't recognize the requested IID (" + iid + ", " +
|
||||
"nsIPrompt=" + Ci.nsIPrompt);
|
||||
return this._wrapped.getPrompt(win, iid);
|
||||
}
|
||||
|
||||
let browserElementChild =
|
||||
BrowserElementPromptService.getBrowserElementChildForWindow(win);
|
||||
if (!browserElementChild) {
|
||||
debug("Falling back to wrapped prompt service because " +
|
||||
"we can't find a browserElementChild for " +
|
||||
win + ", " + win.location);
|
||||
return this._wrapped.getPrompt(win, iid);
|
||||
}
|
||||
|
||||
debug("Returning wrapped getPrompt for " + win);
|
||||
return new BrowserElementPrompt(win, browserElementChild)
|
||||
.QueryInterface(iid);
|
||||
}
|
||||
};
|
||||
|
||||
let BrowserElementPromptService = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
_init: function() {
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.addObserver(this, "outer-window-destroyed", /* ownsWeak = */ true);
|
||||
|
||||
// Wrap the existing @mozilla.org/prompter;1 implementation.
|
||||
var contractID = "@mozilla.org/prompter;1";
|
||||
var oldCID = Cm.contractIDToCID(contractID);
|
||||
var newCID = BrowserElementPromptFactory.prototype.classID;
|
||||
var oldFactory = Cm.getClassObject(Cc[contractID], Ci.nsIFactory);
|
||||
|
||||
if (oldCID == newCID) {
|
||||
debug("WARNING: Wrapped prompt factory is already installed!");
|
||||
return;
|
||||
}
|
||||
|
||||
Cm.unregisterFactory(oldCID, oldFactory);
|
||||
|
||||
var oldInstance = oldFactory.createInstance(null, Ci.nsIPromptFactory);
|
||||
var newInstance = new BrowserElementPromptFactory(oldInstance);
|
||||
|
||||
var newFactory = {
|
||||
createInstance: function(outer, iid) {
|
||||
if (outer != null) {
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
return newInstance.QueryInterface(iid);
|
||||
}
|
||||
};
|
||||
Cm.registerFactory(newCID,
|
||||
"BrowserElementPromptService's prompter;1 wrapper",
|
||||
contractID, newFactory);
|
||||
|
||||
debug("Done installing new prompt factory.");
|
||||
},
|
||||
|
||||
_getOuterWindowID: function(win) {
|
||||
return win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
},
|
||||
|
||||
_browserElementChildMap: {},
|
||||
mapWindowToBrowserElementChild: function(win, browserElementChild) {
|
||||
this._browserElementChildMap[this._getOuterWindowID(win)] = browserElementChild;
|
||||
},
|
||||
|
||||
getBrowserElementChildForWindow: function(win) {
|
||||
return this._browserElementChildMap[this._getOuterWindowID(win)];
|
||||
},
|
||||
|
||||
_observeOuterWindowDestroyed: function(outerWindowID) {
|
||||
let id = outerWindowID.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
debug("observeOuterWindowDestroyed " + id);
|
||||
delete this._browserElementChildMap[outerWindowID.data];
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
switch(topic) {
|
||||
case "outer-window-destroyed":
|
||||
this._observeOuterWindowDestroyed(subject);
|
||||
break;
|
||||
default:
|
||||
debug("Observed unexpected topic " + topic);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
BrowserElementPromptService._init();
|
@ -32,6 +32,7 @@ EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
|
||||
EXTRA_JS_MODULES += \
|
||||
DOMRequestHelper.jsm \
|
||||
IndexedDBHelper.jsm \
|
||||
BrowserElementPromptService.jsm \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
|
@ -1793,7 +1793,6 @@ nsDOMWindowUtils::LeaveModalStateWithWindow(nsIDOMWindow *aWindow)
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_STATE(window);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aWindow);
|
||||
window->LeaveModalState(aWindow);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2473,7 +2473,7 @@ nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
bool
|
||||
nsGlobalWindow::DialogOpenAttempted()
|
||||
{
|
||||
nsGlobalWindow *topWindow = GetTop();
|
||||
nsGlobalWindow *topWindow = GetScriptableTop();
|
||||
if (!topWindow) {
|
||||
NS_ERROR("DialogOpenAttempted() called without a top window?");
|
||||
|
||||
@ -2507,7 +2507,7 @@ nsGlobalWindow::DialogOpenAttempted()
|
||||
bool
|
||||
nsGlobalWindow::AreDialogsBlocked()
|
||||
{
|
||||
nsGlobalWindow *topWindow = GetTop();
|
||||
nsGlobalWindow *topWindow = GetScriptableTop();
|
||||
if (!topWindow) {
|
||||
NS_ASSERTION(!mDocShell, "AreDialogsBlocked() called without a top window?");
|
||||
|
||||
@ -2558,7 +2558,7 @@ nsGlobalWindow::ConfirmDialogAllowed()
|
||||
void
|
||||
nsGlobalWindow::PreventFurtherDialogs()
|
||||
{
|
||||
nsGlobalWindow *topWindow = GetTop();
|
||||
nsGlobalWindow *topWindow = GetScriptableTop();
|
||||
if (!topWindow) {
|
||||
NS_ERROR("PreventFurtherDialogs() called without a top window?");
|
||||
|
||||
@ -6543,7 +6543,9 @@ nsGlobalWindow::ReallyCloseWindow()
|
||||
nsIDOMWindow *
|
||||
nsGlobalWindow::EnterModalState()
|
||||
{
|
||||
nsGlobalWindow* topWin = GetTop();
|
||||
// GetScriptableTop, not GetTop, so that EnterModalState works properly with
|
||||
// <iframe mozbrowser>.
|
||||
nsGlobalWindow* topWin = GetScriptableTop();
|
||||
|
||||
if (!topWin) {
|
||||
NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?");
|
||||
@ -6672,7 +6674,7 @@ private:
|
||||
void
|
||||
nsGlobalWindow::LeaveModalState(nsIDOMWindow *aCallerWin)
|
||||
{
|
||||
nsGlobalWindow *topWin = GetTop();
|
||||
nsGlobalWindow* topWin = GetScriptableTop();
|
||||
|
||||
if (!topWin) {
|
||||
NS_ERROR("Uh, LeaveModalState() called w/o a reachable top window?");
|
||||
@ -6714,7 +6716,7 @@ nsGlobalWindow::LeaveModalState(nsIDOMWindow *aCallerWin)
|
||||
bool
|
||||
nsGlobalWindow::IsInModalState()
|
||||
{
|
||||
nsGlobalWindow *topWin = GetTop();
|
||||
nsGlobalWindow *topWin = GetScriptableTop();
|
||||
|
||||
if (!topWin) {
|
||||
NS_ERROR("Uh, IsInModalState() called w/o a reachable top window?");
|
||||
|
@ -379,7 +379,17 @@ public:
|
||||
nsCOMPtr<nsIDOMWindow> top;
|
||||
GetTop(getter_AddRefs(top));
|
||||
if (top)
|
||||
return static_cast<nsGlobalWindow *>(static_cast<nsIDOMWindow *>(top.get()));
|
||||
return static_cast<nsGlobalWindow *>(top.get());
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
inline nsGlobalWindow* GetScriptableTop()
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> top;
|
||||
GetScriptableTop(getter_AddRefs(top));
|
||||
if (top) {
|
||||
return static_cast<nsGlobalWindow *>(top.get());
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user