Fixing bug 103638 (and bug 273699). Targets with same name in different windows open in the wrong window. Patch by bzbarsky@mit.edu and myself, r=danm.moz@gmail.com, bzbarsky@mit.edu, sr=dveditz@cruzio.com, a=asa@mozilla.org

This commit is contained in:
jst%mozilla.jstenback.com 2005-01-11 19:36:40 +00:00
Родитель a6baf4ca33
Коммит 1a8e54667c
23 изменённых файлов: 541 добавлений и 375 удалений

Просмотреть файл

@ -185,6 +185,11 @@ static PRInt32 gDocShellCount = 0;
// Global reference to the URI fixup service.
nsIURIFixup *nsDocShell::sURIFixup = 0;
// True means we validate window targets to prevent frameset
// spoofing. Initialize this to a non-bolean value so we know to check
// the pref on the creation of the first docshell.
static PRBool gValidateOrigin = (PRBool)0xffffffff;
// Hint for native dispatch of plevents on how long to delay after
// all documents have loaded in milliseconds before favoring normal
// native event dispatch priorites over performance
@ -245,7 +250,6 @@ nsDocShell::nsDocShell():
mEODForCurrentDocument(PR_FALSE),
mURIResultedInDocument(PR_FALSE),
mIsBeingDestroyed(PR_FALSE),
mValidateOrigin(PR_TRUE), // validate frame origins by default
mIsExecutingOnLoadHandler(PR_FALSE),
mIsPrintingOrPP(PR_FALSE),
mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
@ -375,15 +379,9 @@ NS_IMETHODIMP nsDocShell::GetInterface(const nsIID & aIID, void **aSink)
NS_SUCCEEDED(EnsureScriptEnvironment())) {
*aSink = mScriptGlobal;
}
else if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal)) &&
NS_SUCCEEDED(EnsureScriptEnvironment())) {
return mScriptGlobal->QueryInterface(aIID, aSink);
}
else if (aIID.Equals(NS_GET_IID(nsPIDOMWindow)) &&
NS_SUCCEEDED(EnsureScriptEnvironment())) {
return mScriptGlobal->QueryInterface(aIID, aSink);
}
else if (aIID.Equals(NS_GET_IID(nsIDOMWindow)) &&
else if ((aIID.Equals(NS_GET_IID(nsIDOMWindowInternal)) ||
aIID.Equals(NS_GET_IID(nsPIDOMWindow)) ||
aIID.Equals(NS_GET_IID(nsIDOMWindow))) &&
NS_SUCCEEDED(EnsureScriptEnvironment())) {
return mScriptGlobal->QueryInterface(aIID, aSink);
}
@ -863,8 +861,9 @@ nsDocShell::FireUnloadNotification()
// to the host PL_strcmp, it accepts a subdomain (nsHTMLDocument::SetDomain)
// if the document.domain was set.
//
static
PRBool SameOrSubdomainOfTarget(nsIURI* aOriginURI, nsIURI* aTargetURI, PRBool aDocumentDomainSet)
static PRBool
SameOrSubdomainOfTarget(nsIURI* aOriginURI, nsIURI* aTargetURI,
PRBool aDocumentDomainSet)
{
nsCAutoString targetScheme;
nsresult rv = aTargetURI->GetScheme(targetScheme);
@ -939,51 +938,80 @@ PRBool SameOrSubdomainOfTarget(nsIURI* aOriginURI, nsIURI* aTargetURI, PRBool aD
//
// Bug 13871: Prevent frameset spoofing
//
// This routine answers: 'Is origin's document from same domain as target's document?'
// This routine answers: 'Is origin's document from same domain as
// target's document?'
// Be optimistic that domain is same - error cases all answer 'yes'.
//
// We have to compare the URI of the actual document loaded in the origin,
// ignoring any document.domain that was set, with the principal URI of the
// target (including any document.domain that was set). This puts control
// of loading in the hands of the target, which is more secure. (per Nav 4.x)
// We have to compare the URI of the actual document loaded in the
// origin, ignoring any document.domain that was set, with the
// principal URI of the target (including any document.domain that was
// set). This puts control of loading in the hands of the target,
// which is more secure. (per Nav 4.x)
//
static
PRBool ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
nsIDocShellTreeItem* aTargetTreeItem)
static PRBool
ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
nsIDocShellTreeItem* aTargetTreeItem)
{
// Get origin document uri (ignoring document.domain)
nsCOMPtr<nsIWebNavigation> originWebNav(do_QueryInterface(aOriginTreeItem));
NS_ENSURE_TRUE(originWebNav, PR_TRUE);
nsCOMPtr<nsIScriptSecurityManager> securityManager =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
NS_ENSURE_TRUE(securityManager, PR_FALSE);
nsCOMPtr<nsIURI> originDocumentURI;
nsresult rv = originWebNav->GetCurrentURI(getter_AddRefs(originDocumentURI));
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && originDocumentURI, PR_TRUE);
nsCOMPtr<nsIPrincipal> subjectPrincipal;
nsresult rv =
securityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
NS_ENSURE_SUCCESS(rv, PR_TRUE);
// Get target principal uri (including document.domain)
nsCOMPtr<nsIDOMDocument> targetDOMDocument(do_GetInterface(aTargetTreeItem));
nsCOMPtr<nsIDocument> targetDocument(do_QueryInterface(targetDOMDocument));
NS_ENSURE_TRUE(targetDocument, PR_TRUE);
if (subjectPrincipal) {
// We're called from JS, check if UniversalBrowserWrite is
// enabled.
PRBool ubwEnabled = PR_FALSE;
rv = securityManager->IsCapabilityEnabled("UniversalBrowserWrite",
&ubwEnabled);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
nsIPrincipal *targetPrincipal = targetDocument->GetPrincipal();
NS_ENSURE_TRUE(targetPrincipal, PR_TRUE);
if (ubwEnabled) {
return PR_TRUE;
}
}
nsCOMPtr<nsIURI> targetPrincipalURI;
rv = targetPrincipal->GetURI(getter_AddRefs(targetPrincipalURI));
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && targetPrincipalURI, PR_TRUE);
// Get origin document uri (ignoring document.domain)
nsCOMPtr<nsIWebNavigation> originWebNav =
do_QueryInterface(aOriginTreeItem);
NS_ENSURE_TRUE(originWebNav, PR_TRUE);
// Find out if document.domain was set for HTML documents
PRBool documentDomainSet = PR_FALSE;
nsCOMPtr<nsIHTMLDocument> targetHTMLDocument(do_QueryInterface(targetDocument));
nsCOMPtr<nsIURI> originDocumentURI;
rv = originWebNav->GetCurrentURI(getter_AddRefs(originDocumentURI));
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && originDocumentURI, PR_TRUE);
// If we don't have an HTML document, fall through with documentDomainSet false
if (targetHTMLDocument) {
documentDomainSet = targetHTMLDocument->WasDomainSet();
}
// Get target principal uri (including document.domain)
nsCOMPtr<nsIDOMDocument> targetDOMDocument =
do_GetInterface(aTargetTreeItem);
nsCOMPtr<nsIDocument> targetDocument(do_QueryInterface(targetDOMDocument));
NS_ENSURE_TRUE(targetDocument, PR_TRUE);
// Is origin same principal or a subdomain of target's document.domain
// Compare actual URI of origin document, not origin principal's URI. (Per Nav 4.x)
return SameOrSubdomainOfTarget(originDocumentURI, targetPrincipalURI,
documentDomainSet);
nsIPrincipal *targetPrincipal = targetDocument->GetPrincipal();
NS_ENSURE_TRUE(targetPrincipal, PR_TRUE);
nsCOMPtr<nsIURI> targetPrincipalURI;
rv = targetPrincipal->GetURI(getter_AddRefs(targetPrincipalURI));
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && targetPrincipalURI, PR_TRUE);
// Find out if document.domain was set for HTML documents
PRBool documentDomainSet = PR_FALSE;
nsCOMPtr<nsIHTMLDocument> targetHTMLDocument =
do_QueryInterface(targetDocument);
// If we don't have an HTML document, fall through with
// documentDomainSet false
if (targetHTMLDocument) {
documentDomainSet = targetHTMLDocument->WasDomainSet();
}
// Is origin same principal or a subdomain of target's
// document.domain Compare actual URI of origin document, not origin
// principal's URI. (Per Nav 4.x)
return SameOrSubdomainOfTarget(originDocumentURI, targetPrincipalURI,
documentDomainSet);
}
nsresult nsDocShell::FindTarget(const PRUnichar *aWindowTarget,
@ -991,135 +1019,36 @@ nsresult nsDocShell::FindTarget(const PRUnichar *aWindowTarget,
nsIDocShell **aResult)
{
nsresult rv;
nsAutoString name(aWindowTarget);
nsCOMPtr<nsIDocShellTreeItem> treeItem;
PRBool mustMakeNewWindow = PR_FALSE;
*aResult = nsnull;
*aIsNewWindow = PR_FALSE;
if(!name.Length() || name.LowerCaseEqualsLiteral("_self"))
{
*aResult = this;
}
else if (name.LowerCaseEqualsLiteral("_blank") || name.LowerCaseEqualsLiteral("_new"))
{
mustMakeNewWindow = PR_TRUE;
name.Truncate();
}
else if(name.LowerCaseEqualsLiteral("_parent"))
{
GetSameTypeParent(getter_AddRefs(treeItem));
if(!treeItem)
*aResult = this;
}
else if(name.LowerCaseEqualsLiteral("_top"))
{
GetSameTypeRootTreeItem(getter_AddRefs(treeItem));
if(!treeItem)
*aResult = this;
}
// _main is an IE target which should be case-insensitive but isn't
// see bug 217886 for details
else if(name.LowerCaseEqualsLiteral("_content") || name.EqualsLiteral("_main"))
{
if (mTreeOwner) {
mTreeOwner->FindItemWithName(name.get(), nsnull,
getter_AddRefs(treeItem));
} else {
NS_ERROR("Someone isn't setting up the tree owner. "
"You might like to try that. "
"Things will.....you know, work.");
}
// _content should always exist. If the nsIDocShellTreeOwner did
// not find one, then create one...
if (!treeItem) {
mustMakeNewWindow = PR_TRUE;
}
}
else
{
// Try to locate the target window...
FindItemWithName(name.get(), nsnull, getter_AddRefs(treeItem));
// The named window cannot be found so it must be created to receive
// the channel data.
if (!treeItem) {
mustMakeNewWindow = PR_TRUE;
}
// Bug 13871: Prevent frameset spoofing
// See BugSplat 336170, 338737 and XP_FindNamedContextInList in
// the classic codebase
// Per Nav's behaviour:
// - pref controlled: "browser.frame.validate_origin"
// (mValidateOrigin)
// - allow load if host of target or target's parent is same
// as host of origin
// - allow load if target is a top level window
// Check to see if pref is true
if (mValidateOrigin && treeItem)
{
nsCOMPtr<nsIDocShellTreeItem> tmp;
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(tmp));
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
if (sameTypeRoot != tmp && treeItem != tmp) {
// The load was targeted at a frame and initiated in
// another toplevel window. Assume we'll need to make
// a new window until we find that the target, or one
// of its ancestors, are from the same origin as the
// loading docshell.
mustMakeNewWindow = PR_TRUE;
tmp = treeItem;
do {
// Is origin frame from the same domain as target frame?
if (ValidateOrigin(this, tmp)) {
mustMakeNewWindow = PR_FALSE;
break;
}
nsCOMPtr<nsIDocShellTreeItem> t;
tmp->GetSameTypeParent(getter_AddRefs(t));
tmp.swap(t);
} while (tmp);
if (mustMakeNewWindow) {
// Origin mismatch, open the URL in a new blank
// window.
treeItem = nsnull;
name.Truncate();
}
}
}
}
// Try to locate the target window...
nsCOMPtr<nsIDocShellTreeItem> treeItem;
FindItemWithName(aWindowTarget, nsnull, this, getter_AddRefs(treeItem));
PRInt32 linkPref = nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW;
if (mustMakeNewWindow) {
// 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
GetSameTypeRootTreeItem(getter_AddRefs(treeItem));
if(!treeItem)
*aResult = this;
mustMakeNewWindow = PR_FALSE;
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 (mustMakeNewWindow)
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(NS_STATIC_CAST(nsIDocShell*, this));
parentWindow = do_GetInterface(GetAsSupports(this));
if (!parentWindow) {
NS_ASSERTION(0, "Can't get nsIDOMWindowInternal from nsDocShell!");
return NS_ERROR_FAILURE;
@ -1169,12 +1098,19 @@ nsresult nsDocShell::FindTarget(const PRUnichar *aWindowTarget,
// the appropriate measures will be taken when the popup fails
}
if (!newWindow)
rv = parentWindow->Open(EmptyString(), // URL to load
name, // Window name
EmptyString(), // Window features
getter_AddRefs(newWindow));
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...
@ -1877,6 +1813,94 @@ nsDocShell::GetSameTypeRootTreeItem(nsIDocShellTreeItem ** aRootTreeItem)
return NS_OK;
}
static PRBool
CanAccessItem(nsIDocShellTreeItem* aTargetItem,
nsIDocShellTreeItem* aAccessingItem,
PRBool aConsiderOpener = PR_TRUE)
{
NS_PRECONDITION(aTargetItem, "Must have target item!");
if (!gValidateOrigin || !aAccessingItem) {
// Good to go
return PR_TRUE;
}
// XXXbz should we care if aAccessingItem or the document therein is
// chrome? Should those get extra privileges?
// Now do a security check
// Bug 13871: Prevent frameset spoofing
// See BugSplat 336170, 338737 and XP_FindNamedContextInList in
// the classic codebase
// Nav's behaviour was:
// - pref controlled: "browser.frame.validate_origin"
// (gValidateOrigin)
// - allow load if host of target or target's parent is same
// as host of origin
// - allow load if target is a top level window
// We are going to be a little more restrictive, with the
// following algorithm:
// - pref controlled in the same way
// - allow access if the two treeitems are in the same tree
// - allow access if the aTargetItem or one of its ancestors
// has the same origin as aAccessingItem
// - allow access if the target is a toplevel window and we can
// access its opener. Note that we only allow one level of
// recursion there.
nsCOMPtr<nsIDocShellTreeItem> targetRoot;
aTargetItem->GetSameTypeRootTreeItem(getter_AddRefs(targetRoot));
nsCOMPtr<nsIDocShellTreeItem> accessingRoot;
aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot));
if (targetRoot == accessingRoot) {
return PR_TRUE;
}
nsCOMPtr<nsIDocShellTreeItem> target = aTargetItem;
do {
if (ValidateOrigin(aAccessingItem, target)) {
return PR_TRUE;
}
nsCOMPtr<nsIDocShellTreeItem> parent;
target->GetSameTypeParent(getter_AddRefs(parent));
parent.swap(target);
} while (target);
if (aTargetItem != targetRoot) {
// target is a subframe, not in accessor's frame hierarchy, and all its
// ancestors have origins different from that of the accessor. Don't
// allow access.
return PR_FALSE;
}
if (!aConsiderOpener) {
// All done here
return PR_FALSE;
}
nsCOMPtr<nsIDOMWindow> targetWindow(do_GetInterface(aTargetItem));
nsCOMPtr<nsIDOMWindowInternal> targetInternal(do_QueryInterface(targetWindow));
if (!targetInternal) {
NS_ERROR("This should not happen, really");
return PR_FALSE;
}
nsCOMPtr<nsIDOMWindowInternal> targetOpener;
targetInternal->GetOpener(getter_AddRefs(targetOpener));
nsCOMPtr<nsIWebNavigation> openerWebNav(do_GetInterface(targetOpener));
nsCOMPtr<nsIDocShellTreeItem> openerItem(do_QueryInterface(openerWebNav));
if (!openerItem) {
return PR_FALSE;
}
return CanAccessItem(openerItem, aAccessingItem, PR_FALSE);
}
static PRBool
ItemIsActive(nsIDocShellTreeItem *aItem)
{
@ -1897,38 +1921,110 @@ ItemIsActive(nsIDocShellTreeItem *aItem)
NS_IMETHODIMP
nsDocShell::FindItemWithName(const PRUnichar * aName,
nsISupports * aRequestor,
nsIDocShellTreeItem * aOriginalRequestor,
nsIDocShellTreeItem ** _retval)
{
NS_ENSURE_ARG(aName);
NS_ENSURE_ARG_POINTER(_retval);
*_retval = nsnull; // if we don't find one, we return NS_OK and a null result
// If we don't find one, we return NS_OK and a null result
*_retval = nsnull;
// This QI may fail, but the places where we want to compare, comparing
// against nsnull serves the same purpose.
nsCOMPtr<nsIDocShellTreeItem>
reqAsTreeItem(do_QueryInterface(aRequestor));
if (!aRequestor)
{
nsCOMPtr<nsIDocShellTreeItem> foundItem;
// This is the entry point into the target-finding algorithm. Check
// for special names. This should only be done once, hence the check
// for a null aRequestor.
nsDependentString name(aName);
if (name.IsEmpty() || name.LowerCaseEqualsLiteral("_self")) {
foundItem = this;
}
else if (name.LowerCaseEqualsLiteral("_blank") ||
name.LowerCaseEqualsLiteral("_new"))
{
// Just return null. Caller must handle creating a new window with
// a blank name himself.
return NS_OK;
}
else if (name.LowerCaseEqualsLiteral("_parent"))
{
GetSameTypeParent(getter_AddRefs(foundItem));
if(!foundItem)
foundItem = this;
}
else if (name.LowerCaseEqualsLiteral("_top"))
{
GetSameTypeRootTreeItem(getter_AddRefs(foundItem));
if(!foundItem)
foundItem = this;
}
// _main is an IE target which should be case-insensitive but isn't
// see bug 217886 for details
else if (name.LowerCaseEqualsLiteral("_content") ||
name.EqualsLiteral("_main"))
{
if (mTreeOwner)
mTreeOwner->GetPrimaryContentShell(getter_AddRefs(foundItem));
#ifdef DEBUG
else {
NS_ERROR("Someone isn't setting up the tree owner. "
"You might like to try that. "
"Things will.....you know, work.");
// Note: _content should always exist. If we don't have one
// hanging off the treeowner, just create a named window....
// so don't return here, in case we did that and can now find
// it.
}
#endif
}
if (foundItem && !CanAccessItem(foundItem, aOriginalRequestor)) {
foundItem = nsnull;
}
if (foundItem) {
// We return foundItem here even if it's not an active
// item since all the names we've dealt with so far are
// special cases that we won't bother looking for further.
foundItem.swap(*_retval);
return NS_OK;
}
}
// Keep looking
// First we check our name.
if (mName.Equals(aName) && ItemIsActive(this)) {
*_retval = this;
NS_ADDREF(*_retval);
if (mName.Equals(aName) && ItemIsActive(this) &&
CanAccessItem(this, aOriginalRequestor)) {
NS_ADDREF(*_retval = this);
return NS_OK;
}
// Second we check our children making sure not to ask a child if it
// is the aRequestor.
NS_ENSURE_SUCCESS(FindChildWithName(aName, PR_TRUE, PR_TRUE, reqAsTreeItem,
_retval), NS_ERROR_FAILURE);
// This QI may fail, but the places where we want to compare, comparing
// against nsnull serves the same purpose.
nsCOMPtr<nsIDocShellTreeItem> reqAsTreeItem(do_QueryInterface(aRequestor));
// Second we check our children making sure not to ask a child if
// it is the aRequestor.
#ifdef DEBUG
nsresult rv =
#endif
FindChildWithName(aName, PR_TRUE, PR_TRUE, reqAsTreeItem,
aOriginalRequestor, _retval);
NS_ASSERTION(NS_SUCCEEDED(rv),
"FindChildWithName should not be failing here.");
if (*_retval)
return NS_OK;
// Third if we have a parent and it isn't the requestor then we should ask
// it to do the search. If it is the requestor we should just stop here
// and let the parent do the rest.
// If we don't have a parent, then we should ask the docShellTreeOwner to do
// the search.
// Third if we have a parent and it isn't the requestor then we
// should ask it to do the search. If it is the requestor we
// should just stop here and let the parent do the rest. If we
// don't have a parent, then we should ask the
// docShellTreeOwner to do the search.
nsCOMPtr<nsIDocShellTreeItem> parentAsTreeItem =
do_QueryInterface(GetAsSupports(mParent));
if (parentAsTreeItem) {
@ -1938,12 +2034,15 @@ nsDocShell::FindItemWithName(const PRUnichar * aName,
PRInt32 parentType;
parentAsTreeItem->GetItemType(&parentType);
if (parentType == mItemType) {
return parentAsTreeItem->FindItemWithName(aName,
NS_STATIC_CAST
(nsIDocShellTreeItem *,
this), _retval);
return parentAsTreeItem->
FindItemWithName(aName,
NS_STATIC_CAST(nsIDocShellTreeItem*,
this),
aOriginalRequestor,
_retval);
}
}
// If the parent is null or not of the same type fall through and ask tree
// owner.
@ -1951,12 +2050,13 @@ nsDocShell::FindItemWithName(const PRUnichar * aName,
nsCOMPtr<nsIDocShellTreeOwner>
reqAsTreeOwner(do_GetInterface(aRequestor));
if (mTreeOwner && (mTreeOwner != reqAsTreeOwner.get())) {
NS_ENSURE_SUCCESS(mTreeOwner->FindItemWithName(aName,
NS_STATIC_CAST
(nsIDocShellTreeItem *,
this), _retval),
NS_ERROR_FAILURE);
if (mTreeOwner && mTreeOwner != reqAsTreeOwner) {
return mTreeOwner->
FindItemWithName(aName,
NS_STATIC_CAST(nsIDocShellTreeItem*,
this),
aOriginalRequestor,
_retval);
}
return NS_OK;
@ -2275,6 +2375,7 @@ NS_IMETHODIMP
nsDocShell::FindChildWithName(const PRUnichar * aName,
PRBool aRecurse, PRBool aSameType,
nsIDocShellTreeItem * aRequestor,
nsIDocShellTreeItem * aOriginalRequestor,
nsIDocShellTreeItem ** _retval)
{
NS_ENSURE_ARG(aName);
@ -2295,9 +2396,9 @@ nsDocShell::FindChildWithName(const PRUnichar * aName,
PRBool childNameEquals = PR_FALSE;
child->NameEquals(aName, &childNameEquals);
if (childNameEquals && ItemIsActive(child)) {
*_retval = child;
NS_ADDREF(*_retval);
if (childNameEquals && ItemIsActive(child) &&
CanAccessItem(child, aOriginalRequestor)) {
child.swap(*_retval);
break;
}
@ -2309,18 +2410,22 @@ nsDocShell::FindChildWithName(const PRUnichar * aName,
// See if child contains the shell with the given name
nsCOMPtr<nsIDocShellTreeNode>
childAsNode(do_QueryInterface(child));
if (child) {
NS_ENSURE_SUCCESS(childAsNode->FindChildWithName(aName, PR_TRUE,
aSameType,
NS_STATIC_CAST
(nsIDocShellTreeItem
*, this),
_retval),
NS_ERROR_FAILURE);
if (childAsNode) {
#ifdef DEBUG
nsresult rv =
#endif
childAsNode->FindChildWithName(aName, PR_TRUE,
aSameType,
NS_STATIC_CAST(nsIDocShellTreeItem*,
this),
aOriginalRequestor,
_retval);
NS_ASSERTION(NS_SUCCEEDED(rv),
"FindChildWithName should not fail here");
if (*_retval) // found it
return NS_OK;
}
}
if (*_retval) // found it
return NS_OK;
}
return NS_OK;
}
@ -3145,17 +3250,22 @@ nsDocShell::Create()
rv = mPrefs->GetBoolPref("browser.frames.enabled", &tmpbool);
if (NS_SUCCEEDED(rv))
mAllowSubframes = tmpbool;
mAllowSubframes = tmpbool;
// Check pref to see if we should prevent frameset spoofing
rv = mPrefs->GetBoolPref("browser.frame.validate_origin", &tmpbool);
if (NS_SUCCEEDED(rv))
mValidateOrigin = tmpbool;
if (gValidateOrigin == (PRBool)0xffffffff) {
// Check pref to see if we should prevent frameset spoofing
rv = mPrefs->GetBoolPref("browser.frame.validate_origin", &tmpbool);
if (NS_SUCCEEDED(rv)) {
gValidateOrigin = tmpbool;
} else {
gValidateOrigin = PR_TRUE;
}
}
// Should we use XUL error pages instead of alerts if possible?
rv = mPrefs->GetBoolPref("browser.xul.error_pages.enabled", &tmpbool);
if (NS_SUCCEEDED(rv))
mUseErrorPages = tmpbool;
mUseErrorPages = tmpbool;
return NS_OK;
}
@ -4929,9 +5039,16 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
nsresult
nsDocShell::CheckLoadingPermissions()
{
// This method checks whether the caller may load content into
// this docshell. Even though we've done our best to hide windows
// from code that doesn't have the right to access them, it's
// still possible for an evil site to open a window and access
// frames in the new window through window.frames[] (which is
// allAccess for historic reasons), so we still need to do this
// check on load.
nsresult rv = NS_OK, sameOrigin = NS_OK;
if (!mValidateOrigin || !IsFrame()) {
if (!gValidateOrigin || !IsFrame()) {
// Origin validation was turned off, or we're not a frame.
// Permit all loads.
@ -5139,6 +5256,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
// 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);
@ -5166,6 +5284,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
nsCOMPtr<nsIDocShellTreeItem> targetTreeItem;
FindItemWithName(name.get(),
nsnull,
this,
getter_AddRefs(targetTreeItem));
if (targetTreeItem)
targetDocShell = do_QueryInterface(targetTreeItem);

Просмотреть файл

@ -368,9 +368,6 @@ protected:
PRPackedBool mIsBeingDestroyed;
// Validate window targets to prevent frameset spoofing
PRPackedBool mValidateOrigin;
PRPackedBool mIsExecutingOnLoadHandler;
// Indicates that a DocShell in this "docshell tree" is printing

Просмотреть файл

@ -48,7 +48,7 @@ interface nsIDocShellTreeOwner;
* node or a leaf.
*/
[scriptable, uuid(1b3416f3-0ec6-49e6-8bdf-77bfdbc4a102)]
[scriptable, uuid(7d935d63-6d2a-4600-afb5-9a4f7d68b825)]
interface nsIDocShellTreeItem : nsISupports
{
/*
@ -130,8 +130,12 @@ interface nsIDocShellTreeItem : nsISupports
a shell by the specified name. Inversely the child uses it to ensure it
does not ask its parent to do the search if its parent is the one that
asked it to search. Children also use this to test against the treeOwner;
aOriginalRequestor - The original treeitem that made the request, if any.
This is used to ensure that we don't run into cross-site issues.
*/
nsIDocShellTreeItem findItemWithName(in wstring name, in nsISupports aRequestor);
nsIDocShellTreeItem findItemWithName(in wstring name,
in nsISupports aRequestor,
in nsIDocShellTreeItem aOriginalRequestor);
/*
The owner of the DocShell Tree. This interface will be called upon when

Просмотреть файл

@ -50,7 +50,7 @@
// XXXbz this interface should probably inherit from nsIDocShellTreeItem, and
// some methods should move from there to here...
[scriptable, uuid(C094F810-A8AB-11d3-AFC6-00A024FFC08C)]
[scriptable, uuid(37f1ab73-f224-44b1-82f0-d2834ab1cec0)]
interface nsIDocShellTreeNode : nsISupports
{
/*
@ -87,11 +87,16 @@ interface nsIDocShellTreeNode : nsISupports
aRequestor - This is the docshellTreeItem that is requesting the find. This
parameter is used when recursion is being used to avoid searching the same
tree again when a child has asked a parent to search for children.
aOriginalRequestor - The original treeitem that made the request, if any.
This is used to ensure that we don't run into cross-site issues.
Note the search is depth first when recursing.
// XXXbz this should return an nsIDocShellTreeNode, I think.
*/
nsIDocShellTreeItem findChildWithName(in wstring aName, in boolean aRecurse,
in boolean aSameType, in nsIDocShellTreeItem aRequestor);
nsIDocShellTreeItem findChildWithName(in wstring aName,
in boolean aRecurse,
in boolean aSameType,
in nsIDocShellTreeItem aRequestor,
in nsIDocShellTreeItem aOriginalRequestor);
};

Просмотреть файл

@ -45,7 +45,7 @@
interface nsIDocShellTreeItem;
[scriptable, uuid(80F30E10-A7CF-11d3-AFC5-00A024FFC08C)]
[scriptable, uuid(9e508466-5ebb-4618-abfa-9ad47bed0b2e)]
interface nsIDocShellTreeOwner : nsISupports
{
/*
@ -58,9 +58,13 @@ interface nsIDocShellTreeOwner : nsISupports
a shell by the specified name. Inversely the child uses it to ensure it
does not ask its parent to do the search if its parent is the one that
asked it to search.
aOriginalRequestor - The original treeitem that made the request, if any.
This is used to ensure that we don't run into cross-site issues.
*/
nsIDocShellTreeItem findItemWithName(in wstring name,
in nsIDocShellTreeItem aRequestor);
in nsIDocShellTreeItem aRequestor,
in nsIDocShellTreeItem aOriginalRequestor);
/*
Called when a content shell is added to the the docShell Tree.

Просмотреть файл

@ -4712,7 +4712,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
const jschar *chars = ::JS_GetStringChars(str);
dsn->FindChildWithName(NS_REINTERPRET_CAST(const PRUnichar*, chars),
PR_FALSE, PR_TRUE, nsnull,
PR_FALSE, PR_TRUE, nsnull, nsnull,
getter_AddRefs(child));
nsCOMPtr<nsIDOMWindow> child_win(do_GetInterface(child));

Просмотреть файл

@ -175,7 +175,7 @@ nsDOMWindowList::NamedItem(const nsAString& aName, nsIDOMWindow** aReturn)
if (mDocShellNode) {
mDocShellNode->FindChildWithName(PromiseFlatString(aName).get(),
PR_FALSE, PR_FALSE,
PR_FALSE, PR_FALSE, nsnull,
nsnull, getter_AddRefs(item));
nsCOMPtr<nsIScriptGlobalObject> globalObject(do_GetInterface(item));

Просмотреть файл

@ -2109,6 +2109,71 @@ nsGlobalWindow::DispatchCustomEvent(const char *aEventName)
return preventDefault;
}
static already_AddRefed<nsIDocShellTreeItem>
GetCallerDocShellTreeItem()
{
nsCOMPtr<nsIJSContextStack> stack =
do_GetService(sJSStackContractID);
JSContext *cx = nsnull;
if (stack) {
stack->Peek(&cx);
}
nsIDocShellTreeItem *callerItem = nsnull;
if (cx) {
nsCOMPtr<nsIWebNavigation> callerWebNav =
do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
if (callerWebNav) {
CallQueryInterface(callerWebNav, &callerItem);
}
}
return callerItem;
}
PRBool
nsGlobalWindow::WindowExists(const nsAString& aName)
{
nsCOMPtr<nsIDocShellTreeItem> caller = GetCallerDocShellTreeItem();
PRBool foundWindow = PR_FALSE;
if (!caller) {
// If we can't reach a caller, try to use our own docshell
caller = do_QueryInterface(mDocShell);
}
nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryInterface(mDocShell));
if (docShell) {
nsCOMPtr<nsIDocShellTreeItem> namedItem;
docShell->FindItemWithName(PromiseFlatString(aName).get(), nsnull, caller,
getter_AddRefs(namedItem));
foundWindow = !!namedItem;
} else {
// No caller reachable and we don't have a docshell any more. Fall
// back to using the windowwatcher service to find any window by
// name.
nsCOMPtr<nsIWindowWatcher> wwatch =
do_GetService(NS_WINDOWWATCHER_CONTRACTID);
if (wwatch) {
nsCOMPtr<nsIDOMWindow> namedWindow;
wwatch->GetWindowByName(PromiseFlatString(aName).get(), nsnull,
getter_AddRefs(namedWindow));
foundWindow = !!namedWindow;
}
}
return foundWindow;
}
NS_IMETHODIMP
nsGlobalWindow::SetFullScreen(PRBool aFullScreen)
{
@ -2431,11 +2496,11 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
// Test whether title needs to prefixed with [script]
nsAutoString title;
if (!IsCallerChrome()) {
MakeScriptDialogTitle(aTitle, title);
MakeScriptDialogTitle(aTitle, title);
} else {
NS_WARNING("chrome shouldn't be calling prompt(), use the prompt "
"service");
title.Assign(aTitle);
NS_WARNING("chrome shouldn't be calling prompt(), use the prompt "
"service");
title.Assign(aTitle);
}
nsresult rv = prompter->Prompt(title.get(),
@ -3116,24 +3181,17 @@ nsGlobalWindow::CheckOpenAllow(PopupControlState aAbuseLevel,
allowWindow = allowWhitelisted;
else {
// Special case items that don't actually open new windows.
nsAutoString name(aName);
if (!name.IsEmpty()) {
if (!aName.IsEmpty()) {
// _main is an IE target which should be case-insensitive but isn't
// see bug 217886 for details
if (name.LowerCaseEqualsLiteral("_top") ||
name.LowerCaseEqualsLiteral("_self") ||
name.LowerCaseEqualsLiteral("_content") ||
name.EqualsLiteral("_main"))
if (aName.LowerCaseEqualsLiteral("_top") ||
aName.LowerCaseEqualsLiteral("_self") ||
aName.LowerCaseEqualsLiteral("_content") ||
aName.EqualsLiteral("_main"))
allowWindow = allowSelf;
else {
nsCOMPtr<nsIWindowWatcher> wwatch =
do_GetService(NS_WINDOWWATCHER_CONTRACTID);
if (wwatch) {
nsCOMPtr<nsIDOMWindow> namedWindow;
wwatch->GetWindowByName(PromiseFlatString(aName).get(), this,
getter_AddRefs(namedWindow));
if (namedWindow)
allowWindow = allowExtant;
if (WindowExists(aName)) {
allowWindow = allowExtant;
}
}
}
@ -4627,33 +4685,12 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
if (NS_FAILED(rv))
return rv;
nsAutoString nameString(aName);
// determine whether we must divert the open window to a new tab.
PRBool divertOpen = PR_TRUE; // at first, assume we will divert
PRBool divertOpen = !WindowExists(aName);
// first, does the named window already exist? (see nsWindowWatcher)
if (nameString.EqualsIgnoreCase("_top") ||
nameString.EqualsIgnoreCase("_self") ||
nameString.EqualsIgnoreCase("_content") ||
nameString.EqualsIgnoreCase("_parent") ||
nameString.Equals(NS_LITERAL_STRING("_main")))
divertOpen = PR_FALSE;
else {
nsCOMPtr<nsIDocShellTreeOwner> docOwner;
GetTreeOwner(getter_AddRefs(docOwner));
if (docOwner) {
nsCOMPtr<nsIDocShellTreeItem> namedWindow;
docOwner->FindItemWithName(nameString.get(), 0,
getter_AddRefs(namedWindow));
if (namedWindow)
divertOpen = PR_FALSE;
}
}
// second, what do the prefs prescribe?
// also check what the prefs prescribe?
// XXXbz this duplicates docshell code. Need to consolidate.
PRInt32 containerPref = nsIBrowserDOMWindow::OPEN_NEWWINDOW;
@ -4671,8 +4708,8 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
PRBool chromeTab = PR_FALSE;
if (tabURI)
tabURI->SchemeIs("chrome", &chromeTab);
if (!thisChrome && !chromeTab) {
if (!thisChrome && !chromeTab) {
containerPref=nsContentUtils::GetIntPref("browser.link.open_newwindow",
nsIBrowserDOMWindow::OPEN_NEWWINDOW);
PRInt32 restrictionPref = nsContentUtils::GetIntPref(
@ -4738,8 +4775,8 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
GetTop(getter_AddRefs(domReturn));
}
if (domReturn && !nameString.EqualsIgnoreCase("_blank") &&
!nameString.EqualsIgnoreCase("_new"))
if (domReturn && !aName.LowerCaseEqualsLiteral("_blank") &&
!aName.LowerCaseEqualsLiteral("_new"))
domReturn->SetName(aName);
}

Просмотреть файл

@ -294,6 +294,8 @@ protected:
PRBool DispatchCustomEvent(const char *aEventName);
PRBool WindowExists(const nsAString& aName);
// When adding new member variables, be careful not to create cycles
// through JavaScript. If there is any chance that a member variable
// could own objects that are implemented in JavaScript, then those

Просмотреть файл

@ -209,6 +209,7 @@ nsDocShellTreeOwner::GetInterface(const nsIID& aIID, void** aSink)
NS_IMETHODIMP
nsDocShellTreeOwner::FindItemWithName(const PRUnichar* aName,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem** aFoundItem)
{
NS_ENSURE_ARG(aName);
@ -250,7 +251,8 @@ nsDocShellTreeOwner::FindItemWithName(const PRUnichar* aName,
}
// next, check our children
rv = FindChildWithName(aName, PR_TRUE, aRequestor, aFoundItem);
rv = FindChildWithName(aName, PR_TRUE, aRequestor, aOriginalRequestor,
aFoundItem);
if(NS_FAILED(rv) || *aFoundItem)
return rv;
@ -260,20 +262,21 @@ nsDocShellTreeOwner::FindItemWithName(const PRUnichar* aName,
if(mTreeOwner) {
if (mTreeOwner != reqAsTreeOwner)
return mTreeOwner->FindItemWithName(aName, mWebBrowser->mDocShellAsItem,
aFoundItem);
aOriginalRequestor, aFoundItem);
return NS_OK;
}
// finally, failing everything else, search all windows, if we're not already
if (mWebBrowser->mDocShellAsItem != aRequestor)
return FindItemWithNameAcrossWindows(aName, aFoundItem);
return FindItemWithNameAcrossWindows(aName, aOriginalRequestor, aFoundItem);
return NS_OK; // failed
}
nsresult
nsDocShellTreeOwner::FindChildWithName(const PRUnichar *aName, PRBool aRecurse,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem **aFoundItem)
{
if (!mWebBrowser)
@ -302,7 +305,8 @@ nsDocShellTreeOwner::FindChildWithName(const PRUnichar *aName, PRBool aRecurse,
nsCOMPtr<nsIDocShellTreeItem> item =
do_QueryInterface(sgo->GetDocShell());
if (item && item != aRequestor) {
rv = item->FindItemWithName(aName, mWebBrowser->mDocShellAsItem, aFoundItem);
rv = item->FindItemWithName(aName, mWebBrowser->mDocShellAsItem,
aOriginalRequestor, aFoundItem);
if (NS_FAILED(rv) || *aFoundItem)
break;
}
@ -314,6 +318,7 @@ nsDocShellTreeOwner::FindChildWithName(const PRUnichar *aName, PRBool aRecurse,
nsresult
nsDocShellTreeOwner::FindItemWithNameAcrossWindows(const PRUnichar* aName,
nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem** aFoundItem)
{
// search for the item across the list of top-level windows
@ -341,7 +346,7 @@ nsDocShellTreeOwner::FindItemWithNameAcrossWindows(const PRUnichar* aName,
nsCOMPtr<nsIDocShellTreeItem> item =
do_QueryInterface(sgo->GetDocShell());
if (item) {
rv = item->FindItemWithName(aName, item, aFoundItem);
rv = item->FindItemWithName(aName, item, aOriginalRequestor, aFoundItem);
if (NS_FAILED(rv) || *aFoundItem)
break;
}

Просмотреть файл

@ -123,9 +123,11 @@ protected:
NS_IMETHOD RemoveChromeListeners();
nsresult FindChildWithName(const PRUnichar *aName,
PRBool aRecurse, nsIDocShellTreeItem* aRequestor,
PRBool aRecurse, nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem **aFoundItem);
nsresult FindItemWithNameAcrossWindows(const PRUnichar* aName,
nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem **aFoundItem);
void EnsurePrompter();

Просмотреть файл

@ -563,13 +563,15 @@ NS_IMETHODIMP nsWebBrowser::GetSameTypeRootTreeItem(nsIDocShellTreeItem** aRootT
}
NS_IMETHODIMP nsWebBrowser::FindItemWithName(const PRUnichar *aName,
nsISupports* aRequestor, nsIDocShellTreeItem **_retval)
nsISupports* aRequestor, nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem **_retval)
{
NS_ENSURE_STATE(mDocShell);
NS_ASSERTION(mDocShellTreeOwner, "This should always be set when in this situation");
return mDocShellAsItem->FindItemWithName(aName,
NS_STATIC_CAST(nsIDocShellTreeOwner*, mDocShellTreeOwner), _retval);
NS_STATIC_CAST(nsIDocShellTreeOwner*, mDocShellTreeOwner),
aOriginalRequestor, _retval);
}
NS_IMETHODIMP nsWebBrowser::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner)

Просмотреть файл

@ -160,6 +160,10 @@ interface nsIWindowWatcher : nsISupports {
@param aCurrentWindow a starting point in the window hierarchy to
begin the search. If null, each toplevel window
will be searched.
Note: This method will search all open windows for any window or
frame with the given window name. Make sure you understand the
security implications of this before using this method!
*/
nsIDOMWindow getWindowByName(in wstring aTargetName,
in nsIDOMWindow aCurrentWindow);

Просмотреть файл

@ -91,6 +91,15 @@ nsWWJSUtils::GetDynamicScriptContext(JSContext *aContext)
return GetScriptContextFromJSContext(aContext);
}
nsIScriptGlobalObject *
nsWWJSUtils::GetDynamicScriptGlobal(JSContext* aContext)
{
nsIScriptContext *scriptCX = GetDynamicScriptContext(aContext);
if (!scriptCX)
return nsnull;
return scriptCX->GetGlobalObject();
}
nsIScriptContext *
nsWWJSUtils::GetStaticScriptContext(JSContext* aContext,
JSObject* aObj)

Просмотреть файл

@ -480,7 +480,7 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent,
uriToLoadIsChrome = PR_FALSE;
PRUint32 chromeFlags;
nsAutoString name; // string version of aName
nsCString features; // string version of aFeatures
nsCAutoString features; // string version of aFeatures
nsCOMPtr<nsIURI> uriToLoad; // from aUrl, if any
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner; // from the parent window, if any
nsCOMPtr<nsIDocShellTreeItem> newDocShellItem; // from the new window
@ -522,41 +522,37 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent,
// try to find an extant window with the given name
if (nameSpecified) {
/* Oh good. special target names are now handled in multiple places:
Here and within FindItemWithName, just below. I put _top here because
here it's able to do what it should: get the topmost shell of the same
(content/chrome) type as the docshell. treeOwner is always chrome, so
this scheme doesn't work there, where a lot of other special case
targets are handled. (treeOwner is, however, a good place to look
for browser windows by name, as it does.)
*/
if (aParent) {
if (name.LowerCaseEqualsLiteral("_self")) {
GetWindowTreeItem(aParent, getter_AddRefs(newDocShellItem));
} else if (name.LowerCaseEqualsLiteral("_top")) {
nsCOMPtr<nsIDocShellTreeItem> shelltree;
GetWindowTreeItem(aParent, getter_AddRefs(shelltree));
if (shelltree)
shelltree->GetSameTypeRootTreeItem(getter_AddRefs(newDocShellItem));
} else if (name.LowerCaseEqualsLiteral("_parent")) {
nsCOMPtr<nsIDocShellTreeItem> shelltree;
GetWindowTreeItem(aParent, getter_AddRefs(shelltree));
if (shelltree)
shelltree->GetSameTypeParent(getter_AddRefs(newDocShellItem));
// If there is no real parent then _self acts as _parent
if (!newDocShellItem)
newDocShellItem = shelltree;
} else {
/* parent is being simultaneously torn down (probably because of
the code that keeps an old docshell alive but disconnected while
we load a new one). not much to do but open the new window
without a parent. */
if (parentTreeOwner)
parentTreeOwner->FindItemWithName(name.get(), nsnull,
getter_AddRefs(newDocShellItem));
}
nsCOMPtr<nsIJSContextStack> stack =
do_GetService(sJSStackContractID);
JSContext *cx = nsnull;
if (stack) {
stack->Peek(&cx);
}
nsCOMPtr<nsIDocShellTreeItem> callerItem;
if (cx) {
nsCOMPtr<nsIWebNavigation> callerWebNav =
do_GetInterface(nsWWJSUtils::GetDynamicScriptGlobal(cx));
callerItem = do_QueryInterface(callerWebNav);
}
nsCOMPtr<nsIDocShellTreeItem> parentItem;
GetWindowTreeItem(aParent, getter_AddRefs(parentItem));
if (!callerItem) {
callerItem = parentItem;
}
if (parentItem) {
parentItem->FindItemWithName(name.get(), nsnull, callerItem,
getter_AddRefs(newDocShellItem));
} else
FindItemWithName(name.get(), getter_AddRefs(newDocShellItem));
FindItemWithName(name.get(), callerItem,
getter_AddRefs(newDocShellItem));
}
// no extant window? make a new one.
@ -1055,14 +1051,15 @@ nsWindowWatcher::GetWindowByName(const PRUnichar *aTargetName,
docShellTreeItem = do_QueryInterface(webNav);
if (docShellTreeItem) {
docShellTreeItem->FindItemWithName(aTargetName, nsnull,
// XXXbz sort out original requestor?
docShellTreeItem->FindItemWithName(aTargetName, nsnull, nsnull,
getter_AddRefs(treeItem));
}
}
// Next, see if the TargetName exists in any window hierarchy
if (!treeItem) {
FindItemWithName(aTargetName, getter_AddRefs(treeItem));
FindItemWithName(aTargetName, nsnull, getter_AddRefs(treeItem));
}
if (treeItem) {
@ -1382,19 +1379,18 @@ nsWindowWatcher::WinHasOption(const char *aOptions, const char *aName,
necessarily return a failure method value. check aFoundItem.
*/
nsresult
nsWindowWatcher::FindItemWithName(
const PRUnichar* aName,
nsIDocShellTreeItem** aFoundItem)
nsWindowWatcher::FindItemWithName(const PRUnichar* aName,
nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem** aFoundItem)
{
PRBool more;
nsresult rv;
nsAutoString name(aName);
*aFoundItem = 0;
/* special cases */
if(name.IsEmpty())
if(!aName || !*aName)
return NS_OK;
nsDependentString name(aName);
if(name.LowerCaseEqualsLiteral("_blank") || name.LowerCaseEqualsLiteral("_new"))
return NS_OK;
// _content will be handled by individual windows, below
@ -1404,7 +1400,9 @@ nsWindowWatcher::FindItemWithName(
if (!windows)
return NS_ERROR_FAILURE;
rv = NS_OK;
PRBool more;
nsresult rv = NS_OK;
do {
windows->HasMoreElements(&more);
if (!more)
@ -1417,7 +1415,8 @@ nsWindowWatcher::FindItemWithName(
nsCOMPtr<nsIDocShellTreeItem> treeItem;
GetWindowTreeItem(nextWindow, getter_AddRefs(treeItem));
if (treeItem) {
rv = treeItem->FindItemWithName(aName, treeItem, aFoundItem);
rv = treeItem->FindItemWithName(aName, treeItem, aOriginalRequestor,
aFoundItem);
if (NS_FAILED(rv) || *aFoundItem)
break;
}

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -85,6 +85,7 @@ private:
nsresult RemoveWindow(nsWatcherWindowEntry *inInfo);
nsresult FindItemWithName(const PRUnichar *aName,
nsIDocShellTreeItem *aOriginalRequestor,
nsIDocShellTreeItem **aFoundItem);
static JSContext *GetJSContextFromWindow(nsIDOMWindow *aWindow);

Просмотреть файл

@ -376,7 +376,7 @@ nsMessenger::SetWindow(nsIDOMWindowInternal *aWin, nsIMsgWindow *aMsgWindow)
{
nsCOMPtr<nsIDocShellTreeItem> childAsItem;
nsresult rv = rootDocShellAsNode->FindChildWithName(NS_LITERAL_STRING("messagepane").get(),
PR_TRUE, PR_FALSE, nsnull, getter_AddRefs(childAsItem));
PR_TRUE, PR_FALSE, nsnull, nsnull, getter_AddRefs(childAsItem));
mDocShell = do_QueryInterface(childAsItem);

Просмотреть файл

@ -282,8 +282,9 @@ nsMsgPrintEngine::SetWindow(nsIDOMWindowInternal *aWin)
NS_ENSURE_TRUE(rootAsNode, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocShellTreeItem> childItem;
rootAsNode->FindChildWithName(NS_LITERAL_STRING("content").get(), PR_TRUE, PR_FALSE, nsnull,
getter_AddRefs(childItem));
rootAsNode->FindChildWithName(NS_LITERAL_STRING("content").get(), PR_TRUE,
PR_FALSE, nsnull, nsnull,
getter_AddRefs(childItem));
mDocShell = do_QueryInterface(childItem);

Просмотреть файл

@ -123,8 +123,9 @@ void nsMsgWindow::GetMessageWindowDocShell(nsIDocShell ** aDocShell)
nsCOMPtr<nsIDocShellTreeItem> msgDocShellItem;
if(rootAsNode)
rootAsNode->FindChildWithName(NS_LITERAL_STRING("messagepane").get(), PR_TRUE, PR_FALSE,
nsnull, getter_AddRefs(msgDocShellItem));
rootAsNode->FindChildWithName(NS_LITERAL_STRING("messagepane").get(),
PR_TRUE, PR_FALSE, nsnull, nsnull,
getter_AddRefs(msgDocShellItem));
docShell = do_QueryInterface(msgDocShellItem);
// we don't own mMessageWindowDocShell so don't try to keep a reference to it!

Просмотреть файл

@ -174,38 +174,6 @@ NS_IMETHODIMP nsWebBrowserChrome::DestroyBrowserWindow()
return mBrowserWindow->Destroy();
}
#if 0
/* Just commenting out for now because it looks like somebody went to
a lot of work here. This method has been removed from nsIWebBrowserChrome
per the 5 Feb 01 API review, to be handled one level further down
in nsDocShellTreeOwner.
*/
NS_IMETHODIMP nsWebBrowserChrome::FindNamedBrowserItem(const PRUnichar* aName,
nsIDocShellTreeItem** aBrowserItem)
{
NS_ENSURE_ARG_POINTER(aBrowserItem);
*aBrowserItem = nsnull;
PRInt32 i = 0;
PRInt32 n = mBrowserWindow->gBrowsers.Count();
nsString aNameStr(aName);
for (i = 0; i < n; i++)
{
nsBrowserWindow* bw = (nsBrowserWindow*)mBrowserWindow->gBrowsers.ElementAt(i);
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(bw->mWebBrowser));
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
docShellAsItem->FindItemWithName(aName, NS_STATIC_CAST(nsIWebBrowserChrome*, this), aBrowserItem);
if(!*aBrowserItem)
return NS_OK;
}
return NS_OK;
}
#endif
NS_IMETHODIMP nsWebBrowserChrome::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY)
{
mSizeSet = PR_TRUE;

Просмотреть файл

@ -165,19 +165,21 @@ NS_IMETHODIMP nsChromeTreeOwner::GetInterface(const nsIID& aIID, void** aSink)
//*****************************************************************************
NS_IMETHODIMP nsChromeTreeOwner::FindItemWithName(const PRUnichar* aName,
nsIDocShellTreeItem* aRequestor, nsIDocShellTreeItem** aFoundItem)
nsIDocShellTreeItem* aRequestor, nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem** aFoundItem)
{
NS_ENSURE_ARG_POINTER(aFoundItem);
*aFoundItem = nsnull;
nsAutoString name(aName);
PRBool fIs_Content = PR_FALSE;
/* Special Cases */
if(name.IsEmpty())
if(!aName || !*aName)
return NS_OK;
nsDependentString name(aName);
if(name.LowerCaseEqualsLiteral("_blank"))
return NS_OK;
// _main is an IE target which should be case-insensitive but isn't
@ -229,7 +231,8 @@ NS_IMETHODIMP nsChromeTreeOwner::FindItemWithName(const PRUnichar* aName,
shellAsTreeItem->GetTreeOwner(getter_AddRefs(shellOwner));
nsCOMPtr<nsISupports> shellOwnerSupports(do_QueryInterface(shellOwner));
shellAsTreeItem->FindItemWithName(aName, shellOwnerSupports, aFoundItem);
shellAsTreeItem->FindItemWithName(aName, shellOwnerSupports,
aOriginalRequestor, aFoundItem);
}
}
if(*aFoundItem)

Просмотреть файл

@ -167,19 +167,21 @@ NS_IMETHODIMP nsContentTreeOwner::GetInterface(const nsIID& aIID, void** aSink)
//*****************************************************************************
NS_IMETHODIMP nsContentTreeOwner::FindItemWithName(const PRUnichar* aName,
nsIDocShellTreeItem* aRequestor, nsIDocShellTreeItem** aFoundItem)
nsIDocShellTreeItem* aRequestor, nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem** aFoundItem)
{
NS_ENSURE_ARG_POINTER(aFoundItem);
*aFoundItem = nsnull;
nsAutoString name(aName);
PRBool fIs_Content = PR_FALSE;
/* Special Cases */
if(name.IsEmpty())
if(!aName || !*aName)
return NS_OK;
nsDependentString name(aName);
if(name.LowerCaseEqualsLiteral("_blank"))
return NS_OK;
// _main is an IE target which should be case-insensitive but isn't
@ -227,7 +229,8 @@ NS_IMETHODIMP nsContentTreeOwner::FindItemWithName(const PRUnichar* aName,
shellAsTreeItem->GetTreeOwner(getter_AddRefs(shellOwner));
nsCOMPtr<nsISupports> shellOwnerSupports(do_QueryInterface(shellOwner));
shellAsTreeItem->FindItemWithName(aName, shellOwnerSupports, aFoundItem);
shellAsTreeItem->FindItemWithName(aName, shellOwnerSupports,
aOriginalRequestor, aFoundItem);
}
if(*aFoundItem)
return NS_OK;

Просмотреть файл

@ -1329,7 +1329,7 @@ nsCOMPtr<nsIDOMDocument> nsWebShellWindow::GetNamedDOMDoc(const nsAString & aDoc
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem;
nsCOMPtr<nsIDocShellTreeNode> docShellAsNode(do_QueryInterface(mDocShell));
docShellAsNode->FindChildWithName(PromiseFlatString(aDocShellName).get(),
PR_TRUE, PR_FALSE, nsnull, getter_AddRefs(docShellAsItem));
PR_TRUE, PR_FALSE, nsnull, nsnull, getter_AddRefs(docShellAsItem));
childDocShell = do_QueryInterface(docShellAsItem);
if (!childDocShell)
return domDoc;