Bug 445004. Make the base and document URI of document.written documents be the base and document URI of the document on whose current context our code is running. r+sr=jst, r=dcamp

This commit is contained in:
Boris Zbarsky 2008-11-18 17:54:36 -05:00
parent 7a34f9500d
commit 127c0998fe
28 changed files with 676 additions and 33 deletions

View File

@ -168,6 +168,7 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
#include "nsIProgressEventSink.h"
#include "nsISecurityEventSink.h"
#include "nsIPrompt.h"
#include "nsIPropertyBag2.h"
#include "nsFrameLoader.h"
@ -1880,6 +1881,16 @@ nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
ResetToURI(uri, aLoadGroup, principal);
nsCOMPtr<nsIPropertyBag2> bag = do_QueryInterface(aChannel);
if (bag) {
nsCOMPtr<nsIURI> baseURI;
bag->GetPropertyAsInterface(NS_LITERAL_STRING("baseURI"),
NS_GET_IID(nsIURI), getter_AddRefs(baseURI));
if (baseURI) {
mDocumentBaseURI = baseURI;
}
}
mChannel = aChannel;
}

View File

@ -91,6 +91,8 @@ _TEST_FILES = test_bug5141.html \
test_bug254337.html \
test_bug276037-1.html \
test_bug276037-2.xhtml \
test_bug298064.html \
bug298064-subframe.html \
test_bug308484.html \
test_bug311681.xml \
test_bug322317.html \

View File

@ -0,0 +1,24 @@
<!DOCTYPE HTML>
<html>
<head>
<script>
function test_func() {
var bar = new Option();
top.is(bar.ownerDocument, document,
"Unexpected document for our new option");
bar = new Image();
top.is(bar.ownerDocument, document,
"Unexpected document for our new image");
bar = new top.Option();
top.is(bar.ownerDocument, top.document,
"Unexpected document for top new option");
bar = new top.Image();
top.is(bar.ownerDocument, top.document,
"Unexpected document for top new image");
top.isnot(top.document, document, "Documents should be different");
}
</script>
</head>
<html>

View File

@ -0,0 +1,33 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=298064
-->
<head>
<title>Test for Bug 298064</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=298064">Mozilla Bug 298064</a>
<p id="display"><iframe src="bug298064-subframe.html"></iframe></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 298064 **/
SimpleTest.waitForExplicitFinish()
addLoadEvent(function() {
window.frames[0].test_func();
});
addLoadEvent(SimpleTest.finish);
</script>
</pre>
</body>
</html>

View File

