Skip to content
Permalink
Browse files
2010-07-17 Tony Gentilcore <tonyg@chromium.org>
        Reviewed by Darin Fisher.

        [Web Timing] Move times to DocumentLoader and fix bugs in mark points
        https://bugs.webkit.org/show_bug.cgi?id=42512

        * fast/dom/script-tests/webtiming-navigate-within-document.js: Added. Previously, navigating within a document via a fragment would reset navigationStart. This test verifies that no times are changed after navigating within a document.
        (checkTimingNotChanged):
        ():
        (loadHandler):
        * fast/dom/webtiming-expected.txt: Test now passes because when correcting for clock skew, requestTime is set to fetchStart when it is less than fetchStart. Previously it was 0, now it is fetchStart. This, unfortunately, hides the fact that test_shell isn't populating the ResourceLoadTiming API. I'll think of a way to test that when I make the change to cause test_shell to fill the ResourceLoadTiming.
        * fast/dom/webtiming-navigate-within-document-expected.txt: Added.
        * fast/dom/webtiming-navigate-within-document.html: Added.
        * platform/gtk/Skipped: Skip new test on platform where Web Timing is not enabled.
        * platform/mac/Skipped: Skip new test on platform where Web Timing is not enabled.
        * platform/qt/Skipped: Skip new test on platform where Web Timing is not enabled.
        * platform/win/Skipped: Skip new test on platform where Web Timing is not enabled.
2010-07-17  Tony Gentilcore  <tonyg@chromium.org>

        Reviewed by Darin Fisher.

        [Web Timing] Move times to DocumentLoader and fix bugs in mark points
        https://bugs.webkit.org/show_bug.cgi?id=42512

        Test: fast/dom/webtiming-navigate-within-document.html

        * loader/DocumentLoader.h: Move the FrameLoadTimeline (now call DocumentLoadTiming) to the DocumentLoader.
        (WebCore::DocumentLoader::documentLoadTiming):
        * loader/FrameLoader.cpp:
        (WebCore::FrameLoader::stopLoading): Set unloadEventEnd on the provisional DocumentLoader. Add some ASSERTs to tighten things up.
        (WebCore::FrameLoader::loadWithDocumentLoader): This was not the right place to set navigationStart. Setting it here caused it to be set before the unload form prompt and caused it to be reset when navigating within the document.
        (WebCore::FrameLoader::finishedLoading): Set responseEnd on the active DocumentLoader.
        (WebCore::FrameLoader::continueLoadAfterWillSubmitForm): This is the right place for navigationStart as defined by the spec.
        * loader/FrameLoader.h: Get rid of FrameLoadTimeline.
        * loader/FrameLoaderTypes.h: Rename FrameLoadTimeline to DocumentLoadTiming. It is even more apparent this doesn't belong in this file now. I am planning to submit a patch moving it out ASAP, but didn't want to muddy this patch with all those build files.
        (WebCore::DocumentLoadTiming::DocumentLoadTiming):
        * loader/MainResourceLoader.cpp:
        (WebCore::MainResourceLoader::willSendRequest): Move fetchStart out of this method to load(), and rewrite setting of redirectStart, redirectEnd, and redirectCount to be more readable.
        (WebCore::MainResourceLoader::load): Set fetchStart slightly earlier here and tighten it up with some ASSERTs.
        * page/DOMWindow.cpp:
        (WebCore::DOMWindow::dispatchLoadEvent): Set loadEventStart and loadEventEnd on the DocumentLoader.
        * page/Navigation.cpp:
        (WebCore::Navigation::redirectCount): Retrieve redirectCount from the DocumentLoader.
        * page/Timing.cpp:
        (WebCore::getPossiblySkewedTimeInKnownRange): The skew problem turned out to be due to the fact that chromium's currentTime() implementation only syncs to the system time every 60 seconds. So absolute times across threads may be skewed slightly. I resolved this temporarily by clipping the time from another thread into a known bound. A better long term solution is probably to add a currentTimeFromSystemTime() method and call that for web timing marks.
        (WebCore::Timing::navigationStart):
        (WebCore::Timing::unloadEventEnd):
        (WebCore::Timing::redirectStart):
        (WebCore::Timing::redirectEnd):
        (WebCore::Timing::fetchStart):
        (WebCore::Timing::domainLookupStart):
        (WebCore::Timing::domainLookupEnd):
        (WebCore::Timing::connectStart):
        (WebCore::Timing::connectEnd):
        (WebCore::Timing::requestStart):
        (WebCore::Timing::requestEnd):
        (WebCore::Timing::responseStart):
        (WebCore::Timing::responseEnd):
        (WebCore::Timing::loadEventStart):
        (WebCore::Timing::loadEventEnd):
        (WebCore::Timing::documentLoader):
        (WebCore::Timing::documentLoadTiming):
        (WebCore::Timing::resourceLoadTiming):
        (WebCore::Timing::resourceLoadTimeRelativeToAbsolute): Ensure requestTime is in the range of fetchStart to responseEnd.
        * page/Timing.h:

