Skip to content
Permalink
Browse files
Implement PerformanceResourceTiming.workerStart in ServiceWorkers
https://bugs.webkit.org/show_bug.cgi?id=179377
rdar://problem/35391187

Patch by Youenn Fablet <youennf@gmail.com> on 2022-06-14
Reviewed by Alex Christensen.

Store the time when we are about to either fire the fetch event or run the service worker to fire the fetch event.
To do so, we store it in NetworkResourceLoader and send the value to WebResourceLoader.
In case of process swap, we send it back to the new WebResourceLoader.
WebResourceLoader is then responsible to update the network load metrics when receiving the response/finish load metrics.

Covered by updated tests.

* LayoutTests/http/wpt/service-workers/navigation-timing.https-expected.txt:
* LayoutTests/http/wpt/service-workers/navigation-timing.js:
(event.setTimeout):
* LayoutTests/http/wpt/service-workers/resources/navigation-timing-part-2.html:
* Source/WebCore/page/PerformanceResourceTiming.cpp:
(WebCore::PerformanceResourceTiming::workerStart const):
* Source/WebCore/platform/network/NetworkLoadMetrics.cpp:
(WebCore::NetworkLoadMetrics::updateFromFinalMetrics):
(WebCore::NetworkLoadMetrics::isolatedCopy const):
* Source/WebCore/platform/network/NetworkLoadMetrics.h:
(WebCore::NetworkLoadMetrics::encode const):
(WebCore::NetworkLoadMetrics::decode):
* Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::transferToNewWebProcess):
(WebKit::NetworkResourceLoader::continueWillSendRequest):
(WebKit::NetworkResourceLoader::setWorkerStart):
* Source/WebKit/NetworkProcess/NetworkResourceLoader.h:
* Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:
(WebKit::ServiceWorkerFetchTask::ServiceWorkerFetchTask):
* Source/WebKit/WebProcess/Network/WebResourceLoader.cpp:
(WebKit::WebResourceLoader::didReceiveResponse):
(WebKit::WebResourceLoader::didFinishResourceLoad):
* Source/WebKit/WebProcess/Network/WebResourceLoader.h:
(WebKit::WebResourceLoader::setWorkerStart):
* Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in:

Canonical link: https://commits.webkit.org/251523@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@295518 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
youennf authored and webkit-commit-queue committed Jun 14, 2022
1 parent 0e76c10 commit 729991ba18101356da55e5f09dcce7140c473613
Showing 12 changed files with 64 additions and 15 deletions.
@@ -1 +1 @@
PASS - navigation timing as expected
PASS
@@ -8,6 +8,8 @@ self.addEventListener('fetch', (event) => {
setTimeout(()=>{
event.respondWith(caches.open("cache_name").then((cache) => {
return cache.match(event.request).then((response) => {
if (!response)
return fetch(event.request);
return response;
});
}));
@@ -7,19 +7,33 @@
async function doTest()
{
const navTiming = performance.getEntries()[0];
const navTimingResult = (navigator.serviceWorker.controller
const navTimingResult = navigator.serviceWorker.controller
&& navTiming.fetchStart >= navTiming.workerStart
&& navTiming.requestStart + navTiming.responseStart + navTiming.responseEnd > 0
&& navTiming.responseStart >= navTiming.requestStart
&& navTiming.responseEnd >= navTiming.responseStart) ? "PASS - navigation timing as expected"
: "FAIL - navigation timing incorrect "
&& navTiming.responseEnd >= navTiming.responseStart;

if (!navTimingResult) {
document.body.innerHTML = "FAIL - navigation timing incorrect "
+ navTiming.fetchStart + " "
+ navTiming.workerStart + " "
+ navTiming.requestStart + " "
+ navTiming.responseStart + " "
+ navTiming.responseEnd;

document.body.innerHTML = navTimingResult;
if (window.testRunner) {
testRunner.notifyDone();
if (window.testRunner)
testRunner.notifyDone();
return;
}

const response = await fetch("/?test");
await response.text();
const fetchTiming = performance.getEntries()[1];

const fetchTimingResult = fetchTiming.fetchStart && fetchTiming.workerStart && fetchTiming.fetchStart >= fetchTiming.workerStart;
document.body.innerHTML = fetchTimingResult ? "PASS" : "Failed fetchTimingResult " + fetchTiming.fetchStart + " " + fetchTiming.workerStart;
if (window.testRunner)
testRunner.notifyDone();
}
</script>
</body>
@@ -107,8 +107,10 @@ const String& PerformanceResourceTiming::nextHopProtocol() const

double PerformanceResourceTiming::workerStart() const
{
// FIXME: <https://webkit.org/b/179377> Implement PerformanceResourceTiming.workerStart in ServiceWorkers
return 0.0;
if (m_resourceTiming.networkLoadMetrics().failsTAOCheck)
return 0.0;

return networkLoadTimeToDOMHighResTimeStamp(m_timeOrigin, m_resourceTiming.networkLoadMetrics().workerStart);
}

double PerformanceResourceTiming::redirectStart() const
@@ -44,6 +44,7 @@ void NetworkLoadMetrics::updateFromFinalMetrics(const NetworkLoadMetrics& other)
MonotonicTime originalRequestStart = requestStart;
MonotonicTime originalResponseStart = responseStart;
MonotonicTime originalResponseEnd = responseEnd;
MonotonicTime originalWorkerStart = workerStart;

*this = other;

@@ -67,6 +68,8 @@ void NetworkLoadMetrics::updateFromFinalMetrics(const NetworkLoadMetrics& other)
responseStart = originalResponseStart;
if (!responseEnd)
responseEnd = originalResponseEnd;
if (!workerStart)
workerStart = originalWorkerStart;

if (!responseEnd)
responseEnd = MonotonicTime::now();
@@ -109,6 +112,7 @@ NetworkLoadMetrics NetworkLoadMetrics::isolatedCopy() const
copy.requestStart = requestStart.isolatedCopy();
copy.responseStart = responseStart.isolatedCopy();
copy.responseEnd = responseEnd.isolatedCopy();
copy.workerStart = workerStart.isolatedCopy();

copy.protocol = protocol.isolatedCopy();

@@ -88,7 +88,8 @@ class NetworkLoadMetrics {
MonotonicTime requestStart;
MonotonicTime responseStart;
MonotonicTime responseEnd;

MonotonicTime workerStart;

// ALPN Protocol ID: https://w3c.github.io/resource-timing/#bib-RFC7301
String protocol;

@@ -159,6 +160,7 @@ void NetworkLoadMetrics::encode(Encoder& encoder) const
encoder << requestStart;
encoder << responseStart;
encoder << responseEnd;
encoder << workerStart;

encoder << protocol;

@@ -201,6 +203,7 @@ std::optional<NetworkLoadMetrics> NetworkLoadMetrics::decode(Decoder& decoder)
&& decoder.decode(metrics.requestStart)
&& decoder.decode(metrics.responseStart)
&& decoder.decode(metrics.responseEnd)
&& decoder.decode(metrics.workerStart)
&& decoder.decode(metrics.protocol)
&& decoder.decode(metrics.redirectCount)))
return std::nullopt;
@@ -591,6 +591,8 @@ void NetworkResourceLoader::transferToNewWebProcess(NetworkConnectionToWebProces
if (auto* swConnection = newConnection.swConnection())
swConnection->transferServiceWorkerLoadToNewWebProcess(*this, *m_serviceWorkerRegistration);
}
if (m_workerStart)
send(Messages::WebResourceLoader::SetWorkerStart { m_workerStart }, coreIdentifier());
#else
ASSERT(m_responseCompletionHandler || m_cacheEntryWaitingForContinueDidReceiveResponse);
#endif
@@ -1234,6 +1236,7 @@ void NetworkResourceLoader::continueWillSendRequest(ResourceRequest&& newRequest
#if ENABLE(SERVICE_WORKER)
if (shouldTryToMatchRegistrationOnRedirection(parameters().options, !!m_serviceWorkerFetchTask)) {
m_serviceWorkerRegistration = { };
setWorkerStart({ });
if (auto serviceWorkerFetchTask = m_connection->createFetchTask(*this, newRequest)) {
LOADER_RELEASE_LOG("continueWillSendRequest: Created a ServiceWorkerFetchTask to handle the redirect (fetchIdentifier=%" PRIu64 ")", serviceWorkerFetchTask->fetchIdentifier().toUInt64());
m_networkLoad = nullptr;
@@ -1776,6 +1779,12 @@ bool NetworkResourceLoader::isCrossOriginPrefetch() const
}

#if ENABLE(SERVICE_WORKER)
void NetworkResourceLoader::setWorkerStart(MonotonicTime value)
{
m_workerStart = value;
send(Messages::WebResourceLoader::SetWorkerStart { m_workerStart }, coreIdentifier());
}

void NetworkResourceLoader::startWithServiceWorker()
{
LOADER_RELEASE_LOG("startWithServiceWorker:");
@@ -44,6 +44,7 @@
#include <WebCore/SecurityPolicyViolationEvent.h>
#include <WebCore/SharedBuffer.h>
#include <WebCore/Timer.h>
#include <wtf/MonotonicTime.h>
#include <wtf/WeakPtr.h>

namespace WebCore {
@@ -156,6 +157,8 @@ class NetworkResourceLoader final
void setResultingClientIdentifier(String&& identifier) { m_resultingClientIdentifier = WTFMove(identifier); }
const String& resultingClientIdentifier() const { return m_resultingClientIdentifier; }
void setServiceWorkerRegistration(WebCore::SWServerRegistration& serviceWorkerRegistration) { m_serviceWorkerRegistration = serviceWorkerRegistration; }
void setWorkerStart(MonotonicTime);
MonotonicTime workerStart() const { return m_workerStart; }
#endif

std::optional<WebCore::ResourceError> doCrossOriginOpenerHandlingOfResponse(const WebCore::ResourceResponse&);
@@ -291,6 +294,7 @@ class NetworkResourceLoader final
std::unique_ptr<ServiceWorkerFetchTask> m_serviceWorkerFetchTask;
String m_resultingClientIdentifier;
WeakPtr<WebCore::SWServerRegistration> m_serviceWorkerRegistration;
MonotonicTime m_workerStart;
#endif
NetworkResourceLoadIdentifier m_resourceLoadID;
WebCore::ResourceResponse m_redirectResponse;
@@ -105,6 +105,8 @@ ServiceWorkerFetchTask::ServiceWorkerFetchTask(WebSWServerConnection& swServerCo
weakThis->preloadResponseIsReady();
});
}

loader.setWorkerStart(MonotonicTime::now());
}

ServiceWorkerFetchTask::~ServiceWorkerFetchTask()
@@ -156,8 +156,10 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR

Ref<WebResourceLoader> protectedThis(*this);

if (metrics)
if (metrics) {
metrics->workerStart = m_workerStart;
response.setDeprecatedNetworkLoadMetrics(Box<NetworkLoadMetrics>::create(WTFMove(*metrics)));
}

if (privateRelayed == PrivateRelayed::Yes && mainFrameMainResource() == MainFrameMainResource::Yes)
WebProcess::singleton().setHadMainFrameMainResourcePrivateRelayed();
@@ -241,19 +243,21 @@ void WebResourceLoader::didReceiveData(IPC::SharedBufferReference&& data, int64_
m_coreLoader->didReceiveData(data.isNull() ? SharedBuffer::create() : data.unsafeBuffer().releaseNonNull(), encodedDataLength, DataPayloadBytes);
}

void WebResourceLoader::didFinishResourceLoad(const NetworkLoadMetrics& networkLoadMetrics)
void WebResourceLoader::didFinishResourceLoad(NetworkLoadMetrics&& networkLoadMetrics)
{
LOG(Network, "(WebProcess) WebResourceLoader::didFinishResourceLoad for '%s'", m_coreLoader->url().string().latin1().data());
WEBRESOURCELOADER_RELEASE_LOG("didFinishResourceLoad: (length=%zd)", m_numBytesReceived);

if (UNLIKELY(m_interceptController.isIntercepting(m_coreLoader->identifier()))) {
m_interceptController.defer(m_coreLoader->identifier(), [this, protectedThis = Ref { *this }, networkLoadMetrics]() mutable {
m_interceptController.defer(m_coreLoader->identifier(), [this, protectedThis = Ref { *this }, networkLoadMetrics = WTFMove(networkLoadMetrics)]() mutable {
if (m_coreLoader)
didFinishResourceLoad(networkLoadMetrics);
didFinishResourceLoad(WTFMove(networkLoadMetrics));
});
return;
}

networkLoadMetrics.workerStart = m_workerStart;

ASSERT_WITH_MESSAGE(!m_isProcessingNetworkResponse, "Load should not be able to finish before we've validated the response");
m_coreLoader->didFinishLoading(networkLoadMetrics);
}
@@ -34,6 +34,7 @@
#include <WebCore/FrameIdentifier.h>
#include <WebCore/PageIdentifier.h>
#include <WebCore/ResourceLoaderIdentifier.h>
#include <wtf/MonotonicTime.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>

@@ -87,11 +88,12 @@ class WebResourceLoader : public RefCounted<WebResourceLoader>, public IPC::Mess
void didSendData(uint64_t bytesSent, uint64_t totalBytesToBeSent);
void didReceiveResponse(WebCore::ResourceResponse&&, PrivateRelayed, bool needsContinueDidReceiveResponseMessage, std::optional<WebCore::NetworkLoadMetrics>&&);
void didReceiveData(IPC::SharedBufferReference&& data, int64_t encodedDataLength);
void didFinishResourceLoad(const WebCore::NetworkLoadMetrics&);
void didFinishResourceLoad(WebCore::NetworkLoadMetrics&&);
void didFailResourceLoad(const WebCore::ResourceError&);
void didFailServiceWorkerLoad(const WebCore::ResourceError&);
void serviceWorkerDidNotHandle();
void didBlockAuthenticationChallenge();
void setWorkerStart(MonotonicTime value) { m_workerStart = value; }

void stopLoadingAfterXFrameOptionsOrContentSecurityPolicyDenied(const WebCore::ResourceResponse&);

@@ -113,6 +115,8 @@ class WebResourceLoader : public RefCounted<WebResourceLoader>, public IPC::Mess
#if ASSERT_ENABLED
bool m_isProcessingNetworkResponse { false };
#endif

MonotonicTime m_workerStart;
};

} // namespace WebKit
@@ -22,6 +22,7 @@

messages -> WebResourceLoader LegacyReceiver {
WillSendRequest(WebCore::ResourceRequest request, IPC::FormDataReference requestBody, WebCore::ResourceResponse redirectResponse)
SetWorkerStart(MonotonicTime value)
DidSendData(uint64_t bytesSent, uint64_t totalBytesToBeSent)
DidReceiveResponse(WebCore::ResourceResponse response, enum:bool WebKit::PrivateRelayed privateRelayed, bool needsContinueDidReceiveResponseMessage, std::optional<WebCore::NetworkLoadMetrics> optionalNetworkLoadMetrics)
DidReceiveData(IPC::SharedBufferReference data, int64_t encodedDataLength)

0 comments on commit 729991b

Please sign in to comment.