@ -1820,10 +1820,13 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
do_QueryInterface(nsContentUtils::GetDocumentFromContext());
// Grab a reference to the calling documents security info (if any)
// and principal as it may be lost in the call to Reset().
// and URIs as they may be lost in the call to Reset().
nsCOMPtr<nsISupports> securityInfo;
nsCOMPtr<nsIURI> uri, baseURI;
if (callerDoc) {
securityInfo = callerDoc->GetSecurityInfo();
uri = callerDoc->GetDocumentURI();
baseURI = callerDoc->GetBaseURI();
}
nsCOMPtr<nsIPrincipal> callerPrincipal;
@ -1854,18 +1857,6 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
return NS_ERROR_DOM_SECURITY_ERR;
}
// The URI for the document after this call. Get it from the calling
// principal (if available), or set it to "about:blank" if no
// principal is reachable.
nsCOMPtr<nsIURI> uri;
callerPrincipal->GetURI(getter_AddRefs(uri));
if (!uri) {
rv = NS_NewURI(getter_AddRefs(uri),
NS_LITERAL_CSTRING("about:blank"));
NS_ENSURE_SUCCESS(rv, rv);
}
// Stop current loads targeted at the window this document is in.
if (mScriptGlobalObject) {
nsCOMPtr<nsIContentViewer> cv;
@ -1897,6 +1888,9 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
return rv;
}
// We can't depend on channels implementing property bags, so do our
// base URI manually after reset.
// Set the caller principal, if any, on the channel so that we'll
// make sure to use it when we reset.
rv = channel->SetOwner(callerPrincipal);
@ -1969,6 +1963,9 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
// null.
Reset(channel, group);
if (baseURI) {
mDocumentBaseURI = baseURI;
}
if (root) {
// Tear down the frames for the root element.

View File

@ -46,6 +46,7 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_bug1682.html \
test_bug1823.html \
test_bug57600.html \
test_bug196523.html \
bug196523-subframe.html \
test_bug199692.html \
@ -73,6 +74,12 @@ _TEST_FILES = test_bug1682.html \
test_form-parsing.html \
test_viewport.html \
test_documentAll.html \
test_bug445004.html \
bug445004-inner.js \
bug445004-outer-rel.html \
bug445004-outer-abs.html \
bug445004-outer-write.html \
bug445004-inner.html \
test_bug448564.html \
bug448564-iframe-1.html \
bug448564-iframe-2.html \

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<base href="http://test1.example.org/tests/content/html/document/test/bug445004-inner.html">
<script src="bug445004-inner.js"></script>
</head>
<body>
<iframe name="w" id="w" width="100" height="100"></iframe>
<iframe name="x" id="x" width="100" height="100"></iframe>
<iframe name="y" id="y" width="100" height="100"></iframe>
<iframe name="z" id="z" width="100" height="100"></iframe>
<img src="test1.example.org.png">
</body>
</html>

View File

@ -0,0 +1,23 @@
document.domain = "example.org";
function $(str) { return document.getElementById(str); }
function hookLoad(str) {
$(str).onload = function() { window.parent.parent.postMessage('end', '*'); };
window.parent.parent.postMessage('start', '*');
}
window.onload = function() {
hookLoad("w");
$("w").contentWindow.location.href = "test1.example.org.png";
hookLoad("x");
var doc = $("x").contentDocument;
doc.write('<img src="test1.example.org.png">');
doc.close();
};
function doIt() {
hookLoad("y");
$("y").contentWindow.location.href = "example.org.png";
hookLoad("z");
var doc = $("z").contentDocument;
doc.write('<img src="example.org.png">');
doc.close();
}
window.addEventListener("message", doIt, false);

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<base href="http://example.org/tests/content/html/document/test/bug445004-outer.html">
<script>document.domain = "example.org"</script>
</head>
<body>
<iframe width="500" height="200" src="http://test1.example.org/tests/content/html/document/test/bug445004-inner.html"
onload="window.frames[0].doIt()"></iframe>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<base href="http://example.org/tests/content/html/document/test/bug445004-outer.html">
<script>document.domain = "example.org"</script>
</head>
<body>
<iframe width="500" height="200" src="bug445004-inner.html"
onload="window.frames[0].doIt()"></iframe>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<base href="http://example.org/tests/content/html/document/test/bug445004-outer.html">
<script>document.domain = "example.org"</script>
</head>
<body>
<iframe width="500" height="200" src="javascript:&quot;<!DOCTYPE html> <html> <script> function $(str) { return document.getElementById(str); } function hookLoad(str) { $(str).onload = function() { window.parent.parent.postMessage('end', '*'); }; window.parent.parent.postMessage('start', '*'); } window.onload = function() { hookLoad(\&quot;w\&quot;); $(\&quot;w\&quot;).contentWindow.location.href = \&quot;example.org.png\&quot;; hookLoad(\&quot;x\&quot;); var doc = $(\&quot;x\&quot;).contentDocument; doc.write('<img src=\&quot;example.org.png\&quot;>'); doc.close(); }; function doIt() { hookLoad(\&quot;y\&quot;); $(\&quot;y\&quot;).contentWindow.location.href = \&quot;example.org.png\&quot;; hookLoad(\&quot;z\&quot;); var doc = $(\&quot;z\&quot;).contentDocument; doc.write('<img src=\&quot;example.org.png\&quot;>'); doc.close(); } </script> <body> <iframe name=\&quot;w\&quot; id=\&quot;w\&quot; width=\&quot;100\&quot; height=\&quot;100\&quot;></iframe> <iframe name=\&quot;x\&quot; id=\&quot;x\&quot; width=\&quot;100\&quot; height=\&quot;100\&quot;></iframe> <iframe name=\&quot;y\&quot; id=\&quot;y\&quot; width=\&quot;100\&quot; height=\&quot;100\&quot;></iframe> <iframe name=\&quot;z\&quot; id=\&quot;z\&quot; width=\&quot;100\&quot; height=\&quot;100\&quot;></iframe><img src=\&quot;example.org.png\&quot;> </body> </html>&quot; "
onload="window.frames[0].doIt();"></iframe>
</body>
</html>

View File

@ -0,0 +1,139 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=445004
-->
<head>
<title>Test for Bug 445004</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=445004">Mozilla Bug 445004</a>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 445004 **/
is(window.location.hostname, "localhost", "Unexpected hostname");
is(window.location.port, "8888", "Unexpected port; fix testcase");
SimpleTest.waitForExplicitFinish();
var loads = 0;
function loadStarted() {
++loads;
}
function loadEnded() {
--loads;
if (loads == 0) {
doTest();
}
}
function getMessage(evt) {
ok(evt.data == "start" || evt.data == "end", "Must have start or end");
if (evt.data == "start")
loadStarted();
else
loadEnded();
}
window.addEventListener("message", getMessage, false);
function checkURI(uri, name, type) {
var host = uri.match(/^http:\/\/([a-z.0-9]*)/)[1];
var file = uri.match(/([^\/]*).png$/)[1];
is(host, file, "Unexpected base URI for test " + name +
" when testing " + type);
}
function checkFrame(num) {
// Just snarf our data
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var outer = window.frames[num]
name = outer.name;
is(outer.document.baseURI,
"http://example.org/tests/content/html/document/test/bug445004-outer.html",
"Unexpected base URI for " + name);
var iswrite = name.match(/write/);
var inner = outer.frames[0];
if (iswrite) {
is(inner.document.baseURI,
"http://example.org/tests/content/html/document/test/bug445004-outer.html",
"Unexpected inner base URI for " + name);
} else {
is(inner.document.baseURI,
"http://test1.example.org/tests/content/html/document/test/bug445004-inner.html",
"Unexpected inner base URI for " + name);
}
var isrel = name.match(/rel/);
var offsite = name.match(/offsite/);
if (!iswrite) {
if ((isrel && !offsite) || (!isrel && offsite)) {
is(inner.location.hostname, outer.location.hostname,
"Unexpected hostnames for " + name);
} else {
isnot(inner.location.hostname, outer.location.hostname,
"Unexpected hostnames for " + name);
}
}
checkURI(inner.frames[0].location.href, name, "direct location");
checkURI(inner.frames[1].document.getElementsByTagName("img")[0].src,
name, "direct write");
if (!iswrite) {
is(inner.frames[1].location.hostname, inner.location.hostname,
"Incorrect hostname for " + name + " direct write")
}
checkURI(inner.frames[2].location.href, name, "indirect location");
checkURI(inner.frames[3].document.getElementsByTagName("img")[0].src,
name, "indirect write");
if (!iswrite) {
is(inner.frames[3].location.hostname, outer.location.hostname,
"Incorrect hostname for " + name + " indirect write")
}
checkURI(inner.document.getElementsByTagName("img")[0].src,
name, "direct image load");
}
function doTest() {
for (var num = 0; num < 5; ++num) {
checkFrame(num);
}
SimpleTest.finish();
}
</script>
</pre>
<p id="display">
<iframe
src="http://example.org/tests/content/html/document/test/bug445004-outer-rel.html"
name="bug445004-outer-rel.html"></iframe>
<iframe
src="http://test1.example.org/tests/content/html/document/test/bug445004-outer-rel.html">
name="bug445004-outer-rel.html offsite"></iframe>
<iframe
src="http://example.org/tests/content/html/document/test/bug445004-outer-abs.html">
name="bug445004-outer-abs.html"></iframe>
<iframe
src="http://test1.example.org/tests/content/html/document/test/bug445004-outer-abs.html"
name="bug445004-outer-abs.html offsite"></iframe>
<iframe
src="http://example.org/tests/content/html/document/test/bug445004-outer-write.html"
name="bug445004-outer-write.html"></iframe>
</p>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=57600
-->
<head>
<title>Test for Bug 57600</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=57600">Mozilla Bug 57600</a>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 57600 **/
SimpleTest.waitForExplicitFinish();
var count = 0;
function disp(win) {
var d = win ? win.document : self.testname.document;
var str = 'You should see this';
d.open();
d.write(str);
d.close();
is(d.documentElement.textContent, str, "Unexpected text");
if (++count == 2) {
SimpleTest.finish();
}
}
</script>
</pre>
<p id="display">
<iframe src="javascript:'<body onload=&quot;this.onerror = parent.onerror; parent.disp(self)&quot;></body>'">
</iframe>
<iframe name="testname" src="javascript:'<body onload=&quot;this.onerror = parent.onerror; parent.disp()&quot;></body>'">
</iframe>
</p>
</body>
</html>

View File

@ -244,7 +244,9 @@ nsLocation::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
// Walk up the docshell hierarchy and find a usable base URI. Basically
// anything that would allow a relative uri.
// XXXbz we don't need this for javascript: URIs anymore. Do we need
// it for about:blank? I would think that we don't, and that we can
// nuke this code.
nsresult
nsLocation::FindUsableBaseURI(nsIURI * aBaseURI, nsIDocShell * aParent,
nsIURI ** aUsableURI)

View File

@ -75,6 +75,11 @@
#include "nsIJSContextStack.h"
#include "nsIScriptChannel.h"
#include "nsIDocument.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsIWritablePropertyBag2.h"
static NS_DEFINE_CID(kJSURICID, NS_JSURI_CID);
class nsJSThunk : public nsIInputStream
{
@ -383,7 +388,8 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
class nsJSChannel : public nsIChannel,
public nsIStreamListener,
public nsIScriptChannel
public nsIScriptChannel,
public nsIPropertyBag2
{
public:
nsJSChannel();
@ -394,6 +400,8 @@ public:
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSISCRIPTCHANNEL
NS_FORWARD_SAFE_NSIPROPERTYBAG(mPropertyBag)
NS_FORWARD_SAFE_NSIPROPERTYBAG2(mPropertyBag)
nsresult Init(nsIURI *aURI);
@ -411,6 +419,7 @@ protected:
protected:
nsCOMPtr<nsIChannel> mStreamChannel;
nsCOMPtr<nsIPropertyBag2> mPropertyBag;
nsCOMPtr<nsIStreamListener> mListener; // Our final listener
nsCOMPtr<nsISupports> mContext; // The context passed to AsyncOpen
nsCOMPtr<nsPIDOMWindow> mOriginalInnerWindow; // The inner window our load
@ -464,7 +473,10 @@ nsresult nsJSChannel::StopAll()
nsresult nsJSChannel::Init(nsIURI *aURI)
{
nsresult rv;
nsRefPtr<nsJSURI> jsURI;
nsresult rv = aURI->QueryInterface(kJSURICID,
getter_AddRefs(jsURI));
NS_ENSURE_SUCCESS(rv, rv);
// Create the nsIStreamIO layer used by the nsIStreamIOChannel.
mIOThunk = new nsJSThunk();
@ -485,6 +497,13 @@ nsresult nsJSChannel::Init(nsIURI *aURI)
rv = mIOThunk->Init(aURI);
if (NS_SUCCEEDED(rv)) {
mStreamChannel = channel;
mPropertyBag = do_QueryInterface(channel);
nsCOMPtr<nsIWritablePropertyBag2> writableBag =
do_QueryInterface(channel);
if (writableBag && jsURI->GetBaseURI()) {
writableBag->SetPropertyAsInterface(NS_LITERAL_STRING("baseURI"),
jsURI->GetBaseURI());
}
}
return rv;
@ -494,17 +513,9 @@ nsresult nsJSChannel::Init(nsIURI *aURI)
// nsISupports implementation...
//
NS_IMPL_ADDREF(nsJSChannel)
NS_IMPL_RELEASE(nsJSChannel)
NS_INTERFACE_MAP_BEGIN(nsJSChannel)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChannel)
NS_INTERFACE_MAP_ENTRY(nsIRequest)
NS_INTERFACE_MAP_ENTRY(nsIChannel)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIScriptChannel)
NS_INTERFACE_MAP_END
NS_IMPL_ISUPPORTS7(nsJSChannel, nsIChannel, nsIRequest, nsIRequestObserver,
nsIStreamListener, nsIScriptChannel, nsIPropertyBag,
nsIPropertyBag2)
//
// nsIRequest implementation...
@ -1164,7 +1175,7 @@ nsJSProtocolHandler::GetProtocolFlags(PRUint32 *result)
NS_IMETHODIMP
nsJSProtocolHandler::NewURI(const nsACString &aSpec,
const char *aCharset, // ignore charset info
const char *aCharset,
nsIURI *aBaseURI,
nsIURI **result)
{
@ -1174,8 +1185,7 @@ nsJSProtocolHandler::NewURI(const nsACString &aSpec,
// provided by standard URLs, so there is no "outer" object given to
// CreateInstance.
nsIURI* url;
rv = CallCreateInstance(NS_SIMPLEURI_CONTRACTID, &url);
nsCOMPtr<nsIURI> url = do_CreateInstance(NS_SIMPLEURI_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
@ -1194,11 +1204,13 @@ nsJSProtocolHandler::NewURI(const nsACString &aSpec,
}
if (NS_FAILED(rv)) {
NS_RELEASE(url);
return rv;
}
*result = url;
*result = new nsJSURI(aBaseURI, url);
NS_ENSURE_TRUE(*result, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*result);
return rv;
}
@ -1233,3 +1245,149 @@ nsJSProtocolHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval
return NS_OK;
}
////////////////////////////////////////////////////////////
// nsJSURI implementation
NS_IMPL_ADDREF(nsJSURI)
NS_IMPL_RELEASE(nsJSURI)
NS_INTERFACE_MAP_BEGIN(nsJSURI)
NS_INTERFACE_MAP_ENTRY(nsIURI)
NS_INTERFACE_MAP_ENTRY(nsISerializable)
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
NS_INTERFACE_MAP_ENTRY(nsIMutable)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURI)
if (aIID.Equals(kJSURICID))
foundInterface = static_cast<nsIURI*>(this);
else
NS_INTERFACE_MAP_END
// nsISerializable methods:
NS_IMETHODIMP
nsJSURI::Read(nsIObjectInputStream* aStream)
{
nsresult rv;
rv = aStream->ReadObject(PR_TRUE, getter_AddRefs(mSimpleURI));
if (NS_FAILED(rv)) return rv;
mMutable = do_QueryInterface(mSimpleURI);
NS_ENSURE_TRUE(mMutable, NS_ERROR_UNEXPECTED);
PRBool haveBase;
rv = aStream->ReadBoolean(&haveBase);
if (NS_FAILED(rv)) return rv;
if (haveBase) {
rv = aStream->ReadObject(PR_TRUE, getter_AddRefs(mBaseURI));
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}
NS_IMETHODIMP
nsJSURI::Write(nsIObjectOutputStream* aStream)
{
nsresult rv;
rv = aStream->WriteObject(mSimpleURI, PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = aStream->WriteBoolean(mBaseURI != nsnull);
if (NS_FAILED(rv)) return rv;
if (mBaseURI) {
rv = aStream->WriteObject(mBaseURI, PR_TRUE);
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}
// nsIURI methods:
NS_IMETHODIMP
nsJSURI::Clone(nsIURI** aClone)
{
nsCOMPtr<nsIURI> simpleClone;
nsresult rv = mSimpleURI->Clone(getter_AddRefs(simpleClone));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> baseClone;
if (mBaseURI) {
rv = mBaseURI->Clone(getter_AddRefs(baseClone));
NS_ENSURE_SUCCESS(rv, rv);
}
nsIURI* newURI = new nsJSURI(baseClone, simpleClone);
NS_ENSURE_TRUE(newURI, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aClone = newURI);
return NS_OK;
}
// nsIClassInfo methods:
NS_IMETHODIMP
nsJSURI::GetInterfaces(PRUint32 *count, nsIID * **array)
{
*count = 0;
*array = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsJSURI::GetHelperForLanguage(PRUint32 language, nsISupports **_retval)
{
*_retval = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsJSURI::GetContractID(char * *aContractID)
{
// Make sure to modify any subclasses as needed if this ever
// changes.
*aContractID = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsJSURI::GetClassDescription(char * *aClassDescription)
{
*aClassDescription = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsJSURI::GetClassID(nsCID * *aClassID)
{
// Make sure to modify any subclasses as needed if this ever
// changes to not call the virtual GetClassIDNoAlloc.
*aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
if (!*aClassID)
return NS_ERROR_OUT_OF_MEMORY;
return GetClassIDNoAlloc(*aClassID);
}
NS_IMETHODIMP
nsJSURI::GetImplementationLanguage(PRUint32 *aImplementationLanguage)
{
*aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
return NS_OK;
}
NS_IMETHODIMP
nsJSURI::GetFlags(PRUint32 *aFlags)
{
*aFlags = nsIClassInfo::MAIN_THREAD_ONLY;
return NS_OK;
}
NS_IMETHODIMP
nsJSURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
{
*aClassIDNoAlloc = kJSURICID;
return NS_OK;
}

View File

@ -40,6 +40,10 @@
#include "nsIProtocolHandler.h"
#include "nsITextToSubURI.h"
#include "nsIURI.h"
#include "nsIMutable.h"
#include "nsISerializable.h"
#include "nsIClassInfo.h"
#define NS_JSPROTOCOLHANDLER_CID \
{ /* bfc310d2-38a0-11d3-8cd3-0060b0fc14a3 */ \
@ -49,6 +53,14 @@
{0x8c, 0xd3, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
}
#define NS_JSURI_CID \
{ /* 58f089ee-512a-42d2-a935-d0c874128930 */ \
0x58f089ee, \
0x512a, \
0x42d2, \
{0xa9, 0x35, 0xd0, 0xc8, 0x74, 0x12, 0x89, 0x30} \
}
#define NS_JSPROTOCOLHANDLER_CONTRACTID \
NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "javascript"
@ -78,4 +90,57 @@ protected:
nsCOMPtr<nsITextToSubURI> mTextToSubURI;
};
// Use an extra base object to avoid having to manually retype all the
// nsIURI methods. I wish we could just inherit from nsSimpleURI instead.
class nsJSURI_base : public nsIURI,
public nsIMutable
{
public:
nsJSURI_base(nsIURI* aSimpleURI) :
mSimpleURI(aSimpleURI)
{
mMutable = do_QueryInterface(mSimpleURI);
NS_ASSERTION(aSimpleURI && mMutable, "This isn't going to work out");
}
virtual ~nsJSURI_base() {}
// For use only from deserialization
nsJSURI_base() {}
NS_FORWARD_NSIURI(mSimpleURI->)
NS_FORWARD_NSIMUTABLE(mMutable->)
protected:
nsCOMPtr<nsIURI> mSimpleURI;
nsCOMPtr<nsIMutable> mMutable;
};
class nsJSURI : public nsJSURI_base,
public nsISerializable,
public nsIClassInfo
{
public:
nsJSURI(nsIURI* aBaseURI, nsIURI* aSimpleURI) :
nsJSURI_base(aSimpleURI), mBaseURI(aBaseURI)
{}
virtual ~nsJSURI() {}
// For use only from deserialization
nsJSURI() : nsJSURI_base() {}
NS_DECL_ISUPPORTS
NS_DECL_NSISERIALIZABLE
NS_DECL_NSICLASSINFO
// Override Clone()
NS_IMETHOD Clone(nsIURI** aClone);
nsIURI* GetBaseURI() const {
return mBaseURI;
}
private:
nsCOMPtr<nsIURI> mBaseURI;
};
#endif /* nsJSProtocolHandler_h___ */

View File

@ -125,6 +125,7 @@
#include "nsITimelineService.h"
#include "nsGfxCIID.h"
#include "nsStyleSheetService.h"
#include "ImageErrors.h"
#include "nsIPrompt.h"
#include "imgIContainer.h" // image animation mode constants
@ -963,7 +964,12 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
// Now, fire either an OnLoad or OnError event to the document...
PRBool restoring = PR_FALSE;
if(NS_SUCCEEDED(aStatus) && window) {
// XXXbz imagelib kills off the document load for a full-page image with
// NS_IMAGELIB_ERROR_LOAD_ABORTED if it's in the cache. So we want to treat
// that one as a success code; otherwise whether we fire onload for the image
// will depend on whether it's cached!
if(window &&
(NS_SUCCEEDED(aStatus) || aStatus == NS_IMAGELIB_ERROR_LOAD_ABORTED)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE, NS_LOAD);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;

View File

@ -540,6 +540,8 @@ MAKE_CTOR(CreateCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D, NS_New
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStyleSheetService, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSURI)
// views are not refcounted, so this is the same as
// NS_GENERIC_FACTORY_CONSTRUCTOR without the NS_ADDREF/NS_RELEASE
#define NS_GENERIC_FACTORY_CONSTRUCTOR_NOREFS(_InstanceClass) \
@ -1255,6 +1257,10 @@ static const nsModuleComponentInfo gComponents[] = {
NS_JSPROTOCOLHANDLER_CID,
NS_JSPROTOCOLHANDLER_CONTRACTID,
nsJSProtocolHandler::Create },
{ "JavaScript URI",
NS_JSURI_CID,
nsnull,
nsJSURIConstructor },
{ "Window Command Table",
NS_WINDOWCOMMANDTABLE_CID,
"",

View File

@ -0,0 +1,4 @@
<!DOCTYPE html>
<body>
<iframe width="500" height="200" src="subdir/445004-ref-subframe.html"></iframe>
</body>

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
var loads = 0;
function loadStarted() {
++loads;
}
function loadEnded() {
--loads;
if (loads == 0) {
document.documentElement.className = "";
}
}
loadStarted();
window.onload = function() {
if (location.protocol != 'file:') {
var txt = document.createTextNode('Must be run from file://');
var div = document.createElement("div");
div.appendChild(txt);
document.body.appendChild(div);
}
loadEnded();
}
</script>
</head>
<body>
<iframe width="500" height="200" src="subdir/445004-subframe.html"
onload="window.frames[0].doIt();"></iframe>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -918,6 +918,7 @@ fails == 441259-2.html 441259-2-ref.html # bug 441400
== 444928-1.html 444928-1-ref.html
== 444928-2.html 444928-2-ref.html
!= 444928-3.html 444928-3-notref.html
== 445004-1.html 445004-1-ref.html
== 446100-1a.html about:blank
== 446100-1b.html about:blank
== 446100-1c.html about:blank

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<body>
<iframe name="w" width="100" height="100" src="passinner.png"></iframe>
<iframe name="x" width="100" height="100" src="445004-ref-subsubframe.html"></iframe>
<iframe name="y" width="100" height="100" src="passinner.png"></iframe>
<iframe name="z" width="100" height="100" src="445004-ref-subsubframe.html"></iframe>
<img src="passinner.png">
</body>

View File

@ -0,0 +1 @@
<img src="passinner.png">

View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<script>
function $(str) { return document.getElementById(str); }
function hookLoad(str) {
$(str).onload = function() { window.parent.loadEnded(); };
window.parent.loadStarted();
}
window.onload = function() {
hookLoad("w");
$("w").contentWindow.location.href = "passinner.png";
hookLoad("x");
var doc = $("x").contentDocument;
doc.write('<img src="passinner.png">');
doc.close();
};
function doIt() {
hookLoad("y");
$("y").contentWindow.location.href = "passouter.png";
hookLoad("z");
var doc = $("z").contentDocument;
doc.write('<img src="passouter.png">');
doc.close();
}
</script>
</head>
<body>
<iframe name="w" id="w" width="100" height="100"></iframe>
<iframe name="x" id="x" width="100" height="100"></iframe>
<iframe name="y" id="y" width="100" height="100"></iframe>
<iframe name="z" id="z" width="100" height="100"></iframe>
<img src="passinner.png">
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B