From 000321b234291fee3a00e14a4c5d0a045b85d838 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 15 Mar 2021 16:17:45 +0100 Subject: [PATCH] mshtml: Use single navigator instance per inner window. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/mshtml/htmlwindow.c | 14 ++++++++++++-- dlls/mshtml/mshtml_private.h | 3 ++- dlls/mshtml/omnavigator.c | 9 +++++---- dlls/mshtml/tests/dom.c | 4 +++- dlls/mshtml/tests/dom.js | 10 ++++++++++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index a373bbe1916..5d9a603e686 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -294,6 +294,8 @@ static void release_inner_window(HTMLInnerWindow *This) IOmHistory_Release(&This->history->IOmHistory_iface); } + if(This->navigator) + IOmNavigator_Release(This->navigator); if(This->session_storage) IHTMLStorage_Release(This->session_storage); if(This->local_storage) @@ -918,11 +920,19 @@ static HRESULT WINAPI HTMLWindow2_get_opener(IHTMLWindow2 *iface, VARIANT *p) static HRESULT WINAPI HTMLWindow2_get_navigator(IHTMLWindow2 *iface, IOmNavigator **p) { HTMLWindow *This = impl_from_IHTMLWindow2(iface); + HTMLInnerWindow *window = This->inner_window; TRACE("(%p)->(%p)\n", This, p); - *p = OmNavigator_Create(); - return *p ? S_OK : E_OUTOFMEMORY; + if(!window->navigator) { + HRESULT hres; + hres = create_navigator(dispex_compat_mode(&window->event_target.dispex), &window->navigator); + if(FAILED(hres)) + return hres; + } + + IOmNavigator_AddRef(*p = window->navigator); + return S_OK; } static HRESULT WINAPI HTMLWindow2_put_name(IHTMLWindow2 *iface, BSTR v) diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 784432b30b2..f870c05f2cb 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -535,6 +535,7 @@ struct HTMLInnerWindow { HTMLXMLHttpRequestFactory *xhr_factory; IHTMLScreen *screen; OmHistory *history; + IOmNavigator *navigator; IHTMLStorage *session_storage; IHTMLStorage *local_storage; @@ -910,7 +911,7 @@ HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,HTMLOptionElementFactor HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,HTMLImageElementFactory**) DECLSPEC_HIDDEN; HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,HTMLXMLHttpRequestFactory**) DECLSPEC_HIDDEN; HRESULT HTMLLocation_Create(HTMLInnerWindow*,HTMLLocation**) DECLSPEC_HIDDEN; -IOmNavigator *OmNavigator_Create(void) DECLSPEC_HIDDEN; +HRESULT create_navigator(compat_mode_t,IOmNavigator**) DECLSPEC_HIDDEN; HRESULT create_html_screen(compat_mode_t,IHTMLScreen**) DECLSPEC_HIDDEN; HRESULT create_performance(IHTMLPerformance**) DECLSPEC_HIDDEN; HRESULT create_history(HTMLInnerWindow*,OmHistory**) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index f3a3ec54924..624e66b4c95 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1453,20 +1453,21 @@ static dispex_static_data_t OmNavigator_dispex = { OmNavigator_iface_tids }; -IOmNavigator *OmNavigator_Create(void) +HRESULT create_navigator(compat_mode_t compat_mode, IOmNavigator **navigator) { OmNavigator *ret; ret = heap_alloc_zero(sizeof(*ret)); if(!ret) - return NULL; + return E_OUTOFMEMORY; ret->IOmNavigator_iface.lpVtbl = &OmNavigatorVtbl; ret->ref = 1; - init_dispex(&ret->dispex, (IUnknown*)&ret->IOmNavigator_iface, &OmNavigator_dispex); + init_dispex_with_compat_mode(&ret->dispex, (IUnknown*)&ret->IOmNavigator_iface, &OmNavigator_dispex, compat_mode); - return &ret->IOmNavigator_iface; + *navigator = &ret->IOmNavigator_iface; + return S_OK; } typedef struct { diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index ebed27b48e8..3c9deec7d0b 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -6296,12 +6296,13 @@ static void test_navigator(IHTMLDocument2 *doc) hres = IHTMLWindow2_get_navigator(window, &navigator2); ok(hres == S_OK, "get_navigator failed: %08x\n", hres); + todo_wine ok(navigator != navigator2, "navigator2 != navigator\n"); IOmNavigator_Release(navigator2); hres = IHTMLWindow2_get_clientInformation(window, &navigator2); ok(hres == S_OK, "get_clientInformation failed: %08x\n", hres); - todo_wine ok(iface_cmp((IUnknown*)navigator, (IUnknown*)navigator2), "navigator2 != navigator\n"); + ok(iface_cmp((IUnknown*)navigator, (IUnknown*)navigator2), "navigator2 != navigator\n"); IOmNavigator_Release(navigator2); IHTMLWindow2_Release(window); @@ -6416,6 +6417,7 @@ static void test_navigator(IHTMLDocument2 *doc) test_mime_types_col(navigator); ref = IOmNavigator_Release(navigator); + todo_wine ok(!ref, "navigator should be destroyed here\n"); } diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index 7fc6b87882c..e1c60d6ea53 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -415,3 +415,13 @@ async_test("animation", function() { document.body.appendChild(div); div.className = "testAnimation"; }); + +sync_test("navigator", function() { + ok(typeof(window.navigator) === "object", + "typeof(window.navigator) = " + typeof(window.navigator)); + + var v = window.navigator; + ok(v === window.navigator, "v != window.navigator"); + v.testProp = true; + ok(window.navigator.testProp, "window.navigator.testProp = " + window.navigator.testProp); +});