From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/mutation.c | 2 + dlls/mshtml/omnavigator.c | 4 +- dlls/mshtml/tests/documentmode.js | 5 ++ dlls/mshtml/tests/htmldoc.c | 81 +++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 61b22306d43..e63db0ec480 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -604,6 +604,7 @@ struct HTMLInnerWindow { ULONGLONG request_time; ULONGLONG response_start_time; ULONGLONG response_end_time; + ULONGLONG dom_interactive_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 7166d74cf0c..f3472354fe5 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -305,6 +305,8 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo }
bind_event_scripts(This); + + This->window->dom_interactive_time = get_time_stamp(); set_ready_state(This->outer_window, READYSTATE_INTERACTIVE); return NS_OK; } diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 6212432fb09..b29c3be2850 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1764,9 +1764,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domInteractive(IHTMLPerformanceT { HTMLPerformanceTiming *This = impl_from_IHTMLPerformanceTiming(iface);
- FIXME("(%p)->(%p) returning fake value\n", This, p); + TRACE("(%p)->(%p)\n", This, p);
- *p = TIMING_FAKE_TIMESTAMP; + *p = This->window->dom_interactive_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index c09f10ae54a..2c6a800d8cf 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -29,6 +29,7 @@ ok(performance.timing.requestStart >= performance.timing.connectEnd, "requestSta ok(performance.timing.responseStart >= performance.timing.requestStart, "responseStart < requestStart"); ok(performance.timing.responseEnd >= performance.timing.responseStart, "responseEnd < responseStart"); ok(performance.timing.domLoading >= performance.timing.responseEnd, "domLoading < responseEnd"); +ok(performance.timing.domInteractive === 0, "domInteractive != 0"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); @@ -75,6 +76,10 @@ if(window.addEventListener) { document.attachEvent("onunload", function() { ok(false, "unload fired on document"); }); }
+sync_test("performance timing", function() { + ok(performance.timing.domInteractive >= performance.timing.domLoading, "domInteractive < domLoading"); +}); + sync_test("page transition events", function() { if(document.documentMode < 11) ok(pageshow_fired === false, "pageshow fired"); diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c index 49c0ddfe5c4..85fe540db59 100644 --- a/dlls/mshtml/tests/htmldoc.c +++ b/dlls/mshtml/tests/htmldoc.c @@ -450,6 +450,85 @@ static void _test_current_url(unsigned line, IUnknown *unk, const WCHAR *exurl) IHTMLDocument2_Release(doc); }
+#define test_performance_timing(a,b,c) _test_performance_timing(__LINE__,a,b,c) +static void _test_performance_timing(unsigned line, IUnknown *unk, const WCHAR *prop, BOOL expect_non_zero) +{ + DISPPARAMS dp = { 0 }; + IHTMLWindow2 *window; + IHTMLDocument2 *doc; + IDispatchEx *dispex; + DISPID dispid; + HRESULT hres; + VARIANT var; + BSTR bstr; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLDocument2, (void**)&doc); + ok_(__FILE__,line)(hres == S_OK, "QueryInterface(IID_IHTMLDocument2) failed: %08lx\n", hres); + + /* load_state may be out of sync here for interactive */ + if(editmode && load_state == LD_LOADING && !wcscmp(prop, L"domInteractive")) { + hres = IHTMLDocument2_get_readyState(doc, &bstr); + ok_(__FILE__,line)(hres == S_OK, "get_readyState failed: %08lx\n", hres); + if(!wcscmp(bstr, L"interactive")) + expect_non_zero = TRUE; + SysFreeString(bstr); + } + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok_(__FILE__,line)(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + IHTMLDocument2_Release(doc); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IDispatchEx, (void**)&dispex); + ok_(__FILE__,line)(hres == S_OK, "QueryInterface(IID_IDispatchEx) failed: %08lx\n", hres); + IHTMLWindow2_Release(window); + + bstr = SysAllocString(L"performance"); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); + ok_(__FILE__,line)(hres == S_OK, "GetDispID(performance) failed: %08lx\n", hres); + SysFreeString(bstr); + + V_VT(&var) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok_(__FILE__,line)(hres == S_OK, "InvokeEx(performance) failed: %08lx\n", hres); + ok_(__FILE__,line)(V_VT(&var) == VT_DISPATCH, "V_VT(performance) = %d\n", V_VT(&var)); + ok_(__FILE__,line)(V_DISPATCH(&var) != NULL, "V_DISPATCH(performance) = NULL\n"); + IDispatchEx_Release(dispex); + + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDispatchEx, (void**)&dispex); + ok_(__FILE__,line)(hres == S_OK, "QueryInterface(IID_IDispatchEx) failed: %08lx\n", hres); + VariantClear(&var); + + bstr = SysAllocString(L"timing"); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); + ok_(__FILE__,line)(hres == S_OK, "GetDispID(timing) failed: %08lx\n", hres); + SysFreeString(bstr); + + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok_(__FILE__,line)(hres == S_OK, "InvokeEx(timing) failed: %08lx\n", hres); + ok_(__FILE__,line)(V_VT(&var) == VT_DISPATCH, "V_VT(timing) = %d\n", V_VT(&var)); + ok_(__FILE__,line)(V_DISPATCH(&var) != NULL, "V_DISPATCH(timing) = NULL\n"); + IDispatchEx_Release(dispex); + + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDispatchEx, (void**)&dispex); + ok_(__FILE__,line)(hres == S_OK, "QueryInterface(IID_IDispatchEx) failed: %08lx\n", hres); + VariantClear(&var); + + bstr = SysAllocString(prop); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); + ok_(__FILE__,line)(hres == S_OK, "GetDispID(%s) failed: %08lx\n", wine_dbgstr_w(prop), hres); + SysFreeString(bstr); + + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok_(__FILE__,line)(hres == S_OK, "InvokeEx(%s) failed: %08lx\n", wine_dbgstr_w(prop), hres); + ok_(__FILE__,line)(V_VT(&var) == VT_UI8, "V_VT(%s) = %d\n", wine_dbgstr_w(prop), V_VT(&var)); + IDispatchEx_Release(dispex); + + if(expect_non_zero) + ok_(__FILE__,line)(V_UI8(&var) != 0, "%s is 0\n", wine_dbgstr_w(prop)); + else + ok_(__FILE__,line)(V_UI8(&var) == 0, "%s is not 0\n", wine_dbgstr_w(prop)); +} + static BSTR get_mime_type_display_name(const WCHAR *content_type) { WCHAR buffer[128], ext[128], *str, *progid; @@ -1039,6 +1118,7 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D if(!editmode) test_readyState(NULL); readystate_set_interactive = (load_state != LD_INTERACTIVE); + test_performance_timing(doc_unk, L"domInteractive", load_state != LD_LOADING); return S_OK; case 1012: CHECK_EXPECT2(OnChanged_1012); @@ -3574,6 +3654,7 @@ static HRESULT WINAPI DocObjectService_FireNavigateComplete2( { CHECK_EXPECT(FireNavigateComplete2); test_readyState(NULL); + test_performance_timing(doc_unk, L"domInteractive", load_state != LD_LOADING);
if(loading_hash) ok(dwFlags == 0x10 || broken(!dwFlags), "dwFlags = %lx, expected 0x10\n", dwFlags);