Canonical link: https://commits.webkit.org/54529@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@63689 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
tonygentilcore committed Jul 19, 2010
1 parent 63467e3 commit 9a51393d7f8e299dd10a9b70fa03b3a124a0606c
@@ -1,3 +1,22 @@
2010-07-17 Tony Gentilcore <tonyg@chromium.org>

Reviewed by Darin Fisher.

[Web Timing] Move times to DocumentLoader and fix bugs in mark points
https://bugs.webkit.org/show_bug.cgi?id=42512

* fast/dom/script-tests/webtiming-navigate-within-document.js: Added. Previously, navigating within a document via a fragment would reset navigationStart. This test verifies that no times are changed after navigating within a document.
(checkTimingNotChanged):
():
(loadHandler):
* fast/dom/webtiming-expected.txt: Test now passes because when correcting for clock skew, requestTime is set to fetchStart when it is less than fetchStart. Previously it was 0, now it is fetchStart. This, unfortunately, hides the fact that test_shell isn't populating the ResourceLoadTiming API. I'll think of a way to test that when I make the change to cause test_shell to fill the ResourceLoadTiming.
* fast/dom/webtiming-navigate-within-document-expected.txt: Added.
* fast/dom/webtiming-navigate-within-document.html: Added.
* platform/gtk/Skipped: Skip new test on platform where Web Timing is not enabled.
* platform/mac/Skipped: Skip new test on platform where Web Timing is not enabled.
* platform/qt/Skipped: Skip new test on platform where Web Timing is not enabled.
* platform/win/Skipped: Skip new test on platform where Web Timing is not enabled.

2010-07-19 Eric Carlson <eric.carlson@apple.com>

Unreviewed, build fix.
@@ -0,0 +1,36 @@
description("This test checks that navigating within the document does not reset Web Timing numbers.");

var performance = window.webkitPerformance || {};
var timing = performance.timing || {};

function checkTimingNotChanged()
{
for (var property in timing) {
if (timing[property] === initialTiming[property])
testPassed(property + " is unchanged.");
else
testFailed(property + " changed.");
}
finishJSTest();
}

var initialTiming = {};
function saveTimingAfterLoad()
{
for (var property in timing) {
initialTiming[property] = timing[property];
}
window.location.href = "#1";
setTimeout("checkTimingNotChanged()", 0);
}

function loadHandler()
{
window.removeEventListener("load", loadHandler);
setTimeout("saveTimingAfterLoad()", 0);
}
window.addEventListener("load", loadHandler, false);

jsTestIsAsync = true;

