mshtml: Try to not use nsIDOMHTMLFormElement::Submit for IHTMLFormElelement::submit implementation.

This commit is contained in:
Jacek Caban 2013-09-27 15:22:30 +02:00 committed by Alexandre Julliard
parent 5c7c954658
commit e61de218ee
5 changed files with 191 additions and 46 deletions

View File

@ -106,6 +106,7 @@ typedef struct {
#define BINDING_REPLACE 0x0002
#define BINDING_FROMHIST 0x0004
#define BINDING_REFRESH 0x0008
#define BINDING_SUBMIT 0x0010
HRESULT set_http_header(struct list*,const WCHAR*,int,const WCHAR*,int) DECLSPEC_HIDDEN;
HRESULT create_redirect_nschannel(const WCHAR*,nsChannel*,nsChannel**) DECLSPEC_HIDDEN;
@ -120,6 +121,7 @@ HRESULT super_navigate(HTMLOuterWindow*,IUri*,DWORD,const WCHAR*,BYTE*,DWORD) DE
HRESULT load_uri(HTMLOuterWindow*,IUri*,DWORD) DECLSPEC_HIDDEN;
HRESULT navigate_new_window(HTMLOuterWindow*,IUri*,const WCHAR*,IHTMLWindow2**) DECLSPEC_HIDDEN;
HRESULT navigate_url(HTMLOuterWindow*,const WCHAR*,IUri*,DWORD) DECLSPEC_HIDDEN;
HRESULT submit_form(HTMLOuterWindow*,IUri*,nsIInputStream*) DECLSPEC_HIDDEN;
HRESULT create_channelbsc(IMoniker*,const WCHAR*,BYTE*,DWORD,BOOL,nsChannelBSC**) DECLSPEC_HIDDEN;
HRESULT channelbsc_load_stream(HTMLInnerWindow*,IMoniker*,IStream*) DECLSPEC_HIDDEN;

View File

@ -30,6 +30,7 @@
#include "mshtml_private.h"
#include "htmlevent.h"
#include "binding.h"
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
@ -361,17 +362,61 @@ static HRESULT WINAPI HTMLFormElement_get_onreset(IHTMLFormElement *iface, VARIA
static HRESULT WINAPI HTMLFormElement_submit(IHTMLFormElement *iface)
{
HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
HTMLOuterWindow *window = NULL;
nsIInputStream *post_stream;
nsAString action_uri_str;
IUri *uri;
nsresult nsres;
HRESULT hres;
TRACE("(%p)->()\n", This);
nsres = nsIDOMHTMLFormElement_Submit(This->nsform);
if(NS_FAILED(nsres)) {
ERR("Submit failed: %08x\n", nsres);
return E_FAIL;
if(This->element.node.doc) {
HTMLDocumentNode *doc = This->element.node.doc;
if(doc->window && doc->window->base.outer_window)
window = doc->window->base.outer_window;
}
if(!window) {
TRACE("No outer window\n");
return S_OK;
}
return S_OK;
/*
* FIXME: We currently don't use our submit implementation for sub-windows because
* load_nsuri can't support post data. We should fix it.
*/
if(!window->doc_obj || window->doc_obj->basedoc.window != window) {
nsres = nsIDOMHTMLFormElement_Submit(This->nsform);
if(NS_FAILED(nsres)) {
ERR("Submit failed: %08x\n", nsres);
return E_FAIL;
}
return S_OK;
}
nsAString_Init(&action_uri_str, NULL);
nsres = nsIDOMHTMLFormElement_GetFormData(This->nsform, NULL, &action_uri_str, &post_stream);
if(NS_SUCCEEDED(nsres)) {
const PRUnichar *action_uri;
nsAString_GetData(&action_uri_str, &action_uri);
hres = create_uri(action_uri, 0, &uri);
}else {
ERR("GetFormData failed: %08x\n", nsres);
hres = E_FAIL;
}
nsAString_Finish(&action_uri_str);
if(SUCCEEDED(hres)) {
window->readystate_locked++;
hres = submit_form(window, uri, post_stream);
window->readystate_locked--;
IUri_Release(uri);
}
if(post_stream)
nsIInputStream_Release(post_stream);
return hres;
}
static HRESULT WINAPI HTMLFormElement_reset(IHTMLFormElement *iface)

View File

@ -385,7 +385,10 @@ struct HTMLOuterWindow {
nsIDOMWindow *nswindow;
HTMLOuterWindow *parent;
HTMLFrameBase *frame_element;
READYSTATE readystate;
BOOL readystate_locked;
unsigned readystate_pending;
HTMLInnerWindow *pending_window;
IMoniker *mon;

View File

@ -2238,7 +2238,32 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC
prepare_for_binding(&window->doc_obj->basedoc, mon, flags);
hres = IUri_GetScheme(uri, &scheme);
if(SUCCEEDED(hres) && scheme != URL_SCHEME_JAVASCRIPT) {
if(SUCCEEDED(hres) && scheme == URL_SCHEME_JAVASCRIPT) {
navigate_javascript_task_t *task;
IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
IMoniker_Release(mon);
task = heap_alloc(sizeof(*task));
if(!task)
return E_OUTOFMEMORY;
/* Why silently? */
window->readystate = READYSTATE_COMPLETE;
if(!(flags & BINDING_FROMHIST))
call_docview_84(window->doc_obj);
IUri_AddRef(uri);
task->window = window;
task->uri = uri;
hres = push_task(&task->header, navigate_javascript_proc, navigate_javascript_task_destr, window->task_magic);
}else if(flags & BINDING_SUBMIT) {
hres = set_moniker(window, mon, uri, NULL, bsc, TRUE);
if(SUCCEEDED(hres))
hres = start_binding(window->pending_window, &bsc->bsc, NULL);
IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
IMoniker_Release(mon);
}else {
navigate_task_t *task;
task = heap_alloc(sizeof(*task));
@ -2261,25 +2286,6 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC
IUri_AddRef(uri);
task->uri = uri;
hres = push_task(&task->header, navigate_proc, navigate_task_destr, window->task_magic);
}else {
navigate_javascript_task_t *task;
IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
IMoniker_Release(mon);
task = heap_alloc(sizeof(*task));
if(!task)
return E_OUTOFMEMORY;
/* Why silently? */
window->readystate = READYSTATE_COMPLETE;
if(!(flags & BINDING_FROMHIST))
call_docview_84(window->doc_obj);
IUri_AddRef(uri);
task->window = window;
task->uri = uri;
hres = push_task(&task->header, navigate_javascript_proc, navigate_javascript_task_destr, window->task_magic);
}
return hres;
@ -2396,7 +2402,8 @@ HRESULT hlink_frame_navigate(HTMLDocument *doc, LPCWSTR url, nsChannel *nschanne
return hres;
}
static HRESULT navigate_uri(HTMLOuterWindow *window, IUri *uri, const WCHAR *display_uri, DWORD flags)
static HRESULT navigate_uri(HTMLOuterWindow *window, IUri *uri, const WCHAR *display_uri, const request_data_t *request_data,
DWORD flags)
{
nsWineURI *nsuri;
HRESULT hres;
@ -2404,18 +2411,22 @@ static HRESULT navigate_uri(HTMLOuterWindow *window, IUri *uri, const WCHAR *dis
TRACE("%s\n", debugstr_w(display_uri));
if(window->doc_obj && window->doc_obj->webbrowser && window == window->doc_obj->basedoc.window) {
DWORD post_data_len = request_data ? request_data->post_data_len : 0;
void *post_data = post_data_len ? request_data->post_data : NULL;
const WCHAR *headers = request_data ? request_data->headers : NULL;
if(!(flags & BINDING_REFRESH)) {
BOOL cancel = FALSE;
hres = IDocObjectService_FireBeforeNavigate2(window->doc_obj->doc_object_service, NULL, display_uri, 0x40,
NULL, NULL, 0, NULL, TRUE, &cancel);
NULL, post_data, post_data_len ? post_data_len+1 : 0, headers, TRUE, &cancel);
if(SUCCEEDED(hres) && cancel) {
TRACE("Navigation canceled\n");
return S_OK;
}
}
return super_navigate(window, uri, flags, NULL, NULL, 0);
return super_navigate(window, uri, flags, headers, post_data, post_data_len);
}
if(window->doc_obj && window == window->doc_obj->basedoc.window) {
@ -2449,31 +2460,21 @@ HRESULT load_uri(HTMLOuterWindow *window, IUri *uri, DWORD flags)
if(FAILED(hres))
return hres;
hres = navigate_uri(window, uri, display_uri, flags);
hres = navigate_uri(window, uri, display_uri, NULL, flags);
SysFreeString(display_uri);
return hres;
}
HRESULT navigate_url(HTMLOuterWindow *window, const WCHAR *new_url, IUri *base_uri, DWORD flags)
static HRESULT translate_uri(HTMLOuterWindow *window, IUri *orig_uri, BSTR *ret_display_uri, IUri **ret_uri)
{
IUri *uri = NULL;
BSTR display_uri;
IUri *uri;
HRESULT hres;
if(new_url && base_uri)
hres = CoInternetCombineUrlEx(base_uri, new_url, URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
&uri, 0);
else
hres = create_uri(new_url, 0, &uri);
hres = IUri_GetDisplayUri(orig_uri, &display_uri);
if(FAILED(hres))
return hres;
hres = IUri_GetDisplayUri(uri, &display_uri);
if(FAILED(hres)) {
IUri_Release(uri);
return hres;
}
if(window->doc_obj && window->doc_obj->hostui) {
OLECHAR *translated_url = NULL;
@ -2482,7 +2483,6 @@ HRESULT navigate_url(HTMLOuterWindow *window, const WCHAR *new_url, IUri *base_u
if(hres == S_OK) {
TRACE("%08x %s -> %s\n", hres, debugstr_w(display_uri), debugstr_w(translated_url));
SysFreeString(display_uri);
IUri_Release(uri);
hres = create_uri(translated_url, 0, &uri);
CoTaskMemFree(translated_url);
if(FAILED(hres))
@ -2496,8 +2496,57 @@ HRESULT navigate_url(HTMLOuterWindow *window, const WCHAR *new_url, IUri *base_u
}
}
hres = navigate_uri(window, uri, display_uri, flags);
if(!uri) {
IUri_AddRef(orig_uri);
uri = orig_uri;
}
*ret_display_uri = display_uri;
*ret_uri = uri;
return S_OK;
}
HRESULT submit_form(HTMLOuterWindow *window, IUri *submit_uri, nsIInputStream *post_stream)
{
request_data_t request_data = {NULL};
BSTR display_uri;
IUri *uri;
HRESULT hres;
hres = read_post_data_stream(post_stream, TRUE, NULL, &request_data);
if(FAILED(hres))
return hres;
hres = translate_uri(window, submit_uri, &display_uri, &uri);
if(SUCCEEDED(hres)) {
hres = navigate_uri(window, uri, display_uri, &request_data, BINDING_NAVIGATED|BINDING_SUBMIT);
IUri_Release(uri);
SysFreeString(display_uri);
}
release_request_data(&request_data);
return hres;
}
HRESULT navigate_url(HTMLOuterWindow *window, const WCHAR *new_url, IUri *base_uri, DWORD flags)
{
IUri *uri, *nav_uri;
BSTR display_uri;
HRESULT hres;
if(new_url && base_uri)
hres = CoInternetCombineUrlEx(base_uri, new_url, URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
&nav_uri, 0);
else
hres = create_uri(new_url, 0, &nav_uri);
if(FAILED(hres))
return hres;
hres = translate_uri(window, nav_uri, &display_uri, &uri);
IUri_Release(nav_uri);
if(FAILED(hres))
return hres;
hres = navigate_uri(window, uri, display_uri, NULL, flags);
IUri_Release(uri);
SysFreeString(display_uri);
return hres;

View File

@ -438,9 +438,9 @@ HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBind
return S_OK;
}
void set_ready_state(HTMLOuterWindow *window, READYSTATE readystate)
static void notif_readystate(HTMLOuterWindow *window)
{
window->readystate = readystate;
window->readystate_pending = FALSE;
if(window->doc_obj && window->doc_obj->basedoc.window == window)
call_property_onchanged(&window->doc_obj->basedoc.cp_container, DISPID_READYSTATE);
@ -453,6 +453,52 @@ void set_ready_state(HTMLOuterWindow *window, READYSTATE readystate)
TRUE, window->frame_element->element.node.nsnode, NULL, NULL);
}
typedef struct {
task_t header;
HTMLOuterWindow *window;
} readystate_task_t;
static void notif_readystate_proc(task_t *_task)
{
readystate_task_t *task = (readystate_task_t*)_task;
notif_readystate(task->window);
}
static void notif_readystate_destr(task_t *_task)
{
readystate_task_t *task = (readystate_task_t*)_task;
IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
}
void set_ready_state(HTMLOuterWindow *window, READYSTATE readystate)
{
READYSTATE prev_state = window->readystate;
window->readystate = readystate;
if(window->readystate_locked) {
readystate_task_t *task;
HRESULT hres;
if(window->readystate_pending || prev_state == readystate)
return;
task = heap_alloc(sizeof(*task));
if(!task)
return;
IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
task->window = window;
hres = push_task(&task->header, notif_readystate_proc, notif_readystate_destr, window->task_magic);
if(SUCCEEDED(hres))
window->readystate_pending = TRUE;
return;
}
notif_readystate(window);
}
static HRESULT get_doc_string(HTMLDocumentNode *This, char **str)
{
nsIDOMNode *nsnode;