From: Gabriel Ivăncescu gabrielopcode@gmail.com
And likewise from the window, so we know when to detach it.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Needed by performance.timing (and in future patches as well). --- dlls/mshtml/htmlwindow.c | 17 +++++++++-------- dlls/mshtml/mshtml_private.h | 7 +++++-- dlls/mshtml/omnavigator.c | 14 ++++++++++++-- 3 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index baaedb6b6d4..1d3c71d83bf 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -308,6 +308,10 @@ static void release_inner_window(HTMLInnerWindow *This) IHTMLStorage_Release(This->local_storage); }
+ if(This->performance_obj && This->performance_obj != NO_PERFORMANCE_OBJ) + detach_performance(This->performance_obj); + VariantClear(&This->performance); + if(This->mon) IMoniker_Release(This->mon);
@@ -2414,9 +2418,9 @@ static HRESULT WINAPI HTMLWindow7_put_performance(IHTMLWindow7 *iface, VARIANT v
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- if(!This->performance_initialized) { + if(!This->performance_obj) { V_VT(&This->performance) = VT_EMPTY; - This->performance_initialized = TRUE; + This->performance_obj = NO_PERFORMANCE_OBJ; }
return VariantCopy(&This->performance, &v); @@ -2429,16 +2433,13 @@ static HRESULT WINAPI HTMLWindow7_get_performance(IHTMLWindow7 *iface, VARIANT *
TRACE("(%p)->(%p)\n", This, p);
- if(!This->performance_initialized) { - IHTMLPerformance *performance; - - hres = create_performance(dispex_compat_mode(&This->event_target.dispex), &performance); + if(!This->performance_obj) { + hres = create_performance(This, &This->performance_obj); if(FAILED(hres)) return hres;
V_VT(&This->performance) = VT_DISPATCH; - V_DISPATCH(&This->performance) = (IDispatch*)performance; - This->performance_initialized = TRUE; + V_DISPATCH(&This->performance) = (IDispatch*)This->performance_obj; }
V_VT(p) = VT_NULL; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index d9e2d93d220..e8dd0997639 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -577,7 +577,7 @@ struct HTMLInnerWindow { IHTMLStorage *session_storage; IHTMLStorage *local_storage;
- BOOL performance_initialized; + IHTMLPerformance *performance_obj; VARIANT performance;
unsigned parser_callback_cnt; @@ -596,6 +596,8 @@ struct HTMLInnerWindow { struct list bindings; };
+#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) + typedef enum { UNKNOWN_USERMODE, BROWSEMODE, @@ -966,7 +968,8 @@ HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,HTMLXMLHttpRequestFact HRESULT HTMLLocation_Create(HTMLInnerWindow*,HTMLLocation**) DECLSPEC_HIDDEN; HRESULT create_navigator(compat_mode_t,IOmNavigator**) DECLSPEC_HIDDEN; HRESULT create_html_screen(compat_mode_t,IHTMLScreen**) DECLSPEC_HIDDEN; -HRESULT create_performance(compat_mode_t,IHTMLPerformance**) DECLSPEC_HIDDEN; +HRESULT create_performance(HTMLInnerWindow*,IHTMLPerformance**) DECLSPEC_HIDDEN; +void detach_performance(IHTMLPerformance*) DECLSPEC_HIDDEN; HRESULT create_history(HTMLInnerWindow*,OmHistory**) DECLSPEC_HIDDEN; HRESULT create_namespace_collection(compat_mode_t,IHTMLNamespaceCollection**) DECLSPEC_HIDDEN; HRESULT create_dom_implementation(HTMLDocumentNode*,IHTMLDOMImplementation**) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index db48cc6213b..f25cce2c105 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -2023,6 +2023,7 @@ typedef struct {
IHTMLPerformanceNavigation *navigation; IHTMLPerformanceTiming *timing; + HTMLInnerWindow *window; } HTMLPerformance;
static inline HTMLPerformance *impl_from_IHTMLPerformance(IHTMLPerformance *iface) @@ -2070,6 +2071,8 @@ static ULONG WINAPI HTMLPerformance_Release(IHTMLPerformance *iface) TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) { + if(This->window) + This->window->performance_obj = NO_PERFORMANCE_OBJ; if(This->timing) IHTMLPerformanceTiming_Release(This->timing); if(This->navigation) @@ -2208,7 +2211,7 @@ static dispex_static_data_t HTMLPerformance_dispex = { HTMLPerformance_iface_tids };
-HRESULT create_performance(compat_mode_t compat_mode, IHTMLPerformance **ret) +HRESULT create_performance(HTMLInnerWindow *window, IHTMLPerformance **ret) { HTMLPerformance *performance;
@@ -2218,14 +2221,21 @@ HRESULT create_performance(compat_mode_t compat_mode, IHTMLPerformance **ret)
performance->IHTMLPerformance_iface.lpVtbl = &HTMLPerformanceVtbl; performance->ref = 1; + performance->window = window;
init_dispatch(&performance->dispex, (IUnknown*)&performance->IHTMLPerformance_iface, - &HTMLPerformance_dispex, compat_mode); + &HTMLPerformance_dispex, dispex_compat_mode(&window->event_target.dispex));
*ret = &performance->IHTMLPerformance_iface; return S_OK; }
+void detach_performance(IHTMLPerformance *iface) +{ + HTMLPerformance *performance = impl_from_IHTMLPerformance(iface); + performance->window = NULL; +} + typedef struct { DispatchEx dispex; IHTMLNamespaceCollection IHTMLNamespaceCollection_iface;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/navigate.c | 4 +++- dlls/mshtml/omnavigator.c | 9 +++++++-- dlls/mshtml/tests/documentmode.js | 2 ++ 4 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index e8dd0997639..77a23362415 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -594,6 +594,8 @@ struct HTMLInnerWindow { IMoniker *mon; nsChannelBSC *bscallback; struct list bindings; + + ULONGLONG navigation_start_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 5825e0f27c0..79c88ae31fc 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1357,8 +1357,10 @@ static HRESULT nsChannelBSC_start_binding(BSCallback *bsc) { nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
- if(This->is_doc_channel) + if(This->is_doc_channel) { This->bsc.window->base.outer_window->base.inner_window->doc->skip_mutation_notif = FALSE; + This->bsc.window->navigation_start_time = get_time_stamp(); + }
return S_OK; } diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index f25cce2c105..d62872a593b 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1502,6 +1502,7 @@ typedef struct { IHTMLPerformanceTiming IHTMLPerformanceTiming_iface;
LONG ref; + HTMLInnerWindow *window; } HTMLPerformanceTiming;
static inline HTMLPerformanceTiming *impl_from_IHTMLPerformanceTiming(IHTMLPerformanceTiming *iface) @@ -1549,6 +1550,7 @@ static ULONG WINAPI HTMLPerformanceTiming_Release(IHTMLPerformanceTiming *iface) TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) { + IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface); release_dispex(&This->dispex); heap_free(This); } @@ -1597,9 +1599,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_navigationStart(IHTMLPerformance { 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->navigation_start_time; return S_OK; }
@@ -2160,6 +2162,9 @@ static HRESULT WINAPI HTMLPerformance_get_timing(IHTMLPerformance *iface, IHTMLP
timing->IHTMLPerformanceTiming_iface.lpVtbl = &HTMLPerformanceTimingVtbl; timing->ref = 1; + timing->window = This->window; + IHTMLWindow2_AddRef(&timing->window->base.IHTMLWindow2_iface); + init_dispatch(&timing->dispex, (IUnknown*)&timing->IHTMLPerformanceTiming_iface, &HTMLPerformanceTiming_dispex, dispex_compat_mode(&This->dispex));
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 33d60f7e835..f83597d305a 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -19,6 +19,8 @@ var compat_version; var tests = [];
+ok(performance.timing.navigationStart > 0, "navigationStart <= 0"); + var pageshow_fired = false, pagehide_fired = false; document.doc_unload_events_called = false; window.onbeforeunload = function() { ok(false, "beforeunload fired"); };
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/navigate.c | 2 ++ dlls/mshtml/omnavigator.c | 4 ++-- dlls/mshtml/tests/documentmode.js | 1 + 4 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 77a23362415..4bf8fb65624 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -596,6 +596,7 @@ struct HTMLInnerWindow { struct list bindings;
ULONGLONG navigation_start_time; + ULONGLONG redirect_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 79c88ae31fc..06e3b1e9544 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1717,6 +1717,8 @@ static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG progress, ULONG t This->nschannel->content_type = heap_strdupWtoA(status_text); break; case BINDSTATUS_REDIRECTING: + if(This->is_doc_channel && !This->bsc.window->redirect_time) + This->bsc.window->redirect_time = get_time_stamp(); return handle_redirect(This, status_text); case BINDSTATUS_BEGINDOWNLOADDATA: { IWinInetHttpInfo *http_info; diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index d62872a593b..4c0d7143d39 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1629,9 +1629,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_redirectStart(IHTMLPerformanceTi { 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->redirect_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index f83597d305a..f0a91fea545 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -20,6 +20,7 @@ var compat_version; var tests = [];
ok(performance.timing.navigationStart > 0, "navigationStart <= 0"); +ok(performance.timing.redirectStart === 0, "redirectStart != 0");
var pageshow_fired = false, pagehide_fired = false; document.doc_unload_events_called = false;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 3 +++ dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/nsevents.c | 9 ++++++++- dlls/mshtml/omnavigator.c | 8 ++++---- dlls/mshtml/tests/documentmode.js | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 1d3c71d83bf..dcf21460b8d 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -4116,6 +4116,9 @@ HRESULT create_outer_window(GeckoBrowser *browser, mozIDOMWindowProxy *mozwindow return hres; }
+ /* Initial empty doc does not have unload events or timings */ + window->base.inner_window->doc->unload_sent = TRUE; + if(parent) { IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 4bf8fb65624..90aba4e9236 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -596,6 +596,8 @@ struct HTMLInnerWindow { struct list bindings;
ULONGLONG navigation_start_time; + ULONGLONG unload_event_start_time; + ULONGLONG unload_event_end_time; ULONGLONG redirect_time; };
diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 0248737b012..f2f17bc180a 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -383,8 +383,8 @@ static nsresult NSAPI handle_beforeunload(nsIDOMEventListener *iface, nsIDOMEven static nsresult NSAPI handle_unload(nsIDOMEventListener *iface, nsIDOMEvent *nsevent) { nsEventListener *This = impl_from_nsIDOMEventListener(iface); + HTMLInnerWindow *window, *pending_window; HTMLDocumentNode *doc = This->This->doc; - HTMLInnerWindow *window; DOMEvent *event; HRESULT hres;
@@ -392,12 +392,19 @@ static nsresult NSAPI handle_unload(nsIDOMEventListener *iface, nsIDOMEvent *nse return NS_OK; doc->unload_sent = TRUE;
+ pending_window = window->base.outer_window->pending_window; + if(pending_window) + pending_window->unload_event_start_time = get_time_stamp(); + hres = create_event_from_nsevent(nsevent, dispex_compat_mode(&doc->node.event_target.dispex), &event); if(SUCCEEDED(hres)) { dispatch_event(&window->event_target, event); IDOMEvent_Release(&event->IDOMEvent_iface); }
+ if(pending_window) + pending_window->unload_event_end_time = get_time_stamp(); + return NS_OK; }
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 4c0d7143d39..013330e9658 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1609,9 +1609,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_unloadEventStart(IHTMLPerformanc { 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->unload_event_start_time; return S_OK; }
@@ -1619,9 +1619,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_unloadEventEnd(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->unload_event_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index f0a91fea545..a9c2b36ceee 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -20,6 +20,8 @@ var compat_version; var tests = [];
ok(performance.timing.navigationStart > 0, "navigationStart <= 0"); +ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); +ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0");
var pageshow_fired = false, pagehide_fired = false;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 3 ++ dlls/mshtml/navigate.c | 12 +++++++ dlls/mshtml/omnavigator.c | 52 ++++++++++++++++++++++--------- dlls/mshtml/tests/documentmode.js | 7 +++++ 4 files changed, 60 insertions(+), 14 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 90aba4e9236..59439823817 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -599,6 +599,9 @@ struct HTMLInnerWindow { ULONGLONG unload_event_start_time; ULONGLONG unload_event_end_time; ULONGLONG redirect_time; + ULONGLONG dns_lookup_time; + ULONGLONG connect_time; + ULONGLONG request_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 06e3b1e9544..6ca2fbe1dcb 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1720,6 +1720,18 @@ static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG progress, ULONG t if(This->is_doc_channel && !This->bsc.window->redirect_time) This->bsc.window->redirect_time = get_time_stamp(); return handle_redirect(This, status_text); + case BINDSTATUS_FINDINGRESOURCE: + if(This->is_doc_channel && !This->bsc.window->dns_lookup_time) + This->bsc.window->dns_lookup_time = get_time_stamp(); + break; + case BINDSTATUS_CONNECTING: + if(This->is_doc_channel) + This->bsc.window->connect_time = get_time_stamp(); + break; + case BINDSTATUS_SENDINGREQUEST: + if(This->is_doc_channel) + This->bsc.window->request_time = get_time_stamp(); + break; case BINDSTATUS_BEGINDOWNLOADDATA: { IWinInetHttpInfo *http_info; DWORD status, size = sizeof(DWORD); diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 013330e9658..1a9c6174214 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1595,6 +1595,24 @@ static HRESULT WINAPI HTMLPerformanceTiming_Invoke(IHTMLPerformanceTiming *iface
#define TIMING_FAKE_TIMESTAMP 0xdeadbeef
+static ULONGLONG get_fetch_time(HTMLPerformanceTiming *This) +{ + /* If there's no prior doc unloaded and no redirects, fetch time == navigationStart time */ + if(!This->window->unload_event_end_time && !This->window->redirect_time) + return This->window->navigation_start_time; + + if(This->window->dns_lookup_time) + return This->window->dns_lookup_time; + if(This->window->connect_time) + return This->window->connect_time; + if(This->window->request_time) + return This->window->request_time; + if(This->window->unload_event_end_time) + return This->window->unload_event_end_time; + + return This->window->redirect_time; +} + static HRESULT WINAPI HTMLPerformanceTiming_get_navigationStart(IHTMLPerformanceTiming *iface, ULONGLONG *p) { HTMLPerformanceTiming *This = impl_from_IHTMLPerformanceTiming(iface); @@ -1639,9 +1657,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_redirectEnd(IHTMLPerformanceTimi { 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->redirect_time ? get_fetch_time(This) : 0; return S_OK; }
@@ -1649,9 +1667,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_fetchStart(IHTMLPerformanceTimin { 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 = get_fetch_time(This); return S_OK; }
@@ -1659,9 +1677,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domainLookupStart(IHTMLPerforman { 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->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
@@ -1669,9 +1687,10 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domainLookupEnd(IHTMLPerformance { 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->connect_time ? This->window->connect_time : + This->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
@@ -1679,9 +1698,10 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_connectStart(IHTMLPerformanceTim { 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->connect_time ? This->window->connect_time : + This->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
@@ -1689,9 +1709,11 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_connectEnd(IHTMLPerformanceTimin { 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->request_time ? This->window->request_time : + This->window->connect_time ? This->window->connect_time : + This->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
@@ -1699,9 +1721,11 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_requestStart(IHTMLPerformanceTim { 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->request_time ? This->window->request_time : + This->window->connect_time ? This->window->connect_time : + This->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index a9c2b36ceee..e933ea0ff54 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -20,9 +20,16 @@ var compat_version; var tests = [];
ok(performance.timing.navigationStart > 0, "navigationStart <= 0"); +ok(performance.timing.fetchStart == performance.timing.navigationStart, "fetchStart != navigationStart"); +ok(performance.timing.domainLookupStart >= performance.timing.fetchStart, "domainLookupStart < fetchStart"); +ok(performance.timing.domainLookupEnd >= performance.timing.domainLookupStart, "domainLookupEnd < domainLookupStart"); +ok(performance.timing.connectStart >= performance.timing.domainLookupEnd, "connectStart < domainLookupEnd"); +ok(performance.timing.connectEnd >= performance.timing.connectStart, "connectEnd < connectStart"); +ok(performance.timing.requestStart >= performance.timing.connectEnd, "requestStart < connectEnd"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); +ok(performance.timing.redirectEnd === 0, "redirectEnd != 0");
var pageshow_fired = false, pagehide_fired = false; document.doc_unload_events_called = false;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/navigate.c | 23 ++++++++++++++++------- dlls/mshtml/omnavigator.c | 8 ++++---- dlls/mshtml/tests/documentmode.js | 2 ++ 4 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 59439823817..61b22306d43 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -602,6 +602,8 @@ struct HTMLInnerWindow { ULONGLONG dns_lookup_time; ULONGLONG connect_time; ULONGLONG request_time; + ULONGLONG response_start_time; + ULONGLONG response_end_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 6ca2fbe1dcb..c5a9cfd1263 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1107,6 +1107,9 @@ static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) if(!This->response_processed) { IWinInetHttpInfo *wininet_info;
+ if(This->is_doc_channel) + This->bsc.window->response_start_time = get_time_stamp(); + This->response_processed = TRUE; if(This->bsc.binding) { hres = IBinding_QueryInterface(This->bsc.binding, &IID_IWinInetHttpInfo, (void**)&wininet_info); @@ -1522,13 +1525,16 @@ static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result) { nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
- if(result != E_ABORT && This->is_doc_channel && This->bsc.window) { - if(FAILED(result)) - handle_navigation_error(This, result); - else if(This->nschannel) { - result = async_stop_request(This); - if(SUCCEEDED(result)) - return S_OK; + if(This->is_doc_channel && This->bsc.window) { + This->bsc.window->response_end_time = get_time_stamp(); + if(result != E_ABORT) { + if(FAILED(result)) + handle_navigation_error(This, result); + else if(This->nschannel) { + result = async_stop_request(This); + if(SUCCEEDED(result)) + return S_OK; + } } }
@@ -1786,6 +1792,9 @@ static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code, char *str; HRESULT hres;
+ if(This->is_doc_channel) + This->bsc.window->response_start_time = get_time_stamp(); + This->response_processed = TRUE; This->nschannel->response_status = response_code;
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 1a9c6174214..fc9eed72bd5 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1733,9 +1733,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_responseStart(IHTMLPerformanceTi { 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->response_start_time; return S_OK; }
@@ -1743,9 +1743,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_responseEnd(IHTMLPerformanceTimi { 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->response_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index e933ea0ff54..881a08e9a54 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -26,6 +26,8 @@ ok(performance.timing.domainLookupEnd >= performance.timing.domainLookupStart, " ok(performance.timing.connectStart >= performance.timing.domainLookupEnd, "connectStart < domainLookupEnd"); ok(performance.timing.connectEnd >= performance.timing.connectStart, "connectEnd < connectStart"); ok(performance.timing.requestStart >= performance.timing.connectEnd, "requestStart < connectEnd"); +ok(performance.timing.responseStart >= performance.timing.requestStart, "responseStart < requestStart"); +ok(performance.timing.responseEnd >= performance.timing.responseStart, "responseEnd < responseStart"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0");
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/omnavigator.c | 5 +++-- dlls/mshtml/tests/documentmode.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index fc9eed72bd5..6212432fb09 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1753,9 +1753,10 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domLoading(IHTMLPerformanceTimin { 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; + /* Make sure this is after responseEnd, when the Gecko parser starts */ + *p = This->window->response_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 881a08e9a54..c09f10ae54a 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -28,6 +28,7 @@ ok(performance.timing.connectEnd >= performance.timing.connectStart, "connectEnd ok(performance.timing.requestStart >= performance.timing.connectEnd, "requestStart < connectEnd"); 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.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0");
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);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/nsevents.c | 1 + dlls/mshtml/omnavigator.c | 4 ++-- dlls/mshtml/tests/documentmode.js | 2 ++ dlls/mshtml/tests/htmldoc.c | 3 +++ 5 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index e63db0ec480..bbf79f8ed4b 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -605,6 +605,7 @@ struct HTMLInnerWindow { ULONGLONG response_start_time; ULONGLONG response_end_time; ULONGLONG dom_interactive_time; + ULONGLONG dom_complete_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index f2f17bc180a..6d29f26394d 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -319,6 +319,7 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event if(doc_obj) handle_docobj_load(doc_obj);
+ doc->window->dom_complete_time = get_time_stamp(); set_ready_state(doc->outer_window, READYSTATE_COMPLETE);
if(doc_obj) { diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index b29c3be2850..dbc21fb9cb8 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1794,9 +1794,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domComplete(IHTMLPerformanceTimi { 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_complete_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 2c6a800d8cf..72311d5903b 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -30,6 +30,7 @@ ok(performance.timing.responseStart >= performance.timing.requestStart, "respons 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.domComplete === 0, "domComplete != 0"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); @@ -78,6 +79,7 @@ if(window.addEventListener) {
sync_test("performance timing", function() { ok(performance.timing.domInteractive >= performance.timing.domLoading, "domInteractive < domLoading"); + ok(performance.timing.domComplete >= performance.timing.domInteractive, "domComplete < domInteractive"); });
sync_test("page transition events", function() { diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c index 85fe540db59..bf0ec04d7de 100644 --- a/dlls/mshtml/tests/htmldoc.c +++ b/dlls/mshtml/tests/htmldoc.c @@ -2983,6 +2983,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID ok(nCmdexecopt == 0, "nCmdexecopts=%08lx\n", nCmdexecopt); ok(pvaOut == NULL, "pvaOut=%p\n", pvaOut); ok(pvaIn == NULL, "pvaIn=%p\n", pvaIn); + test_performance_timing(doc_unk, L"domComplete", load_state == LD_COMPLETE); readystate_set_loading = FALSE; readystate_set_interactive = FALSE; load_state = LD_COMPLETE; @@ -3130,6 +3131,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID ok(pvaOut == NULL, "pvaOut != NULL\n");
test_readyState(NULL); + test_performance_timing(doc_unk, L"domComplete", load_state == LD_COMPLETE); return E_NOTIMPL;
case 105: @@ -3192,6 +3194,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID CHECK_EXPECT(Exec_MSHTML_PARSECOMPLETE); ok(pvaIn == NULL, "pvaIn != NULL\n"); ok(pvaOut == NULL, "pvaOut != NULL\n"); + test_performance_timing(doc_unk, L"domComplete", load_state == LD_COMPLETE); return S_OK; default: ok(0, "unexpected command %ld\n", nCmdID);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlevent.c | 2 +- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/nsevents.c | 43 +++++++++++++++++++++++++------ dlls/mshtml/omnavigator.c | 8 +++--- dlls/mshtml/tests/documentmode.js | 6 ++++- 5 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 01a385130b1..fec280d9a70 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -117,7 +117,7 @@ typedef struct { /* Keep these sorted case sensitively */ static const event_info_t event_info[] = { {L"DOMContentLoaded", EVENT_TYPE_EVENT, 0, - EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE}, + EVENT_BUBBLES | EVENT_CANCELABLE}, {L"abort", EVENT_TYPE_EVENT, DISPID_EVMETH_ONABORT, EVENT_BIND_TO_TARGET}, {L"animationend", EVENT_TYPE_EVENT, DISPID_EVPROP_ONANIMATIONEND, diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index bbf79f8ed4b..b8adbf359b6 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -606,6 +606,8 @@ struct HTMLInnerWindow { ULONGLONG response_end_time; ULONGLONG dom_interactive_time; ULONGLONG dom_complete_time; + ULONGLONG dom_content_loaded_event_start_time; + ULONGLONG dom_content_loaded_event_end_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 6d29f26394d..606b04c3e50 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -56,6 +56,7 @@ typedef struct { static nsresult NSAPI handle_blur(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_focus(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_keypress(nsIDOMEventListener*,nsIDOMEvent*); +static nsresult NSAPI handle_dom_content_loaded(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_pageshow(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_pagehide(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_load(nsIDOMEventListener*,nsIDOMEvent*); @@ -72,14 +73,15 @@ static const struct { enum doc_event_listener_flags flags; nsIDOMEventListenerVtbl vtbl; } doc_event_listeners[] = { - { EVENTID_BLUR, 0, EVENTLISTENER_VTBL(handle_blur) }, - { EVENTID_FOCUS, 0, EVENTLISTENER_VTBL(handle_focus) }, - { EVENTID_KEYPRESS, BUBBLES, EVENTLISTENER_VTBL(handle_keypress) }, - { EVENTID_PAGESHOW, OVERRIDE, EVENTLISTENER_VTBL(handle_pageshow), }, - { EVENTID_PAGEHIDE, OVERRIDE, EVENTLISTENER_VTBL(handle_pagehide), }, - { EVENTID_LOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_load), }, - { EVENTID_BEFOREUNLOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_beforeunload), }, - { EVENTID_UNLOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_unload) }, + { EVENTID_BLUR, 0, EVENTLISTENER_VTBL(handle_blur) }, + { EVENTID_FOCUS, 0, EVENTLISTENER_VTBL(handle_focus) }, + { EVENTID_KEYPRESS, BUBBLES, EVENTLISTENER_VTBL(handle_keypress) }, + { EVENTID_DOMCONTENTLOADED, OVERRIDE, EVENTLISTENER_VTBL(handle_dom_content_loaded) }, + { EVENTID_PAGESHOW, OVERRIDE, EVENTLISTENER_VTBL(handle_pageshow) }, + { EVENTID_PAGEHIDE, OVERRIDE, EVENTLISTENER_VTBL(handle_pagehide) }, + { EVENTID_LOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_load) }, + { EVENTID_BEFOREUNLOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_beforeunload) }, + { EVENTID_UNLOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_unload) }, };
struct nsDocumentEventListener { @@ -216,6 +218,31 @@ static nsresult NSAPI handle_keypress(nsIDOMEventListener *iface, return NS_OK; }
+static nsresult NSAPI handle_dom_content_loaded(nsIDOMEventListener *iface, nsIDOMEvent *nsevent) +{ + nsEventListener *This = impl_from_nsIDOMEventListener(iface); + HTMLDocumentNode *doc = This->This->doc; + DOMEvent *event; + HRESULT hres; + + if(!doc) + return NS_OK; + + if(doc->window) + doc->window->dom_content_loaded_event_start_time = get_time_stamp(); + + hres = create_event_from_nsevent(nsevent, dispex_compat_mode(&doc->node.event_target.dispex), &event); + if(SUCCEEDED(hres)) { + dispatch_event(&doc->node.event_target, event); + IDOMEvent_Release(&event->IDOMEvent_iface); + } + + if(doc->window) + doc->window->dom_content_loaded_event_end_time = get_time_stamp(); + + return NS_OK; +} + static nsresult NSAPI handle_pageshow(nsIDOMEventListener *iface, nsIDOMEvent *nsevent) { nsEventListener *This = impl_from_nsIDOMEventListener(iface); diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index dbc21fb9cb8..899aaab81fb 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1774,9 +1774,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domContentLoadedEventStart(IHTML { 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_content_loaded_event_start_time; return S_OK; }
@@ -1784,9 +1784,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domContentLoadedEventEnd(IHTMLPe { 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_content_loaded_event_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 72311d5903b..237ac224cbb 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -31,6 +31,8 @@ ok(performance.timing.responseEnd >= performance.timing.responseStart, "response ok(performance.timing.domLoading >= performance.timing.responseEnd, "domLoading < responseEnd"); ok(performance.timing.domInteractive === 0, "domInteractive != 0"); ok(performance.timing.domComplete === 0, "domComplete != 0"); +ok(performance.timing.domContentLoadedEventStart === 0, "domContentLoadedEventStart != 0"); +ok(performance.timing.domContentLoadedEventEnd === 0, "domContentLoadedEventEnd != 0"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); @@ -79,7 +81,9 @@ if(window.addEventListener) {
sync_test("performance timing", function() { ok(performance.timing.domInteractive >= performance.timing.domLoading, "domInteractive < domLoading"); - ok(performance.timing.domComplete >= performance.timing.domInteractive, "domComplete < domInteractive"); + ok(performance.timing.domContentLoadedEventStart >= performance.timing.domInteractive, "domContentLoadedEventStart < domInteractive"); + ok(performance.timing.domContentLoadedEventEnd >= performance.timing.domContentLoadedEventStart, "domContentLoadedEventEnd < domContentLoadedEventStart"); + ok(performance.timing.domComplete >= performance.timing.domContentLoadedEventEnd, "domComplete < domContentLoadedEventEnd"); });
sync_test("page transition events", function() {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
connect_scripts at the top of the function already uses the window unconditionally, so if it was NULL it would crash there anyway. --- dlls/mshtml/nsevents.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 606b04c3e50..f2f8910d5d6 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -373,14 +373,10 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event WARN("no dom_document\n"); }
- if(doc->window) { - hres = create_event_from_nsevent(event, dispex_compat_mode(&doc->node.event_target.dispex), &load_event); - if(SUCCEEDED(hres)) { - dispatch_event(&doc->window->event_target, load_event); - IDOMEvent_Release(&load_event->IDOMEvent_iface); - } - }else { - WARN("no window\n"); + hres = create_event_from_nsevent(event, dispex_compat_mode(&doc->node.event_target.dispex), &load_event); + if(SUCCEEDED(hres)) { + dispatch_event(&doc->window->event_target, load_event); + IDOMEvent_Release(&load_event->IDOMEvent_iface); }
IHTMLDOMNode_Release(&doc->node.IHTMLDOMNode_iface);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/nsevents.c | 4 ++++ dlls/mshtml/omnavigator.c | 8 ++++---- dlls/mshtml/tests/documentmode.js | 5 +++++ 4 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index b8adbf359b6..76ddb80f317 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -608,6 +608,8 @@ struct HTMLInnerWindow { ULONGLONG dom_complete_time; ULONGLONG dom_content_loaded_event_start_time; ULONGLONG dom_content_loaded_event_end_time; + ULONGLONG load_event_start_time; + ULONGLONG load_event_end_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index f2f8910d5d6..d63fcde6feb 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -363,6 +363,8 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event IDocObjectService_FireDocumentComplete(doc_obj->doc_object_service, &doc->outer_window->base.IHTMLWindow2_iface, 0);
+ doc->window->load_event_start_time = get_time_stamp(); + if(doc->dom_document) { hres = create_document_event(doc, EVENTID_LOAD, &load_event); if(SUCCEEDED(hres)) { @@ -379,6 +381,8 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event IDOMEvent_Release(&load_event->IDOMEvent_iface); }
+ doc->window->load_event_end_time = get_time_stamp(); + IHTMLDOMNode_Release(&doc->node.IHTMLDOMNode_iface); return NS_OK; } diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 899aaab81fb..bf411b6d749 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1804,9 +1804,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_loadEventStart(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->load_event_start_time; return S_OK; }
@@ -1814,9 +1814,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_loadEventEnd(IHTMLPerformanceTim { 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->load_event_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 237ac224cbb..30d4a790261 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -33,6 +33,8 @@ ok(performance.timing.domInteractive === 0, "domInteractive != 0"); ok(performance.timing.domComplete === 0, "domComplete != 0"); ok(performance.timing.domContentLoadedEventStart === 0, "domContentLoadedEventStart != 0"); ok(performance.timing.domContentLoadedEventEnd === 0, "domContentLoadedEventEnd != 0"); +ok(performance.timing.loadEventStart === 0, "loadEventStart != 0"); +ok(performance.timing.loadEventEnd === 0, "loadEventEnd != 0"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); @@ -59,6 +61,7 @@ if(window.addEventListener) { ok(r === "[object PageTransitionEvent]", "pageshow toString = " + r); ok("persisted" in e, "'persisted' not in pageshow event"); ok(document.readyState === "complete", "pageshow readyState = " + document.readyState); + ok(performance.timing.loadEventEnd > 0, "loadEventEnd <= 0 in pageshow handler"); }, true);
window.addEventListener("pagehide", function(e) { @@ -84,6 +87,8 @@ sync_test("performance timing", function() { ok(performance.timing.domContentLoadedEventStart >= performance.timing.domInteractive, "domContentLoadedEventStart < domInteractive"); ok(performance.timing.domContentLoadedEventEnd >= performance.timing.domContentLoadedEventStart, "domContentLoadedEventEnd < domContentLoadedEventStart"); ok(performance.timing.domComplete >= performance.timing.domContentLoadedEventEnd, "domComplete < domContentLoadedEventEnd"); + ok(performance.timing.loadEventStart >= performance.timing.domComplete, "loadEventStart < domComplete"); + ok(performance.timing.loadEventEnd >= performance.timing.loadEventStart, "loadEventEnd < loadEventStart"); });
sync_test("page transition events", function() {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/omnavigator.c | 6 ++---- dlls/mshtml/tests/documentmode.js | 1 + dlls/mshtml/view.c | 3 +++ 4 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 76ddb80f317..5fe503a730d 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -610,6 +610,7 @@ struct HTMLInnerWindow { ULONGLONG dom_content_loaded_event_end_time; ULONGLONG load_event_start_time; ULONGLONG load_event_end_time; + ULONGLONG first_paint_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index bf411b6d749..30ce6be4e1e 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1593,8 +1593,6 @@ static HRESULT WINAPI HTMLPerformanceTiming_Invoke(IHTMLPerformanceTiming *iface pDispParams, pVarResult, pExcepInfo, puArgErr); }
-#define TIMING_FAKE_TIMESTAMP 0xdeadbeef - static ULONGLONG get_fetch_time(HTMLPerformanceTiming *This) { /* If there's no prior doc unloaded and no redirects, fetch time == navigationStart time */ @@ -1824,9 +1822,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_msFirstPaint(IHTMLPerformanceTim { 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->first_paint_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 30d4a790261..157a7337c04 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -39,6 +39,7 @@ ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); ok(performance.timing.redirectEnd === 0, "redirectEnd != 0"); +ok(performance.timing.msFirstPaint === 0, "msFirstPaint != 0");
var pageshow_fired = false, pagehide_fired = false; document.doc_unload_events_called = false; diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index 063f7afab9d..deb640fd8e3 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -50,6 +50,9 @@ static void paint_document(HTMLDocumentObj *This) RECT rect; HDC hdc;
+ if(This->window && This->window->base.inner_window && !This->window->base.inner_window->first_paint_time) + This->window->base.inner_window->first_paint_time = get_time_stamp(); + GetClientRect(This->hwnd, &rect);
hdc = BeginPaint(This->hwnd, &ps);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=126479
Your paranoid android.
=== w10pro64_ar (64 bit report) ===
mshtml: htmldoc.c:351: Test failed: expected Exec_SETTITLE htmldoc.c:3019: Test failed: unexpected call Exec_SETTITLE
=== w10pro64_ja (64 bit report) ===
mshtml: htmldoc.c:1121: Test failed: L"domInteractive" is 0
=== debian11 (32 bit report) ===
d3d9: stateblock: Timeout visual: Timeout
d3dcompiler_43: asm: Timeout blob: Timeout hlsl_d3d11: Timeout hlsl_d3d9: Timeout reflection: Timeout
d3dcompiler_46: asm: Timeout blob: Timeout hlsl_d3d11: Timeout hlsl_d3d9: Timeout reflection: Timeout
d3dcompiler_47: asm: Timeout blob: Timeout hlsl_d3d11: Timeout hlsl_d3d9: Timeout reflection: Timeout
d3drm: d3drm: Timeout vector: Timeout
d3dx10_34: d3dx10: Timeout
d3dx10_35: d3dx10: Timeout
d3dx10_36: d3dx10: Timeout
d3dx10_37: d3dx10: Timeout
d3dx10_38: d3dx10: Timeout
d3dx10_39: d3dx10: Timeout
d3dx10_40: d3dx10: Timeout
d3dx10_41: d3dx10: Timeout
d3dx10_42: d3dx10: Timeout
d3dx10_43: d3dx10: Timeout
d3dx11_42: d3dx11: Timeout
d3dx11_43: d3dx11: Timeout
d3dx9_36: asm: Timeout core: Timeout effect: Timeout line: Timeout
Report validation errors: math: Timeout
=== debian11 (build log) ===
WineRunWineTest.pl:error: The task timed out