Bug 498648 - Start private browsing while editing a message, cancel, doesn't cancel private browsing; r=bz,jst,ehsan
This commit is contained in:
@@ -124,6 +124,9 @@ PrivateBrowsingService.prototype = {
|
|||||||
// List of view source window URIs for restoring later
|
// List of view source window URIs for restoring later
|
||||||
_viewSrcURLs: [],
|
_viewSrcURLs: [],
|
||||||
|
|
||||||
|
// List of nsIXULWindows we are going to be closing during the transition
|
||||||
|
_windowsToClose: [],
|
||||||
|
|
||||||
// XPCOM registration
|
// XPCOM registration
|
||||||
classDescription: "PrivateBrowsing Service",
|
classDescription: "PrivateBrowsing Service",
|
||||||
contractID: "@mozilla.org/privatebrowsing;1",
|
contractID: "@mozilla.org/privatebrowsing;1",
|
||||||
@@ -208,12 +211,20 @@ PrivateBrowsingService.prototype = {
|
|||||||
// just in case the only remaining window after setBrowserState is different.
|
// just in case the only remaining window after setBrowserState is different.
|
||||||
// it probably shouldn't be with the current sessionstore impl, but we shouldn't
|
// it probably shouldn't be with the current sessionstore impl, but we shouldn't
|
||||||
// rely on behaviour the API doesn't guarantee
|
// rely on behaviour the API doesn't guarantee
|
||||||
let browser = this._getBrowserWindow().gBrowser;
|
browserWindow = this._getBrowserWindow();
|
||||||
|
let browser = browserWindow.gBrowser;
|
||||||
|
|
||||||
// this ensures a clean slate from which to transition into or out of
|
// this ensures a clean slate from which to transition into or out of
|
||||||
// private browsing
|
// private browsing
|
||||||
browser.addTab();
|
browser.addTab();
|
||||||
|
browser.getBrowserForTab(browser.tabContainer.firstChild).stop();
|
||||||
browser.removeTab(browser.tabContainer.firstChild);
|
browser.removeTab(browser.tabContainer.firstChild);
|
||||||
|
browserWindow.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||||
|
.treeOwner
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIXULWindow)
|
||||||
|
.docShell.contentViewer.resetCloseWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,6 +309,20 @@ PrivateBrowsingService.prototype = {
|
|||||||
getMostRecentWindow("navigator:browser");
|
getMostRecentWindow("navigator:browser");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_ensureCanCloseWindows: function PBS__ensureCanCloseWindows() {
|
||||||
|
let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||||
|
getService(Ci.nsIWindowMediator);
|
||||||
|
let windowsEnum = windowMediator.getXULWindowEnumerator("navigator:browser");
|
||||||
|
|
||||||
|
while (windowsEnum.hasMoreElements()) {
|
||||||
|
let win = windowsEnum.getNext().QueryInterface(Ci.nsIXULWindow);
|
||||||
|
if (win.docShell.contentViewer.permitUnload(true))
|
||||||
|
this._windowsToClose.push(win);
|
||||||
|
else
|
||||||
|
throw Cr.NS_ERROR_ABORT;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_closePageInfoWindows: function PBS__closePageInfoWindows() {
|
_closePageInfoWindows: function PBS__closePageInfoWindows() {
|
||||||
let pageInfoEnum = Cc["@mozilla.org/appshell/window-mediator;1"].
|
let pageInfoEnum = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||||
getService(Ci.nsIWindowMediator).
|
getService(Ci.nsIWindowMediator).
|
||||||
@@ -401,6 +426,8 @@ PrivateBrowsingService.prototype = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._ensureCanCloseWindows();
|
||||||
|
|
||||||
this._autoStarted = this._prefs.getBoolPref("browser.privatebrowsing.autostart");
|
this._autoStarted = this._prefs.getBoolPref("browser.privatebrowsing.autostart");
|
||||||
this._inPrivateBrowsing = val != false;
|
this._inPrivateBrowsing = val != false;
|
||||||
|
|
||||||
@@ -422,9 +449,16 @@ PrivateBrowsingService.prototype = {
|
|||||||
this._onAfterPrivateBrowsingModeChange();
|
this._onAfterPrivateBrowsingModeChange();
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
Cu.reportError("Exception thrown while processing the " +
|
// We aborted the transition to/from private browsing, we must restore the
|
||||||
"private browsing mode change request: " + ex.toString());
|
// beforeunload handling on all the windows for which we switched it off.
|
||||||
|
for (let i = 0; i < this._windowsToClose.length; i++)
|
||||||
|
this._windowsToClose[i].docShell.contentViewer.resetCloseWindow();
|
||||||
|
// We don't log an error when the transition is canceled from beforeunload
|
||||||
|
if (ex != Cr.NS_ERROR_ABORT)
|
||||||
|
Cu.reportError("Exception thrown while processing the " +
|
||||||
|
"private browsing mode change request: " + ex.toString());
|
||||||
} finally {
|
} finally {
|
||||||
|
this._windowsToClose = [];
|
||||||
this._alreadyChangingMode = false;
|
this._alreadyChangingMode = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1870,7 +1870,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
|
|||||||
|
|
||||||
if (cv) {
|
if (cv) {
|
||||||
PRBool okToUnload;
|
PRBool okToUnload;
|
||||||
rv = cv->PermitUnload(&okToUnload);
|
rv = cv->PermitUnload(PR_FALSE, &okToUnload);
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
||||||
// We don't want to unload, so stop here, but don't throw an
|
// We don't want to unload, so stop here, but don't throw an
|
||||||
|
|||||||
@@ -6149,7 +6149,7 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
|
|||||||
// in the current document.
|
// in the current document.
|
||||||
|
|
||||||
PRBool okToUnload;
|
PRBool okToUnload;
|
||||||
rv = mContentViewer->PermitUnload(&okToUnload);
|
rv = mContentViewer->PermitUnload(PR_FALSE, &okToUnload);
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
||||||
// The user chose not to unload the page, interrupt the load.
|
// The user chose not to unload the page, interrupt the load.
|
||||||
@@ -7939,7 +7939,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||||||
// protocol handler deals with this for javascript: URLs.
|
// protocol handler deals with this for javascript: URLs.
|
||||||
if (!bIsJavascript && mContentViewer) {
|
if (!bIsJavascript && mContentViewer) {
|
||||||
PRBool okToUnload;
|
PRBool okToUnload;
|
||||||
rv = mContentViewer->PermitUnload(&okToUnload);
|
rv = mContentViewer->PermitUnload(PR_FALSE, &okToUnload);
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
||||||
// The user chose not to unload the page, interrupt the
|
// The user chose not to unload the page, interrupt the
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ struct nsIntRect;
|
|||||||
[ptr] native nsIWidgetPtr(nsIWidget);
|
[ptr] native nsIWidgetPtr(nsIWidget);
|
||||||
[ref] native nsIntRectRef(nsIntRect);
|
[ref] native nsIntRectRef(nsIntRect);
|
||||||
|
|
||||||
[scriptable, uuid(c9aba5da-7d8b-46a8-87cd-9ab7e16480b8)]
|
[scriptable, uuid(08665a60-b398-11de-8a39-0800200c9a66)]
|
||||||
interface nsIContentViewer : nsISupports
|
interface nsIContentViewer : nsISupports
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -24,7 +24,27 @@ interface nsIContentViewer : nsISupports
|
|||||||
|
|
||||||
void loadStart(in nsISupports aDoc);
|
void loadStart(in nsISupports aDoc);
|
||||||
void loadComplete(in unsigned long aStatus);
|
void loadComplete(in unsigned long aStatus);
|
||||||
boolean permitUnload();
|
|
||||||
|
/**
|
||||||
|
* Checks if the document wants to prevent unloading by firing beforeunload on
|
||||||
|
* the document, and if it does, prompts the user. The result is returned.
|
||||||
|
*
|
||||||
|
* @param aCallerClosesWindow indicates that the current caller will close the
|
||||||
|
* window. If the method returns true, all subsequent calls will be
|
||||||
|
* ignored.
|
||||||
|
*/
|
||||||
|
boolean permitUnload([optional] in boolean aCallerClosesWindow);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Works in tandem with permitUnload, if the caller decides not to close the
|
||||||
|
* window it indicated it will, it is the caller's responsibility to reset
|
||||||
|
* that with this method.
|
||||||
|
*
|
||||||
|
* @Note this method is only meant to be called on documents for which the
|
||||||
|
* caller has indicated that it will close the window. If that is not the case
|
||||||
|
* the behavior of this method is undefined.
|
||||||
|
*/
|
||||||
|
void resetCloseWindow();
|
||||||
void pageHide(in boolean isUnload);
|
void pageHide(in boolean isUnload);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5540,7 +5540,7 @@ nsGlobalWindow::Close()
|
|||||||
if (!mInClose && !mIsClosed && cv) {
|
if (!mInClose && !mIsClosed && cv) {
|
||||||
PRBool canClose;
|
PRBool canClose;
|
||||||
|
|
||||||
rv = cv->PermitUnload(&canClose);
|
rv = cv->PermitUnload(PR_FALSE, &canClose);
|
||||||
if (NS_SUCCEEDED(rv) && !canClose)
|
if (NS_SUCCEEDED(rv) && !canClose)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
|
|||||||
@@ -784,7 +784,7 @@ nsJSChannel::EvaluateScript()
|
|||||||
if (cv) {
|
if (cv) {
|
||||||
PRBool okToUnload;
|
PRBool okToUnload;
|
||||||
|
|
||||||
if (NS_SUCCEEDED(cv->PermitUnload(&okToUnload)) &&
|
if (NS_SUCCEEDED(cv->PermitUnload(PR_FALSE, &okToUnload)) &&
|
||||||
!okToUnload) {
|
!okToUnload) {
|
||||||
// The user didn't want to unload the current
|
// The user didn't want to unload the current
|
||||||
// page, translate this into an undefined
|
// page, translate this into an undefined
|
||||||
|
|||||||
@@ -497,6 +497,7 @@ protected:
|
|||||||
nsCString mPrevDocCharacterSet;
|
nsCString mPrevDocCharacterSet;
|
||||||
|
|
||||||
PRPackedBool mIsPageMode;
|
PRPackedBool mIsPageMode;
|
||||||
|
PRPackedBool mCallerIsClosingWindow;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -528,6 +529,7 @@ void DocumentViewerImpl::PrepareToStartLoad()
|
|||||||
mStopped = PR_FALSE;
|
mStopped = PR_FALSE;
|
||||||
mLoaded = PR_FALSE;
|
mLoaded = PR_FALSE;
|
||||||
mDeferredWindowClose = PR_FALSE;
|
mDeferredWindowClose = PR_FALSE;
|
||||||
|
mCallerIsClosingWindow = PR_FALSE;
|
||||||
|
|
||||||
#ifdef NS_PRINTING
|
#ifdef NS_PRINTING
|
||||||
mPrintIsPending = PR_FALSE;
|
mPrintIsPending = PR_FALSE;
|
||||||
@@ -1083,11 +1085,11 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload)
|
DocumentViewerImpl::PermitUnload(PRBool aCallerClosesWindow, PRBool *aPermitUnload)
|
||||||
{
|
{
|
||||||
*aPermitUnload = PR_TRUE;
|
*aPermitUnload = PR_TRUE;
|
||||||
|
|
||||||
if (!mDocument || mInPermitUnload) {
|
if (!mDocument || mInPermitUnload || mCallerIsClosingWindow) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1193,15 +1195,47 @@ DocumentViewerImpl::PermitUnload(PRBool *aPermitUnload)
|
|||||||
|
|
||||||
if (docShell) {
|
if (docShell) {
|
||||||
nsCOMPtr<nsIContentViewer> cv;
|
nsCOMPtr<nsIContentViewer> cv;
|
||||||
docShell->GetContentViewer(getter_AddRefs(cv));
|
docShell->GetContentViewer(getter_AddRefs(cv));
|
||||||
|
|
||||||
if (cv) {
|
if (cv) {
|
||||||
cv->PermitUnload(aPermitUnload);
|
cv->PermitUnload(aCallerClosesWindow, aPermitUnload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aCallerClosesWindow && *aPermitUnload)
|
||||||
|
mCallerIsClosingWindow = PR_TRUE;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
DocumentViewerImpl::ResetCloseWindow()
|
||||||
|
{
|
||||||
|
mCallerIsClosingWindow = PR_FALSE;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
|
||||||
|
if (docShellNode) {
|
||||||
|
PRInt32 childCount;
|
||||||
|
docShellNode->GetChildCount(&childCount);
|
||||||
|
|
||||||
|
for (PRInt32 i = 0; i < childCount; ++i) {
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> item;
|
||||||
|
docShellNode->GetChildAt(i, getter_AddRefs(item));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(item));
|
||||||
|
|
||||||
|
if (docShell) {
|
||||||
|
nsCOMPtr<nsIContentViewer> cv;
|
||||||
|
docShell->GetContentViewer(getter_AddRefs(cv));
|
||||||
|
|
||||||
|
if (cv) {
|
||||||
|
cv->ResetCloseWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user