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 diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -163,16 +163,17 @@ static NS_DEFINE_CID(kDOMEventGroupCID, #include "nsIContentViewer.h" #include "nsIXMLContentSink.h" #include "nsIChannelEventSink.h" #include "nsContentErrors.h" #include "nsIXULDocument.h" #include "nsIProgressEventSink.h" #include "nsISecurityEventSink.h" #include "nsIPrompt.h" +#include "nsIPropertyBag2.h" #include "nsFrameLoader.h" #include "mozAutoDocUpdate.h" #ifdef MOZ_LOGGING // so we can get logging even in release builds @@ -1875,16 +1876,26 @@ nsDocument::Reset(nsIChannel* aChannel, if (securityManager) { securityManager->GetChannelPrincipal(aChannel, getter_AddRefs(principal)); } } ResetToURI(uri, aLoadGroup, principal); + nsCOMPtr bag = do_QueryInterface(aChannel); + if (bag) { + nsCOMPtr baseURI; + bag->GetPropertyAsInterface(NS_LITERAL_STRING("baseURI"), + NS_GET_IID(nsIURI), getter_AddRefs(baseURI)); + if (baseURI) { + mDocumentBaseURI = baseURI; + } + } + mChannel = aChannel; } void nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, nsIPrincipal* aPrincipal) { NS_PRECONDITION(aURI, "Null URI passed to ResetToURI"); diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -86,16 +86,18 @@ _TEST_FILES = test_bug5141.html \ test_bug218236.html \ file_bug218236_multipart.txt \ file_bug218236_multipart.txt^headers^ \ test_bug218277.html \ test_bug238409.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 \ test_bug330925.xhtml \ test_bug337631.html \ test_bug338541.xhtml \ test_bug338679.html \ test_bug339494.html \ diff --git a/content/base/test/bug298064-subframe.html b/content/base/test/bug298064-subframe.html new file mode 100644 --- /dev/null +++ b/content/base/test/bug298064-subframe.html @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/content/base/test/test_bug298064.html b/content/base/test/test_bug298064.html new file mode 100644 --- /dev/null +++ b/content/base/test/test_bug298064.html @@ -0,0 +1,33 @@ + + + + + Test for Bug 298064 + + + + + +Mozilla Bug 298064 +

+ +
+
+
+ + diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1815,20 +1815,23 @@ nsHTMLDocument::OpenCommon(const nsACStr // Note: We want to use GetDocumentFromContext here because this document // should inherit the security information of the document that's opening us, // (since if it's secure, then it's presumeably trusted). nsCOMPtr callerDoc = 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 securityInfo; + nsCOMPtr uri, baseURI; if (callerDoc) { securityInfo = callerDoc->GetSecurityInfo(); + uri = callerDoc->GetDocumentURI(); + baseURI = callerDoc->GetBaseURI(); } nsCOMPtr callerPrincipal; nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager(); secMan->GetSubjectPrincipal(getter_AddRefs(callerPrincipal)); if (!callerPrincipal) { @@ -1849,28 +1852,16 @@ nsHTMLDocument::OpenCommon(const nsACStr // thing to do anyways. PRBool equals = PR_FALSE; if (NS_FAILED(callerPrincipal->Equals(NodePrincipal(), &equals)) || !equals) { 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 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 cv; shell->GetContentViewer(getter_AddRefs(cv)); if (cv) { PRBool okToUnload; rv = cv->PermitUnload(&okToUnload); @@ -1891,16 +1882,19 @@ nsHTMLDocument::OpenCommon(const nsACStr nsCOMPtr channel; nsCOMPtr group = do_QueryReferent(mDocumentLoadGroup); rv = NS_NewChannel(getter_AddRefs(channel), uri, nsnull, group); if (NS_FAILED(rv)) { 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); NS_ENSURE_SUCCESS(rv, rv); // Before we reset the doc notify the globalwindow of the change, // but only if we still have a window (i.e. our window object the @@ -1964,16 +1958,19 @@ nsHTMLDocument::OpenCommon(const nsACStr // Call Reset(), this will now do the full reset, except removing // the root from the document, doing that confuses the scrollbar // code in mozilla since the document in the root element and all // the anonymous content (i.e. scrollbar elements) is set to // null. Reset(channel, group); + if (baseURI) { + mDocumentBaseURI = baseURI; + } if (root) { // Tear down the frames for the root element. MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_MODEL, PR_TRUE); nsNodeUtils::ContentRemoved(this, root, 0); // Put the root element back into the document, we don't notify // the document about this insertion since the sink will do that diff --git a/content/html/document/test/Makefile.in b/content/html/document/test/Makefile.in --- a/content/html/document/test/Makefile.in +++ b/content/html/document/test/Makefile.in @@ -41,16 +41,17 @@ VPATH = @srcdir@ VPATH = @srcdir@ relativesrcdir = content/html/document/test include $(DEPTH)/config/autoconf.mk 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 \ bug199692-nested.html \ bug199692-nested-d2.html \ bug199692-popup.html \ bug199692-scrolled.html \ test_bug172261.html \ @@ -68,16 +69,22 @@ _TEST_FILES = test_bug1682.html \ test_bug391777.html \ test_bug402680.html \ test_bug403868.html \ test_bug403868.xhtml \ test_bug404320.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 \ bug448564-iframe-3.html \ bug448564-echo.sjs \ bug448564-submit.js \ $(NULL) diff --git a/content/html/document/test/bug445004-inner.html b/content/html/document/test/bug445004-inner.html new file mode 100644 --- /dev/null +++ b/content/html/document/test/bug445004-inner.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/content/html/document/test/bug445004-inner.js b/content/html/document/test/bug445004-inner.js new file mode 100644 --- /dev/null +++ b/content/html/document/test/bug445004-inner.js @@ -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(''); + doc.close(); +}; +function doIt() { + hookLoad("y"); + $("y").contentWindow.location.href = "example.org.png"; + hookLoad("z"); + var doc = $("z").contentDocument; + doc.write(''); + doc.close(); +} +window.addEventListener("message", doIt, false); \ No newline at end of file diff --git a/content/html/document/test/bug445004-outer-abs.html b/content/html/document/test/bug445004-outer-abs.html new file mode 100644 --- /dev/null +++ b/content/html/document/test/bug445004-outer-abs.html @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/content/html/document/test/bug445004-outer-rel.html b/content/html/document/test/bug445004-outer-rel.html new file mode 100644 --- /dev/null +++ b/content/html/document/test/bug445004-outer-rel.html @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/content/html/document/test/bug445004-outer-write.html b/content/html/document/test/bug445004-outer-write.html new file mode 100644 --- /dev/null +++ b/content/html/document/test/bug445004-outer-write.html @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/content/html/document/test/test_bug445004.html b/content/html/document/test/test_bug445004.html new file mode 100644 --- /dev/null +++ b/content/html/document/test/test_bug445004.html @@ -0,0 +1,139 @@ + + + + + Test for Bug 445004 + + + + + +Mozilla Bug 445004 + +
+
+
+

+ + + + + +

+ + diff --git a/content/html/document/test/test_bug57600.html b/content/html/document/test/test_bug57600.html new file mode 100644 --- /dev/null +++ b/content/html/document/test/test_bug57600.html @@ -0,0 +1,43 @@ + + + + + Test for Bug 57600 + + + + + +Mozilla Bug 57600 + +
+
+
+

+ + +

+ + diff --git a/dom/src/base/nsLocation.cpp b/dom/src/base/nsLocation.cpp --- a/dom/src/base/nsLocation.cpp +++ b/dom/src/base/nsLocation.cpp @@ -239,17 +239,19 @@ nsLocation::CheckURL(nsIURI* aURI, nsIDo loadInfo.swap(*aLoadInfo); return NS_OK; } // 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) { if (!aBaseURI || !aParent) return NS_ERROR_FAILURE; NS_ENSURE_ARG_POINTER(aUsableURI); diff --git a/dom/src/jsurl/nsJSProtocolHandler.cpp b/dom/src/jsurl/nsJSProtocolHandler.cpp --- a/dom/src/jsurl/nsJSProtocolHandler.cpp +++ b/dom/src/jsurl/nsJSProtocolHandler.cpp @@ -70,16 +70,21 @@ #include "nsIContentViewer.h" #include "nsIXPConnect.h" #include "nsContentUtils.h" #include "nsJSUtils.h" #include "nsThreadUtils.h" #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 { public: nsJSThunk(); NS_DECL_ISUPPORTS NS_FORWARD_SAFE_NSIINPUTSTREAM(mInnerStream) @@ -378,27 +383,30 @@ nsresult nsJSThunk::EvaluateScript(nsICh return rv; } //////////////////////////////////////////////////////////////////////////////// class nsJSChannel : public nsIChannel, public nsIStreamListener, - public nsIScriptChannel + public nsIScriptChannel, + public nsIPropertyBag2 { public: nsJSChannel(); NS_DECL_ISUPPORTS NS_DECL_NSIREQUEST NS_DECL_NSICHANNEL NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER NS_DECL_NSISCRIPTCHANNEL + NS_FORWARD_SAFE_NSIPROPERTYBAG(mPropertyBag) + NS_FORWARD_SAFE_NSIPROPERTYBAG2(mPropertyBag) nsresult Init(nsIURI *aURI); // Actually evaluate the script. void EvaluateScript(); protected: virtual ~nsJSChannel(); @@ -406,16 +414,17 @@ protected: nsresult StopAll(); void NotifyListener(); void CleanupStrongRefs(); protected: nsCOMPtr mStreamChannel; + nsCOMPtr mPropertyBag; nsCOMPtr mListener; // Our final listener nsCOMPtr mContext; // The context passed to AsyncOpen nsCOMPtr mOriginalInnerWindow; // The inner window our load // started against. // If we blocked onload on a document in AsyncOpen, this is the document we // did it on. nsCOMPtr mDocumentOnloadBlockedOn; @@ -459,17 +468,20 @@ nsresult nsJSChannel::StopAll() rv = webNav->Stop(nsIWebNavigation::STOP_ALL); } return rv; } nsresult nsJSChannel::Init(nsIURI *aURI) { - nsresult rv; + nsRefPtr 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(); if (!mIOThunk) return NS_ERROR_OUT_OF_MEMORY; // Create a stock input stream channel... // Remember, until AsyncOpen is called, the script will not be evaluated @@ -480,36 +492,35 @@ nsresult nsJSChannel::Init(nsIURI *aURI) // treat it as html. rv = NS_NewInputStreamChannel(getter_AddRefs(channel), aURI, mIOThunk, NS_LITERAL_CSTRING("text/html")); if (NS_FAILED(rv)) return rv; rv = mIOThunk->Init(aURI); if (NS_SUCCEEDED(rv)) { mStreamChannel = channel; + mPropertyBag = do_QueryInterface(channel); + nsCOMPtr writableBag = + do_QueryInterface(channel); + if (writableBag && jsURI->GetBaseURI()) { + writableBag->SetPropertyAsInterface(NS_LITERAL_STRING("baseURI"), + jsURI->GetBaseURI()); + } } return rv; } // // 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... // NS_IMETHODIMP nsJSChannel::GetName(nsACString &aResult) { @@ -1159,28 +1170,27 @@ nsJSProtocolHandler::GetProtocolFlags(PR { *result = URI_NORELATIVE | URI_NOAUTH | URI_INHERITS_SECURITY_CONTEXT | URI_LOADABLE_BY_ANYONE | URI_NON_PERSISTABLE; return NS_OK; } NS_IMETHODIMP nsJSProtocolHandler::NewURI(const nsACString &aSpec, - const char *aCharset, // ignore charset info + const char *aCharset, nsIURI *aBaseURI, nsIURI **result) { nsresult rv; // javascript: URLs (currently) have no additional structure beyond that // provided by standard URLs, so there is no "outer" object given to // CreateInstance. - nsIURI* url; - rv = CallCreateInstance(NS_SIMPLEURI_CONTRACTID, &url); + nsCOMPtr url = do_CreateInstance(NS_SIMPLEURI_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; if (!aCharset || !nsCRT::strcasecmp("UTF-8", aCharset)) rv = url->SetSpec(aSpec); else { nsCAutoString utf8Spec; @@ -1189,21 +1199,23 @@ nsJSProtocolHandler::NewURI(const nsACSt if (utf8Spec.IsEmpty()) rv = url->SetSpec(aSpec); else rv = url->SetSpec(utf8Spec); } } 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; } NS_IMETHODIMP nsJSProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result) { nsresult rv; nsJSChannel * channel; @@ -1228,8 +1240,154 @@ NS_IMETHODIMP NS_IMETHODIMP nsJSProtocolHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval) { // don't override anything. *_retval = PR_FALSE; 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(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 simpleClone; + nsresult rv = mSimpleURI->Clone(getter_AddRefs(simpleClone)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr 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; +} diff --git a/dom/src/jsurl/nsJSProtocolHandler.h b/dom/src/jsurl/nsJSProtocolHandler.h --- a/dom/src/jsurl/nsJSProtocolHandler.h +++ b/dom/src/jsurl/nsJSProtocolHandler.h @@ -35,23 +35,35 @@ * * ***** END LICENSE BLOCK ***** */ #ifndef nsJSProtocolHandler_h___ #define nsJSProtocolHandler_h___ #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 */ \ 0xbfc310d2, \ 0x38a0, \ 0x11d3, \ {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" class nsJSProtocolHandler : public nsIProtocolHandler { @@ -73,9 +85,62 @@ protected: protected: nsresult EnsureUTF8Spec(const nsAFlatCString &aSpec, const char *aCharset, nsACString &aUTF8Spec); nsCOMPtr 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 mSimpleURI; + nsCOMPtr 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 mBaseURI; +}; + #endif /* nsJSProtocolHandler_h___ */ diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -120,16 +120,17 @@ #include "nsIFocusController.h" #include "nsIMenuParent.h" #include "nsIScrollableView.h" #include "nsIHTMLDocument.h" #include "nsITimelineService.h" #include "nsGfxCIID.h" #include "nsStyleSheetService.h" +#include "ImageErrors.h" #include "nsIPrompt.h" #include "imgIContainer.h" // image animation mode constants //-------------------------- // Printing Include //--------------------------- #ifdef NS_PRINTING @@ -958,17 +959,22 @@ DocumentViewerImpl::LoadComplete(nsresul // First, get the window from the document... nsPIDOMWindow *window = mDocument->GetWindow(); mLoaded = PR_TRUE; // 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; // XXX Dispatching to |window|, but using |document| as the target. event.target = mDocument; // If the document presentation is being restored, we don't want to fire // onload to the document content since that would likely confuse scripts diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -535,16 +535,18 @@ MAKE_CTOR(CreateVideoDocument, #endif #ifdef MOZ_ENABLE_CANVAS MAKE_CTOR(CreateCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D, NS_NewCanvasRenderingContext2D) #endif 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) \ static NS_IMETHODIMP \ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \ void **aResult) \ { \ nsresult rv; \ @@ -1250,16 +1252,20 @@ static const nsModuleComponentInfo gComp NS_BASE_DOM_EXCEPTION_CID, nsnull, nsBaseDOMExceptionConstructor }, { "JavaScript Protocol Handler", NS_JSPROTOCOLHANDLER_CID, NS_JSPROTOCOLHANDLER_CONTRACTID, nsJSProtocolHandler::Create }, + { "JavaScript URI", + NS_JSURI_CID, + nsnull, + nsJSURIConstructor }, { "Window Command Table", NS_WINDOWCOMMANDTABLE_CID, "", CreateWindowCommandTableConstructor }, { "Window Command Controller", NS_WINDOWCONTROLLER_CID, NS_WINDOWCONTROLLER_CONTRACTID, diff --git a/layout/reftests/bugs/445004-1-ref.html b/layout/reftests/bugs/445004-1-ref.html new file mode 100644 --- /dev/null +++ b/layout/reftests/bugs/445004-1-ref.html @@ -0,0 +1,4 @@ + + + + diff --git a/layout/reftests/bugs/445004-1.html b/layout/reftests/bugs/445004-1.html new file mode 100644 --- /dev/null +++ b/layout/reftests/bugs/445004-1.html @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/layout/reftests/bugs/passinner.png b/layout/reftests/bugs/passinner.png new file mode 100644 index 0000000000000000000000000000000000000000..ce5c1d9738bb4f0e3e47d68cb00b2acfea7da4a3 GIT binary patch literal 563 zc$@(<0?hr1P)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3Lh3W78MYXYybcN8FWQhbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b0ia1lK~zY`?N+_ZL2(p5=k_W#UxP(a zcaxI*0~WJvJ_g+U50b%PmF!q3Nt80lU{#7@vB;tf;P}4AG@wJbqH7(=nS3Lxg_6YzJ($lw2iz-DW-&6F&qZw9&03CHM+!NaVSu$X}y-J)gM<11c*rTc+NUV zt(KCjWPgx+uSdz`L2BFWVN^aJXthu%>{E>f@;q=HwA+uD{BlX1j(m>eV7a8(3|Mww z+-{@SO9lh1R*$8n2&)y{Za`!vlk?pSg(#PM4K0jB0Fh!b;Q5nyI*rlji)b+nhQlx# zQ9gg3ve__|0+$Q={b$ocj|a?V`W5?$7VC9PrI6!DfflkX9PQBlRW=KP@Q(u_yU$Xs zMnt0BF8^vWA)XgC8rcIO3(;gc?tq{F)`!-E@C~LuCvrq&_UQls002ovPDHLkV1i=V B>AnB} diff --git a/layout/reftests/bugs/passouter.png b/layout/reftests/bugs/passouter.png new file mode 100644 index 0000000000000000000000000000000000000000..3b30b1de7c5fdc8f71fe7a526a0b50338f23da58 GIT binary patch literal 1036 zc$@(Y1oQieP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3Lh3VIhE}G_5c6?8FWQhbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b19?eAK~zY`W0XphU>JOWiD6KJLFz0P zOrfVUpTpUI{{DXX@zv2AM<#5W@bL8mxHvx-|M{+q?5ynBbFwy^UXNyinTlDKd$y6H zu>iNgw_o2LzJ7S_-r339Cp~-rj7SA6SRH%y@zt5Tr!z1xu(Gh}%IQX0N4e>{yS2DH zefJciAjmwJot6FD&urEMT^DxddgjRr%RYYl7_PS> zpz__9ckV5&AHRKs3$nAav$L`jsestDwfpjJ1_lNNF+~VhS58-3R(r*fWh;&@XJB9m zw~9bktSqi{?a5VSD;XFVe*XUX>DwnF6%gwzWpNb-28MT^-@=3H_n+TuPON$O=Hc;M z$HJ__nHUk~JbVA#P|-+3N&}Z^1QjqaFfj8P^PmY8`<6U@`*{D=eVlBZyqtU%YL-2* zy#m|&E8>=U|*tw22A7fx-G%VF8QUMD|g>Sf31S2D3>EaT!d{iD#5n&a9%UR!ke!KDP zhJ~snE@Lqjkl-vPMy4>U@EcFBFFUdnO-fx#z1X)zUta&>!;4Nj&ik(HMV1xg6El!E zy!HGRgiBBXY0k3OvX>H+T7G01rqs4`TZ?^5B5k5BKD@X%cgcfS_jh03bLYkF-+z89 ziYbO$g>!Lmb*yiLC?=?YG-pNHL@_WhY&*XVQ|iXE8~0w`3os36SXE!Ru)s;%$xY8S z-aej*k@5AXHz#hNn6Yd6#fKLmiU}&fp5#XxHlxm>3IG85UFc%7TZv}?0000 + + + + + + + diff --git a/layout/reftests/bugs/subdir/445004-ref-subsubframe.html b/layout/reftests/bugs/subdir/445004-ref-subsubframe.html new file mode 100644 --- /dev/null +++ b/layout/reftests/bugs/subdir/445004-ref-subsubframe.html @@ -0,0 +1,1 @@ + diff --git a/layout/reftests/bugs/subdir/445004-subframe.html b/layout/reftests/bugs/subdir/445004-subframe.html new file mode 100644 --- /dev/null +++ b/layout/reftests/bugs/subdir/445004-subframe.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + + diff --git a/layout/reftests/bugs/subdir/passinner.png b/layout/reftests/bugs/subdir/passinner.png new file mode 100644 index 0000000000000000000000000000000000000000..3b30b1de7c5fdc8f71fe7a526a0b50338f23da58 GIT binary patch literal 1036 zc$@(Y1oQieP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3Lh3VIhE}G_5c6?8FWQhbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b19?eAK~zY`W0XphU>JOWiD6KJLFz0P zOrfVUpTpUI{{DXX@zv2AM<#5W@bL8mxHvx-|M{+q?5ynBbFwy^UXNyinTlDKd$y6H zu>iNgw_o2LzJ7S_-r339Cp~-rj7SA6SRH%y@zt5Tr!z1xu(Gh}%IQX0N4e>{yS2DH zefJciAjmwJot6FD&urEMT^DxddgjRr%RYYl7_PS> zpz__9ckV5&AHRKs3$nAav$L`jsestDwfpjJ1_lNNF+~VhS58-3R(r*fWh;&@XJB9m zw~9bktSqi{?a5VSD;XFVe*XUX>DwnF6%gwzWpNb-28MT^-@=3H_n+TuPON$O=Hc;M z$HJ__nHUk~JbVA#P|-+3N&}Z^1QjqaFfj8P^PmY8`<6U@`*{D=eVlBZyqtU%YL-2* zy#m|&E8>=U|*tw22A7fx-G%VF8QUMD|g>Sf31S2D3>EaT!d{iD#5n&a9%UR!ke!KDP zhJ~snE@Lqjkl-vPMy4>U@EcFBFFUdnO-fx#z1X)zUta&>!;4Nj&ik(HMV1xg6El!E zy!HGRgiBBXY0k3OvX>H+T7G01rqs4`TZ?^5B5k5BKD@X%cgcfS_jh03bLYkF-+z89 ziYbO$g>!Lmb*yiLC?=?YG-pNHL@_WhY&*XVQ|iXE8~0w`3os36SXE!Ru)s;%$xY8S z-aej*k@5AXHz#hNn6Yd6#fKLmiU}&fp5#XxHlxm>3IG85UFc%7TZv}?0000Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3Lh3W78MYXYybcN8FWQhbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b0ia1lK~zY`?N+_ZL2(p5=k_W#UxP(a zcaxI*0~WJvJ_g+U50b%PmF!q3Nt80lU{#7@vB;tf;P}4AG@wJbqH7(=nS3Lxg_6YzJ($lw2iz-DW-&6F&qZw9&03CHM+!NaVSu$X}y-J)gM<11c*rTc+NUV zt(KCjWPgx+uSdz`L2BFWVN^aJXthu%>{E>f@;q=HwA+uD{BlX1j(m>eV7a8(3|Mww z+-{@SO9lh1R*$8n2&)y{Za`!vlk?pSg(#PM4K0jB0Fh!b;Q5nyI*rlji)b+nhQlx# zQ9gg3ve__|0+$Q={b$ocj|a?V`W5?$7VC9PrI6!DfflkX9PQBlRW=KP@Q(u_yU$Xs zMnt0BF8^vWA)XgC8rcIO3(;gc?tq{F)`!-E@C~LuCvrq&_UQls002ovPDHLkV1i=V B>AnB}