Permalink
Browse files

Move the "force into tab" code out of Gecko and allow embeddors to do…

… the same

sort of thing.  Bug 323810, r=bsmedberg, sr=jst
  • Loading branch information...
bzbarsky%mit.edu
bzbarsky%mit.edu committed Feb 7, 2006
1 parent 7d72129 commit fc0b0f2bea298ee1cad53e8de2cb68a3649c4773
@@ -62,7 +62,6 @@
#include "nsIPresShell.h"
#include "nsGUIEvent.h"
#include "nsPresContext.h"
#include "nsIBrowserDOMWindow.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIDOMViewCSS.h"
#include "nsIXBLService.h"
@@ -221,17 +220,10 @@ nsXMLElement::MaybeTriggerAutoLink(nsIDocShell *aShell)
// XXX Should probably do this using atoms
if (value.EqualsLiteral("new")) {
if (nsContentUtils::GetBoolPref("dom.disable_open_during_load")) {
// disabling open during load
return NS_OK;
}
if (nsContentUtils::GetIntPref("browser.link.open_newwindow",
nsIBrowserDOMWindow::OPEN_NEWWINDOW) ==
nsIBrowserDOMWindow::OPEN_NEWWINDOW) {
verb = eLinkVerb_New;
}
// We should just act like an HTML link with target="_blank" and if
// someone diverts or blocks those, that's fine with us. We don't
// care.
verb = eLinkVerb_New;
} else if (value.EqualsLiteral("replace")) {
// We want to actually stop processing the current document now.
// We do this by returning the correct value so that the one
@@ -307,11 +299,7 @@ nsXMLElement::HandleDOMEvent(nsPresContext* aPresContext,
// XXX Should probably do this using atoms
if (show.EqualsLiteral("new")) {
if (nsContentUtils::GetIntPref("browser.link.open_newwindow",
nsIBrowserDOMWindow::OPEN_NEWWINDOW) ==
nsIBrowserDOMWindow::OPEN_NEWWINDOW) {
verb = eLinkVerb_New;
}
verb = eLinkVerb_New;
} else if (show.EqualsLiteral("replace")) {
verb = eLinkVerb_Replace;
} else if (show.EqualsLiteral("embed")) {
@@ -1097,160 +1097,6 @@ nsDocShell::ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
documentDomainSet);
}
nsresult nsDocShell::FindTarget(const PRUnichar *aWindowTarget,
PRBool *aIsNewWindow,
nsIDocShell **aResult)
{
nsresult rv = NS_OK;
*aResult = nsnull;
*aIsNewWindow = PR_FALSE;
// Try to locate the target window...
nsCOMPtr<nsIDocShellTreeItem> treeItem;
FindItemWithName(aWindowTarget, nsnull, this, getter_AddRefs(treeItem));
PRInt32 linkPref = nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW;
// XXXbz this should live inside FindItemWithName, I think...
if (!treeItem) {
mPrefs->GetIntPref("browser.link.open_newwindow", &linkPref);
if (linkPref == nsIBrowserDOMWindow::OPEN_CURRENTWINDOW) {
// force new window to go to _top
FindItemWithName(NS_LITERAL_STRING("_top").get(),
nsnull, this, getter_AddRefs(treeItem));
NS_ASSERTION(treeItem,
"We better get a treeitem when asking for '_top' "
"with |this| as the original requestor");
}
}
if (!treeItem)
{
/// XXXbz this should really happen in FindItemWithName too, I think...
nsCOMPtr<nsIDOMWindow> newWindow;
nsCOMPtr<nsIDOMWindowInternal> parentWindow;
// This DocShell is the parent window
parentWindow = do_GetInterface(GetAsSupports(this));
if (!parentWindow) {
NS_ASSERTION(0, "Can't get nsIDOMWindowInternal from nsDocShell!");
return NS_ERROR_FAILURE;
}
if (linkPref == nsIBrowserDOMWindow::OPEN_NEWTAB) {
// is it a popup?
PRBool allowTab = PR_TRUE;
nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(mScriptGlobal);
if (pWindow) {
// skip the window search-by-name of GetOpenAllow
// by using _self. we don't care about that at this point.
OpenAllowValue allow = pWindow->GetOpenAllow(
NS_LITERAL_STRING("_self"));
if (allow == allowNot || allow == allowSelf)
allowTab = PR_FALSE;
}
// try to get our tab-opening interface
if (allowTab) {
nsCOMPtr<nsIBrowserDOMWindow> bwin;
nsCOMPtr<nsIDocShellTreeItem> rootItem;
GetRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsIDOMWindow> rootWin(do_GetInterface(rootItem));
nsCOMPtr<nsIDOMChromeWindow> chromeWin(
do_QueryInterface(rootWin));
if (chromeWin)
chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
// open a new tab
if (bwin) {
rv = bwin->OpenURI(0, 0, nsIBrowserDOMWindow::OPEN_NEWTAB,
nsIBrowserDOMWindow::OPEN_NEW,
getter_AddRefs(newWindow));
nsCOMPtr<nsPIDOMWindow> newPIWindow =
do_GetInterface(newWindow);
if (newPIWindow)
newPIWindow->SetOpenerWindow(parentWindow);
}
}
// else fall through to the normal Open method, from which
// the appropriate measures will be taken when the popup fails
}
if (!newWindow) {
nsAutoString name(aWindowTarget);
// XXXbz this should be handled somewhere else.... and in fact, it
// may be safe to just pass those through here. Check.
if (name.LowerCaseEqualsLiteral("_blank") ||
name.LowerCaseEqualsLiteral("_new")) {
name.Truncate();
}
rv = parentWindow->Open(EmptyString(), // URL to load
name, // Window name
EmptyString(), // Window features
getter_AddRefs(newWindow));
}
if (NS_FAILED(rv)) return rv;
{
// Get the DocShell from the new window...
nsCOMPtr<nsPIDOMWindow> piwindow(do_QueryInterface(newWindow));
// *aResult will be AddRef()'ed below...
*aResult = piwindow->GetDocShell();
}
// If all went well, indicate that a new window has been created.
if (*aResult) {
NS_ADDREF(*aResult);
*aIsNewWindow = PR_TRUE;
// if we just open a new window for this link, charset from current docshell
// should be kept, as what we did in js openNewWindowWith(url)
nsCOMPtr<nsIMarkupDocumentViewer> muCV, target_muCV;
nsCOMPtr<nsIContentViewer> cv, target_cv;
this->GetContentViewer(getter_AddRefs(cv));
(*aResult)->GetContentViewer(getter_AddRefs(target_cv));
if (cv && target_cv) {
muCV = do_QueryInterface(cv);
target_muCV = do_QueryInterface(target_cv);
if (muCV && target_muCV) {
nsCAutoString defaultCharset;
nsCAutoString prevDocCharset;
rv = muCV->GetDefaultCharacterSet(defaultCharset);
if(NS_SUCCEEDED(rv)) {
target_muCV->SetDefaultCharacterSet(defaultCharset);
}
rv = muCV->GetPrevDocCharacterSet(prevDocCharset);
if(NS_SUCCEEDED(rv)) {
target_muCV->SetPrevDocCharacterSet(prevDocCharset);
}
}
}
}
return rv;
}
else
{
if (treeItem)
{
NS_ASSERTION(!*aResult, "aResult should be null if treeItem is set!");
treeItem->QueryInterface(NS_GET_IID(nsIDocShell), (void **)aResult);
}
else
{
NS_IF_ADDREF(*aResult);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetEldestPresContext(nsPresContext** aPresContext)
{
@@ -6336,68 +6182,38 @@ nsDocShell::InternalLoad(nsIURI * aURI,
// load to it...
//
if (aWindowTarget && *aWindowTarget) {
PRBool bIsNewWindow;
nsCOMPtr<nsIDocShell> targetDocShell;
nsAutoString name(aWindowTarget);
//
// This is a hack to prevent top-level windows from ever being
// created. It really doesn't belong here, but until there is a
// way for embeddors to get involved in window targeting, this is
// as good a place as any...
// XXXbz no, it's not.... fixme!!!!
//
PRInt32 linkPref = nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW;
mPrefs->GetIntPref("browser.link.open_newwindow", &linkPref);
if (linkPref == nsIBrowserDOMWindow::OPEN_CURRENTWINDOW) {
PRBool bIsChromeOrResource = PR_FALSE;
if (mCurrentURI)
mCurrentURI->SchemeIs("chrome", &bIsChromeOrResource);
if (!bIsChromeOrResource) {
aURI->SchemeIs("chrome", &bIsChromeOrResource);
if (!bIsChromeOrResource) {
aURI->SchemeIs("resource", &bIsChromeOrResource);
}
}
if (!bIsChromeOrResource) {
if (name.LowerCaseEqualsLiteral("_blank") ||
name.LowerCaseEqualsLiteral("_new")) {
name.AssignLiteral("_top");
}
// _main is an IE target which should be case-insensitive but isn't
// see bug 217886 for details
else if (!name.LowerCaseEqualsLiteral("_parent") &&
!name.LowerCaseEqualsLiteral("_self") &&
!name.LowerCaseEqualsLiteral("_content") &&
!name.EqualsLiteral("_main")) {
nsCOMPtr<nsIDocShellTreeItem> targetTreeItem;
FindItemWithName(name.get(),
nsnull,
this,
getter_AddRefs(targetTreeItem));
if (targetTreeItem)
targetDocShell = do_QueryInterface(targetTreeItem);
else
name.AssignLiteral("_top");
}
}
}
//
// Locate the target DocShell.
// This may involve creating a new toplevel window - if necessary.
//
nsCOMPtr<nsIDocShellTreeItem> targetItem;
FindItemWithName(aWindowTarget, nsnull, this,
getter_AddRefs(targetItem));
nsCOMPtr<nsIDocShell> targetDocShell = do_QueryInterface(targetItem);
PRBool isNewWindow = PR_FALSE;
if (!targetDocShell) {
rv = FindTarget(name.get(), &bIsNewWindow,
getter_AddRefs(targetDocShell));
}
nsCOMPtr<nsIDOMWindowInternal> win =
do_GetInterface(GetAsSupports(this));
NS_ENSURE_TRUE(win, NS_ERROR_NOT_AVAILABLE);
NS_ASSERTION(targetDocShell, "No Target docshell could be found!");
isNewWindow = PR_TRUE;
nsDependentString name(aWindowTarget);
nsCOMPtr<nsIDOMWindow> newWin;
rv = win->Open(EmptyString(), // URL to load
name, // window name
EmptyString(), // Features
getter_AddRefs(newWin));
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(newWin);
targetDocShell = do_QueryInterface(webNav);
}
//
// Transfer the load to the target DocShell... Pass nsnull as the
// window target name from to prevent recursive retargeting!
//
if (targetDocShell) {
if (NS_SUCCEEDED(rv) && targetDocShell) {
rv = targetDocShell->InternalLoad(aURI,
aReferrer,
owner,
@@ -6412,26 +6228,19 @@ nsDocShell::InternalLoad(nsIURI * aURI,
aDocShell,
aRequest);
if (rv == NS_ERROR_NO_CONTENT) {
if (bIsNewWindow) {
// XXXbz except we never reach this code!
if (isNewWindow) {
//
// At this point, a new window has been created, but the
// URI did not have any data associated with it...
//
// So, the best we can do, is to tear down the new window
// that was just created!
//
nsCOMPtr<nsIDocShellTreeItem> treeItem;
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
treeItem = do_QueryInterface(targetDocShell);
treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
if (treeOwner) {
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
treeOwnerAsWin = do_QueryInterface(treeOwner);
if (treeOwnerAsWin) {
treeOwnerAsWin->Destroy();
}
nsCOMPtr<nsIDOMWindowInternal> domWin =
do_GetInterface(targetDocShell);
if (domWin) {
domWin->Close();
}
}
//
@@ -6442,12 +6251,16 @@ nsDocShell::InternalLoad(nsIURI * aURI,
//
rv = NS_OK;
}
else if (bIsNewWindow) {
else if (isNewWindow) {
// XXX: Once new windows are created hidden, the new
// window will need to be made visible... For now,
// do nothing.
}
}
// Else we ran out of memory, or were a popup and got blocked,
// or something.
return rv;
}
@@ -439,10 +439,6 @@ friend class nsDSURIContentListener;
return t_sec;
}
nsresult FindTarget(const PRUnichar *aTargetName,
PRBool *aIsNewWindow,
nsIDocShell **aResult);
PRBool IsFrame();
//
@@ -768,6 +768,7 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent,
nsresult rv;
switch(aVerb) {
case eLinkVerb_New:
NS_ASSERTION(target.IsEmpty(), "Losing window name information");
target.AssignLiteral("_blank");
// Fall into replace case
case eLinkVerb_Undefined:
@@ -66,12 +66,11 @@ enum PopupControlState {
enum OpenAllowValue {
allowNot = 0, // the window opening is denied
allowNoAbuse, // allowed: not a popup
allowSelf, // allowed: it's the same window (_self, _top, et.al.)
allowExtant, // allowed: an already open window
allowWhitelisted // allowed: it's whitelisted or popup blocking is disabled
};
class nsIDocShell;
class nsIDocShellTreeItem;
class nsIFocusController;
class nsIDocument;
struct nsTimeout;
@@ -258,6 +257,11 @@ class nsPIDOMWindow : public nsIDOMWindowInternal
PRBool aForce) const = 0;
virtual void PopPopupControlState(PopupControlState state) const = 0;
virtual PopupControlState GetPopupControlState() const = 0;
// GetOpenAllow must not be called on a window that no longer has a docshell
// This function is deprecated. It will assume that there is no existing
// window with name aName for purposes of its answer. Expect this function
// to get removed soon!
virtual OpenAllowValue GetOpenAllow(const nsAString &aName) = 0;
// Returns an object containing the window's state. This also suspends
Oops, something went wrong.

0 comments on commit fc0b0f2

Please sign in to comment.