var successfullyParsed = true;
@@ -13,7 +13,7 @@ PASS timing.domainLookupStart is >= timing.fetchStart
PASS timing.domainLookupEnd is >= timing.domainLookupStart
PASS timing.connectStart is >= timing.domainLookupEnd
PASS timing.connectEnd is >= timing.connectStart
FAIL timing.requestStart should be >= timing.connectEnd. Was 0 (of type number).
PASS timing.requestStart is >= timing.connectEnd
PASS timing.requestEnd is >= timing.requestStart
PASS timing.responseStart is >= timing.requestEnd
PASS timing.loadEventStart is 0
@@ -28,7 +28,7 @@ PASS timing.domainLookupStart is >= timing.fetchStart
PASS timing.domainLookupEnd is >= timing.domainLookupStart
PASS timing.connectStart is >= timing.domainLookupEnd
PASS timing.connectEnd is >= timing.connectStart
FAIL timing.requestStart should be >= timing.connectEnd. Was 0 (of type number).
PASS timing.requestStart is >= timing.connectEnd
PASS timing.requestEnd is >= timing.requestStart
PASS timing.responseStart is >= timing.requestEnd
PASS timing.responseEnd is >= timing.responseStart
@@ -44,7 +44,7 @@ PASS timing.domainLookupStart is >= timing.fetchStart
PASS timing.domainLookupEnd is >= timing.domainLookupStart
PASS timing.connectStart is >= timing.domainLookupEnd
PASS timing.connectEnd is >= timing.connectStart
FAIL timing.requestStart should be >= timing.connectEnd. Was 0 (of type number).
PASS timing.requestStart is >= timing.connectEnd
PASS timing.requestEnd is >= timing.requestStart
PASS timing.responseStart is >= timing.requestEnd
PASS timing.responseEnd is >= timing.responseStart
@@ -0,0 +1,24 @@
This test checks that navigating within the document does not reset Web Timing numbers.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS requestEnd is unchanged.
PASS responseStart is unchanged.
PASS connectStart is unchanged.
PASS domainLookupStart is unchanged.
PASS connectEnd is unchanged.
PASS responseEnd is unchanged.
PASS requestStart is unchanged.
PASS navigationStart is unchanged.
PASS loadEventEnd is unchanged.
PASS redirectStart is unchanged.
PASS domainLookupEnd is unchanged.
PASS unloadEventEnd is unchanged.
PASS fetchStart is unchanged.
PASS loadEventStart is unchanged.
PASS redirectEnd is unchanged.
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,13 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="../js/resources/js-test-style.css">
<script src="../js/resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script src="script-tests/webtiming-navigate-within-document.js"></script>
<script src="../js/resources/js-test-post.js"></script>
</body>
</html>
@@ -5864,5 +5864,6 @@ fast/dom/navigation-type-back-forward.html
fast/dom/navigation-type-navigate.html
fast/dom/navigation-type-reload.html
fast/dom/webtiming.html
fast/dom/webtiming-navigate-within-document.html
http/tests/misc/webtiming-one-redirect.php
http/tests/misc/webtiming-two-redirects.php
@@ -290,5 +290,6 @@ fast/dom/navigation-type-back-forward.html
fast/dom/navigation-type-navigate.html
fast/dom/navigation-type-reload.html
fast/dom/webtiming.html
fast/dom/webtiming-navigate-within-document.html
http/tests/misc/webtiming-one-redirect.php
http/tests/misc/webtiming-two-redirects.php
@@ -5449,6 +5449,7 @@ fast/dom/navigation-type-back-forward.html
fast/dom/navigation-type-navigate.html
fast/dom/navigation-type-reload.html
fast/dom/webtiming.html
fast/dom/webtiming-navigate-within-document.html
http/tests/misc/webtiming-one-redirect.php
http/tests/misc/webtiming-two-redirects.php

@@ -958,6 +958,7 @@ fast/dom/navigation-type-back-forward.html
fast/dom/navigation-type-navigate.html
fast/dom/navigation-type-reload.html
fast/dom/webtiming.html
fast/dom/webtiming-navigate-within-document.html
http/tests/misc/webtiming-one-redirect.php
http/tests/misc/webtiming-two-redirects.php

@@ -1,3 +1,52 @@
2010-07-17 Tony Gentilcore <tonyg@chromium.org>

Reviewed by Darin Fisher.

[Web Timing] Move times to DocumentLoader and fix bugs in mark points
https://bugs.webkit.org/show_bug.cgi?id=42512

Test: fast/dom/webtiming-navigate-within-document.html

