Bug 384192 - Mochitest needs to support subdomain tests; use a proxy hack to pretend the tests are available on example.com, example.org, and various subdomains of each, on various ports, to satisfy this need. r=robcee

This commit is contained in:
jwalden@mit.edu 2007-07-11 22:38:47 -07:00
parent 6b4d9b9fb0
commit 13dd7e4db5
7 changed files with 365 additions and 53 deletions

View File

@ -1,37 +1,37 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Cross domain access to properties</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="runTest()">
<p id="display"></p>
<div id="content" style="display: none">
</div>
<iframe name="frame1" src="file_crossdomainprops_inner.html"></iframe>
<iframe name="frame2" src="http://localhost:8889/tests/dom/tests/mochitest/dom-level0/file_crossdomainprops_inner.html"></iframe>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function runTest() {
ok(frames.frame1.myVar == 10, "access same domain inner window variable");
var otherDomainVar = null;
try {
otherDomainVar = frames.frame2.myVar;
}
catch (e) {
otherDomainVar = -1;
}
ok(otherDomainVar == -1, "access other domain inner window variable");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Cross domain access to properties</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="runTest()">
<p id="display"></p>
<div id="content" style="display: none">
</div>
<iframe name="frame1" src="file_crossdomainprops_inner.html"></iframe>
<iframe name="frame2" src="http://example.com/tests/dom/tests/mochitest/dom-level0/file_crossdomainprops_inner.html"></iframe>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function runTest() {
ok(frames.frame1.myVar == 10, "access same domain inner window variable");
var otherDomainVar = null;
try {
otherDomainVar = frames.frame2.myVar;
}
catch (e) {
otherDomainVar = -1;
}
ok(otherDomainVar == -1, "access other domain inner window variable");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View File

@ -2454,8 +2454,10 @@ RequestMetadata.prototype =
// - handles POSTs by displaying the URL and throwing away the request
// entity
// - need to support RFC 2047-encoded non-US-ASCII characters
// - support absolute URLs (requires telling the server its hostname, beyond
// just localhost:port and 127.0.0.1:port)
// - really support absolute URLs (requires telling the server its hostname,
// beyond just localhost:port and 127.0.0.1:port), not just pretend we
// serve every request that's given to us regardless of the server
// hostname and port
// - etc.
// read the input line by line; the first line either tells us the requested
@ -2548,11 +2550,23 @@ RequestMetadata.prototype =
var fullPath = request[1];
// XXX we don't support absolute URIs yet -- a MUST for HTTP/1.1
if (fullPath.charAt(0) != "/")
{
this.errorCode = 400;
return;
// XXX we don't support absolute URIs yet -- a MUST for HTTP/1.1;
// for now just get the path and use that, ignoring hostport
try
{
var uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(fullPath, null, null);
fullPath = uri.path;
}
catch (e) { /* invalid URI */ }
if (fullPath.charAt(0) != "/")
{
this.errorCode = 400;
return;
}
}
var splitter = fullPath.indexOf("?");

View File

@ -359,9 +359,6 @@ sub initializeProfile {
my ($app_path, $do_browser_tests) = @_;
my $pref_content = <<PREFEND;
user_pref("browser.dom.window.dump.enabled", true);
user_pref("capability.principal.codebase.p1.granted", "UniversalXPConnect UniversalBrowserRead UniversalBrowserWrite UniversalPreferencesRead UniversalPreferencesWrite UniversalFileRead");
user_pref("capability.principal.codebase.p1.id", "http://localhost:8888");
user_pref("capability.principal.codebase.p1.subjectName", "");
user_pref("dom.disable_open_during_load", false);
user_pref("dom.max_script_run_time", 0); // no slow script dialogs
user_pref("signed.applets.codebase_principal_support", true);
@ -369,6 +366,49 @@ user_pref("security.warn_submit_insecure", false);
user_pref("browser.shell.checkDefaultBrowser", false);
PREFEND
#
# Since some tests require cross-domain support in Mochitest, across ports,
# domains, subdomains, etc. we have a proxying hack in cross-domain.js which
# maps a bunch of servers onto localhost:8888. We have to grant them the same
# privileges as localhost:8888 here, since the browser only knows them as the
# URLs they're pretending to be. See cross-domain.js for the other copy of
# this list.
#
# KEEP THESE TWO LISTS IN SYNC!
#
my @servers = ("http://localhost:8888",
"http://example.org:80",
"http://test1.example.org:80",
"http://test2.example.org:80",
"http://sub1.test1.example.org:80",
"http://sub1.test2.example.org:80",
"http://sub2.test1.example.org:80",
"http://sub2.test2.example.org:80",
"http://example.org:8000",
"http://test1.example.org:8000",
"http://test2.example.org:8000",
"http://sub1.test1.example.org:8000",
"http://sub1.test2.example.org:8000",
"http://sub2.test1.example.org:8000",
"http://sub2.test2.example.org:8000",
"http://example.com:80",
"http://test1.example.com:80",
"http://test2.example.com:80",
"http://sub1.test1.example.com:80",
"http://sub1.test2.example.com:80",
"http://sub2.test1.example.com:80",
"http://sub2.test2.example.com:80");
my $i = 1;
my $server;
foreach $server (@servers) {
$pref_content .= <<SERVERPREFEND;
user_pref("capability.principal.codebase.p$i.granted", "UniversalXPConnect UniversalBrowserRead UniversalBrowserWrite UniversalPreferencesRead UniversalPreferencesWrite UniversalFileRead");
user_pref("capability.principal.codebase.p$i.id", "$server");
user_pref("capability.principal.codebase.p$i.subjectName", "");
SERVERPREFEND
$i++;
}
my $chrome_content = <<CHROMEEND;
\@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
toolbar,

View File

@ -42,9 +42,7 @@
// sucks.
const SERVER_PORT = 8888;
const SERVER_PORT_OTHER_DOMAIN = 8889;
var server; // for use in the shutdown handler, if necessary
var otherDomainServer; // for use in the shutdown handler, if necessary
//
// HTML GENERATION
@ -138,16 +136,12 @@ function runServer()
serverBasePath.append("mochitest");
server = new nsHttpServer();
server.registerDirectory("/", serverBasePath);
otherDomainServer = new nsHttpServer();
otherDomainServer.registerDirectory("/", serverBasePath);
if (environment["CLOSE_WHEN_DONE"])
server.registerPathHandler("/server/shutdown", serverShutdown);
server.setIndexHandler(defaultDirHandler);
server.start(SERVER_PORT);
otherDomainServer.setIndexHandler(defaultDirHandler);
otherDomainServer.start(SERVER_PORT_OTHER_DOMAIN);
// touch a file in the profile directory to indicate we're alive
var foStream = Cc["@mozilla.org/network/file-output-stream;1"]
@ -201,7 +195,6 @@ function serverShutdown(metadata, response)
// Note: this doesn't disrupt the current request.
server.stop();
otherDomainServer.stop();
}
//
@ -312,7 +305,7 @@ function linksToListItems(links)
if ((bug_title == null) || (bug_num == null)) {
response += LI({class: classVal}, A({href: link}, link), children);
} else {
var bug_url = "http://bugzilla.mozilla.org/show_bug.cgi?id="+bug_num;
var bug_url = "https://bugzilla.mozilla.org/show_bug.cgi?id="+bug_num;
response += LI({class: classVal}, A({href: link}, link), " - ", A({href: bug_url}, "Bug "+bug_num), children);
}
@ -407,6 +400,8 @@ function testListing(metadata, response)
src: "/tests/SimpleTest/TestRunner.js"}),
SCRIPT({type: "text/javascript",
src: "/tests/SimpleTest/MozillaFileLogger.js"}),
SCRIPT({type: "text/javascript",
src: "/tests/SimpleTest/cross-domain.js"}),
SCRIPT({type: "text/javascript",
src: "/tests/SimpleTest/quit.js"}),
SCRIPT({type: "text/javascript",

View File

@ -51,6 +51,7 @@ _SIMPLETEST_FILES = MozillaFileLogger.js \
TestRunner.js \
setup.js \
EventUtils.js \
cross-domain.js \
$(NULL)
libs:: $(_SIMPLETEST_FILES)

View File

@ -0,0 +1,258 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** 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 the DomainMapper code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jeff Walden <jwalden+code@mit.edu> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 ***** */
//
// http://wp.netscape.com/eng/mozilla/2.0/relnotes/demo/proxy-live.html
// http://kb.mozillazine.org/Network.proxy.autoconfig_url
// http://kb.mozillazine.org/Network.proxy.type
//
try
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
if (!this.Cc)
this.Cc = Components.classes;
if (!this.Ci)
this.Ci = Components.interfaces;
if (!this.Cr)
this.Cr = Components.results;
const PROXY_AUTOCONFIG_PREF = "network.proxy.autoconfig_url";
const PROXY_TYPE_PREF = "network.proxy.type";
const PROXY_TYPE_USE_PAC = 2;
/**
* Maps requests in the browser to particular domains/ports through other
* domains/ports in a customizable manner.
*/
function DomainMapper()
{
/**
* Hash of host:port for mapped host/ports to host:port for the host:port
* which should be used instead.
*/
this._mappings = {};
/** Identifies the old proxy type, if any. */
this._oldProxyType = undefined;
/** Identifies the old PAC URL, if any. */
this._oldPAC = undefined;
/** True when mapping is enabled. */
this._enabled = false;
}
DomainMapper.prototype =
{
/**
* Adds a mapping for requests to fromHost:fromPort so that they are
* actually made to toHost:toPort.
*/
addMapping: function(fromHost, fromPort, toHost, toPort)
{
this._mappings[fromHost + ":" + fromPort] = toHost + ":" + toPort;
},
/**
* Removes a mapping for requests to fromHost:fromPort, if one exists; if
* none exists, this is a no-op.
*/
removeMapping: function(host, port)
{
delete this._mappings[host + ":" + port];
},
/** True if mapping functionality is enabled. */
get isEnabled()
{
return this._enabled;
},
/**
* Enables all registered mappings, or updates mappings if already enabled.
*/
enable: function()
{
if (this._enabled)
{
this.syncMappings();
return;
}
var prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
// Change the proxy autoconfiguration URL first, if it's present
try
{
this._oldPAC = prefs.getCharPref(PROXY_AUTOCONFIG_PREF);
}
catch (e)
{
this._oldPAC = undefined;
}
// Now change the proxy settings to use the PAC URL
try
{
this._oldProxyType = prefs.getIntPref(PROXY_TYPE_PREF);
prefs.setIntPref(PROXY_TYPE_PREF, PROXY_TYPE_USE_PAC);
}
catch (e)
{
this._oldProxyType = 0;
}
this._enabled = true;
this.syncMappings();
},
/**
* Updates URL mappings currently in use with those specified when this was
* enabled.
*
* @throws NS_ERROR_UNEXPECTED
* if this method is called when mapping functionality is not enabled
*/
syncMappings: function()
{
if (!this._enabled)
throw Cr.NS_ERROR_UNEXPECTED;
var url = "data:text/plain,";
url += "function FindProxyForURL(url, host) ";
url += "{ ";
url += " var mappings = " + this._mappings.toSource() + "; ";
url += " var regex = new RegExp('http://(.*?(:\\\\d+)?)/'); ";
url += " var matches = regex.exec(url); ";
url += " var hostport = matches[1], port = matches[2]; ";
url += " if (!port) ";
url += " hostport += ':80'; ";
url += " if (hostport in mappings) ";
url += " return 'PROXY ' + mappings[hostport]; ";
url += " return 'DIRECT'; ";
url += "}";
Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch)
.setCharPref(PROXY_AUTOCONFIG_PREF, url);
},
/** Disables all domain mapping functionality. */
disable: function()
{
if (!this._enabled)
return;
var prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
if (this._oldPAC !== undefined)
prefs.setCharPref(PROXY_AUTOCONFIG_PREF, this._oldPAC);
this._oldPAC = undefined;
prefs.setIntPref(PROXY_TYPE_PREF, this._oldProxyType);
this._oldProxyType = undefined;
this._enabled = false;
}
};
//
// BEGIN CROSS-DOMAIN CODE
//
// Various pieces of code must be able to test functionality when run on
// effectively arbitrary ports, hosts, etc. for cross-domain purposes,
// usually for security. We provide that support here, mapping the desired
// additional host/port pairs onto the original server at localhost:8888.
//
// We have chosen to "take over" the example.org and example.com domains here,
// because per RFC 2606, example.org is reserved for testing and other such
// activities and can be safely "hijacked" for cross-domain testing.
//
// The set of domains chosen here is mostly taken from an IRC conversation
// with bz and from <https://bugzilla.mozilla.org/show_bug.cgi?id=332179>;
// the original set was .org+80, and bz wanted a parallel .com and .org+8000.
//
// This list must be duplicated in runtests.pl.in to set the appropriate
// security preferences to not have to display privilege escalation prompts.
// KEEP THIS LIST IN SYNC WITH THAT ONE!
//
var mappedHostPorts =
[
{host: "example.org", port: 80},
{host: "test1.example.org", port: 80},
{host: "test2.example.org", port: 80},
{host: "sub1.test1.example.org", port: 80},
{host: "sub1.test2.example.org", port: 80},
{host: "sub2.test1.example.org", port: 80},
{host: "sub2.test2.example.org", port: 80},
{host: "example.org", port: 8000},
{host: "test1.example.org", port: 8000},
{host: "test2.example.org", port: 8000},
{host: "sub1.test1.example.org", port: 8000},
{host: "sub1.test2.example.org", port: 8000},
{host: "sub2.test1.example.org", port: 8000},
{host: "sub2.test2.example.org", port: 8000},
{host: "example.com", port: 80},
{host: "test1.example.com", port: 80},
{host: "test2.example.com", port: 80},
{host: "sub1.test1.example.com", port: 80},
{host: "sub1.test2.example.com", port: 80},
{host: "sub2.test1.example.com", port: 80},
{host: "sub2.test2.example.com", port: 80},
];
var crossDomain = new DomainMapper();
for (var i = 0, sz = mappedHostPorts.length; i < sz; i++)
{
var hostPort = mappedHostPorts[i];
crossDomain.addMapping(hostPort.host, hostPort.port, "localhost", 8888);
}
crossDomain.enable();
}
catch (e)
{
throw "privilege failure enabling cross-domain: " + e;
}

View File

@ -99,6 +99,10 @@ function goQuitApplication()
{
return false;
}
// shut down cross-domain mapping (really reverts preference values)
if (crossDomain)
crossDomain.disable();
const kAppStartup = '@mozilla.org/toolkit/app-startup;1';
const kAppShell = '@mozilla.org/appshell/appShellService;1';