mshtml: Hold ref to HTMLDocumentObj when calling external code.

It's possible for it (and the GeckoBrowser) to get detached and destroyed
while processing an external callback notification.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
Gabriel Ivăncescu 2023-03-08 19:36:06 +02:00 committed by Alexandre Julliard
parent ff64d67f76
commit a62be201c8
8 changed files with 105 additions and 42 deletions

View file

@ -854,6 +854,7 @@ static HRESULT WINAPI HTMLDocument_get_scripts(IHTMLDocument2 *iface, IHTMLEleme
static HRESULT WINAPI HTMLDocument_put_designMode(IHTMLDocument2 *iface, BSTR v)
{
HTMLDocumentNode *This = impl_from_IHTMLDocument2(iface);
HTMLDocumentObj *doc_obj;
HRESULT hres;
TRACE("(%p)->(%s)\n", This, debugstr_w(v));
@ -863,7 +864,10 @@ static HRESULT WINAPI HTMLDocument_put_designMode(IHTMLDocument2 *iface, BSTR v)
return E_NOTIMPL;
}
hres = setup_edit_mode(This->doc_obj);
doc_obj = This->doc_obj;
IUnknown_AddRef(doc_obj->outer_unk);
hres = setup_edit_mode(doc_obj);
IUnknown_Release(doc_obj->outer_unk);
if(FAILED(hres))
return hres;

View file

@ -291,17 +291,21 @@ static void parse_complete(HTMLDocumentObj *doc)
static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISupports *arg2)
{
HTMLDocumentObj *doc_obj = This->doc_obj;
TRACE("(%p)\n", This);
if(!This->doc_obj)
if(!doc_obj)
return NS_OK;
if(This == This->doc_obj->doc_node) {
if(This == doc_obj->doc_node) {
/*
* This should be done in the worker thread that parses HTML,
* but we don't have such thread (Gecko parses HTML for us).
*/
parse_complete(This->doc_obj);
IUnknown_AddRef(doc_obj->outer_unk);
parse_complete(doc_obj);
IUnknown_Release(doc_obj->outer_unk);
}
bind_event_scripts(This);

View file

@ -1651,6 +1651,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 +1663,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 +1702,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)
@ -2066,25 +2070,31 @@ 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);
@ -2094,10 +2104,16 @@ static void navigate_javascript_proc(task_t *_task)
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(window->browser->doc, 0);
set_download_state(doc, 0);
}
done:
if(doc)
IUnknown_Release(doc->outer_unk);
}
static void navigate_javascript_task_destr(task_t *_task)
@ -2199,9 +2215,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;
@ -2209,6 +2228,7 @@ static HRESULT navigate_fragment(HTMLOuterWindow *window, IUri *uri)
HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WCHAR *headers, BYTE *post_data, DWORD post_data_size)
{
HTMLDocumentObj *doc_obj;
nsChannelBSC *bsc;
IUri *uri_nofrag;
IMoniker *mon;
@ -2219,10 +2239,13 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC
if(!uri_nofrag)
return E_FAIL;
if(window->browser->doc->client && !(flags & BINDING_REFRESH)) {
doc_obj = window->browser->doc;
IUnknown_AddRef(doc_obj->outer_unk);
if(doc_obj->client && !(flags & BINDING_REFRESH)) {
IOleCommandTarget *cmdtrg;
hres = IOleClientSite_QueryInterface(window->browser->doc->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
hres = IOleClientSite_QueryInterface(doc_obj->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
if(SUCCEEDED(hres)) {
VARIANT in, out;
BSTR url_str;
@ -2249,14 +2272,15 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC
if(SUCCEEDED(hres) && eq) {
IUri_Release(uri_nofrag);
TRACE("fragment navigate\n");
return navigate_fragment(window, uri);
hres = navigate_fragment(window, uri);
goto done;
}
}
hres = CreateURLMonikerEx2(NULL, uri_nofrag, &mon, URL_MK_UNIFORM);
IUri_Release(uri_nofrag);
if(FAILED(hres))
return hres;
goto done;
/* FIXME: Why not set_ready_state? */
window->readystate = READYSTATE_UNINITIALIZED;
@ -2264,10 +2288,10 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC
hres = create_channelbsc(mon, headers, post_data, post_data_size, TRUE, &bsc);
if(FAILED(hres)) {
IMoniker_Release(mon);
return hres;
goto done;
}
prepare_for_binding(window->browser->doc, mon, flags);
prepare_for_binding(doc_obj, mon, flags);
hres = IUri_GetScheme(uri, &scheme);
if(hres == S_OK && scheme == URL_SCHEME_JAVASCRIPT) {
@ -2277,13 +2301,15 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC
IMoniker_Release(mon);
task = malloc(sizeof(*task));
if(!task)
return E_OUTOFMEMORY;
if(!task) {
hres = E_OUTOFMEMORY;
goto done;
}
/* Why silently? */
window->readystate = READYSTATE_COMPLETE;
if(!(flags & BINDING_FROMHIST))
call_docview_84(window->browser->doc);
call_docview_84(doc_obj);
IUri_AddRef(uri);
task->window = window;
@ -2302,13 +2328,14 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC
if(!task) {
IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
IMoniker_Release(mon);
return E_OUTOFMEMORY;
hres = E_OUTOFMEMORY;
goto done;
}
/* Silently and repeated when real loading starts? */
window->readystate = READYSTATE_LOADING;
if(!(flags & (BINDING_FROMHIST|BINDING_REFRESH)))
call_docview_84(window->browser->doc);
call_docview_84(doc_obj);
task->window = window;
task->bscallback = bsc;
@ -2320,6 +2347,8 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC
hres = push_task(&task->header, navigate_proc, navigate_task_destr, window->task_magic);
}
done:
IUnknown_Release(doc_obj->outer_unk);
return hres;
}

View file

@ -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();

View file

@ -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;
}

View file

@ -687,12 +687,19 @@ static HRESULT exec_browsemode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT
static HRESULT exec_editmode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
HTMLDocumentObj *doc_obj;
HRESULT hres;
TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
if(in || out)
FIXME("unsupported args\n");
return setup_edit_mode(doc->browser->doc);
doc_obj = doc->browser->doc;
IUnknown_AddRef(doc_obj->outer_unk);
hres = setup_edit_mode(doc_obj);
IUnknown_Release(doc_obj->outer_unk);
return hres;
}
static HRESULT exec_htmleditmode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out)

View file

@ -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)
@ -341,16 +349,12 @@ HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBind
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 +405,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) {

View file

@ -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;
}