* loader/DocumentLoader.h: Move the FrameLoadTimeline (now call DocumentLoadTiming) to the DocumentLoader.
(WebCore::DocumentLoader::documentLoadTiming):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::stopLoading): Set unloadEventEnd on the provisional DocumentLoader. Add some ASSERTs to tighten things up.
(WebCore::FrameLoader::loadWithDocumentLoader): This was not the right place to set navigationStart. Setting it here caused it to be set before the unload form prompt and caused it to be reset when navigating within the document.
(WebCore::FrameLoader::finishedLoading): Set responseEnd on the active DocumentLoader.
(WebCore::FrameLoader::continueLoadAfterWillSubmitForm): This is the right place for navigationStart as defined by the spec.
* loader/FrameLoader.h: Get rid of FrameLoadTimeline.
* loader/FrameLoaderTypes.h: Rename FrameLoadTimeline to DocumentLoadTiming. It is even more apparent this doesn't belong in this file now. I am planning to submit a patch moving it out ASAP, but didn't want to muddy this patch with all those build files.
(WebCore::DocumentLoadTiming::DocumentLoadTiming):
* loader/MainResourceLoader.cpp:
(WebCore::MainResourceLoader::willSendRequest): Move fetchStart out of this method to load(), and rewrite setting of redirectStart, redirectEnd, and redirectCount to be more readable.
(WebCore::MainResourceLoader::load): Set fetchStart slightly earlier here and tighten it up with some ASSERTs.
* page/DOMWindow.cpp:
(WebCore::DOMWindow::dispatchLoadEvent): Set loadEventStart and loadEventEnd on the DocumentLoader.
* page/Navigation.cpp:
(WebCore::Navigation::redirectCount): Retrieve redirectCount from the DocumentLoader.
* page/Timing.cpp:
(WebCore::getPossiblySkewedTimeInKnownRange): The skew problem turned out to be due to the fact that chromium's currentTime() implementation only syncs to the system time every 60 seconds. So absolute times across threads may be skewed slightly. I resolved this temporarily by clipping the time from another thread into a known bound. A better long term solution is probably to add a currentTimeFromSystemTime() method and call that for web timing marks.
(WebCore::Timing::navigationStart):
(WebCore::Timing::unloadEventEnd):
(WebCore::Timing::redirectStart):
(WebCore::Timing::redirectEnd):
(WebCore::Timing::fetchStart):
(WebCore::Timing::domainLookupStart):
(WebCore::Timing::domainLookupEnd):
(WebCore::Timing::connectStart):
(WebCore::Timing::connectEnd):
(WebCore::Timing::requestStart):
(WebCore::Timing::requestEnd):
(WebCore::Timing::responseStart):
(WebCore::Timing::responseEnd):
(WebCore::Timing::loadEventStart):
(WebCore::Timing::loadEventEnd):
(WebCore::Timing::documentLoader):
(WebCore::Timing::documentLoadTiming):
(WebCore::Timing::resourceLoadTiming):
(WebCore::Timing::resourceLoadTimeRelativeToAbsolute): Ensure requestTime is in the range of fetchStart to responseEnd.
* page/Timing.h:

2010-07-19 Chris Marrin <cmarrin@apple.com>

Reviewed by Darin Adler.
@@ -205,6 +205,8 @@ namespace WebCore {
void recordMemoryCacheLoadForFutureClientNotification(const String& url);
void takeMemoryCacheLoadsForClientNotification(Vector<String>& loads);

DocumentLoadTiming* timing() { return &m_documentLoadTiming; }

#if ENABLE(OFFLINE_WEB_APPLICATIONS)
ApplicationCacheHost* applicationCacheHost() const { return m_applicationCacheHost.get(); }
#endif
@@ -294,6 +296,8 @@ namespace WebCore {
String m_clientRedirectSourceForHistory;
bool m_didCreateGlobalHistoryEntry;

DocumentLoadTiming m_documentLoadTiming;

#if ENABLE(OFFLINE_WEB_APPLICATIONS)
friend class ApplicationCacheHost; // for substitute resource delivery
OwnPtr<ApplicationCacheHost> m_applicationCacheHost;
@@ -449,7 +449,13 @@ void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolic
m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame->document()->inPageCache()), m_frame->document());
if (!m_frame->document()->inPageCache())
m_frame->domWindow()->dispatchEvent(Event::create(eventNames().unloadEvent, false, false), m_frame->domWindow()->document());
m_frameLoadTimeline.unloadEventEnd = currentTime();
if (m_provisionalDocumentLoader) {
DocumentLoadTiming* timing = m_provisionalDocumentLoader->timing();
ASSERT(timing->navigationStart);
ASSERT(!timing->unloadEventEnd);
timing->unloadEventEnd = currentTime();
ASSERT(timing->unloadEventEnd >= timing->navigationStart);
}
}
m_pageDismissalEventBeingDispatched = false;
if (m_frame->document())
@@ -1500,9 +1506,6 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t
if (m_pageDismissalEventBeingDispatched)
return;

m_frameLoadTimeline = FrameLoadTimeline();
m_frameLoadTimeline.navigationStart = currentTime();

policyChecker()->setLoadType(type);
RefPtr<FormState> formState = prpFormState;
bool isFormSubmission = formState;
@@ -2215,10 +2218,9 @@ void FrameLoader::finishedLoading()
// Retain because the stop may release the last reference to it.
RefPtr<Frame> protect(m_frame);

ASSERT(!m_frameLoadTimeline.responseEnd);
m_frameLoadTimeline.responseEnd = currentTime();

RefPtr<DocumentLoader> dl = activeDocumentLoader();
ASSERT(!dl->timing()->responseEnd);
dl->timing()->responseEnd = currentTime();
dl->finishedLoading();
if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
return;
@@ -2509,6 +2511,9 @@ void FrameLoader::continueLoadAfterWillSubmitForm()
notifier()->assignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
}

