Fix nsWindowWatcher::FindItemWithName to pass in the right requestor; expose it

on nsPIWindowWatcher and use it from nsDocShellTreeOwner.  Bug 282296, r=danm,
sr=jst
This commit is contained in:
bzbarsky%mit.edu 2005-03-03 17:26:34 +00:00
parent ead05b8709
commit 20fcb245ac
4 changed files with 60 additions and 65 deletions

View File

@ -325,52 +325,12 @@ nsDocShellTreeOwner::FindItemWithNameAcrossWindows(const PRUnichar* aName,
nsIDocShellTreeItem** aFoundItem)
{
// search for the item across the list of top-level windows
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
nsCOMPtr<nsPIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
if (!wwatch)
return NS_OK;
PRBool more;
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> windows;
wwatch->GetWindowEnumerator(getter_AddRefs(windows));
rv = NS_OK;
do {
windows->HasMoreElements(&more);
if (!more)
break;
nsCOMPtr<nsISupports> nextSupWindow;
windows->GetNext(getter_AddRefs(nextSupWindow));
if (nextSupWindow) {
// it's a DOM Window. cut straight to the ScriptGlobalObject.
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nextSupWindow));
if (sgo) {
nsCOMPtr<nsIDocShellTreeItem> item =
do_QueryInterface(sgo->GetDocShell());
if (item) {
// Get the root tree item of same type, since roots are the only
// things that call into the treeowner to look for named items.
nsCOMPtr<nsIDocShellTreeItem> root;
item->GetSameTypeRootTreeItem(getter_AddRefs(root));
NS_ASSERTION(root, "Must have root tree item of same type");
// Make sure not to call back into our kid if we got called from it
if (root != aRequestor) {
// Get the tree owner so we can pass it in as the
// requestor so the child knows not to call back up.
nsCOMPtr<nsIDocShellTreeOwner> rootOwner;
root->GetTreeOwner(getter_AddRefs(rootOwner));
rv = root->FindItemWithName(aName, rootOwner, aOriginalRequestor,
aFoundItem);
if (NS_FAILED(rv) || *aFoundItem)
break;
}
}
}
}
} while(1);
return rv;
return wwatch->FindItemWithName(aName, aRequestor, aOriginalRequestor,
aFoundItem);
}
void

View File

