From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlform.c | 2 +- dlls/mshtml/htmlwindow.c | 25 ++++++++++++++++++++----- dlls/mshtml/mshtml_private.h | 8 ++++++++ dlls/mshtml/mutation.c | 2 +- dlls/mshtml/navigate.c | 8 ++++---- dlls/mshtml/script.c | 4 ++-- dlls/mshtml/tests/events.c | 5 ++--- 7 files changed, 38 insertions(+), 16 deletions(-)
diff --git a/dlls/mshtml/htmlform.c b/dlls/mshtml/htmlform.c index fc30742d540..0f084ef9341 100644 --- a/dlls/mshtml/htmlform.c +++ b/dlls/mshtml/htmlform.c @@ -570,7 +570,7 @@ static HRESULT WINAPI HTMLFormElement_submit(IHTMLFormElement *iface)
if(This->element.node.doc) { HTMLDocumentNode *doc = This->element.node.doc; - if(doc->window && doc->window->base.outer_window) + if(doc->window && !is_detached_window(doc->window)) this_window = doc->window->base.outer_window; } if(!this_window) { diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 11c7c6d892d..4ff5086cfb0 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -110,6 +110,10 @@ static void detach_inner_window(HTMLInnerWindow *window) HTMLOuterWindow *outer_window = window->base.outer_window; HTMLDocumentNode *doc = window->doc;
+ /* Check if already detached */ + if(!list_empty(&window->outer_window_entry)) + return; + while(!list_empty(&window->children)) { HTMLOuterWindow *child = LIST_ENTRY(list_tail(&window->children), HTMLOuterWindow, sibling_entry);
@@ -134,11 +138,13 @@ static void detach_inner_window(HTMLInnerWindow *window) abort_window_bindings(window); remove_target_tasks(window->task_magic); release_script_hosts(window); - window->base.outer_window = NULL;
- if(outer_window && outer_window->base.inner_window == window) { - outer_window->base.inner_window = NULL; - IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); + if(outer_window) { + list_add_tail(&outer_window->detached_inner_windows, &window->outer_window_entry); + if(outer_window->base.inner_window == window) { + outer_window->base.inner_window = NULL; + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); + } } }
@@ -4016,6 +4022,7 @@ static void HTMLWindow_destructor(DispatchEx *dispex) HTMLInnerWindow *This = impl_from_DispatchEx(dispex); unsigned i;
+ list_remove(&This->outer_window_entry); VariantClear(&This->performance);
for(i = 0; i < This->global_prop_cnt; i++) @@ -4337,6 +4344,12 @@ static nsresult NSAPI outer_window_unlink(void *p) { HTMLOuterWindow *window = HTMLOuterWindow_from_IHTMLWindow2(p);
+ while(!list_empty(&window->detached_inner_windows)) { + HTMLInnerWindow *inner_window = LIST_ENTRY(list_head(&window->detached_inner_windows), HTMLInnerWindow, outer_window_entry); + list_remove(&inner_window->outer_window_entry); + list_init(&inner_window->outer_window_entry); + inner_window->base.outer_window = NULL; + } if(window->browser) { list_remove(&window->browser_entry); window->browser = NULL; @@ -4425,6 +4438,7 @@ static HRESULT create_inner_window(HTMLOuterWindow *outer_window, IMoniker *mon, list_init(&window->script_hosts); list_init(&window->bindings); list_init(&window->script_queue); + list_init(&window->outer_window_entry);
window->base.outer_window = outer_window; window->base.inner_window = window; @@ -4459,6 +4473,7 @@ HRESULT create_outer_window(GeckoBrowser *browser, mozIDOMWindowProxy *mozwindow window->base.inner_window = NULL; window->browser = browser; list_add_head(&browser->outer_windows, &window->browser_entry); + list_init(&window->detached_inner_windows); ccref_init(&window->ccref, 1);
mozIDOMWindowProxy_AddRef(mozwindow); @@ -4511,7 +4526,7 @@ HRESULT create_pending_window(HTMLOuterWindow *outer_window, nsChannelBSC *chann
if(outer_window->pending_window) { abort_window_bindings(outer_window->pending_window); - outer_window->pending_window->base.outer_window = NULL; + list_add_tail(&outer_window->detached_inner_windows, &outer_window->pending_window->outer_window_entry); IHTMLWindow2_Release(&outer_window->pending_window->base.IHTMLWindow2_iface); }
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 23e1decc68b..f398f7d8f71 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -573,6 +573,7 @@ struct HTMLOuterWindow {
struct list sibling_entry; struct wine_rb_entry entry; + struct list detached_inner_windows; };
struct HTMLInnerWindow { @@ -633,6 +634,8 @@ struct HTMLInnerWindow { ULONGLONG load_event_start_time; ULONGLONG load_event_end_time; ULONGLONG first_paint_time; + + struct list outer_window_entry; };
typedef enum { @@ -1129,6 +1132,11 @@ static inline BOOL is_main_content_window(HTMLOuterWindow *window) return window->browser && window == window->browser->content_window; }
+static inline BOOL is_detached_window(HTMLInnerWindow *window) +{ + return !list_empty(&window->outer_window_entry) || !window->base.outer_window; +} + struct HTMLAttributeCollection { DispatchEx dispex; IHTMLAttributeCollection IHTMLAttributeCollection_iface; diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index a1438debd6f..7117e0f4740 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -437,7 +437,7 @@ static void set_document_mode(HTMLDocumentNode *doc, compat_mode_t document_mode
TRACE("%p: %d\n", doc, document_mode);
- max_compat_mode = doc->window && doc->window->base.outer_window + max_compat_mode = doc->window && !is_detached_window(doc->window) ? get_max_compat_mode(doc->window->base.outer_window->uri) : COMPAT_MODE_IE11; if(max_compat_mode < document_mode) { diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 90ca22ea8b1..f05bf0be9c6 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -578,7 +578,7 @@ static HRESULT WINAPI BindCallbackRedirect_Redirect(IBindCallbackRedirect *iface
TRACE("(%p)->(%s %p)\n", This, debugstr_w(url), vbCancel);
- if(This->window && This->window->base.outer_window && (browser = This->window->base.outer_window->browser) + if(This->window && !is_detached_window(This->window) && (browser = This->window->base.outer_window->browser) && browser->doc->doc_object_service) { if(is_main_content_window(This->window->base.outer_window)) { hres = IHTMLWindow2_get_name(&This->window->base.IHTMLWindow2_iface, &frame_name); @@ -1269,7 +1269,7 @@ static nsresult NSAPI nsAsyncVerifyRedirectCallback_OnRedirectVerifyCallback(nsI ERR("AddRequest failed: %08lx\n", nsres); }
- if(This->bsc->is_doc_channel && This->bsc->bsc.window && This->bsc->bsc.window->base.outer_window) { + if(This->bsc->is_doc_channel && This->bsc->bsc.window && !is_detached_window(This->bsc->bsc.window)) { IUri *uri = nsuri_get_uri(This->nschannel->uri);
if(uri) { @@ -1445,7 +1445,7 @@ static void handle_navigation_error(nsChannelBSC *This, DWORD result) BSTR unk; HRESULT hres;
- if(!This->is_doc_channel || !This->bsc.window || !This->bsc.window->base.outer_window + if(!This->is_doc_channel || !This->bsc.window || is_detached_window(This->bsc.window) || !This->bsc.window->base.outer_window->browser) return;
@@ -1644,7 +1644,7 @@ static void handle_extern_mime_navigation(nsChannelBSC *This) VARIANT flags; HRESULT hres;
- if(!This->bsc.window || !This->bsc.window->base.outer_window || !This->bsc.window->base.outer_window->browser) + if(!This->bsc.window || is_detached_window(This->bsc.window) || !This->bsc.window->base.outer_window->browser) return;
doc_obj = This->bsc.window->base.outer_window->browser->doc; diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c index cad0f17671a..514b2a9c140 100644 --- a/dlls/mshtml/script.c +++ b/dlls/mshtml/script.c @@ -374,7 +374,7 @@ static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPC if(wcscmp(pstrName, L"window")) return DISP_E_MEMBERNOTFOUND;
- if(!This->window || !This->window->base.outer_window) + if(!This->window || is_detached_window(This->window)) return E_FAIL;
/* FIXME: Return proxy object */ @@ -518,7 +518,7 @@ static HRESULT WINAPI ActiveScriptSiteWindow_GetWindow(IActiveScriptSiteWindow *
TRACE("(%p)->(%p)\n", This, phwnd);
- if(!This->window || !This->window->base.outer_window) + if(!This->window || is_detached_window(This->window)) return E_UNEXPECTED;
*phwnd = This->window->base.outer_window->browser->doc->hwnd; diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index e5b9984e546..c11d53d611f 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -3304,10 +3304,10 @@ static void test_window_refs(IHTMLDocument2 *doc) IHTMLWindow2_Release(child);
hres = IHTMLXMLHttpRequestFactory_create(xhr_factory, &xhr); - todo_wine ok(hres == S_OK, "create failed: %08lx\n", hres); + ok(xhr != NULL, "xhr == NULL\n"); IHTMLXMLHttpRequestFactory_Release(xhr_factory); - if(hres == S_OK) IHTMLXMLHttpRequest_Release(xhr); + IHTMLXMLHttpRequest_Release(xhr);
hres = IHTMLImageElementFactory_create(image_factory, vempty, vempty, &img_elem); ok(hres == S_OK, "create failed: %08lx\n", hres); @@ -3323,7 +3323,6 @@ static void test_window_refs(IHTMLDocument2 *doc)
hres = IOmHistory_get_length(history, &length); ok(hres == S_OK, "get_length failed: %08lx\n", hres); - todo_wine ok(length == 42, "length = %d\n", length); IOmHistory_Release(history); }