ASSERT(!m_provisionalDocumentLoader->timing()->navigationStart);
m_provisionalDocumentLoader->timing()->navigationStart = currentTime();

if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
m_provisionalDocumentLoader->updateLoading();
}
@@ -193,7 +193,6 @@ class FrameLoader : public Noncopyable {
void didChangeIcons(DocumentLoader*);

FrameLoadType loadType() const;
FrameLoadTimeline* frameLoadTimeline() { return &m_frameLoadTimeline; }

CachePolicy subresourceCachePolicy() const;

@@ -446,7 +445,6 @@ class FrameLoader : public Noncopyable {

FrameState m_state;
FrameLoadType m_loadType;
FrameLoadTimeline m_frameLoadTimeline;

// Document loaders for the three phases of frame loading. Note that while
// a new request is being loaded, the old document loader may still be referenced.
@@ -60,9 +60,9 @@ namespace WebCore {
FrameLoadTypeBackWMLDeckNotAccessible
};

// FIXME: Move this to a new header file.
struct FrameLoadTimeline {
FrameLoadTimeline()
// FIXME: Move to DocumentLoadTiming.h.
struct DocumentLoadTiming {
DocumentLoadTiming()
: navigationStart(0.0)
, unloadEventEnd(0.0)
, redirectStart(0.0)
@@ -159,14 +159,15 @@ void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const Reso
// reference to this object; one example of this is 3266216.
RefPtr<MainResourceLoader> protect(this);

FrameLoadTimeline* frameLoadTimeline = frameLoader()->frameLoadTimeline();
double fetchTime = currentTime();
if (double fetchStart = frameLoadTimeline->fetchStart) {
if (!frameLoadTimeline->redirectCount++)
frameLoadTimeline->redirectStart = fetchStart;
frameLoadTimeline->redirectEnd = fetchTime;
ASSERT(documentLoader()->timing()->fetchStart);
if (!redirectResponse.isNull()) {
DocumentLoadTiming* documentLoadTiming = documentLoader()->timing();
documentLoadTiming->redirectCount++;
if (!documentLoadTiming->redirectStart)
documentLoadTiming->redirectStart = documentLoadTiming->fetchStart;
documentLoadTiming->redirectEnd = currentTime();
documentLoadTiming->fetchStart = documentLoadTiming->redirectEnd;
}
frameLoadTimeline->fetchStart = fetchTime;

// Update cookie policy base URL as URL changes, except for subframes, which use the
// URL of the main frame which doesn't change when we redirect.
@@ -542,6 +543,9 @@ bool MainResourceLoader::load(const ResourceRequest& r, const SubstituteData& su

m_substituteData = substituteData;

ASSERT(documentLoader()->timing()->navigationStart);
ASSERT(!documentLoader()->timing()->fetchStart);
documentLoader()->timing()->fetchStart = currentTime();
ResourceRequest request(r);

#if ENABLE(OFFLINE_WEB_APPLICATIONS)
@@ -35,6 +35,7 @@
#include "CSSStyleSelector.h"
#include "Chrome.h"
#include "Console.h"
#include "DocumentLoader.h"
#include "DOMApplicationCache.h"
#include "DOMSelection.h"
#include "DOMTimer.h"
@@ -1438,11 +1439,11 @@ bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener

void DOMWindow::dispatchLoadEvent()
{
if (m_frame)
m_frame->loader()->frameLoadTimeline()->loadEventStart = currentTime();
if (DocumentLoader* documentLoader = m_frame ? m_frame->loader()->documentLoader() : 0)
documentLoader->timing()->loadEventStart = currentTime();
dispatchEvent(Event::create(eventNames().loadEvent, false, false), document());
if (m_frame)
m_frame->loader()->frameLoadTimeline()->loadEventEnd = currentTime();
if (DocumentLoader* documentLoader = m_frame ? m_frame->loader()->documentLoader() : 0)
documentLoader->timing()->loadEventEnd = currentTime();

// For load events, send a separate load event to the enclosing frame only.
// This is a DOM extension and is independent of bubbling/capturing rules of
@@ -79,7 +79,11 @@ unsigned short Navigation::redirectCount() const
if (!m_frame)
return 0;

return m_frame->loader()->frameLoadTimeline()->redirectCount;
DocumentLoader* loader = m_frame->loader()->documentLoader();
if (!loader)
return 0;

return loader->timing()->redirectCount;
}

} // namespace WebCore

0 comments on commit 9a51393

Please sign in to comment.