@ -45,6 +45,7 @@
interface nsIDOMWindow;
interface nsISimpleEnumerator;
interface nsIWebBrowserChrome;
interface nsIDocShellTreeItem;
%{C++
#include "jspubtd.h"
@ -52,7 +53,7 @@ interface nsIWebBrowserChrome;
[ptr] native jsvalptr(jsval);
[uuid(d535806e-afaf-47d1-8d89-783ad088c62a)]
[uuid(3aaad312-e09d-4010-a013-78ef653dac99)]
interface nsPIWindowWatcher : nsISupports
{
@ -88,6 +89,28 @@ interface nsPIWindowWatcher : nsISupports
in string aName, in string aFeatures, in boolean aDialog,
in PRUint32 argc, in jsvalptr argv);
/**
* Find a named docshell tree item amongst all windows registered
* with the window watcher. This may be a subframe in some window,
* for example.
*
* @param aName the name of the window. Must not be null.
* @param aRequestor the tree item immediately making the request.
* We should make sure to not recurse down into its findItemWithName
* method.
* @param aOriginalRequestor the original treeitem that made the request.
* Used for security checks.
* @return the tree item with aName as the name, or null if there
* isn't one. "Special" names, like _self, _top, etc, will be
* treated specially only if aRequestor is null; in that case they
* will be resolved relative to the first window the windowwatcher
* knows about.
* @see findItemWithName methods on nsIDocShellTreeItem and
* nsIDocShellTreeOwner
*/
nsIDocShellTreeItem findItemWithName(in wstring aName,
in nsIDocShellTreeItem aRequestor,
in nsIDocShellTreeItem aOriginalRequestor);
};
%{C++

View File

@ -558,7 +558,7 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent,
parentItem->FindItemWithName(name.get(), nsnull, callerItem,
getter_AddRefs(newDocShellItem));
} else
FindItemWithName(name.get(), callerItem,
FindItemWithName(name.get(), nsnull, callerItem,
getter_AddRefs(newDocShellItem));
}
@ -1069,7 +1069,7 @@ nsWindowWatcher::GetWindowByName(const PRUnichar *aTargetName,
docShellTreeItem = do_QueryInterface(webNav);
if (docShellTreeItem) {
// XXXbz sort out original requestor?
// Note: original requestor is null here, per idl comments
docShellTreeItem->FindItemWithName(aTargetName, nsnull, nsnull,
getter_AddRefs(treeItem));
}
@ -1077,7 +1077,8 @@ nsWindowWatcher::GetWindowByName(const PRUnichar *aTargetName,
// Next, see if the TargetName exists in any window hierarchy
if (!treeItem) {
FindItemWithName(aTargetName, nsnull, getter_AddRefs(treeItem));
// Note: original requestor is null here, per idl comments
FindItemWithName(aTargetName, nsnull, nsnull, getter_AddRefs(treeItem));
}
if (treeItem) {
@ -1396,8 +1397,9 @@ nsWindowWatcher::WinHasOption(const char *aOptions, const char *aName,
known open window. a failure to find the item will not
necessarily return a failure method value. check aFoundItem.
*/
nsresult
NS_IMETHODIMP
nsWindowWatcher::FindItemWithName(const PRUnichar* aName,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem** aFoundItem)
{
@ -1409,10 +1411,6 @@ nsWindowWatcher::FindItemWithName(const PRUnichar* aName,
nsDependentString name(aName);
if(name.LowerCaseEqualsLiteral("_blank") || name.LowerCaseEqualsLiteral("_new"))
return NS_OK;
// _content will be handled by individual windows, below
nsCOMPtr<nsISimpleEnumerator> windows;
GetWindowEnumerator(getter_AddRefs(windows));
if (!windows)
@ -1427,15 +1425,33 @@ nsWindowWatcher::FindItemWithName(const PRUnichar* aName,
break;
nsCOMPtr<nsISupports> nextSupWindow;
windows->GetNext(getter_AddRefs(nextSupWindow));
if (nextSupWindow) {
nsCOMPtr<nsIDOMWindow> nextWindow(do_QueryInterface(nextSupWindow));
if (nextWindow) {
nsCOMPtr<nsIDocShellTreeItem> treeItem;
GetWindowTreeItem(nextWindow, getter_AddRefs(treeItem));
if (treeItem) {
rv = treeItem->FindItemWithName(aName, treeItem, aOriginalRequestor,
aFoundItem);
if (NS_FAILED(rv) || *aFoundItem)
nsCOMPtr<nsIDOMWindow> nextWindow(do_QueryInterface(nextSupWindow));
if (nextWindow) {
nsCOMPtr<nsIDocShellTreeItem> treeItem;
GetWindowTreeItem(nextWindow, getter_AddRefs(treeItem));
if (treeItem) {
// Get the root tree item of same type, since roots are the only
// things that call into the treeowner to look for named items.
nsCOMPtr<nsIDocShellTreeItem> root;
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
NS_ASSERTION(root, "Must have root tree item of same type");
// Make sure not to call back into aRequestor
if (root != aRequestor) {
// Get the tree owner so we can pass it in as the requestor so
// the child knows not to call back up, since we're walking
// all windows already.
nsCOMPtr<nsIDocShellTreeOwner> rootOwner;
// Note: if we have no aRequestor, then we want to also look for
// "special" window names, so pass a null requestor. This will mean
// that the treeitem calls back up to us, effectively (with a
// non-null aRequestor), so break the loop immediately after the
// call in that case.
if (aRequestor) {
root->GetTreeOwner(getter_AddRefs(rootOwner));
}
rv = root->FindItemWithName(aName, rootOwner, aOriginalRequestor,
aFoundItem);
if (NS_FAILED(rv) || *aFoundItem || !aRequestor)
break;
}
}

View File

@ -84,10 +84,6 @@ private:
nsWatcherWindowEntry *FindWindowEntry(nsIDOMWindow *aWindow);
nsresult RemoveWindow(nsWatcherWindowEntry *inInfo);
nsresult FindItemWithName(const PRUnichar *aName,
nsIDocShellTreeItem *aOriginalRequestor,
nsIDocShellTreeItem **aFoundItem);
static JSContext *GetJSContextFromWindow(nsIDOMWindow *aWindow);
static JSContext *GetJSContextFromCallStack();
static nsresult URIfromURL(const char *aURL,