This should fix some rare crashes in e.g. FFXIV Launcher (requires Proton patches to have it working though).
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Like it is done in nsevents, we must assume navigation can happen when calling external code (and thus, windows becoming detached) and handle it appropriately, to avoid crashes.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/editor.c | 10 ++-- dlls/mshtml/mutation.c | 8 +++- dlls/mshtml/navigate.c | 104 +++++++++++++++++++++++++++++------------ dlls/mshtml/nsevents.c | 15 +++--- dlls/mshtml/nsio.c | 11 ++++- dlls/mshtml/olecmd.c | 2 +- dlls/mshtml/persist.c | 40 +++++++++++----- dlls/mshtml/view.c | 3 ++ 8 files changed, 138 insertions(+), 55 deletions(-)
diff --git a/dlls/mshtml/editor.c b/dlls/mshtml/editor.c index 478c30932c1..b478bfdebf6 100644 --- a/dlls/mshtml/editor.c +++ b/dlls/mshtml/editor.c @@ -1195,6 +1195,7 @@ HRESULT setup_edit_mode(HTMLDocumentObj *doc) return S_OK;
doc->nscontainer->usermode = EDITMODE; + IUnknown_AddRef(doc->outer_unk);
if(doc->window->mon) { CLSID clsid = IID_NULL; @@ -1250,14 +1251,14 @@ HRESULT setup_edit_mode(HTMLDocumentObj *doc) hres = CreateURLMoniker(NULL, L"about:blank", &mon); if(FAILED(hres)) { FIXME("CreateURLMoniker failed: %08lx\n", hres); - return hres; + goto done; } }
hres = IPersistMoniker_Load(&doc->IPersistMoniker_iface, TRUE, mon, NULL, 0); IMoniker_Release(mon); if(FAILED(hres)) - return hres; + goto done;
if(doc->ui_active) { if(doc->ip_window) @@ -1281,6 +1282,9 @@ HRESULT setup_edit_mode(HTMLDocumentObj *doc) if(doc->frame) IOleInPlaceFrame_SetBorderSpace(doc->frame, &rcBorderWidths); } + hres = S_OK;
- return S_OK; +done: + IUnknown_Release(doc->outer_unk); + return hres; } diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index e308c1af31b..74424bb8afc 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -295,6 +295,8 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo
if(!This->doc_obj) return NS_OK; + IUnknown_AddRef(This->doc_obj->outer_unk); + IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface);
if(This == This->doc_obj->doc_node) { /* @@ -308,6 +310,9 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo
This->window->performance_timing->dom_interactive_time = get_time_stamp(); set_ready_state(This->outer_window, READYSTATE_INTERACTIVE); + + IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface); + IUnknown_Release(This->doc_obj->outer_unk); return NS_OK; }
@@ -364,14 +369,13 @@ static nsresult run_insert_script(HTMLDocumentNode *doc, nsISupports *script_ifa free(iter); }
- IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); - if(nsparser) { window->parser_callback_cnt--; nsIParser_EndEvaluatingParserInsertedScript(nsparser); nsIParser_Release(nsparser); }
+ IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); IHTMLScriptElement_Release(&script_elem->IHTMLScriptElement_iface);
return NS_OK; diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index b8d7937f071..fc6b36e267c 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1419,6 +1419,7 @@ static void stop_request_task_destr(task_t *_task)
static HRESULT async_stop_request(nsChannelBSC *This) { + LONG task_magic = This->bsc.window->task_magic; stop_request_task_t *task;
if(!This->bsc.read) { @@ -1433,7 +1434,7 @@ static HRESULT async_stop_request(nsChannelBSC *This) IBindStatusCallback_AddRef(&This->bsc.IBindStatusCallback_iface); task->bsc = This;
- return push_task(&task->header, stop_request_proc, stop_request_task_destr, This->bsc.window->task_magic); + return push_task(&task->header, stop_request_proc, stop_request_task_destr, task_magic); }
static void handle_navigation_error(nsChannelBSC *This, DWORD result) @@ -1651,6 +1652,7 @@ static void handle_extern_mime_navigation(nsChannelBSC *This) return;
doc_obj = This->bsc.window->base.outer_window->browser->doc; + IUnknown_AddRef(doc_obj->outer_unk);
hres = IOleClientSite_QueryInterface(doc_obj->client, &IID_IOleCommandTarget, (void**)&cmdtrg); if(SUCCEEDED(hres)) { @@ -1662,17 +1664,17 @@ static void handle_extern_mime_navigation(nsChannelBSC *This)
if(!doc_obj->webbrowser) { FIXME("unimplemented in non-webbrowser mode\n"); - return; + goto done; }
uri = get_moniker_uri(This->bsc.mon); if(!uri) - return; + goto done;
hres = CreateBindCtx(0, &bind_ctx); if(FAILED(hres)) { IUri_Release(uri); - return; + goto done; }
V_VT(&flags) = VT_I4; @@ -1701,6 +1703,9 @@ static void handle_extern_mime_navigation(nsChannelBSC *This) }
IUri_Release(uri); + +done: + IUnknown_Release(doc_obj->outer_unk); }
static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG progress, ULONG total, ULONG status_code, LPCWSTR status_text) @@ -1939,8 +1944,12 @@ typedef struct { static void start_doc_binding_proc(task_t *_task) { start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task; + HTMLOuterWindow *window = task->window; + + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); + set_current_mon(window, task->pending_window->bscallback->bsc.mon, task->flags); + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
- set_current_mon(task->window, task->pending_window->bscallback->bsc.mon, task->flags); start_binding(task->pending_window, &task->pending_window->bscallback->bsc, NULL); }
@@ -2007,6 +2016,7 @@ void abort_window_bindings(HTMLInnerWindow *window)
HRESULT channelbsc_load_stream(HTMLInnerWindow *pending_window, IMoniker *mon, IStream *stream) { + HTMLOuterWindow *window = pending_window->base.outer_window; nsChannelBSC *bscallback = pending_window->bscallback; HRESULT hres = S_OK;
@@ -2019,7 +2029,9 @@ HRESULT channelbsc_load_stream(HTMLInnerWindow *pending_window, IMoniker *mon, I if(!bscallback->nschannel->content_type) return E_OUTOFMEMORY;
- set_current_mon(pending_window->base.outer_window, mon, 0); + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); + set_current_mon(window, mon, 0); + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
bscallback->bsc.window = pending_window; if(stream) @@ -2066,38 +2078,52 @@ static void navigate_javascript_proc(task_t *_task) { navigate_javascript_task_t *task = (navigate_javascript_task_t*)_task; HTMLOuterWindow *window = task->window; + HTMLDocumentObj *doc = NULL; BSTR code = NULL; VARIANT v; HRESULT hres;
- task->window->readystate = READYSTATE_COMPLETE; + window->readystate = READYSTATE_COMPLETE; + if(window->browser) { + doc = window->browser->doc; + IUnknown_AddRef(doc->outer_unk); + }
hres = IUri_GetPath(task->uri, &code); if(hres != S_OK) { SysFreeString(code); - return; + goto done; }
hres = UrlUnescapeW(code, NULL, NULL, URL_UNESCAPE_INPLACE); if(FAILED(hres)) { SysFreeString(code); - return; + goto done; }
- set_download_state(window->browser->doc, 1); + if(doc) + set_download_state(doc, 1);
- V_VT(&v) = VT_EMPTY; - hres = exec_script(window->base.inner_window, code, L"jscript", &v); - SysFreeString(code); - if(SUCCEEDED(hres) && V_VT(&v) != VT_EMPTY) { - FIXME("javascirpt URL returned %s\n", debugstr_variant(&v)); - VariantClear(&v); + if(window->base.inner_window) { + V_VT(&v) = VT_EMPTY; + hres = exec_script(window->base.inner_window, code, L"jscript", &v); + SysFreeString(code); + if(SUCCEEDED(hres) && V_VT(&v) != VT_EMPTY) { + FIXME("javascirpt URL returned %s\n", debugstr_variant(&v)); + VariantClear(&v); + } }
- if(window->browser->doc->view_sink) - IAdviseSink_OnViewChange(window->browser->doc->view_sink, DVASPECT_CONTENT, -1); + if(doc) { + if(doc->view_sink) + IAdviseSink_OnViewChange(doc->view_sink, DVASPECT_CONTENT, -1); + + set_download_state(doc, 0); + }
- set_download_state(window->browser->doc, 0); +done: + if(doc) + IUnknown_Release(doc->outer_unk); }
static void navigate_javascript_task_destr(task_t *_task) @@ -2119,14 +2145,19 @@ typedef struct { static void navigate_proc(task_t *_task) { navigate_task_t *task = (navigate_task_t*)_task; + HTMLOuterWindow *window = task->window; HRESULT hres;
- hres = set_moniker(task->window, task->mon, task->uri, NULL, task->bscallback, TRUE); + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); + + hres = set_moniker(window, task->mon, task->uri, NULL, task->bscallback, TRUE); if(SUCCEEDED(hres)) { - set_current_mon(task->window, task->bscallback->bsc.mon, task->flags); - set_current_uri(task->window, task->uri); - start_binding(task->window->pending_window, &task->bscallback->bsc, NULL); + set_current_mon(window, task->bscallback->bsc.mon, task->flags); + set_current_uri(window, task->uri); + start_binding(window->pending_window, &task->bscallback->bsc, NULL); } + + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); }
static void navigate_task_destr(task_t *_task) @@ -2199,9 +2230,12 @@ static HRESULT navigate_fragment(HTMLOuterWindow *window, IUri *uri) SysFreeString(frag);
if(window->browser->doc->doc_object_service) { - IDocObjectService_FireNavigateComplete2(window->browser->doc->doc_object_service, &window->base.IHTMLWindow2_iface, 0x10); - IDocObjectService_FireDocumentComplete(window->browser->doc->doc_object_service, &window->base.IHTMLWindow2_iface, 0); + HTMLDocumentObj *doc_obj = window->browser->doc;
+ IUnknown_AddRef(doc_obj->outer_unk); + IDocObjectService_FireNavigateComplete2(doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0x10); + IDocObjectService_FireDocumentComplete(doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0); + IUnknown_Release(doc_obj->outer_unk); }
return S_OK; @@ -2240,6 +2274,9 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC SysFreeString(url_str); } } + + if(!window->browser) + return S_OK; }
if(!(flags & BINDING_NOFRAG) && window->uri_nofrag && !post_data_size) { @@ -2268,6 +2305,11 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC }
prepare_for_binding(window->browser->doc, mon, flags); + if(!window->browser) { + IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface); + IMoniker_Release(mon); + return S_OK; + }
hres = IUri_GetScheme(uri, &scheme); if(hres == S_OK && scheme == URL_SCHEME_JAVASCRIPT) { @@ -2639,14 +2681,16 @@ HRESULT navigate_url(HTMLOuterWindow *window, const WCHAR *new_url, IUri *base_u hres = create_uri(new_url, 0, &nav_uri); if(FAILED(hres)) return hres; + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
hres = translate_uri(window, nav_uri, &display_uri, &uri); IUri_Release(nav_uri); - if(FAILED(hres)) - return hres; + if(SUCCEEDED(hres)) { + hres = navigate_uri(window, uri, display_uri, NULL, flags); + IUri_Release(uri); + SysFreeString(display_uri); + }
- hres = navigate_uri(window, uri, display_uri, NULL, flags); - IUri_Release(uri); - SysFreeString(display_uri); + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); return hres; } diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index b3616b64964..177981acc25 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -339,9 +339,10 @@ static nsresult handle_load(HTMLDocumentNode *doc, nsIDOMEvent *event)
if(!doc->outer_window) return NS_ERROR_FAILURE; - if(doc->doc_obj && doc->doc_obj->doc_node == doc) + if(doc->doc_obj && doc->doc_obj->doc_node == doc) { doc_obj = doc->doc_obj; - + IUnknown_AddRef(doc_obj->outer_unk); + } connect_scripts(doc->window);
if(doc_obj) @@ -357,11 +358,13 @@ static nsresult handle_load(HTMLDocumentNode *doc, nsIDOMEvent *event) set_statustext(doc_obj, IDS_STATUS_DONE, NULL);
update_title(doc_obj); - }
- if(doc_obj && doc_obj->doc_object_service && !(doc->outer_window->load_flags & BINDING_REFRESH)) - IDocObjectService_FireDocumentComplete(doc_obj->doc_object_service, - &doc->outer_window->base.IHTMLWindow2_iface, 0); + if(doc_obj->doc_object_service && !(doc->outer_window->load_flags & BINDING_REFRESH)) + IDocObjectService_FireDocumentComplete(doc_obj->doc_object_service, + &doc->outer_window->base.IHTMLWindow2_iface, 0); + + IUnknown_Release(doc_obj->outer_unk); + }
doc->window->performance_timing->load_event_start_time = get_time_stamp();
diff --git a/dlls/mshtml/nsio.c b/dlls/mshtml/nsio.c index 509a83efbd3..d29bb43544e 100644 --- a/dlls/mshtml/nsio.c +++ b/dlls/mshtml/nsio.c @@ -217,6 +217,9 @@ static BOOL exec_shldocvw_67(HTMLDocumentObj *doc, BSTR url) IOleCommandTarget *cmdtrg = NULL; HRESULT hres;
+ if(!doc->client) + return TRUE; + hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&cmdtrg); if(SUCCEEDED(hres)) { VARIANT varUrl, varRes; @@ -252,6 +255,7 @@ static nsresult before_async_open(nsChannel *channel, GeckoBrowser *container, B hres = IUri_GetDisplayUri(channel->uri->uri, &display_uri); if(FAILED(hres)) return NS_ERROR_FAILURE; + IUnknown_AddRef(doc->outer_unk);
if(doc->hostui) { OLECHAR *new_url; @@ -261,7 +265,7 @@ static nsresult before_async_open(nsChannel *channel, GeckoBrowser *container, B FIXME("TranslateUrl returned new URL %s -> %s\n", debugstr_w(display_uri), debugstr_w(new_url)); CoTaskMemFree(new_url); *cancel = TRUE; - return NS_OK; + goto done; } CoTaskMemFree(new_url); } @@ -270,13 +274,16 @@ static nsresult before_async_open(nsChannel *channel, GeckoBrowser *container, B if(!exec_shldocvw_67(doc, display_uri)) { SysFreeString(display_uri); *cancel = FALSE; - return NS_OK; + goto done; }
hres = hlink_frame_navigate(doc, display_uri, channel, 0, cancel); SysFreeString(display_uri); if(FAILED(hres)) *cancel = TRUE; + +done: + IUnknown_Release(doc->outer_unk); return NS_OK; }
diff --git a/dlls/mshtml/olecmd.c b/dlls/mshtml/olecmd.c index 9e59778ccb9..ff900c76c04 100644 --- a/dlls/mshtml/olecmd.c +++ b/dlls/mshtml/olecmd.c @@ -438,7 +438,7 @@ static void refresh_proc(task_t *_task) IOleCommandTarget_Exec(window->browser->doc->client_cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL); }
- load_uri(task->window, task->window->uri, BINDING_REFRESH|BINDING_NOFRAG); + load_uri(window, window->uri, BINDING_REFRESH|BINDING_NOFRAG); }
static void refresh_destr(task_t *_task) diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c index 486643d8b21..bbecc8ce1c2 100644 --- a/dlls/mshtml/persist.c +++ b/dlls/mshtml/persist.c @@ -208,6 +208,8 @@ static void set_progress_proc(task_t *_task)
TRACE("(%p)\n", doc);
+ IUnknown_AddRef(doc->outer_unk); + if(doc->client) IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
@@ -238,6 +240,8 @@ static void set_progress_proc(task_t *_task) hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick, debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS)); } + + IUnknown_Release(doc->outer_unk); }
static void set_progress_destr(task_t *_task) @@ -252,13 +256,14 @@ static void set_downloading_proc(task_t *_task)
TRACE("(%p)\n", doc);
+ IUnknown_AddRef(doc->outer_unk); set_statustext(doc, IDS_STATUS_DOWNLOADINGFROM, task->url);
if(task->set_download) set_download_state(doc, 1);
if(!doc->client) - return; + goto done;
if(doc->view_sink) IAdviseSink_OnViewChange(doc->view_sink, DVASPECT_CONTENT, -1); @@ -272,6 +277,9 @@ static void set_downloading_proc(task_t *_task) IDropTarget_Release(drop_target); } } + +done: + IUnknown_Release(doc->outer_unk); }
static void set_downloading_task_destr(task_t *_task) @@ -285,6 +293,8 @@ void prepare_for_binding(HTMLDocumentObj *This, IMoniker *mon, DWORD flags) { HRESULT hres;
+ IUnknown_AddRef(This->outer_unk); + if(This->client) { VARIANT silent, offline;
@@ -335,22 +345,20 @@ void prepare_for_binding(HTMLDocumentObj *This, IMoniker *mon, DWORD flags) IOleCommandTarget_Release(cmdtrg); } } + + IUnknown_Release(This->outer_unk); }
HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBindCtx *pibc, nsChannelBSC *async_bsc, BOOL set_download) { download_proc_task_t *download_task; - HTMLDocumentObj *doc_obj = NULL; nsChannelBSC *bscallback; nsWineURI *nsuri; LPOLESTR url; IUri *uri; HRESULT hres;
- if(is_main_content_window(window)) - doc_obj = window->browser->doc; - hres = IMoniker_GetDisplayName(mon, pibc, NULL, &url); if(FAILED(hres)) { WARN("GetDisplayName failed: %08lx\n", hres); @@ -401,7 +409,9 @@ HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBind return hres; }
- if(doc_obj) { + if(is_main_content_window(window)) { + HTMLDocumentObj *doc_obj = window->browser->doc; + HTMLDocument_LockContainer(doc_obj, TRUE);
if(doc_obj->frame) { @@ -431,27 +441,35 @@ HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBind
static void notif_readystate(HTMLOuterWindow *window) { + HTMLInnerWindow *inner_window = window->base.inner_window; + HTMLFrameBase *frame_element = window->frame_element; DOMEvent *event; HRESULT hres;
window->readystate_pending = FALSE;
+ IHTMLWindow2_AddRef(&inner_window->base.IHTMLWindow2_iface); + if(frame_element) + IHTMLDOMNode_AddRef(&frame_element->element.node.IHTMLDOMNode_iface); + if(is_main_content_window(window)) call_property_onchanged(&window->browser->doc->cp_container, DISPID_READYSTATE);
- hres = create_document_event(window->base.inner_window->doc, EVENTID_READYSTATECHANGE, &event); + hres = create_document_event(inner_window->doc, EVENTID_READYSTATECHANGE, &event); if(SUCCEEDED(hres)) { event->no_event_obj = TRUE; - dispatch_event(&window->base.inner_window->doc->node.event_target, event); + dispatch_event(&inner_window->doc->node.event_target, event); IDOMEvent_Release(&event->IDOMEvent_iface); } + IHTMLWindow2_Release(&inner_window->base.IHTMLWindow2_iface);
- if(window->frame_element) { - hres = create_document_event(window->frame_element->element.node.doc, EVENTID_READYSTATECHANGE, &event); + if(frame_element) { + hres = create_document_event(frame_element->element.node.doc, EVENTID_READYSTATECHANGE, &event); if(SUCCEEDED(hres)) { - dispatch_event(&window->frame_element->element.node.event_target, event); + dispatch_event(&frame_element->element.node.event_target, event); IDOMEvent_Release(&event->IDOMEvent_iface); } + IHTMLDOMNode_Release(&frame_element->element.node.IHTMLDOMNode_iface); } }
diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index 6b7ecb0bc27..346fccf4955 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -117,6 +117,7 @@ static LRESULT on_timer(HTMLDocumentObj *This)
if(!This->update) return 0; + IUnknown_AddRef(This->outer_unk);
if(This->update & UPDATE_UI) { if(This->hostui) @@ -138,6 +139,8 @@ static LRESULT on_timer(HTMLDocumentObj *This)
update_title(This); This->update = 0; + + IUnknown_Release(This->outer_unk); return 0; }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/view.c | 74 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 23 deletions(-)
diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index 346fccf4955..3f31e609e39 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -414,45 +414,73 @@ HRESULT call_set_active_object(IOleInPlaceUIWindow *window, IOleInPlaceActiveObj return IOleInPlaceUIWindow_SetActiveObject(window, act_obj, act_obj ? html_documentW : NULL); }
-static void send_unload_events_impl(HTMLInnerWindow *window) +static unsigned get_window_list_num(HTMLInnerWindow *window) { HTMLOuterWindow *child; + unsigned ret = 1; + + LIST_FOR_EACH_ENTRY(child, &window->children, HTMLOuterWindow, sibling_entry) + ret += get_window_list_num(child->base.inner_window); + return ret; +} + +static HTMLInnerWindow **get_window_list(HTMLInnerWindow *window, HTMLInnerWindow **output) +{ + HTMLOuterWindow *child; + + *output++ = window; + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); + + LIST_FOR_EACH_ENTRY(child, &window->children, HTMLOuterWindow, sibling_entry) + output = get_window_list(child->base.inner_window, output); + return output; +} + +static void send_unload_events(HTMLDocumentObj *doc) +{ + HTMLInnerWindow **windows, *window; DOMEvent *event; + unsigned i, num; HRESULT hres;
- if(!window) + if(!doc->window || !doc->doc_node->content_ready) + return; + window = doc->window->base.inner_window; + + /* Grab list of all windows ahead, and keep refs, + since it can be detached from under our feet. */ + num = get_window_list_num(window); + if(!(windows = malloc(num * sizeof(*windows)))) return; + get_window_list(window, windows); + + for(i = 0; i < num; i++) { + window = windows[i];
- if(window->doc && !window->doc->unload_sent) { - window->doc->unload_sent = TRUE; + if(window->doc && !window->doc->unload_sent) { + window->doc->unload_sent = TRUE; + + /* Native sends pagehide events prior to unload on the same window + before it moves on to the next window, so they're interleaved. */ + if(window->doc->document_mode >= COMPAT_MODE_IE11) { + hres = create_document_event(window->doc, EVENTID_PAGEHIDE, &event); + if(SUCCEEDED(hres)) { + dispatch_event(&window->event_target, event); + IDOMEvent_Release(&event->IDOMEvent_iface); + } + }
- /* Native sends pagehide events prior to unload on the same window - before it moves on to the next window, so they're interleaved. */ - if(window->doc->document_mode >= COMPAT_MODE_IE11) { - hres = create_document_event(window->doc, EVENTID_PAGEHIDE, &event); + hres = create_document_event(window->doc, EVENTID_UNLOAD, &event); if(SUCCEEDED(hres)) { dispatch_event(&window->event_target, event); IDOMEvent_Release(&event->IDOMEvent_iface); } }
- hres = create_document_event(window->doc, EVENTID_UNLOAD, &event); - if(SUCCEEDED(hres)) { - dispatch_event(&window->event_target, event); - IDOMEvent_Release(&event->IDOMEvent_iface); - } + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); }
- LIST_FOR_EACH_ENTRY(child, &window->children, HTMLOuterWindow, sibling_entry) - send_unload_events_impl(child->base.inner_window); -} - -static void send_unload_events(HTMLDocumentObj *doc) -{ - if(!doc->window || !doc->doc_node->content_ready) - return; - - send_unload_events_impl(doc->window->base.inner_window); + free(windows); }
/**********************************************************
Please split the first patch.