diff --git a/content/html/content/public/nsIFormSubmitObserver.h b/content/html/content/public/nsIFormSubmitObserver.h index 8c510f88411..997a7a73d0a 100644 --- a/content/html/content/public/nsIFormSubmitObserver.h +++ b/content/html/content/public/nsIFormSubmitObserver.h @@ -30,8 +30,10 @@ #ifndef nsIFormSubmitObserver_h__ #define nsIFormSubmitObserver_h__ -#include "nsISupports.h" +#include "nsIObserver.h" #include "prtypes.h" +#include "nsIDOMWindow.h" +#include "nsIURI.h" class nsString; @@ -41,15 +43,19 @@ class nsString; #define NS_FORMSUBMIT_SUBJECT "formsubmit" -class nsIFormSubmitObserver : public nsISupports { +class nsIFormSubmitObserver : public nsIObserver { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFORMSUBMITOBSERVER_IID) /* * Subject calls the observer when the form is submitted * @param formNode- the dom node corresonding to this form. + * @param window- the window that the form submit occured in. + * NOTE: This is not necessarily the same window the form submit result + * will be loaded in (form could have target attribute set) + * @param actionURL- URL to which the form will be submitted. */ - NS_IMETHOD Notify(nsIContent* formNode) = 0; + NS_IMETHOD Notify(nsIContent* formNode, nsIDOMWindow* window, nsIURI* actionURL) = 0; }; diff --git a/extensions/wallet/src/nsWalletService.cpp b/extensions/wallet/src/nsWalletService.cpp index 8d52544defc..b3e51584323 100644 --- a/extensions/wallet/src/nsWalletService.cpp +++ b/extensions/wallet/src/nsWalletService.cpp @@ -39,6 +39,7 @@ #include "nsIDOMHTMLInputElement.h" #include "nsIFormControl.h" #include "nsIDocShell.h" +#include "nsIDOMWindow.h" static NS_DEFINE_IID(kDocLoaderServiceCID, NS_DOCUMENTLOADER_SERVICE_CID); @@ -62,9 +63,8 @@ nsWalletlibService::~nsWalletlibService() NS_IF_RELEASE(gKeyedStreamGenerator); } -NS_IMPL_THREADSAFE_ISUPPORTS6(nsWalletlibService, +NS_IMPL_THREADSAFE_ISUPPORTS5(nsWalletlibService, nsIWalletService, - nsIObserver, nsIFormSubmitObserver, nsIDocumentLoaderObserver, nsIPasswordSink, @@ -176,7 +176,7 @@ NS_IMETHODIMP nsWalletlibService::Observe(nsISupports*, const PRUnichar*, const } #define CRLF "\015\012" -NS_IMETHODIMP nsWalletlibService::Notify(nsIContent* formNode) +NS_IMETHODIMP nsWalletlibService::Notify(nsIContent* formNode, nsIDOMWindow* window, nsIURI* actionURL) { if (!formNode) { return NS_ERROR_FAILURE; diff --git a/extensions/wallet/src/nsWalletService.h b/extensions/wallet/src/nsWalletService.h index 870e89338fa..3c2fed99f97 100644 --- a/extensions/wallet/src/nsWalletService.h +++ b/extensions/wallet/src/nsWalletService.h @@ -29,9 +29,10 @@ #include "nsIDocumentLoaderObserver.h" #include "nsWeakReference.h" #include "nsIPasswordSink.h" +#include "nsIDOMWindow.h" +#include "nsIURI.h" class nsWalletlibService : public nsIWalletService, - public nsIObserver, public nsIFormSubmitObserver, public nsIDocumentLoaderObserver, public nsIPasswordSink, @@ -75,7 +76,7 @@ public: // nsIObserver NS_DECL_NSIOBSERVER - NS_IMETHOD Notify(nsIContent* formNode); + NS_IMETHOD Notify(nsIContent* formNode, nsIDOMWindow* window, nsIURI* actionURL); // nsIDocumentLoaderObserver NS_DECL_NSIDOCUMENTLOADEROBSERVER diff --git a/layout/html/forms/public/nsIFormSubmitObserver.h b/layout/html/forms/public/nsIFormSubmitObserver.h index 8c510f88411..997a7a73d0a 100644 --- a/layout/html/forms/public/nsIFormSubmitObserver.h +++ b/layout/html/forms/public/nsIFormSubmitObserver.h @@ -30,8 +30,10 @@ #ifndef nsIFormSubmitObserver_h__ #define nsIFormSubmitObserver_h__ -#include "nsISupports.h" +#include "nsIObserver.h" #include "prtypes.h" +#include "nsIDOMWindow.h" +#include "nsIURI.h" class nsString; @@ -41,15 +43,19 @@ class nsString; #define NS_FORMSUBMIT_SUBJECT "formsubmit" -class nsIFormSubmitObserver : public nsISupports { +class nsIFormSubmitObserver : public nsIObserver { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFORMSUBMITOBSERVER_IID) /* * Subject calls the observer when the form is submitted * @param formNode- the dom node corresonding to this form. + * @param window- the window that the form submit occured in. + * NOTE: This is not necessarily the same window the form submit result + * will be loaded in (form could have target attribute set) + * @param actionURL- URL to which the form will be submitted. */ - NS_IMETHOD Notify(nsIContent* formNode) = 0; + NS_IMETHOD Notify(nsIContent* formNode, nsIDOMWindow* window, nsIURI* actionURL) = 0; }; diff --git a/layout/html/forms/src/nsFormFrame.cpp b/layout/html/forms/src/nsFormFrame.cpp index 6860d93cf7f..82e2e249e39 100644 --- a/layout/html/forms/src/nsFormFrame.cpp +++ b/layout/html/forms/src/nsFormFrame.cpp @@ -109,6 +109,8 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); // Security #include "nsIScriptSecurityManager.h" +#include "nsIDOMWindow.h" + static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); static NS_DEFINE_CID(kPlatformCharsetCID, NS_PLATFORMCHARSET_CID); static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID); @@ -691,29 +693,6 @@ nsFormFrame::OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame) aFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); } - // Notify observers that the form is being submitted. - result = NS_OK; - NS_WITH_SERVICE(nsIObserverService, service, NS_OBSERVERSERVICE_PROGID, &result); - if (NS_FAILED(result)) return result; - - nsString theTopic; theTopic.AssignWithConversion(NS_FORMSUBMIT_SUBJECT); - nsIEnumerator* theEnum; - result = service->EnumerateObserverList(theTopic.GetUnicode(), &theEnum); - if (NS_SUCCEEDED(result) && theEnum){ - nsCOMPtr inst; - - for (theEnum->First(); theEnum->IsDone() != NS_OK; theEnum->Next()) { - result = theEnum->CurrentItem(getter_AddRefs(inst)); - if (NS_SUCCEEDED(result) && inst) { - nsCOMPtr formSubmitObserver = do_QueryInterface(inst, &result); - if (NS_SUCCEEDED(result) && formSubmitObserver) { - formSubmitObserver->Notify(mContent); - } - } - } - NS_RELEASE(theEnum); - } - nsIFileSpec* multipartDataFile = nsnull; if (isURLEncoded) { result = ProcessAsURLEncoded(formProcessor, isPost, data, fcFrame); @@ -734,13 +713,16 @@ nsFormFrame::OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame) nsAutoString href; GetAction(&href); + // Get the document. + // We'll need it now to form the URL we're submitting to. + // We'll also need it later to get the DOM window when notifying form submit observers (bug 33203) + nsCOMPtr document; + mContent->GetDocument(*getter_AddRefs(document)); + if (!document) return NS_OK; // No doc means don't submit, see Bug 28988 + // Resolve url to an absolute url nsCOMPtr docURL; - nsCOMPtr doc; - mContent->GetDocument(*getter_AddRefs(doc)); - if (!doc) return NS_OK; // No doc means don't submit, see Bug 28988 - - doc->GetBaseURL(*getter_AddRefs(docURL)); + document->GetBaseURL(*getter_AddRefs(docURL)); NS_ASSERTION(docURL, "No Base URL found in Form Submit!\n"); // If an action is not specified and we are inside @@ -752,7 +734,7 @@ nsFormFrame::OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame) if (href.IsEmpty()) { nsCOMPtr htmlDoc; - if (PR_FALSE == NS_SUCCEEDED(doc->QueryInterface(kIHTMLDocumentIID, + if (PR_FALSE == NS_SUCCEEDED(document->QueryInterface(kIHTMLDocumentIID, getter_AddRefs(htmlDoc)))) { // Must be a XML, XUL or other non-HTML document type // so do nothing. @@ -761,12 +743,11 @@ nsFormFrame::OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame) // Necko's MakeAbsoluteURI doesn't reuse the baseURL's rel path if it is // passed a zero length rel path. - char* relPath = nsnull; - docURL->GetSpec(&relPath); + nsXPIDLCString relPath; + docURL->GetSpec(getter_Copies(relPath)); NS_ASSERTION(relPath, "Rel path couldn't be formed in form submit!\n"); if (relPath) { href.AppendWithConversion(relPath); - nsCRT::free(relPath); // If re-using the same URL, chop off old query string (bug 25330) PRInt32 queryStart = href.FindChar('?'); @@ -834,6 +815,40 @@ nsFormFrame::OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame) result = NS_MakeAbsoluteURI(absURLSpec, href, docURL); if (NS_FAILED(result)) return result; + // Notify observers that the form is being submitted. + result = NS_OK; + NS_WITH_SERVICE(nsIObserverService, service, NS_OBSERVERSERVICE_PROGID, &result); + if (NS_FAILED(result)) return result; + + nsString theTopic; theTopic.AssignWithConversion(NS_FORMSUBMIT_SUBJECT); + nsIEnumerator* theEnum; + result = service->EnumerateObserverList(theTopic.GetUnicode(), &theEnum); + if (NS_SUCCEEDED(result) && theEnum){ + nsCOMPtr inst; + nsresult submitStatus = NS_OK; + + nsCOMPtr globalObject; + document->GetScriptGlobalObject(getter_AddRefs(globalObject)); + nsCOMPtr window = do_QueryInterface(globalObject); + + for (theEnum->First(); theEnum->IsDone() != NS_OK; theEnum->Next()) { + result = theEnum->CurrentItem(getter_AddRefs(inst)); + if (NS_SUCCEEDED(result) && inst) { + nsCOMPtr formSubmitObserver = do_QueryInterface(inst, &result); + if (NS_SUCCEEDED(result) && formSubmitObserver) { + nsresult notifyStatus = formSubmitObserver->Notify(mContent, window, actionURL); + if (NS_FAILED(notifyStatus)) { + submitStatus = notifyStatus; + } + } + } + } + NS_RELEASE(theEnum); + if (NS_FAILED(submitStatus)) { + return submitStatus; + } + } + // Now pass on absolute url to the click handler nsIInputStream* postDataStream = nsnull; if (isPost) {