From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmldoc.c | 2 +- dlls/mshtml/htmlwindow.c | 12 +-- dlls/mshtml/navigate.c | 5 +- dlls/mshtml/nsevents.c | 6 +- dlls/mshtml/nsio.c | 2 +- dlls/mshtml/oleobj.c | 72 +++++++++++++++++- dlls/mshtml/tests/events.c | 148 ++++++++++++++++++++++++++++++++++++ dlls/mshtml/tests/htmldoc.c | 36 ++++++++- dlls/mshtml/tests/script.c | 17 +++++ 9 files changed, 283 insertions(+), 17 deletions(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index d347ecb93c7..9750ad19765 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -6196,7 +6196,7 @@ HRESULT create_document_node(nsIDOMDocument *nsdoc, GeckoBrowser *browser, HTMLI lock_document_mode(doc); }
- if(!doc_obj->window || (window && is_main_content_window(window->base.outer_window))) + if(doc_obj && (!doc_obj->window || (window && is_main_content_window(window->base.outer_window)))) doc->cp_container.forward_container = &doc_obj->cp_container;
/* Share reference with HTMLDOMNode */ diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 2034ae8487a..80d23ecc12d 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -2906,7 +2906,7 @@ static HRESULT WINAPI HTMLPrivateWindow_GetAddressBarUrl(IHTMLPrivateWindow *ifa if(!url) return E_INVALIDARG;
- *url = SysAllocString(This->outer_window->url); + *url = SysAllocString(This->outer_window->url ? This->outer_window->url : L"about:blank"); return S_OK; }
@@ -4564,10 +4564,12 @@ HRESULT update_window_doc(HTMLInnerWindow *window)
if(is_main_content_window(outer_window) || !outer_window->browser->content_window) { HTMLDocumentObj *doc_obj = outer_window->browser->doc; - if(doc_obj->doc_node) - IHTMLDOMNode_Release(&doc_obj->doc_node->node.IHTMLDOMNode_iface); - doc_obj->doc_node = window->doc; - IHTMLDOMNode_AddRef(&window->doc->node.IHTMLDOMNode_iface); + if(doc_obj) { + if(doc_obj->doc_node) + IHTMLDOMNode_Release(&doc_obj->doc_node->node.IHTMLDOMNode_iface); + doc_obj->doc_node = window->doc; + IHTMLDOMNode_AddRef(&window->doc->node.IHTMLDOMNode_iface); + } }
return hres; diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 8172abd8040..8af2de6705c 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1012,7 +1012,8 @@ static HRESULT on_start_nsrequest(nsChannelBSC *This)
if(This->bsc.binding) process_document_response_headers(This->bsc.window->doc, This->bsc.binding); - if(This->bsc.window->base.outer_window->readystate != READYSTATE_LOADING) + if(This->bsc.window->base.outer_window->readystate != READYSTATE_LOADING && + This->bsc.window->base.outer_window->browser->doc) set_ready_state(This->bsc.window->base.outer_window, READYSTATE_LOADING); }
@@ -1370,7 +1371,7 @@ static HRESULT nsChannelBSC_init_bindinfo(BSCallback *bsc) HRESULT hres;
if(This->is_doc_channel && This->bsc.window && This->bsc.window->base.outer_window - && (browser = This->bsc.window->base.outer_window->browser)) { + && (browser = This->bsc.window->base.outer_window->browser) && browser->doc) { if(browser->doc->hostinfo.dwFlags & DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION) This->bsc.bindinfo_options |= BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS; } diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 78a54c83955..8c6631626d1 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -208,6 +208,8 @@ static nsresult handle_focus(HTMLDocumentNode *doc, nsIDOMEvent *event)
TRACE("(%p)\n", doc);
+ if(!doc->doc_obj) + return NS_ERROR_FAILURE; doc_obj = doc->doc_obj;
if(!doc_obj->focus) { @@ -220,7 +222,7 @@ static nsresult handle_focus(HTMLDocumentNode *doc, nsIDOMEvent *event)
static nsresult handle_keypress(HTMLDocumentNode *doc, nsIDOMEvent *event) { - if(!doc->browser) + if(!doc->browser || !doc->browser->doc) return NS_ERROR_FAILURE;
TRACE("(%p)->(%p)\n", doc, event); @@ -391,7 +393,7 @@ static nsresult handle_beforeunload(HTMLDocumentNode *doc, nsIDOMEvent *nsevent) DOMEvent *event; HRESULT hres;
- if(!(window = doc->window)) + if(!(window = doc->window) || doc->unload_sent) return NS_OK;
/* Gecko dispatches this to the document, but IE dispatches it to the window */ diff --git a/dlls/mshtml/nsio.c b/dlls/mshtml/nsio.c index c0e0e2e9f5d..e42319dec13 100644 --- a/dlls/mshtml/nsio.c +++ b/dlls/mshtml/nsio.c @@ -1082,7 +1082,7 @@ static nsresult NSAPI nsChannel_AsyncOpen(nsIHttpChannel *iface, nsIStreamListen TRACE("canceled\n"); nsres = NS_BINDING_ABORTED; } - }else if(window->browser->doc->mime) { + }else if(window->browser->doc && window->browser->doc->mime) { free(This->content_type); This->content_type = strdupWtoA(window->browser->doc->mime); } diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index 870500ff0ab..36ff99338e3 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -35,6 +35,7 @@
#include "mshtml_private.h" #include "htmlevent.h" +#include "binding.h"
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
@@ -2079,8 +2080,10 @@ void HTMLDocumentNode_OleObj_Init(HTMLDocumentNode *This) This->IObjectWithSite_iface.lpVtbl = &DocNodeObjectWithSiteVtbl; This->IOleContainer_iface.lpVtbl = &DocNodeOleContainerVtbl; This->IObjectSafety_iface.lpVtbl = &DocNodeObjectSafetyVtbl; - This->doc_obj->extent.cx = 1; - This->doc_obj->extent.cy = 1; + if(This->doc_obj) { + This->doc_obj->extent.cx = 1; + This->doc_obj->extent.cy = 1; + } }
static void HTMLDocumentObj_OleObj_Init(HTMLDocumentObj *This) @@ -3403,6 +3406,60 @@ static ULONG WINAPI HTMLDocumentObj_AddRef(IUnknown *iface) return ref; }
+static void set_window_uninitialized(HTMLOuterWindow *window) +{ + nsChannelBSC *channelbsc; + nsWineURI *nsuri; + IMoniker *mon; + HRESULT hres; + IUri *uri; + + window->readystate = READYSTATE_UNINITIALIZED; + set_current_uri(window, NULL); + if(window->mon) { + IMoniker_Release(window->mon); + window->mon = NULL; + } + + if(!window->base.inner_window) + return; + + hres = create_uri(L"about:blank", 0, &uri); + if(FAILED(hres)) + return; + + hres = create_doc_uri(uri, &nsuri); + IUri_Release(uri); + if(FAILED(hres)) + return; + + hres = CreateURLMoniker(NULL, L"about:blank", &mon); + if(SUCCEEDED(hres)) { + hres = create_channelbsc(mon, NULL, NULL, 0, TRUE, &channelbsc); + IMoniker_Release(mon); + + if(SUCCEEDED(hres)) { + channelbsc->bsc.bindf = 0; /* synchronous binding */ + + if(window->base.inner_window->doc) + remove_target_tasks(window->base.inner_window->task_magic); + abort_window_bindings(window->base.inner_window); + window->base.inner_window->doc->unload_sent = TRUE; + + hres = load_nsuri(window, nsuri, NULL, channelbsc, LOAD_FLAGS_BYPASS_CACHE); + if(SUCCEEDED(hres)) + hres = create_pending_window(window, channelbsc); + IBindStatusCallback_Release(&channelbsc->bsc.IBindStatusCallback_iface); + } + } + nsISupports_Release((nsISupports*)nsuri); + if(FAILED(hres)) + return; + + window->load_flags |= BINDING_REPLACE; + start_binding(window->pending_window, &window->pending_window->bscallback->bsc, NULL); +} + static ULONG WINAPI HTMLDocumentObj_Release(IUnknown *iface) { HTMLDocumentObj *This = impl_from_IUnknown(iface); @@ -3412,8 +3469,15 @@ static ULONG WINAPI HTMLDocumentObj_Release(IUnknown *iface)
if(!ref) { if(This->doc_node) { - This->doc_node->doc_obj = NULL; - IHTMLDOMNode_Release(&This->doc_node->node.IHTMLDOMNode_iface); + HTMLDocumentNode *doc_node = This->doc_node; + + if(This->nscontainer) + This->nscontainer->doc = NULL; + This->doc_node = NULL; + doc_node->doc_obj = NULL; + + set_window_uninitialized(This->window); + IHTMLDOMNode_Release(&doc_node->node.IHTMLDOMNode_iface); } if(This->window) IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface); diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index f972c2a8316..56b62aa418c 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -5999,6 +5999,151 @@ static void test_empty_document(void) IHTMLDocument2_Release(doc); }
+static void test_document_close(void) +{ + IHTMLPrivateWindow *priv_window; + IHTMLDocument2 *doc, *doc_node; + IHTMLDocument3 *doc3; + IHTMLElement *elem; + DWORD cookie; + HRESULT hres; + VARIANT v; + BSTR bstr; + LONG ref; + MSG msg; + + doc = create_document_with_origin(input_doc_str); + if(!doc) + return; + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLPrivateWindow, (void**)&priv_window); + ok(hres == S_OK, "Could not get IHTMLPrivateWindow) interface: %08lx\n", hres); + hres = IHTMLPrivateWindow_GetAddressBarUrl(priv_window, &bstr); + ok(hres == S_OK, "GetAddressBarUrl failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"http://winetest.example.org/"), "unexpected address bar: %s\n", wine_dbgstr_w(bstr)); + IHTMLPrivateWindow_Release(priv_window); + SysFreeString(bstr); + + elem = get_elem_id(doc_node, L"inputid"); + IHTMLElement_Release(elem); + + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + hres = IHTMLDocument2_get_readyState(doc_node, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"uninitialized"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IHTMLDocument2_get_readyState(doc, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"uninitialized"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLPrivateWindow, (void**)&priv_window); + ok(hres == S_OK, "Could not get IHTMLPrivateWindow) interface: %08lx\n", hres); + hres = IHTMLPrivateWindow_GetAddressBarUrl(priv_window, &bstr); + ok(hres == S_OK, "GetAddressBarUrl failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"about:blank"), "unexpected address bar: %s\n", wine_dbgstr_w(bstr)); + IHTMLPrivateWindow_Release(priv_window); + SysFreeString(bstr); + + bstr = SysAllocString(L"inputid"); + doc3 = get_doc3_iface((IUnknown*)doc); + hres = IHTMLDocument3_getElementById(doc3, bstr, &elem); + ok(hres == S_OK, "getElementById returned: %08lx\n", hres); + ok(elem == NULL, "elem != NULL\n"); + IHTMLDocument3_Release(doc3); + SysFreeString(bstr); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + IHTMLWindow2_Release(window); + window = NULL; + + doc = create_document(); + if(!doc) + return; + set_client_site(doc, TRUE); + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + IHTMLWindow2_Release(window); + window = NULL; + + doc = create_document(); + if(!doc) + return; + set_client_site(doc, TRUE); + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + doc_load_string(doc, empty_doc_ie9_str); + cookie = register_cp((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); + while(!doc_complete && GetMessageA(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + unregister_cp((IUnknown*)doc, &IID_IPropertyNotifySink, cookie); + document_mode = 9; + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&onunload_obj; + hres = IHTMLWindow2_put_onunload(window, v); + ok(hres == S_OK, "put_onunload failed: %08lx\n", hres); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&onbeforeunload_obj; + hres = IHTMLWindow2_put_onbeforeunload(window, v); + ok(hres == S_OK, "put_onbeforeunload failed: %08lx\n", hres); + + IOleDocumentView_Release(view); + view = NULL; + + ref = IHTMLDocument2_Release(doc); + ok(ref == 0, "ref = %ld\n", ref); + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + + V_VT(&v) = VT_EMPTY; + IHTMLWindow2_put_onunload(window, v); + IHTMLWindow2_put_onbeforeunload(window, v); + IHTMLWindow2_Release(window); + window = NULL; +} + static void test_storage_events(const char *doc_str) { static struct { @@ -6372,6 +6517,9 @@ START_TEST(events) test_sync_xhr_events(empty_doc_ie9_str); }
+ /* Test this last since it doesn't close the view properly. */ + test_document_close(); + DestroyWindow(container_hwnd); }else { #if !defined(__i386__) && !defined(__x86_64__) diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c index 9874540e973..4db4777dca4 100644 --- a/dlls/mshtml/tests/htmldoc.c +++ b/dlls/mshtml/tests/htmldoc.c @@ -8461,10 +8461,12 @@ static void test_doc_domain(IHTMLDocument2 *doc)
static void test_HTMLDocument_http(BOOL with_wbapp) { + IHTMLDocument2 *doc, *doc_node; + IHTMLWindow2 *window; IMoniker *http_mon; - IHTMLDocument2 *doc; - ULONG ref; HRESULT hres; + ULONG ref; + BSTR bstr;
trace("Testing HTMLDocument (http%s)...\n", with_wbapp ? " with IWebBrowserApp" : "");
@@ -8529,12 +8531,42 @@ static void test_HTMLDocument_http(BOOL with_wbapp) test_IsDirty(doc, S_FALSE); test_GetCurMoniker((IUnknown*)doc, NULL, prev_url, support_wbapp);
+ hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + hres = IHTMLDocument2_get_readyState(doc_node, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + todo_wine_if(support_wbapp) + ok(!wcscmp(bstr, support_wbapp ? L"interactive" : L"complete"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + if(view) IOleDocumentView_Release(view); view = NULL;
release_document(doc);
+ hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + hres = IHTMLDocument2_get_readyState(doc_node, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"uninitialized"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IHTMLDocument2_get_readyState(doc, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"uninitialized"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + IHTMLWindow2_Release(window); + ref = IMoniker_Release(http_mon); ok(!ref, "ref=%ld, expected 0\n", ref); } diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c index dc5dac98ee7..de1fd056169 100644 --- a/dlls/mshtml/tests/script.c +++ b/dlls/mshtml/tests/script.c @@ -4525,7 +4525,10 @@ static void test_exec_script(IHTMLDocument2 *doc, const WCHAR *codew, const WCHA
static void test_simple_script(void) { + IHTMLDocument2 *doc_node; + IHTMLWindow2 *window; IHTMLDocument2 *doc; + HRESULT hres;
doc = create_document(); if(!doc) @@ -4596,6 +4599,12 @@ static void test_simple_script(void) if(window_dispex) IDispatchEx_Release(window_dispex);
+ hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + SET_EXPECT(SetScriptState_DISCONNECTED); SET_EXPECT(Close); SET_EXPECT(Close2); @@ -4605,6 +4614,14 @@ static void test_simple_script(void) CHECK_CALLED(SetScriptState_DISCONNECTED); CHECK_CALLED(Close); CHECK_CALLED(Close2); + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + IHTMLWindow2_Release(window); }
static void run_from_moniker(IMoniker *mon)