diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 8b67d3b31bfd..7a2706b4944c 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -184,8 +184,22 @@ public: // Check if the (JS) caller can access aNode. static PRBool CanCallerAccess(nsIDOMNode *aNode); + /** + * Get the docshell through the JS context that's currently on the stack. + * If there's no JS context currently on the stack aDocShell will be null. + * + * @param aDocShell The docshell or null if no JS context + */ static void GetDocShellFromCaller(nsIDocShell** aDocShell); + /** + * Get the document through the JS context that's currently on the stack. + * If there's no JS context currently on the stack aDocument will be null. + * + * @param aDocument The document or null if no JS context + */ + static void GetDocumentFromCaller(nsIDOMDocument** aDocument); + // Check if a node is in the document prolog, i.e. before the document // element. static PRBool InProlog(nsIDOMNode *aNode); diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 3b45b5b3220f..d77c10d7bcca 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -53,12 +53,12 @@ #include "nsIURI.h" #include "nsIScriptSecurityManager.h" #include "nsDOMError.h" - +#include "nsIDOMWindowInternal.h" #include "nsIJSContextStack.h" #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" -static const char *sJSStackContractID = "@mozilla.org/js/xpc/ContextStack;1"; +static const char *kJSStackContractID = "@mozilla.org/js/xpc/ContextStack;1"; nsIDOMScriptObjectFactory *nsContentUtils::sDOMScriptObjectFactory = nsnull; nsIXPConnect *nsContentUtils::sXPConnect = nsnull; @@ -80,7 +80,7 @@ nsContentUtils::Init() sSecurityManager = nsnull; } - rv = CallGetService(sJSStackContractID, &sThreadJSContextStack); + rv = CallGetService(kJSStackContractID, &sThreadJSContextStack); if (NS_FAILED(rv)) { sThreadJSContextStack = nsnull; } @@ -91,7 +91,7 @@ nsContentUtils::Init() // static nsresult nsContentUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj, - nsIScriptGlobalObject** aNativeGlobal) + nsIScriptGlobalObject** aNativeGlobal) { if (!sXPConnect) { *aNativeGlobal = nsnull; @@ -126,8 +126,8 @@ nsContentUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj, //static nsresult nsContentUtils::GetStaticScriptContext(JSContext* aContext, - JSObject* aObj, - nsIScriptContext** aScriptContext) + JSObject* aObj, + nsIScriptContext** aScriptContext) { nsCOMPtr nativeGlobal; GetStaticScriptGlobal(aContext, aObj, getter_AddRefs(nativeGlobal)); @@ -142,7 +142,7 @@ nsContentUtils::GetStaticScriptContext(JSContext* aContext, //static nsresult nsContentUtils::GetDynamicScriptGlobal(JSContext* aContext, - nsIScriptGlobalObject** aNativeGlobal) + nsIScriptGlobalObject** aNativeGlobal) { nsCOMPtr scriptCX; GetDynamicScriptContext(aContext, getter_AddRefs(scriptCX)); @@ -156,7 +156,7 @@ nsContentUtils::GetDynamicScriptGlobal(JSContext* aContext, //static nsresult nsContentUtils::GetDynamicScriptContext(JSContext *aContext, - nsIScriptContext** aScriptContext) + nsIScriptContext** aScriptContext) { *aScriptContext = nsnull; @@ -617,7 +617,7 @@ nsContentUtils::InProlog(nsIDOMNode *aNode) // Check that there are no elements before aNode to make sure we are not // in the epilog - PRInt32 pos, i; + PRInt32 pos; doc->IndexOf(cont, pos); while (pos > 0) { --pos; @@ -826,6 +826,30 @@ nsContentUtils::GetDocShellFromCaller(nsIDocShell** aDocShell) } } +void +nsContentUtils::GetDocumentFromCaller(nsIDOMDocument** aDocument) +{ + *aDocument = nsnull; + if (!sThreadJSContextStack) { + return; + } + + JSContext *cx = nsnull; + sThreadJSContextStack->Peek(&cx); + + if (cx) { + nsCOMPtr sgo; + GetDynamicScriptGlobal(cx, getter_AddRefs(sgo)); + + nsCOMPtr win(do_QueryInterface(sgo)); + if (!win) { + return; + } + + win->GetDocument(aDocument); + } +} + PRBool nsContentUtils::IsCallerChrome() { @@ -1138,7 +1162,7 @@ nsCxPusher::Push(nsISupports *aCurrentTarget) if (cx) { if (!mStack) { - mStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); + mStack = do_GetService(kJSStackContractID); } if (mStack) { diff --git a/content/html/content/src/nsHTMLImageElement.cpp b/content/html/content/src/nsHTMLImageElement.cpp index e9ca796bb21f..a79c5711571d 100644 --- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -140,7 +140,6 @@ public: protected: nsresult SetSrcInner(nsIURI* aBaseURL, const nsAString& aSrc); - static nsresult GetCallerSourceURL(nsIURI** sourceURL); nsresult GetImageFrame(nsIImageFrame** aImageFrame); nsresult GetXY(PRInt32* aX, PRInt32* aY); @@ -158,31 +157,13 @@ NS_NewHTMLImageElement(nsIHTMLContent** aInstancePtrResult, /* * nsHTMLImageElement's will be created without a nsINodeInfo passed in * if someone says "var img = new Image();" in JavaScript, in a case like - * that we request the nsINodeInfo from the anonymous nodeinfo list. + * that we request the nsINodeInfo from the document's nodeinfo list. */ + nsresult rv; nsCOMPtr nodeInfo(aNodeInfo); if (!nodeInfo) { - nsCOMPtr stack = - do_GetService("@mozilla.org/js/xpc/ContextStack;1"); - - NS_ENSURE_TRUE(stack, NS_ERROR_NOT_AVAILABLE); - - JSContext *cx = nsnull; - - nsresult rv = stack->Peek(&cx); - - if (NS_FAILED(rv) || !cx) - return NS_ERROR_UNEXPECTED; - - nsCOMPtr globalObject; - nsContentUtils::GetStaticScriptGlobal(cx, ::JS_GetGlobalObject(cx), - getter_AddRefs(globalObject));; - - nsCOMPtr win(do_QueryInterface(globalObject)); - NS_ENSURE_TRUE(win, NS_ERROR_UNEXPECTED); - nsCOMPtr dom_doc; - win->GetDocument(getter_AddRefs(dom_doc)); + nsContentUtils::GetDocumentFromCaller(getter_AddRefs(dom_doc)); nsCOMPtr doc(do_QueryInterface(dom_doc)); NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED); @@ -203,7 +184,7 @@ NS_NewHTMLImageElement(nsIHTMLContent** aInstancePtrResult, return NS_ERROR_OUT_OF_MEMORY; } - nsresult rv = it->Init(nodeInfo); + rv = it->Init(nodeInfo); if (NS_FAILED(rv)) { delete it; @@ -610,60 +591,6 @@ nsHTMLImageElement::HandleDOMEvent(nsIPresContext* aPresContext, aEventStatus); } -nsresult -nsHTMLImageElement::GetCallerSourceURL(nsIURI** sourceURL) -{ - // XXX Code duplicated from nsHTMLDocument - // XXX Question, why does this return NS_OK on failure? - nsresult result = NS_OK; - - // We need to use the dynamically scoped global and assume that the - // current JSContext is a DOM context with a nsIScriptGlobalObject so - // that we can get the url of the caller. - // XXX This will fail on non-DOM contexts :( - - // Get JSContext from stack. - - - - - // XXX: This service should be cached. - nsCOMPtr - stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &result)); - - if (NS_FAILED(result)) - return NS_ERROR_FAILURE; - - JSContext *cx = nsnull; - - // it's possible that there is not a JSContext on the stack. - // specifically this can happen when the DOM is being manipulated - // from native (non-JS) code. - if (NS_FAILED(stack->Peek(&cx)) || !cx) - return NS_ERROR_FAILURE; - - nsCOMPtr global; - nsContentUtils::GetDynamicScriptGlobal(cx, getter_AddRefs(global)); - - nsCOMPtr window(do_QueryInterface(global)); - - if (window) { - nsCOMPtr domDoc; - - result = window->GetDocument(getter_AddRefs(domDoc)); - nsCOMPtr doc(do_QueryInterface(domDoc)); - - if (doc) { - result = doc->GetBaseURL(*sourceURL); - if (!*sourceURL) { - doc->GetDocumentURL(sourceURL); - } - } - } - - return result; -} - NS_IMETHODIMP nsHTMLImageElement::Initialize(JSContext* aContext, JSObject *aObj, PRUint32 argc, jsval *argv) @@ -926,13 +853,23 @@ nsHTMLImageElement::SetSrc(const nsAString& aSrc) nsCOMPtr baseURL; nsresult rv = NS_OK; - (void) GetCallerSourceURL(getter_AddRefs(baseURL)); + nsCOMPtr domDoc; + nsContentUtils::GetDocumentFromCaller(getter_AddRefs(domDoc)); - nsCOMPtr doc; - mNodeInfo->GetDocument(*getter_AddRefs(doc)); - - if (doc && !baseURL) { + nsCOMPtr doc(do_QueryInterface(domDoc)); + if (doc) { + // XXX GetBaseURL should do the GetDocumentURL for us rv = doc->GetBaseURL(*getter_AddRefs(baseURL)); + if (!baseURL) { + rv = doc->GetDocumentURL(getter_AddRefs(baseURL)); + } + } + + if (!baseURL) { + mNodeInfo->GetDocument(*getter_AddRefs(doc)); + if (doc) { + rv = doc->GetBaseURL(*getter_AddRefs(baseURL)); + } } if (NS_SUCCEEDED(rv)) { diff --git a/content/html/content/src/nsHTMLOptionElement.cpp b/content/html/content/src/nsHTMLOptionElement.cpp index 8bc5d4cbfb5f..253f116c1362 100644 --- a/content/html/content/src/nsHTMLOptionElement.cpp +++ b/content/html/content/src/nsHTMLOptionElement.cpp @@ -69,6 +69,7 @@ #include "nsLayoutAtoms.h" #include "nsIEventStateManager.h" #include "nsXULAtoms.h" +#include "nsIDOMDocument.h" /** * Implementation of <option> @@ -154,15 +155,21 @@ NS_NewHTMLOptionElement(nsIHTMLContent** aInstancePtrResult, /* * nsHTMLOptionElement's will be created without a nsINodeInfo passed in - * if someone creates new option elements in JavaScript, in a case like - * that we request the nsINodeInfo from the anonymous nodeinfo list. + * if someone says "var opt = new Option();" in JavaScript, in a case like + * that we request the nsINodeInfo from the document's nodeinfo list. */ + nsresult rv; nsCOMPtr nodeInfo(aNodeInfo); if (!nodeInfo) { + nsCOMPtr dom_doc; + nsContentUtils::GetDocumentFromCaller(getter_AddRefs(dom_doc)); + + nsCOMPtr doc(do_QueryInterface(dom_doc)); + NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED); + nsCOMPtr nodeInfoManager; - nsresult rv; - rv = nsNodeInfoManager::GetAnonymousManager(*getter_AddRefs(nodeInfoManager)); - NS_ENSURE_SUCCESS(rv, rv); + doc->GetNodeInfoManager(*getter_AddRefs(nodeInfoManager)); + NS_ENSURE_TRUE(nodeInfoManager, NS_ERROR_UNEXPECTED); rv = nodeInfoManager->GetNodeInfo(nsHTMLAtoms::option, nsnull, kNameSpaceID_None, @@ -176,7 +183,7 @@ NS_NewHTMLOptionElement(nsIHTMLContent** aInstancePtrResult, return NS_ERROR_OUT_OF_MEMORY; } - nsresult rv = NS_STATIC_CAST(nsGenericElement *, it)->Init(nodeInfo); + rv = NS_STATIC_CAST(nsGenericElement *, it)->Init(nodeInfo); if (NS_FAILED(rv)) { delete it; diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 4829196330d1..57c0a97f6df5 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -2335,8 +2335,7 @@ nsHTMLDocument::SetCookie(const nsAString& aCookie) // static nsresult -nsHTMLDocument::GetSourceDocumentURL(JSContext* cx, - nsIURI** sourceURL) +nsHTMLDocument::GetSourceDocumentURL(nsIURI** sourceURL) { // XXX Tom said this reminded him of the "Six Degrees of // Kevin Bacon" game. We try to get from here to there using @@ -2345,29 +2344,11 @@ nsHTMLDocument::GetSourceDocumentURL(JSContext* cx, // I wish there were a better way. *sourceURL = nsnull; - if (!cx) { - return NS_OK; - } - - // We need to use the dynamically scoped global and assume that the - // current JSContext is a DOM context with a nsIScriptGlobalObject so - // that we can get the url of the caller. // XXX This will fail on non-DOM contexts :( + nsCOMPtr domDoc; + nsContentUtils::GetDocumentFromCaller(getter_AddRefs(domDoc)); - nsCOMPtr global; - nsContentUtils::GetDynamicScriptGlobal(cx, getter_AddRefs(global)); - - nsCOMPtr window(do_QueryInterface(global)); - - if (!window) { - return NS_OK; // Can't get the source URI if we can't get the window. - } - - nsCOMPtr dom_doc; - window->GetDocument(getter_AddRefs(dom_doc)); - - nsCOMPtr doc(do_QueryInterface(dom_doc)); - + nsCOMPtr doc(do_QueryInterface(domDoc)); if (!doc) { return NS_OK; // No document in the window } @@ -2549,35 +2530,24 @@ nsHTMLDocument::Open() NS_IMETHODIMP nsHTMLDocument::Open(nsIDOMDocument** aReturn) { - nsresult result = NS_OK; - nsCOMPtr sourceURL; - // XXX The URL of the newly created document will match // that of the source document. Is this right? - // XXX: This service should be cached. - nsCOMPtr - stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &result)); + // XXX This will fail on non-DOM contexts :( + nsCOMPtr sourceURL; + nsresult result = GetSourceDocumentURL(getter_AddRefs(sourceURL)); - if (NS_FAILED(result)) - return NS_ERROR_FAILURE; - - JSContext *cx; - - if (NS_FAILED(stack->Peek(&cx))) - return NS_ERROR_FAILURE; - - result = GetSourceDocumentURL(cx, getter_AddRefs(sourceURL)); // Recover if we had a problem obtaining the source URL if (!sourceURL) { - result = NS_NewURI(getter_AddRefs(sourceURL), NS_LITERAL_CSTRING("about:blank")); + result = NS_NewURI(getter_AddRefs(sourceURL), + NS_LITERAL_CSTRING("about:blank")); } if (NS_SUCCEEDED(result)) { result = OpenCommon(sourceURL); } - QueryInterface(NS_GET_IID(nsIDOMDocument), (void **)aReturn); + CallQueryInterface(this, aReturn); return result; } diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 652db02dca6f..35edf43a7524 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -209,7 +209,7 @@ protected: static PRBool MatchNameAttribute(nsIContent* aContent, nsString* aData); static PRBool MatchFormControls(nsIContent* aContent, nsString* aData); - static nsresult GetSourceDocumentURL(JSContext* cx, nsIURI** sourceURL); + static nsresult GetSourceDocumentURL(nsIURI** sourceURL); static void DocumentWriteTerminationFunc(nsISupports *aRef);