[PATCH v6 0/4] MR11394: ieframe/mshtml: Fire property change notification when document title is set.
NSIS HTML installers communicate with the installer engine by setting document.title and expecting the host to receive a property change notification. Without this notification the installer never sets the default install path, so clicking the install button has no effect. -- v6: ieframe/tests: Test TitleChange event is fired on navigation. ieframe: Fire TitleChange event on document title change. mshtml/tests: Add test for property change notification when document title is set. mshtml: Fire property change notification when document title is set. https://gitlab.winehq.org/wine/wine/-/merge_requests/11394
From: chenzhengyong <chenzhengyong@uniontech.com> NSIS HTML installers communicate with the installer engine by setting document.title and expecting the host to receive a property change notification. Without this notification the installer never sets the default install path, so clicking the install button has no effect. Signed-off-by: chenzhengyong <chenzhengyong@uniontech.com> --- dlls/mshtml/htmldoc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index ef964297404..f3dee79e997 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -649,6 +649,11 @@ static HRESULT WINAPI HTMLDocument_put_title(IHTMLDocument2 *iface, BSTR v) if(NS_FAILED(nsres)) ERR("SetTitle failed: %08lx\n", nsres); + if(This->doc_obj) + call_property_onchanged(&This->doc_obj->cp_container, DISPID_IHTMLDOCUMENT2_TITLE); + else + call_property_onchanged(&This->cp_container, DISPID_IHTMLDOCUMENT2_TITLE); + return S_OK; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11394
From: chenzhengyong <chenzhengyong@uniontech.com> Verify that IPropertyNotifySink::OnChanged is fired with DISPID_IHTMLDOCUMENT2_TITLE when IHTMLDocument2::put_title is called. Signed-off-by: chenzhengyong <chenzhengyong@uniontech.com> --- dlls/mshtml/tests/dom.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index bfaad84c186..150f7e825c8 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -12528,6 +12528,7 @@ static void test_quirks_mode_perf_toJSON(IHTMLDocument2 *doc) static IHTMLDocument2 *notif_doc; static BOOL doc_complete; +static BOOL called_OnChanged_title; static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, REFIID riid, void**ppv) @@ -12564,6 +12565,8 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D doc_complete = TRUE; SysFreeString(state); + }else if(dispID == DISPID_IHTMLDOCUMENT2_TITLE) { + called_OnChanged_title = TRUE; } return S_OK; @@ -13023,6 +13026,14 @@ static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise) ok(hres == S_OK, "Advise failed: %08lx\n", hres); } +static void test_doc_title_notify(IHTMLDocument2 *doc) +{ + called_OnChanged_title = FALSE; + test_doc_set_title(doc, L"wine title notify test"); + ok(called_OnChanged_title, "OnChanged(DISPID_IHTMLDOCUMENT2_TITLE) not fired\n"); + test_doc_title(doc, L"wine title notify test"); +} + typedef void (*domtest_t)(IHTMLDocument2*); static void run_domtest(const char *str, domtest_t test) @@ -13964,6 +13975,7 @@ START_TEST(dom) run_domtest(doctype_str, test_doctype); run_domtest(case_insens_str, test_case_insens); run_domtest(doc_blank, test_method_vs_getter); + run_domtest(doc_blank, test_doc_title_notify); if(is_ie9plus) { compat_mode = COMPAT_IE9; run_domtest(emptydiv_ie9_str, test_docfrag); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11394
From: chenzhengyong <chenzhengyong@uniontech.com> Fire DWebBrowserEvents2::TitleChange when the document title changes, both from the OLECMDID_SETTITLE command (sent by mshtml during navigation) and from the IPropertyNotifySink::OnChanged(DISPID_IHTMLDOCUMENT2_TITLE) notification (sent when document.title is set via script or COM). This makes NSIS HTML installers receive the title-based communication messages and proceed with installation. Signed-off-by: chenzhengyong <chenzhengyong@uniontech.com> --- dlls/ieframe/dochost.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/dlls/ieframe/dochost.c b/dlls/ieframe/dochost.c index add816fe97e..b603d24aa6e 100644 --- a/dlls/ieframe/dochost.c +++ b/dlls/ieframe/dochost.c @@ -22,6 +22,7 @@ #include "exdispid.h" #include "mshtml.h" +#include "mshtmdid.h" #include "perhist.h" #include "initguid.h" @@ -82,6 +83,40 @@ void abort_dochost_tasks(DocHost *This, task_proc_t proc) } } +static BOOL fire_titlechange(DocHost *This) +{ + IHTMLDocument2 *doc; + BSTR title = NULL; + DISPPARAMS dp = { NULL, NULL, 0, 0 }; + HRESULT hres; + BOOL has_title = FALSE; + VARIANTARG arg; + + if(!This->document) + return FALSE; + + hres = IUnknown_QueryInterface(This->document, &IID_IHTMLDocument2, (void **)&doc); + if(FAILED(hres)) + return FALSE; + + hres = IHTMLDocument2_get_title(doc, &title); + IHTMLDocument2_Release(doc); + if(FAILED(hres) || !title) + return FALSE; + + has_title = *title != 0; + + VariantInit(&arg); + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = title; + dp.rgvarg = &arg; + dp.cArgs = 1; + call_sink(This->cps.wbe2, DISPID_TITLECHANGE, &dp); + VariantClear(&arg); + + return has_title; +} + void on_commandstate_change(DocHost *doc_host, LONG command, BOOL enable) { DISPPARAMS dispparams; @@ -708,6 +743,10 @@ static HRESULT WINAPI ClOleCommandTarget_Exec(IOleCommandTarget *iface, if(!This->olecmd) return E_NOTIMPL; return IOleCommandTarget_Exec(This->olecmd, pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); + case OLECMDID_SETTITLE: + if(fire_titlechange(This) && This->olecmd) + return IOleCommandTarget_Exec(This->olecmd, pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); + return S_OK; case OLECMDID_SETDOWNLOADSTATE: if(pvaIn && V_VT(pvaIn) == VT_I4) This->busy = V_I4(pvaIn) ? VARIANT_TRUE : VARIANT_FALSE; @@ -1109,6 +1148,9 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D update_ready_state(This, ready_state); break; } + case DISPID_IHTMLDOCUMENT2_TITLE: + fire_titlechange(This); + break; default: FIXME("unimplemented dispid %ld\n", dispID); return E_NOTIMPL; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11394
From: chenzhengyong <chenzhengyong@uniontech.com> Remove the todo_wine marker for Invoke_TITLECHANGE, since ieframe now fires DWebBrowserEvents2::TitleChange in response to the OLECMDID_SETTITLE command sent by mshtml during navigation and the DISPID_IHTMLDOCUMENT2_TITLE property change notification. Also validate the BSTR argument passed to the event. Signed-off-by: chenzhengyong <chenzhengyong@uniontech.com> --- dlls/ieframe/tests/webbrowser.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dlls/ieframe/tests/webbrowser.c b/dlls/ieframe/tests/webbrowser.c index 8c514a6ffc2..2cd8491d5f6 100644 --- a/dlls/ieframe/tests/webbrowser.c +++ b/dlls/ieframe/tests/webbrowser.c @@ -1010,7 +1010,10 @@ static HRESULT WINAPI WebBrowserEvents2_Invoke(IDispatch *iface, DISPID dispIdMe case DISPID_TITLECHANGE: CHECK_EXPECT2(Invoke_TITLECHANGE); - /* FIXME */ + ok(pDispParams->rgvarg != NULL, "rgvarg == NULL\n"); + ok(pDispParams->cArgs == 1, "cArgs=%d, expected 1\n", pDispParams->cArgs); + ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(pDispParams->rgvarg)=%d, expected VT_BSTR\n", + V_VT(pDispParams->rgvarg)); break; case DISPID_NAVIGATECOMPLETE2: @@ -3128,7 +3131,7 @@ static void test_download(DWORD flags) CHECK_CALLED(Exec_SETDOWNLOADSTATE_0); else CHECK_CALLED(Invoke_DOWNLOADCOMPLETE); - todo_wine CHECK_CALLED(Invoke_TITLECHANGE); + CHECK_CALLED(Invoke_TITLECHANGE); if(!(flags & DWL_REFRESH)) CHECK_CALLED(Invoke_NAVIGATECOMPLETE2); if(is_first_load) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11394
On Fri Jul 17 13:14:16 2026 +0000, Jacek Caban wrote:
It would be probably better to have those tests in events.c, where we have macros like `CHECK_EXPECT`. This version does not check for unexpected calls, for example. `test_doc_title_notify` calls `test_doc_set_title`, which is defined in `dom.c`. I'd rather not duplicate its definition in `events.c`.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11394#note_146037
On Sun Jul 19 04:01:40 2026 +0000, zhengyong chen wrote:
changed this line in [version 6 of the diff](/wine/wine/-/merge_requests/11394/diffs?diff_id=282763&start_sha=a18f4de8bc4a35352b17478835220ba46af0d9df#cb14ca7a17537e9d2cb95f2e3cacff703423eb84_109_109) I've modified.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11394#note_146038
On Fri Jul 17 13:14:16 2026 +0000, Jacek Caban wrote:
We want Wine to pass tests after each separate commit. Please squash this change into the commit that fixes it. I've fixed it.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11394#note_146039
participants (2)
-
chenzhengyong -
zhengyong chen (@chenzhengyong)