--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1900,58 +1900,59 @@ nsDocShell::CanAccessItem(nsIDocShellTre
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?
+ // For historical context, see:
+ //
+ // Bug 13871: Prevent frameset spoofing
+ // Bug 103638: Targets with same name in different windows open in wrong
+ // window with javascript
+
// 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));
+ //
+ // Allow navigation if
+ // 1) aAccessingItem can script aTargetItem or one of its ancestors in
+ // the frame hierarchy or
+ // 2) aTargetItem is a top-level frame and aAccessingItem is its descendant
+ // 3) aTargetItem is a top-level frame and aAccessingItem can target
+ // its opener per rule (1) or (2).
+
+ if (aTargetItem == aAccessingItem) {
+ // A frame is allowed to navigate itself.
+ return PR_TRUE;
+ }
nsCOMPtr<nsIDocShellTreeItem> accessingRoot;
aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot));
- if (targetRoot == accessingRoot) {
+ if (aTargetItem == accessingRoot) {
+ // A frame can navigate its root.
return PR_TRUE;
}
+ // Check if aAccessingItem can navigate one of aTargetItem's ancestors.
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);
+ nsCOMPtr<nsIDocShellTreeItem> targetRoot;
+ aTargetItem->GetSameTypeRootTreeItem(getter_AddRefs(targetRoot));
+
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) {
@@ -6414,60 +6415,16 @@ nsDocShell::CheckLoadingPermissions()
sameOrigin = NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
nsCOMPtr<nsIDocShellTreeItem> tmp;
item->GetSameTypeParent(getter_AddRefs(tmp));
item.swap(tmp);
} while (item);
- // The caller is not from the same origin as this item, or any if
- // this items ancestors. Only permit loading content if both are
- // part of the same window, assuming we can find the window of the
- // caller.
-
- nsCOMPtr<nsIJSContextStack> stack =
- do_GetService("@mozilla.org/js/xpc/ContextStack;1");
- if (!stack) {
- // No context stack available. Should never happen, but in
- // case it does, return the sameOrigin error from the security
- // check above.
-
- return sameOrigin;
- }
-
- JSContext *cx = nsnull;
- stack->Peek(&cx);
-
- if (!cx) {
- // No caller docshell reachable, return the sameOrigin error
- // from the security check above.
-
- return sameOrigin;
- }
-
- nsIScriptContext *currentCX = GetScriptContextFromJSContext(cx);
- nsCOMPtr<nsIDocShellTreeItem> callerTreeItem;
- nsCOMPtr<nsPIDOMWindow> win;
- if (currentCX &&
- (win = do_QueryInterface(currentCX->GetGlobalObject())) &&
- (callerTreeItem = do_QueryInterface(win->GetDocShell()))) {
- nsCOMPtr<nsIDocShellTreeItem> callerRoot;
- callerTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(callerRoot));
-
- nsCOMPtr<nsIDocShellTreeItem> ourRoot;
- GetSameTypeRootTreeItem(getter_AddRefs(ourRoot));
-
- if (ourRoot == callerRoot) {
- // The running JS is in the same window as the target
- // frame, permit load.
- sameOrigin = NS_OK;
- }
- }
-
return sameOrigin;
}
//*****************************************************************************
// nsDocShell: Site Loading
//*****************************************************************************
class InternalLoadEvent : public nsRunnable
{
--- a/docshell/test/Makefile.in
+++ b/docshell/test/Makefile.in
@@ -40,16 +40,17 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = docshell/test
MODULE = test_docshell
DIRS += chrome \
browser \
+ navigation \
$(NULL)
XPCSHELL_TESTS = unit
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/Makefile.in
@@ -0,0 +1,73 @@
+#
+# ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+# # The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+relativesrcdir = docshell/test/navigation
+
+MODULE = test_docshell
+
+DIRS += $(NULL)
+
+XPCSHELL_TESTS = unit
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES = \
+ test_bug13871.html \
+ test_bug270414.html \
+ test_bug278916.html \
+ test_bug279495.html \
+ test_child.html \
+ test_grandchild.html \
+ test_sibling-off-domain.html \
+ test_sibling-matching-parent.html \
+ test_opener.html \
+ test_not-opener.html \
+ test_popup-navigates-children.html \
+ test_reserved.html \
+ NavigationUtils.js \
+ navigate.html \
+ open.html \
+ iframe.html \
+ parent.html \
+ blank.html \
+ $(NULL)
+
+libs:: $(_TEST_FILES)
+ $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/NavigationUtils.js
@@ -0,0 +1,231 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is NavigationUtils.js
+ *
+ * The Initial Developer of the Original Code is
+ * Stanford University
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Adam Barth <hk9565@gmail.com>
+ * Collin Jackson <mozilla@collinjackson.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Utilities for navigation tests
+//
+///////////////////////////////////////////////////////////////////////////
+
+var body = "This frame was navigated.";
+var target_url = "data:text/html,<html><body>" + body + "</body></html>";
+
+///////////////////////////////////////////////////////////////////////////
+// Functions that navigate frames
+///////////////////////////////////////////////////////////////////////////
+
+function navigateByLocation(wnd) {
+ try {
+ wnd.location = target_url;
+ } catch(ex) {
+ // We need to keep our finished frames count consistent.
+ // Oddly, this ends up simulating the behavior of IE7.
+ window.open(target_url, "_blank", "width=10,height=10");
+ }
+}
+
+function navigateByOpen(name) {
+ window.open(target_url, name, "width=10,height=10");
+}
+
+function navigateByForm(name) {
+ var form = document.createElement("form");
+ form.action = target_url;
+ form.method = "POST";
+ form.target = name; document.body.appendChild(form);
+ form.submit();
+}
+
+var hyperlink_count = 0;
+
+function navigateByHyperlink(name) {
+ var link = document.createElement("a");
+ link.href = target_url;
+ link.target = name;
+ link.id = "navigation_hyperlink_" + hyperlink_count++;
+ document.body.appendChild(link);
+ sendMouseEvent({type:"click"}, link.id);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Functions that call into Mochitest framework
+///////////////////////////////////////////////////////////////////////////
+
+function isNavigated(wnd, message) {
+ var result = null;
+ try {
+ result = wnd.document.body.innerHTML;
+ } catch(ex) {
+ result = ex;
+ }
+ is(result, body, message);
+}
+
+function isBlank(wnd, message) {
+ var result = null;
+ try {
+ result = wnd.document.body.innerHTML;
+ } catch(ex) {
+ result = ex;
+ }
+ is(result, "This is a blank document.", message);
+}
+
+function isAccessible(wnd, message) {
+ try {
+ wnd.document.body.innerHTML;
+ ok(true, message);
+ } catch(ex) {
+ ok(false, message);
+ }
+}
+
+function isInaccessible(wnd, message) {
+ try {
+ wnd.document.body.innerHTML;
+ ok(false, message);
+ } catch(ex) {
+ ok(true, message);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Functions that require UniversalXPConnect privilege
+///////////////////////////////////////////////////////////////////////////
+
+// Note: This only searches for top-level frames with this name.
+function xpcGetFramesByName(name) {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(Components.interfaces.nsIWindowWatcher);
+ var enumerator = ww.getWindowEnumerator();
+
+ var results = [];
+
+ while (enumerator.hasMoreElements()) {
+ var win = enumerator.getNext();
+ var tabs = win.gBrowser.browsers;
+
+ for (var i = 0; i < tabs.length; i++) {
+ var domwindow = tabs[i].docShell.document.defaultView;
+
+ if (domwindow.name == name)
+ results.push(domwindow);
+ }
+ }
+
+ return results;
+}
+
+function xpcCleanupWindows() {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(Components.interfaces.nsIWindowWatcher);
+ var enumerator = ww.getWindowEnumerator();
+
+ while (enumerator.hasMoreElements()) {
+ var win = enumerator.getNext();
+ var tabs = win.gBrowser.browsers;
+
+ for (var i = 0; i < tabs.length; i++) {
+ var domwindow = tabs[i].docShell.document.defaultView;
+
+ if (domwindow.location.protocol == "data:")
+ domwindow.close();
+ }
+ }
+}
+
+function xpcWaitForFinishedFrames(callback, numFrames) {
+ var finishedFrameCount = 0;
+ function frameFinished() {
+ finishedFrameCount++;
+
+ if (finishedFrameCount == numFrames) {
+ clearInterval(frameWaitInterval);
+ setTimeout(callback, 1);
+ return;
+ }
+
+ if (finishedFrameCount > numFrames)
+ throw "Too many frames loaded.";
+ }
+
+ var finishedWindows = [];
+
+ function contains(obj, arr) {
+ for (var i = 0; i < arr.length; i++) {
+ if (obj === arr[i])
+ return true;
+ }
+ return false;
+ }
+
+ function searchForFinishedFrames(win) {
+ if (escape(unescape(win.location)) == escape(target_url)) {
+ if (!contains(win, finishedWindows)) {
+ finishedWindows.push(win);
+ frameFinished();
+ }
+ }
+ for (var i = 0; i < win.frames.length; i++)
+ searchForFinishedFrames(win.frames[i]);
+ }
+
+ function poll() {
+ // This only gives us UniversalXPConnect for the current stack frame
+ // We're using setInterval, so the main page's privileges are still normal
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(Components.interfaces.nsIWindowWatcher);
+ var enumerator = ww.getWindowEnumerator();
+ while (enumerator.hasMoreElements()) {
+ var win = enumerator.getNext();
+ if (!win.gBrowser)
+ continue; // This window hasn't finished initializing
+ var tabs = win.gBrowser.browsers;
+
+ for (var i = 0; i < tabs.length; i++) {
+ searchForFinishedFrames(tabs[i].docShell.document.defaultView);
+ }
+ }
+ }
+
+ var frameWaitInterval = setInterval(poll, 500);
+}
+
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/blank.html
@@ -0,0 +1,1 @@
+<html><body>This is a blank document.</body></html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/iframe.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<script>
+var src = window.location.hash.substring(1);
+document.write('<iframe src="' + src + '"></iframe>');
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/navigate.html
@@ -0,0 +1,30 @@
+<html>
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script src="NavigationUtils.js"></script>
+</head>
+<body>
+<script>
+var arguments = window.location.hash.substring(1).split(",");
+var target = arguments[0];
+var mechanism = arguments[1];
+
+document.write("target=" + target + " mechanism=" + mechanism);
+
+switch(mechanism) {
+case "location":
+ navigateByLocation(eval(target));
+ break;
+case "open":
+ navigateByOpen(target);
+ break;
+case "form":
+ navigateByForm(target);
+ break;
+case "hyperlink":
+ navigateByHyperlink(target);
+ break;
+}
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/open.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+<script>
+var target = window.location.hash.substring(1);
+document.write("target=" + target);
+window.open("data:text/html,<html><body>This is a popup</body></html>", target, "width=10,height=10");
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/parent.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body>
+This document contains a frame.
+<div><iframe src="blank.html"></iframe></div>
+<script>
+frames[0].name = window.name + "_child0";
+</script>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_bug13871.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+window.onload = function () {
+ navigateByLocation(window0.frames[0]);
+ navigateByOpen("window1_child0");
+ navigateByForm("window2_child0");
+ navigateByHyperlink("window3_child0");
+}
+
+xpcWaitForFinishedFrames(function() {
+ isInaccessible(window0.frames[0], "Should not be able to navigate off-domain frame by setting location.");
+ isInaccessible(window1.frames[0], "Should not be able to navigate off-domain frame by calling window.open.");
+ isInaccessible(window2.frames[0], "Should not be able to navigate off-domain frame by submitting form.");
+ isInaccessible(window3.frames[0], "Should not be able to navigate off-domain frame by targeted hyperlink.");
+
+ window0.close();
+ window1.close();
+ window2.close();
+ window3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+
+var window0 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/parent.html", "window0", "width=10,height=10");
+var window1 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/parent.html", "window1", "width=10,height=10");
+var window2 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/parent.html", "window2", "width=10,height=10");
+var window3 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/parent.html", "window3", "width=10,height=10");
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=13871">Mozilla Bug 13871</a>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_bug270414.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+var headerHTML = "<html><head>" +
+ "<script src='/tests/SimpleTest/EventUtils.js'></scr" + "ipt>" +
+ "<script src='NavigationUtils.js'></scr" + "ipt>" +
+ "</head><body>";
+var footerHTML = "</body></html>";
+
+function testChild0() {
+ if (!window.window0) {
+ window0 = window.open("", "window0", "width=10,height=10");
+ window0.document.open();
+ window0.document.write(headerHTML);
+ window0.document.write("<script>navigateByLocation(opener.frames[0])</scr" + "ipt>");
+ window0.document.write(footerHTML);
+ window0.document.close();
+ }
+}
+
+function testChild1() {
+ if (!window.window1) {
+ window1 = window.open("", "window1", "width=10,height=10");
+ window1.document.open();
+ window1.document.write(headerHTML);
+ window1.document.write("<script>navigateByOpen('child1');</scr" + "ipt>");
+ window1.document.write(footerHTML);
+ window1.document.close();
+ }
+}
+
+function testChild2() {
+ if (!window.window2) {
+ window2 = window.open("", "window2", "width=10,height=10");
+ window2.document.open();
+ window2.document.write(headerHTML);
+ window2.document.write("<script>navigateByForm('child2');</scr" + "ipt>");
+ window2.document.write(footerHTML);
+ window2.document.close();
+ }
+}
+
+function testChild3() {
+ if (!window.window3) {
+ window3 = window.open("", "window3", "width=10,height=10");
+ window3.document.open();
+ window3.document.write(headerHTML);
+ window3.document.write("<script>navigateByHyperlink('child3');</scr" + "ipt>");
+ window3.document.write(footerHTML);
+ window3.document.close();
+ }
+}
+
+xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0], "Should be able to navigate on-domain opener's children by setting location.");
+ isNavigated(frames[1], "Should be able to navigate on-domain opener's children by calling window.open.");
+ isNavigated(frames[2], "Should be able to navigate on-domain opener's children by submitting form.");
+ isNavigated(frames[3], "Should be able to navigate on-domain opener's children by targeted hyperlink.");
+
+ window0.close();
+ window1.close();
+ window2.close();
+ window3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=270414">Mozilla Bug 270414</a>
+<div id="frames">
+<iframe onload="testChild0();" name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild1();" name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild2();" name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild3();" name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_bug278916.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+<script>
+window.onload = function () {
+ document.getElementById("link0").href = target_url;
+
+ sendMouseEvent({type:"click"}, "link0");
+}
+
+xpcWaitForFinishedFrames(function() {
+ var array_of_frames = xpcGetFramesByName("window0");
+ is(array_of_frames.length, 1, "Should only open one window using a fancy hyperlink.");
+
+ for (var i=0; i < array_of_frames.length; ++i)
+ array_of_frames[i].close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 1);
+
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=278916">Mozilla Bug 278916</a>
+<div id="links">
+<a id="link0" target="window0" onclick="window.open('', 'window0', 'width=10,height=10');">This is a fancy hyperlink</a>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_bug279495.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+<script>
+window.onload = function () {
+ document.getElementById("link0").href = target_url;
+ document.getElementById("link1").href = target_url;
+
+ sendMouseEvent({type:"click"}, "link0");
+ sendMouseEvent({type:"click"}, "link1");
+}
+
+function countAndClose(name, expected_count) {
+ var array_of_frames = xpcGetFramesByName(name);
+ is(array_of_frames.length, expected_count,
+ "Should only open " + expected_count +
+ " window(s) with name " + name + " using a fancy hyperlink.");
+
+ for (var i=0; i < array_of_frames.length; ++i)
+ array_of_frames[i].close();
+}
+
+xpcWaitForFinishedFrames(function() {
+ countAndClose("window0", 1);
+ countAndClose("window1", 1);
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 2);
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=279495">Mozilla Bug 279495</a>
+<div id="links">
+<a id="link0" target="window0" onclick="window.open('blank.html', 'window0', 'width=10,height=10');">This is a fancy hyperlink</a>
+<a id="link1" target="window1" onclick="window.open('http://test1.example.org:80/tests/docshell/test/navigation/blank.html', 'window1', 'width=10,height=10');">This is a fancy hyperlink</a>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_child.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+window.onload = function() {
+ navigateByLocation(frames[0]);
+ navigateByOpen("child1");
+ navigateByForm("child2");
+ navigateByHyperlink("child3");
+}
+
+xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0], "Should be able to navigate off-domain child by setting location.");
+ isNavigated(frames[1], "Should be able to navigate off-domain child by calling window.open.");
+ isNavigated(frames[2], "Should be able to navigate off-domain child by submitting form.");
+ isNavigated(frames[3], "Should be able to navigate off-domain child by targeted hyperlink.");
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+<iframe name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_grandchild.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 200px; }
+ </style>
+<script>
+window.onload = function () {
+ navigateByLocation(frames[0].frames[0]);
+ navigateByOpen("child1_child0");
+ navigateByForm("child2_child0");
+ navigateByHyperlink("child3_child0");
+}
+
+xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0].frames[0], "Should be able to navigate off-domain grandchild by setting location.");
+ isNavigated(frames[1].frames[0], "Should be able to navigate off-domain grandchild by calling window.open.");
+ isNavigated(frames[2].frames[0], "Should be able to navigate off-domain grandchild by submitting form.");
+ isNavigated(frames[3].frames[0], "Should be able to navigate off-domain grandchild by targeted hyperlink.");
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+<iframe name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/parent.html"></iframe>
+<iframe name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/parent.html"></iframe>
+<iframe name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/parent.html"></iframe>
+<iframe name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/parent.html"></iframe>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_not-opener.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+window.onload = function () {
+ //navigateByLocation(window0); // Don't have a handle to the window.
+ navigateByOpen("window1");
+ navigateByForm("window2");
+ navigateByHyperlink("window3");
+}
+
+xpcWaitForFinishedFrames(function() {
+ is(xpcGetFramesByName("window1").length, 2, "Should not be able to navigate popup's popup by calling window.open.");
+ is(xpcGetFramesByName("window2").length, 2, "Should not be able to navigate popup's popup by submitting form.");
+ is(xpcGetFramesByName("window3").length, 2, "Should not be able to navigate popup's popup by targeted hyperlink.");
+
+ //opener0.close();
+ opener1.close();
+ opener2.close();
+ opener3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 3);
+
+//opener0 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/open.html#window0", "_blank", "width=10,height=10");
+opener1 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/open.html#window1", "_blank", "width=10,height=10");
+opener2 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/open.html#window2", "_blank", "width=10,height=10");
+opener3 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/open.html#window3", "_blank", "width=10,height=10");
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_opener.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+window.onload = function () {
+ navigateByLocation(window0);
+ navigateByOpen("window1");
+ navigateByForm("window2");
+ navigateByHyperlink("window3");
+}
+
+xpcWaitForFinishedFrames(function() {
+ isNavigated(window0, "Should be able to navigate popup by setting location.");
+ isNavigated(window1, "Should be able to navigate popup by calling window.open.");
+ isNavigated(window2, "Should be able to navigate popup by submitting form.");
+ isNavigated(window3, "Should be able to navigate popup by targeted hyperlink.");
+
+ window0.close();
+ window1.close();
+ window2.close();
+ window3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+
+var window0 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/blank.html", "window0", "width=10,height=10");
+var window1 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/blank.html", "window1", "width=10,height=10");
+var window2 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/blank.html", "window2", "width=10,height=10");
+var window3 = window.open("http://test1.example.org:80/tests/docshell/test/navigation/blank.html", "window3", "width=10,height=10");
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_popup-navigates-children.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+function testChild0() {
+ if (!window.window0)
+ window0 = window.open("navigate.html#opener.frames[0],location", "window0", "width=10,height=10");
+}
+
+function testChild1() {
+ if (!window.window1)
+ window1 = window.open("navigate.html#child1,open", "window1", "width=10,height=10");
+}
+
+function testChild2() {
+ if (!window.window2)
+ window2 = window.open("navigate.html#child2,form", "window2", "width=10,height=10");
+}
+
+function testChild3() {
+ if (!window.window3)
+ window3 = window.open("navigate.html#child3,hyperlink", "window3", "width=10,height=10");
+}
+
+xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0], "Should be able to navigate on-domain opener's children by setting location.");
+ isNavigated(frames[1], "Should be able to navigate on-domain opener's children by calling window.open.");
+ isNavigated(frames[2], "Should be able to navigate on-domain opener's children by submitting form.");
+ isNavigated(frames[3], "Should be able to navigate on-domain opener's children by targeted hyperlink.");
+
+ window0.close();
+ window1.close();
+ window2.close();
+ window3.close();
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+
+</script>
+</head>
+<body>
+<div id="frames">
+<iframe onload="testChild0()" name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild1()" name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild2()" name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe onload="testChild3()" name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_reserved.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 200px; }
+ </style>
+<script>
+function testTop() {
+ window0 = window.open("iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#top,location", "_blank", "width=10,height=10");
+
+ xpcWaitForFinishedFrames(function() {
+ isInaccessible(window0, "Should be able to navigate off-domain top by setting location.");
+ window0.close();
+ xpcCleanupWindows();
+
+ window1 = window.open("iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_top,open", "_blank", "width=10,height=10");
+
+ xpcWaitForFinishedFrames(function() {
+ isInaccessible(window1, "Should be able to navigate off-domain top by calling window.open.");
+ window1.close();
+ xpcCleanupWindows();
+
+ window2 = window.open("iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_top,form", "_blank", "width=10,height=10");
+
+ xpcWaitForFinishedFrames(function() {
+ isInaccessible(window2, "Should be able to navigate off-domain top by submitting form.");
+ window2.close();
+ xpcCleanupWindows();
+
+ window3 = window.open("iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_top,hyperlink", "_blank", "width=10,height=10");
+
+ xpcWaitForFinishedFrames(function() {
+ isInaccessible(window3, "Should be able to navigate off-domain top by targeted hyperlink.");
+ window3.close();
+ xpcCleanupWindows();
+
+ testParent();
+ }, 1);
+ }, 1);
+ }, 1);
+ }, 1);
+}
+
+function testParent() {
+ document.getElementById("frames").innerHTML = '<iframe src="iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#parent,location"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isAccessible(frames[0], "Should not be able to navigate off-domain parent by setting location.");
+ xpcCleanupWindows();
+
+ document.getElementById("frames").innerHTML = '<iframe src="iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_parent,open"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isAccessible(frames[0], "Should not be able to navigate off-domain parent by calling window.open.");
+ xpcCleanupWindows();
+
+ document.getElementById("frames").innerHTML = '<iframe src="iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_parent,form"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isAccessible(frames[0], "Should not be able to navigate off-domain parent by submitting form.");
+ xpcCleanupWindows();
+
+ document.getElementById("frames").innerHTML = '<iframe src="iframe.html#http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#_parent,hyperlink"></iframe>';
+
+ xpcWaitForFinishedFrames(function() {
+ isAccessible(frames[0], "Should not be able to navigate off-domain parent by targeted hyperlink.");
+ xpcCleanupWindows();
+
+ document.getElementById("frames").innerHTML = "";
+ SimpleTest.finish();
+ }, 1);
+ }, 1);
+ }, 1);
+ }, 1);
+}
+
+window.onload = function() {
+ testTop();
+}
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+</div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_sibling-matching-parent.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+window.onload = function () {
+ document.getElementById('active').innerHTML =
+ '<iframe src="navigate.html#parent.frames[0],location"></iframe>' +
+ '<iframe src="navigate.html#child1,open"></iframe>' +
+ '<iframe src="navigate.html#child2,form"></iframe>' +
+ '<iframe src="navigate.html#child3,hyperlink"></iframe>';
+}
+
+xpcWaitForFinishedFrames(function() {
+ isNavigated(frames[0], "Should be able to navigate sibling with on-domain parent by setting location.");
+ isNavigated(frames[1], "Should be able to navigate sibling with on-domain parent by calling window.open.");
+ isNavigated(frames[2], "Should be able to navigate sibling with on-domain parent by submitting form.");
+ isNavigated(frames[3], "Should be able to navigate sibling with on-domain parent by targeted hyperlink.");
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+<iframe name="child0" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child1" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child2" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+<iframe name="child3" src="http://test1.example.org:80/tests/docshell/test/navigation/blank.html"></iframe>
+</div>
+<div id="active"></div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/test_sibling-off-domain.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="NavigationUtils.js"></script>
+ <style type="text/css">
+ iframe { width: 90%; height: 50px; }
+ </style>
+<script>
+window.onload = function () {
+ document.getElementById('active').innerHTML =
+ '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#parent.frames[0],location"></iframe>' +
+ '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#child1,open"></iframe>' +
+ '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#child2,form"></iframe>' +
+ '<iframe src="http://test1.example.org:80/tests/docshell/test/navigation/navigate.html#child3,hyperlink"></iframe>';
+}
+
+xpcWaitForFinishedFrames(function() {
+ isBlank(frames[0], "Should not be able to navigate off-domain sibling by setting location.");
+ isBlank(frames[1], "Should not be able to navigate off-domain sibling by calling window.open.");
+ isBlank(frames[2], "Should not be able to navigate off-domain sibling by submitting form.");
+ isBlank(frames[3], "Should not be able to navigate off-domain sibling by targeted hyperlink.");
+
+ xpcCleanupWindows();
+ SimpleTest.finish();
+}, 4);
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408052">Mozilla Bug 408052</a>
+<div id="frames">
+<iframe name="child0" src="blank.html"></iframe>
+<iframe name="child1" src="blank.html"></iframe>
+<iframe name="child2" src="blank.html"></iframe>
+<iframe name="child3" src="blank.html"></iframe>
+</div>
+<div id="active"></div>
+<pre id="test">
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>