Commit 1b2b965b authored by horo's avatar horo Committed by Commit bot

Support PerformanceResourceTiming for Service Worker Navigation Preload

BUG=712809

Review-Url: https://codereview.chromium.org/2847893003
Cr-Commit-Position: refs/heads/master@{#467979}
parent 8bd0a4b2
...@@ -421,7 +421,10 @@ class ServiceWorkerContextClient::NavigationPreloadRequest final ...@@ -421,7 +421,10 @@ class ServiceWorkerContextClient::NavigationPreloadRequest final
client->OnNavigationPreloadResponse(fetch_event_id_, std::move(response_), client->OnNavigationPreloadResponse(fetch_event_id_, std::move(response_),
nullptr); nullptr);
// This will delete |this|. // This will delete |this|.
client->OnNavigationPreloadComplete(fetch_event_id_); client->OnNavigationPreloadComplete(
fetch_event_id_, response_head.response_start,
response_head.encoded_data_length, 0 /* encoded_body_length */,
0 /* decoded_body_length */);
} }
void OnDataDownloaded(int64_t data_length, void OnDataDownloaded(int64_t data_length,
...@@ -484,7 +487,9 @@ class ServiceWorkerContextClient::NavigationPreloadRequest final ...@@ -484,7 +487,9 @@ class ServiceWorkerContextClient::NavigationPreloadRequest final
nullptr); nullptr);
} }
// This will delete |this|. // This will delete |this|.
client->OnNavigationPreloadComplete(fetch_event_id_); client->OnNavigationPreloadComplete(
fetch_event_id_, status.completion_time, status.encoded_data_length,
status.encoded_body_length, status.decoded_body_length);
} }
private: private:
...@@ -1636,7 +1641,14 @@ void ServiceWorkerContextClient::OnNavigationPreloadError( ...@@ -1636,7 +1641,14 @@ void ServiceWorkerContextClient::OnNavigationPreloadError(
} }
void ServiceWorkerContextClient::OnNavigationPreloadComplete( void ServiceWorkerContextClient::OnNavigationPreloadComplete(
int fetch_event_id) { int fetch_event_id,
base::TimeTicks completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) {
proxy_->OnNavigationPreloadComplete(
fetch_event_id, (completion_time - base::TimeTicks()).InSecondsF(),
encoded_data_length, encoded_body_length, decoded_body_length);
context_->preload_requests.Remove(fetch_event_id); context_->preload_requests.Remove(fetch_event_id);
} }
......
...@@ -318,7 +318,11 @@ class ServiceWorkerContextClient : public blink::WebServiceWorkerContextClient, ...@@ -318,7 +318,11 @@ class ServiceWorkerContextClient : public blink::WebServiceWorkerContextClient,
// Called when the navigation preload request completed. Either // Called when the navigation preload request completed. Either
// OnNavigationPreloadComplete() or OnNavigationPreloadError() must be called // OnNavigationPreloadComplete() or OnNavigationPreloadError() must be called
// to release the preload related resources. // to release the preload related resources.
void OnNavigationPreloadComplete(int fetch_event_id); void OnNavigationPreloadComplete(int fetch_event_id,
base::TimeTicks completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length);
// Called when an error occurred while receiving the response of the // Called when an error occurred while receiving the response of the
// navigation preload request. // navigation preload request.
void OnNavigationPreloadError( void OnNavigationPreloadError(
......
<!DOCTYPE html>
<meta charset="utf-8">
<title>Navigation Preload Resource Timing</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.sub.js"></script>
<script>
function check_timing_entry(entry, url, decodedBodySize, encodedBodySize) {
assert_equals(entry.name, url, 'The entry name of '+ url);
assert_equals(
entry.entryType, 'resource',
'The entryType of preload response timing entry must be "resource' +
'" :' + url);
assert_equals(
entry.initiatorType, 'other',
'The initiatorType of preload response timing entry must be ' +
'"other":' + url);
// If the server returns the redirect response, |decodedBodySize| is null and
// |entry.decodedBodySize| shuld be 0. Otherwise |entry.decodedBodySize| must
// same as |decodedBodySize|
assert_equals(
entry.decodedBodySize, Number(decodedBodySize),
'decodedBodySize must same as the decoded size in the server:' + url);
// If the server returns the redirect response, |encodedBodySize| is null and
// |entry.encodedBodySize| shuld be 0. Otherwise |entry.encodedBodySize| must
// same as |encodedBodySize|
assert_equals(
entry.encodedBodySize, Number(encodedBodySize),
'encodedBodySize must same as the encoded size in the server:' + url);
assert_greater_than(
entry.transferSize, entry.decodedBodySize,
'transferSize must greater then encodedBodySize.');
assert_greater_than(entry.startTime, 0, 'startTime of ' + url);
assert_greater_than_equal(entry.fetchStart, entry.startTime,
'fetchStart >= startTime of ' + url);
assert_greater_than_equal(entry.domainLookupStart, entry.fetchStart,
'domainLookupStart >= fetchStart of ' + url);
assert_greater_than_equal(entry.domainLookupEnd, entry.domainLookupStart,
'domainLookupEnd >= domainLookupStart of ' + url);
assert_greater_than_equal(entry.connectStart, entry.domainLookupEnd,
'connectStart >= domainLookupEnd of ' + url);
assert_greater_than_equal(entry.connectEnd, entry.connectStart,
'connectEnd >= connectStart of ' + url);
assert_greater_than_equal(entry.requestStart, entry.connectEnd,
'requestStart >= connectEnd of ' + url);
assert_greater_than_equal(entry.responseStart, entry.requestStart,
'domainLookupStart >= requestStart of ' + url);
assert_greater_than_equal(entry.responseEnd, entry.responseStart,
'responseEnd >= responseStart of ' + url);
assert_greater_than(entry.duration, 0, 'duration of ' + url);
}
promise_test(t => {
var script = 'resources/resource-timing-worker.js';
var scope = 'resources/resource-timing-scope.py';
var registration;
var frames = [];
return service_worker_unregister_and_register(t, script, scope)
.then(reg => {
registration = reg;
add_completion_callback(_ => registration.unregister());
return wait_for_state(t, registration.installing, 'activated');
})
.then(_ => with_iframe(scope + '?type=normal'))
.then(frame => {
frames.push(frame);
return with_iframe(scope + '?type=redirect');
})
.then(frame => {
frames.push(frame);
frames.forEach(frame => {
var result = JSON.parse(frame.contentDocument.body.textContent);
assert_equals(
result.timingEntries.length, 1,
'performance.getEntriesByName() must returns one ' +
'PerformanceResourceTiming entry for the navigation preload.');
var entry = result.timingEntries[0];
check_timing_entry(entry, frame.src, result.decodedBodySize,
result.encodedBodySize);
frame.remove();
});
return registration.unregister();
});
}, 'Navigation Preload Resource Timing.');
</script>
import zlib
def main(request, response):
type = request.GET.first("type")
if type == "normal":
content = "This is Navigation Preload Resource Timing test."
output = zlib.compress(content, 9)
headers = [("Content-type", "text/plain"),
("Content-Encoding", "deflate"),
("X-Decoded-Body-Size", len(content)),
("X-Encoded-Body-Size", len(output)),
("Content-Length", len(output))]
return headers, output
if type == "redirect":
response.status = 302
response.headers.append("Location", "redirect-redirected.html")
return ""
self.addEventListener('activate', event => {
event.waitUntil(self.registration.navigationPreload.enable());
});
self.addEventListener('fetch', event => {
event.respondWith(
event.preloadResponse
.then(response => {
var headers = response.headers;
return response.text().then(text =>
new Response(
JSON.stringify({
decodedBodySize: headers.get('X-Decoded-Body-Size'),
encodedBodySize: headers.get('X-Encoded-Body-Size'),
timingEntries: performance.getEntriesByName(event.request.url)
}),
{headers: {'Content-Type': 'text/html'}}));
}));
});
<!DOCTYPE html>
<meta charset="utf-8">
<title>Navigation Preload Resource Timing after terminating SW</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../resources/test-helpers.js"></script>
<script>
function check_timing_entry(entry, allow_negative_value) {
var name = entry.name;
if (!allow_negative_value) {
assert_greater_than(entry.startTime, 0, 'startTime of ' + name);
assert_greater_than(entry.fetchStart, 0, 'fetchStart of ' + name);
assert_greater_than(entry.domainLookupStart, 0,
'domainLookupStart of ' + name);
assert_greater_than(entry.domainLookupEnd, 0,
'domainLookupEnd of ' + name);
assert_greater_than(entry.connectStart, 0, 'connectStart of ' + name);
assert_greater_than(entry.connectEnd, 0, 'connectEnd of ' + name);
assert_greater_than(entry.requestStart, 0, 'requestStart of ' + name);
assert_greater_than(entry.responseStart, 0, 'responseStart of ' + name);
assert_greater_than(entry.responseEnd, 0, 'responseEnd of ' + name);
}
assert_greater_than_equal(entry.fetchStart, entry.startTime,
'fetchStart >= startTime of ' + name);
assert_greater_than_equal(entry.domainLookupStart, entry.fetchStart,
'domainLookupStart >= fetchStart of ' + name);
assert_greater_than_equal(entry.domainLookupEnd, entry.domainLookupStart,
'domainLookupEnd >= domainLookupStart of ' + name);
assert_greater_than_equal(entry.connectStart, entry.domainLookupEnd,
'connectStart >= domainLookupEnd of ' + name);
assert_greater_than_equal(entry.connectEnd, entry.connectStart,
'connectEnd >= connectStart of ' + name);
assert_greater_than_equal(entry.requestStart, entry.connectEnd,
'requestStart >= connectEnd of ' + name);
assert_greater_than_equal(entry.responseStart, entry.requestStart,
'domainLookupStart >= requestStart of ' + name);
assert_greater_than_equal(entry.responseEnd, entry.responseStart,
'responseEnd >= responseStart of ' + name);
assert_greater_than(entry.duration, 0, 'duration of ' + name);
}
promise_test(t => {
var script = 'resources/navigation-preload-resource-timing-worker.js';
var scope = 'resources/navigation-preload-resource-timing-scope.html';
var registration;
var frames = [];
return service_worker_unregister_and_register(t, script, scope)
.then(reg => {
registration = reg;
add_completion_callback(_ => registration.unregister());
return wait_for_state(t, registration.installing, 'activated');
})
.then(_ => with_iframe(scope + '?1'))
.then(frame => {
frames.push(frame);
return with_iframe(scope + '?2');
})
.then(frame => {
frames.push(frame);
return internals.terminateServiceWorker(registration.active);
})
.then(_ => with_iframe(scope + '?3'))
.then(frame => {
frames.push(frame);
var results = frames.map(frame => {
var result = JSON.parse(frame.contentDocument.body.textContent);
return result.timingEntries.filter(entry => {
return entry.name.indexOf(scope) != -1;
})
});
assert_equals(results.length, 3);
assert_equals(results[0].length, 1,
'The first result must contain only one entry.');
assert_equals(results[0][0].name, frames[0].src,
'The entry of the first result must be the entry for ' +
'the first iframe.');
assert_equals(results[1].length, 2,
'The second result must contain two entry.');
assert_object_equals(results[1][0], results[0][0],
'The first entry of the second result must be ' +
'same as the entry of the first result.');
assert_equals(results[1][1].name, frames[1].src,
'The second entry of the second result must be the ' +
'entry for the second iframe.');
assert_equals(results[2].length, 1,
'The third result must contain only one entry.');
assert_equals(results[2][0].name, frames[2].src,
'The entry of the third result must be the entry for ' +
'the third iframe.');
check_timing_entry(results[1][0], false /* allow_negative_value */);
check_timing_entry(results[1][1], false /* allow_negative_value */);
check_timing_entry(results[2][0], true /* allow_negative_value */);
frames.forEach(frame => frame.remove());
return registration.unregister();
});
}, 'Navigation Preload Resource Timing after terminating SW.');
</script>
self.addEventListener('activate', event => {
event.waitUntil(self.registration.navigationPreload.enable());
});
self.addEventListener('fetch', event => {
event.respondWith(
event.preloadResponse
.then(response => response.text())
.then(text =>
new Response(
JSON.stringify({timingEntries: performance.getEntries()}),
{headers: {'Content-Type': 'text/html'}})));
});
...@@ -505,15 +505,17 @@ double PerformanceBase::ClampTimeResolution(double time_seconds) { ...@@ -505,15 +505,17 @@ double PerformanceBase::ClampTimeResolution(double time_seconds) {
return floor(time_seconds / kResolutionSeconds) * kResolutionSeconds; return floor(time_seconds / kResolutionSeconds) * kResolutionSeconds;
} }
// static
DOMHighResTimeStamp PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( DOMHighResTimeStamp PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
double time_origin, double time_origin,
double monotonic_time) { double monotonic_time,
bool allow_negative_value) {
// Avoid exposing raw platform timestamps. // Avoid exposing raw platform timestamps.
if (!monotonic_time || !time_origin) if (!monotonic_time || !time_origin)
return 0.0; return 0.0;
double time_in_seconds = monotonic_time - time_origin; double time_in_seconds = monotonic_time - time_origin;
if (time_in_seconds < 0) if (time_in_seconds < 0 && !allow_negative_value)
return 0.0; return 0.0;
return ConvertSecondsToDOMHighResTimeStamp( return ConvertSecondsToDOMHighResTimeStamp(
ClampTimeResolution(time_in_seconds)); ClampTimeResolution(time_in_seconds));
...@@ -521,7 +523,8 @@ DOMHighResTimeStamp PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( ...@@ -521,7 +523,8 @@ DOMHighResTimeStamp PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
DOMHighResTimeStamp PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( DOMHighResTimeStamp PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
double monotonic_time) const { double monotonic_time) const {
return MonotonicTimeToDOMHighResTimeStamp(time_origin_, monotonic_time); return MonotonicTimeToDOMHighResTimeStamp(time_origin_, monotonic_time,
false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceBase::now() const { DOMHighResTimeStamp PerformanceBase::now() const {
......
...@@ -76,7 +76,8 @@ class CORE_EXPORT PerformanceBase : public EventTargetWithInlineData { ...@@ -76,7 +76,8 @@ class CORE_EXPORT PerformanceBase : public EventTargetWithInlineData {
static DOMHighResTimeStamp MonotonicTimeToDOMHighResTimeStamp( static DOMHighResTimeStamp MonotonicTimeToDOMHighResTimeStamp(
double time_origin, double time_origin,
double monotonic_time); double monotonic_time,
bool allow_negative_value);
// Translate given platform monotonic time in seconds into a high resolution // Translate given platform monotonic time in seconds into a high resolution
// DOMHighResTimeStamp in milliseconds. The result timestamp is relative to // DOMHighResTimeStamp in milliseconds. The result timestamp is relative to
......
...@@ -133,7 +133,8 @@ DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventStart() const { ...@@ -133,7 +133,8 @@ DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventStart() const {
!timing->HasSameOriginAsPreviousDocument()) !timing->HasSameOriginAsPreviousDocument())
return 0; return 0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->UnloadEventStart()); time_origin_, timing->UnloadEventStart(),
false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventEnd() const { DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventEnd() const {
...@@ -144,7 +145,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventEnd() const { ...@@ -144,7 +145,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventEnd() const {
!timing->HasSameOriginAsPreviousDocument()) !timing->HasSameOriginAsPreviousDocument())
return 0; return 0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->UnloadEventEnd()); time_origin_, timing->UnloadEventEnd(), false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::domInteractive() const { DOMHighResTimeStamp PerformanceNavigationTiming::domInteractive() const {
...@@ -152,7 +153,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::domInteractive() const { ...@@ -152,7 +153,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::domInteractive() const {
if (!timing) if (!timing)
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->DomInteractive()); time_origin_, timing->DomInteractive(), false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventStart() DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventStart()
...@@ -161,7 +162,8 @@ DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventStart() ...@@ -161,7 +162,8 @@ DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventStart()
if (!timing) if (!timing)
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->DomContentLoadedEventStart()); time_origin_, timing->DomContentLoadedEventStart(),
false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventEnd() DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventEnd()
...@@ -170,7 +172,8 @@ DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventEnd() ...@@ -170,7 +172,8 @@ DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventEnd()
if (!timing) if (!timing)
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->DomContentLoadedEventEnd()); time_origin_, timing->DomContentLoadedEventEnd(),
false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::domComplete() const { DOMHighResTimeStamp PerformanceNavigationTiming::domComplete() const {
...@@ -178,7 +181,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::domComplete() const { ...@@ -178,7 +181,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::domComplete() const {
if (!timing) if (!timing)
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->DomComplete()); time_origin_, timing->DomComplete(), false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::loadEventStart() const { DOMHighResTimeStamp PerformanceNavigationTiming::loadEventStart() const {
...@@ -186,7 +189,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::loadEventStart() const { ...@@ -186,7 +189,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::loadEventStart() const {
if (!timing) if (!timing)
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->LoadEventStart()); time_origin_, timing->LoadEventStart(), false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::loadEventEnd() const { DOMHighResTimeStamp PerformanceNavigationTiming::loadEventEnd() const {
...@@ -194,7 +197,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::loadEventEnd() const { ...@@ -194,7 +197,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::loadEventEnd() const {
if (!timing) if (!timing)
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->LoadEventEnd()); time_origin_, timing->LoadEventEnd(), false /* allow_negative_value */);
} }
AtomicString PerformanceNavigationTiming::type() const { AtomicString PerformanceNavigationTiming::type() const {
...@@ -219,7 +222,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::redirectStart() const { ...@@ -219,7 +222,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::redirectStart() const {
if (!allow_redirect_details || !timing) if (!allow_redirect_details || !timing)
return 0; return 0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->RedirectStart()); time_origin_, timing->RedirectStart(), false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::redirectEnd() const { DOMHighResTimeStamp PerformanceNavigationTiming::redirectEnd() const {
...@@ -228,7 +231,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::redirectEnd() const { ...@@ -228,7 +231,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::redirectEnd() const {
if (!allow_redirect_details || !timing) if (!allow_redirect_details || !timing)
return 0; return 0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->RedirectEnd()); time_origin_, timing->RedirectEnd(), false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::fetchStart() const { DOMHighResTimeStamp PerformanceNavigationTiming::fetchStart() const {
...@@ -236,7 +239,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::fetchStart() const { ...@@ -236,7 +239,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::fetchStart() const {
if (!timing) if (!timing)
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->FetchStart()); time_origin_, timing->FetchStart(), false /* allow_negative_value */);
} }
DOMHighResTimeStamp PerformanceNavigationTiming::responseEnd() const { DOMHighResTimeStamp PerformanceNavigationTiming::responseEnd() const {
...@@ -244,7 +247,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::responseEnd() const { ...@@ -244,7 +247,7 @@ DOMHighResTimeStamp PerformanceNavigationTiming::responseEnd() const {
if (!timing) if (!timing)
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->ResponseEnd()); time_origin_, timing->ResponseEnd(), false /* allow_negative_value */);
} }
// Overriding PerformanceEntry's attributes. // Overriding PerformanceEntry's attributes.
......
...@@ -46,14 +46,16 @@ PerformanceResourceTiming::PerformanceResourceTiming( ...@@ -46,14 +46,16 @@ PerformanceResourceTiming::PerformanceResourceTiming(
double last_redirect_end_time, double last_redirect_end_time,
bool allow_timing_details, bool allow_timing_details,
bool allow_redirect_details) bool allow_redirect_details)
: PerformanceEntry( : PerformanceEntry(info.InitialURL().GetString(),
info.InitialURL().GetString(), "resource",
"resource", PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(time_origin, time_origin,
start_time), start_time,
PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( info.NegativeAllowed()),
time_origin, PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
info.LoadFinishTime())), time_origin,
info.LoadFinishTime(),
info.NegativeAllowed())),
initiator_type_(info.InitiatorType()), initiator_type_(info.InitiatorType()),
time_origin_(time_origin), time_origin_(time_origin),
timing_(info.FinalResponse().GetResourceLoadTiming()), timing_(info.FinalResponse().GetResourceLoadTiming()),
...@@ -64,7 +66,8 @@ PerformanceResourceTiming::PerformanceResourceTiming( ...@@ -64,7 +66,8 @@ PerformanceResourceTiming::PerformanceResourceTiming(
decoded_body_size_(info.FinalResponse().DecodedBodyLength()), decoded_body_size_(info.FinalResponse().DecodedBodyLength()),
did_reuse_connection_(info.FinalResponse().ConnectionReused()), did_reuse_connection_(info.FinalResponse().ConnectionReused()),
allow_timing_details_(allow_timing_details), allow_timing_details_(allow_timing_details),
allow_redirect_details_(allow_redirect_details) {} allow_redirect_details_(allow_redirect_details),
allow_negative_value_(info.NegativeAllowed()) {}
// This constructor is for PerformanceNavigationTiming. // This constructor is for PerformanceNavigationTiming.
PerformanceResourceTiming::PerformanceResourceTiming(const String& name, PerformanceResourceTiming::PerformanceResourceTiming(const String& name,
...@@ -109,7 +112,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::workerStart() const { ...@@ -109,7 +112,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::workerStart() const {
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->WorkerStart()); time_origin_, timing->WorkerStart(), allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::WorkerReady() const { DOMHighResTimeStamp PerformanceResourceTiming::WorkerReady() const {
...@@ -118,7 +121,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::WorkerReady() const { ...@@ -118,7 +121,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::WorkerReady() const {
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->WorkerReady()); time_origin_, timing->WorkerReady(), allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::redirectStart() const { DOMHighResTimeStamp PerformanceResourceTiming::redirectStart() const {
...@@ -136,7 +139,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::redirectEnd() const { ...@@ -136,7 +139,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::redirectEnd() const {
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, last_redirect_end_time_); time_origin_, last_redirect_end_time_, allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::fetchStart() const { DOMHighResTimeStamp PerformanceResourceTiming::fetchStart() const {
...@@ -146,7 +149,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::fetchStart() const { ...@@ -146,7 +149,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::fetchStart() const {
if (last_redirect_end_time_) { if (last_redirect_end_time_) {
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->RequestTime()); time_origin_, timing->RequestTime(), allow_negative_value_);
} }
if (DOMHighResTimeStamp worker_ready_time = WorkerReady()) if (DOMHighResTimeStamp worker_ready_time = WorkerReady())
...@@ -163,7 +166,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::domainLookupStart() const { ...@@ -163,7 +166,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::domainLookupStart() const {
return fetchStart(); return fetchStart();
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->DnsStart()); time_origin_, timing->DnsStart(), allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::domainLookupEnd() const { DOMHighResTimeStamp PerformanceResourceTiming::domainLookupEnd() const {
...@@ -173,8 +176,8 @@ DOMHighResTimeStamp PerformanceResourceTiming::domainLookupEnd() const { ...@@ -173,8 +176,8 @@ DOMHighResTimeStamp PerformanceResourceTiming::domainLookupEnd() const {
if (!timing || timing->DnsEnd() == 0.0) if (!timing || timing->DnsEnd() == 0.0)
return domainLookupStart(); return domainLookupStart();
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(time_origin_, return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
timing->DnsEnd()); time_origin_, timing->DnsEnd(), allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::connectStart() const { DOMHighResTimeStamp PerformanceResourceTiming::connectStart() const {
...@@ -190,8 +193,8 @@ DOMHighResTimeStamp PerformanceResourceTiming::connectStart() const { ...@@ -190,8 +193,8 @@ DOMHighResTimeStamp PerformanceResourceTiming::connectStart() const {
if (timing->DnsEnd() > 0.0) if (timing->DnsEnd() > 0.0)
connect_start = timing->DnsEnd(); connect_start = timing->DnsEnd();
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(time_origin_, return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
connect_start); time_origin_, connect_start, allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::connectEnd() const { DOMHighResTimeStamp PerformanceResourceTiming::connectEnd() const {
...@@ -203,7 +206,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::connectEnd() const { ...@@ -203,7 +206,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::connectEnd() const {
return connectStart(); return connectStart();
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->ConnectEnd()); time_origin_, timing->ConnectEnd(), allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::secureConnectionStart() const { DOMHighResTimeStamp PerformanceResourceTiming::secureConnectionStart() const {
...@@ -215,7 +218,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::secureConnectionStart() const { ...@@ -215,7 +218,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::secureConnectionStart() const {
return 0.0; return 0.0;
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->SslStart()); time_origin_, timing->SslStart(), allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::requestStart() const { DOMHighResTimeStamp PerformanceResourceTiming::requestStart() const {
...@@ -226,7 +229,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::requestStart() const { ...@@ -226,7 +229,7 @@ DOMHighResTimeStamp PerformanceResourceTiming::requestStart() const {
return connectEnd(); return connectEnd();
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->SendStart()); time_origin_, timing->SendStart(), allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::responseStart() const { DOMHighResTimeStamp PerformanceResourceTiming::responseStart() const {
...@@ -239,15 +242,15 @@ DOMHighResTimeStamp PerformanceResourceTiming::responseStart() const { ...@@ -239,15 +242,15 @@ DOMHighResTimeStamp PerformanceResourceTiming::responseStart() const {
// FIXME: This number isn't exactly correct. See the notes in // FIXME: This number isn't exactly correct. See the notes in
// PerformanceTiming::responseStart(). // PerformanceTiming::responseStart().
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp( return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
time_origin_, timing->ReceiveHeadersEnd()); time_origin_, timing->ReceiveHeadersEnd(), allow_negative_value_);
} }
DOMHighResTimeStamp PerformanceResourceTiming::responseEnd() const { DOMHighResTimeStamp PerformanceResourceTiming::responseEnd() const {
if (!finish_time_) if (!finish_time_)
return responseStart(); return responseStart();
return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(time_origin_, return PerformanceBase::MonotonicTimeToDOMHighResTimeStamp(
finish_time_); time_origin_, finish_time_, allow_negative_value_);
} }
unsigned long long PerformanceResourceTiming::transferSize() const { unsigned long long PerformanceResourceTiming::transferSize() const {
......
...@@ -121,6 +121,7 @@ class CORE_EXPORT PerformanceResourceTiming : public PerformanceEntry { ...@@ -121,6 +121,7 @@ class CORE_EXPORT PerformanceResourceTiming : public PerformanceEntry {
bool did_reuse_connection_; bool did_reuse_connection_;
bool allow_timing_details_; bool allow_timing_details_;
bool allow_redirect_details_; bool allow_redirect_details_;
bool allow_negative_value_;
}; };
} // namespace blink } // namespace blink
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#ifndef WorkerGlobalScopePerformance_h #ifndef WorkerGlobalScopePerformance_h
#define WorkerGlobalScopePerformance_h #define WorkerGlobalScopePerformance_h
#include "core/CoreExport.h"
#include "core/timing/WorkerPerformance.h" #include "core/timing/WorkerPerformance.h"
#include "core/workers/WorkerGlobalScope.h" #include "core/workers/WorkerGlobalScope.h"
#include "platform/Supplementable.h" #include "platform/Supplementable.h"
...@@ -40,7 +41,7 @@ namespace blink { ...@@ -40,7 +41,7 @@ namespace blink {
class WorkerGlobalScope; class WorkerGlobalScope;
class WorkerGlobalScopePerformance final class CORE_EXPORT WorkerGlobalScopePerformance final
: public GarbageCollected<WorkerGlobalScopePerformance>, : public GarbageCollected<WorkerGlobalScopePerformance>,
public Supplement<WorkerGlobalScope> { public Supplement<WorkerGlobalScope> {
USING_GARBAGE_COLLECTED_MIXIN(WorkerGlobalScopePerformance); USING_GARBAGE_COLLECTED_MIXIN(WorkerGlobalScopePerformance);
......
...@@ -8,12 +8,14 @@ ...@@ -8,12 +8,14 @@
#include "bindings/core/v8/ToV8ForCore.h" #include "bindings/core/v8/ToV8ForCore.h"
#include "bindings/core/v8/V8PrivateProperty.h" #include "bindings/core/v8/V8PrivateProperty.h"
#include "core/dom/ExecutionContext.h" #include "core/dom/ExecutionContext.h"
#include "core/timing/WorkerGlobalScopePerformance.h"
#include "modules/fetch/BytesConsumerForDataConsumerHandle.h" #include "modules/fetch/BytesConsumerForDataConsumerHandle.h"
#include "modules/fetch/Request.h" #include "modules/fetch/Request.h"
#include "modules/fetch/Response.h" #include "modules/fetch/Response.h"
#include "modules/serviceworkers/FetchRespondWithObserver.h" #include "modules/serviceworkers/FetchRespondWithObserver.h"
#include "modules/serviceworkers/ServiceWorkerError.h" #include "modules/serviceworkers/ServiceWorkerError.h"
#include "modules/serviceworkers/ServiceWorkerGlobalScope.h" #include "modules/serviceworkers/ServiceWorkerGlobalScope.h"
#include "platform/loader/fetch/ResourceTimingInfo.h"
#include "platform/network/NetworkUtils.h" #include "platform/network/NetworkUtils.h"
#include "platform/wtf/PtrUtil.h" #include "platform/wtf/PtrUtil.h"
#include "platform/wtf/RefPtr.h" #include "platform/wtf/RefPtr.h"
...@@ -114,7 +116,9 @@ void FetchEvent::OnNavigationPreloadResponse( ...@@ -114,7 +116,9 @@ void FetchEvent::OnNavigationPreloadResponse(
if (!script_state->ContextIsValid()) if (!script_state->ContextIsValid())
return; return;
DCHECK(preload_response_property_); DCHECK(preload_response_property_);
DCHECK(!preload_response_);
ScriptState::Scope scope(script_state); ScriptState::Scope scope(script_state);
preload_response_ = std::move(response);
FetchResponseData* response_data = FetchResponseData* response_data =
data_consume_handle data_consume_handle
? FetchResponseData::CreateWithBuffer(new BodyStreamBuffer( ? FetchResponseData::CreateWithBuffer(new BodyStreamBuffer(
...@@ -123,18 +127,19 @@ void FetchEvent::OnNavigationPreloadResponse( ...@@ -123,18 +127,19 @@ void FetchEvent::OnNavigationPreloadResponse(
std::move(data_consume_handle)))) std::move(data_consume_handle))))
: FetchResponseData::Create(); : FetchResponseData::Create();
Vector<KURL> url_list(1); Vector<KURL> url_list(1);
url_list[0] = response->Url(); url_list[0] = preload_response_->Url();
response_data->SetURLList(url_list); response_data->SetURLList(url_list);
response_data->SetStatus(response->HttpStatusCode()); response_data->SetStatus(preload_response_->HttpStatusCode());
response_data->SetStatusMessage(response->HttpStatusText()); response_data->SetStatusMessage(preload_response_->HttpStatusText());
response_data->SetResponseTime(response->ToResourceResponse().ResponseTime()); response_data->SetResponseTime(
preload_response_->ToResourceResponse().ResponseTime());
const HTTPHeaderMap& headers( const HTTPHeaderMap& headers(
response->ToResourceResponse().HttpHeaderFields()); preload_response_->ToResourceResponse().HttpHeaderFields());
for (const auto& header : headers) { for (const auto& header : headers) {
response_data->HeaderList()->Append(header.key, header.value); response_data->HeaderList()->Append(header.key, header.value);
} }
FetchResponseData* tainted_response = FetchResponseData* tainted_response =
NetworkUtils::IsRedirectResponseCode(response->HttpStatusCode()) NetworkUtils::IsRedirectResponseCode(preload_response_->HttpStatusCode())
? response_data->CreateOpaqueRedirectFilteredResponse() ? response_data->CreateOpaqueRedirectFilteredResponse()
: response_data->CreateBasicFilteredResponse(); : response_data->CreateBasicFilteredResponse();
preload_response_property_->Resolve( preload_response_property_->Resolve(
...@@ -151,6 +156,33 @@ void FetchEvent::OnNavigationPreloadError( ...@@ -151,6 +156,33 @@ void FetchEvent::OnNavigationPreloadError(
ServiceWorkerError::Take(nullptr, *error.get())); ServiceWorkerError::Take(nullptr, *error.get()));
} }
void FetchEvent::OnNavigationPreloadComplete(
WorkerGlobalScope* worker_global_scope,
double completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) {
DCHECK(preload_response_);
std::unique_ptr<WebURLResponse> response = std::move(preload_response_);
ResourceResponse resource_response = response->ToResourceResponse();
resource_response.SetEncodedDataLength(encoded_data_length);
resource_response.SetEncodedBodyLength(encoded_body_length);
resource_response.SetDecodedBodyLength(decoded_body_length);
// According to the current spec of Resource Timing, the initiator type of
// navigation preload request must be "other". But it may change when the spec
// discussion is settled. https://github.com/w3c/resource-timing/issues/110
RefPtr<ResourceTimingInfo> info = ResourceTimingInfo::Create(
"other", resource_response.GetResourceLoadTiming()->RequestTime(),
false /* is_main_resource */);
info->SetNegativeAllowed(true);
info->SetLoadFinishTime(completion_time);
info->SetInitialURL(request_->url());
info->SetFinalResponse(resource_response);
info->AddFinalTransferSize(encoded_data_length);
WorkerGlobalScopePerformance::performance(*worker_global_scope)
->AddResourceTiming(*info);
}
DEFINE_TRACE(FetchEvent) { DEFINE_TRACE(FetchEvent) {
visitor->Trace(observer_); visitor->Trace(observer_);
visitor->Trace(request_); visitor->Trace(request_);
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef FetchEvent_h #ifndef FetchEvent_h
#define FetchEvent_h #define FetchEvent_h
#include <memory>
#include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseProperty.h" #include "bindings/core/v8/ScriptPromiseProperty.h"
#include "modules/EventModules.h" #include "modules/EventModules.h"
...@@ -14,6 +16,7 @@ ...@@ -14,6 +16,7 @@
#include "modules/serviceworkers/FetchEventInit.h" #include "modules/serviceworkers/FetchEventInit.h"
#include "modules/serviceworkers/WaitUntilObserver.h" #include "modules/serviceworkers/WaitUntilObserver.h"
#include "platform/heap/Handle.h" #include "platform/heap/Handle.h"
#include "platform/loader/fetch/ResourceResponse.h"
namespace blink { namespace blink {
...@@ -25,6 +28,7 @@ class ScriptState; ...@@ -25,6 +28,7 @@ class ScriptState;
class WebDataConsumerHandle; class WebDataConsumerHandle;
struct WebServiceWorkerError; struct WebServiceWorkerError;
class WebURLResponse; class WebURLResponse;
class WorkerGlobalScope;
// A fetch event is dispatched by the client to a service worker's script // A fetch event is dispatched by the client to a service worker's script
// context. FetchRespondWithObserver can be used to notify the client about the // context. FetchRespondWithObserver can be used to notify the client about the
...@@ -58,6 +62,11 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent { ...@@ -58,6 +62,11 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent {
std::unique_ptr<WebDataConsumerHandle>); std::unique_ptr<WebDataConsumerHandle>);
void OnNavigationPreloadError(ScriptState*, void OnNavigationPreloadError(ScriptState*,
std::unique_ptr<WebServiceWorkerError>); std::unique_ptr<WebServiceWorkerError>);
void OnNavigationPreloadComplete(WorkerGlobalScope*,
double completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length);
const AtomicString& InterfaceName() const override; const AtomicString& InterfaceName() const override;
...@@ -75,6 +84,7 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent { ...@@ -75,6 +84,7 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent {
Member<FetchRespondWithObserver> observer_; Member<FetchRespondWithObserver> observer_;
Member<Request> request_; Member<Request> request_;
Member<PreloadResponseProperty> preload_response_property_; Member<PreloadResponseProperty> preload_response_property_;
std::unique_ptr<WebURLResponse> preload_response_;
String client_id_; String client_id_;
bool is_reload_; bool is_reload_;
}; };
......
...@@ -22,6 +22,7 @@ PassRefPtr<ResourceTimingInfo> ResourceTimingInfo::Adopt( ...@@ -22,6 +22,7 @@ PassRefPtr<ResourceTimingInfo> ResourceTimingInfo::Adopt(
for (auto& response_data : data->redirect_chain_) for (auto& response_data : data->redirect_chain_)
info->redirect_chain_.push_back(ResourceResponse(response_data.get())); info->redirect_chain_.push_back(ResourceResponse(response_data.get()));
info->transfer_size_ = data->transfer_size_; info->transfer_size_ = data->transfer_size_;
info->negative_allowed_ = data->negative_allowed_;
return info.Release(); return info.Release();
} }
...@@ -40,6 +41,7 @@ ResourceTimingInfo::CopyData() const { ...@@ -40,6 +41,7 @@ ResourceTimingInfo::CopyData() const {
data->redirect_chain_.push_back(response.CopyData()); data->redirect_chain_.push_back(response.CopyData());
data->transfer_size_ = transfer_size_; data->transfer_size_ = transfer_size_;
data->is_main_resource_ = is_main_resource_; data->is_main_resource_ = is_main_resource_;
data->negative_allowed_ = negative_allowed_;
return data; return data;
} }
......
...@@ -104,15 +104,22 @@ class PLATFORM_EXPORT ResourceTimingInfo ...@@ -104,15 +104,22 @@ class PLATFORM_EXPORT ResourceTimingInfo
redirect.SetResourceLoadTiming(nullptr); redirect.SetResourceLoadTiming(nullptr);
} }
// The timestamps in PerformanceResourceTiming are measured relative from the
// time origin. In most cases these timestamps must be positive value, so we
// use 0 for invalid negative values. But the timestamps for Service Worker
// navigation preload requests may be negative, because these requests may
// be started before the service worker started. We set this flag true, to
// support such case.
void SetNegativeAllowed(bool negative_allowed) {
negative_allowed_ = negative_allowed;
}
bool NegativeAllowed() const { return negative_allowed_; }
private: private:
ResourceTimingInfo(const AtomicString& type, ResourceTimingInfo(const AtomicString& type,
const double time, const double time,
bool is_main_resource) bool is_main_resource)
: type_(type), : type_(type), initial_time_(time), is_main_resource_(is_main_resource) {}
initial_time_(time),
transfer_size_(0),
is_main_resource_(is_main_resource),
has_cross_origin_redirect_(false) {}
AtomicString type_; AtomicString type_;
AtomicString original_timing_allow_origin_; AtomicString original_timing_allow_origin_;
...@@ -121,9 +128,10 @@ class PLATFORM_EXPORT ResourceTimingInfo ...@@ -121,9 +128,10 @@ class PLATFORM_EXPORT ResourceTimingInfo
KURL initial_url_; KURL initial_url_;
ResourceResponse final_response_; ResourceResponse final_response_;
Vector<ResourceResponse> redirect_chain_; Vector<ResourceResponse> redirect_chain_;
long long transfer_size_; long long transfer_size_ = 0;
bool is_main_resource_; bool is_main_resource_;
bool has_cross_origin_redirect_; bool has_cross_origin_redirect_ = false;
bool negative_allowed_ = false;
}; };
struct CrossThreadResourceTimingInfoData { struct CrossThreadResourceTimingInfoData {
...@@ -142,6 +150,7 @@ struct CrossThreadResourceTimingInfoData { ...@@ -142,6 +150,7 @@ struct CrossThreadResourceTimingInfoData {
Vector<std::unique_ptr<CrossThreadResourceResponseData>> redirect_chain_; Vector<std::unique_ptr<CrossThreadResourceResponseData>> redirect_chain_;
long long transfer_size_; long long transfer_size_;
bool is_main_resource_; bool is_main_resource_;
bool negative_allowed_;
}; };
template <> template <>
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
#include "modules/serviceworkers/WaitUntilObserver.h" #include "modules/serviceworkers/WaitUntilObserver.h"
#include "platform/CrossThreadFunctional.h" #include "platform/CrossThreadFunctional.h"
#include "platform/RuntimeEnabledFeatures.h" #include "platform/RuntimeEnabledFeatures.h"
#include "platform/loader/fetch/ResourceResponse.h"
#include "platform/wtf/Assertions.h" #include "platform/wtf/Assertions.h"
#include "platform/wtf/Functional.h" #include "platform/wtf/Functional.h"
#include "platform/wtf/PtrUtil.h" #include "platform/wtf/PtrUtil.h"
...@@ -278,7 +279,7 @@ void ServiceWorkerGlobalScopeProxy::DispatchFetchEvent( ...@@ -278,7 +279,7 @@ void ServiceWorkerGlobalScopeProxy::DispatchFetchEvent(
script_state, EventTypeNames::fetch, event_init, respond_with_observer, script_state, EventTypeNames::fetch, event_init, respond_with_observer,
wait_until_observer, navigation_preload_sent); wait_until_observer, navigation_preload_sent);
if (navigation_preload_sent) { if (navigation_preload_sent) {
// Keep |fetchEvent| until onNavigationPreloadResponse() or // Keep |fetchEvent| until OnNavigationPreloadComplete() or
// onNavigationPreloadError() will be called. // onNavigationPreloadError() will be called.
pending_preload_fetch_events_.insert(fetch_event_id, fetch_event); pending_preload_fetch_events_.insert(fetch_event_id, fetch_event);
} }
...@@ -296,7 +297,9 @@ void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadResponse( ...@@ -296,7 +297,9 @@ void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadResponse(
int fetch_event_id, int fetch_event_id,
std::unique_ptr<WebURLResponse> response, std::unique_ptr<WebURLResponse> response,
std::unique_ptr<WebDataConsumerHandle> data_consume_handle) { std::unique_ptr<WebDataConsumerHandle> data_consume_handle) {
FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id); auto it = pending_preload_fetch_events_.find(fetch_event_id);
DCHECK(it != pending_preload_fetch_events_.end());
FetchEvent* fetch_event = it->value.Get();
DCHECK(fetch_event); DCHECK(fetch_event);
fetch_event->OnNavigationPreloadResponse( fetch_event->OnNavigationPreloadResponse(
WorkerGlobalScope()->ScriptController()->GetScriptState(), WorkerGlobalScope()->ScriptController()->GetScriptState(),
...@@ -307,9 +310,7 @@ void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadError( ...@@ -307,9 +310,7 @@ void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadError(
int fetch_event_id, int fetch_event_id,
std::unique_ptr<WebServiceWorkerError> error) { std::unique_ptr<WebServiceWorkerError> error) {
FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id); FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
// This method may be called after onNavigationPreloadResponse() was called. DCHECK(fetch_event);
if (!fetch_event)
return;
// Display an unsanitized console message. // Display an unsanitized console message.
if (!error->unsanitized_message.IsEmpty()) { if (!error->unsanitized_message.IsEmpty()) {
WorkerGlobalScope()->AddConsoleMessage(ConsoleMessage::Create( WorkerGlobalScope()->AddConsoleMessage(ConsoleMessage::Create(
...@@ -322,6 +323,19 @@ void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadError( ...@@ -322,6 +323,19 @@ void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadError(
std::move(error)); std::move(error));
} }
void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadComplete(
int fetch_event_id,
double completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) {
FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
DCHECK(fetch_event);
fetch_event->OnNavigationPreloadComplete(
WorkerGlobalScope(), completion_time, encoded_data_length,
encoded_body_length, decoded_body_length);
}
void ServiceWorkerGlobalScopeProxy::DispatchForeignFetchEvent( void ServiceWorkerGlobalScopeProxy::DispatchForeignFetchEvent(
int fetch_event_id, int fetch_event_id,
const WebServiceWorkerRequest& web_request) { const WebServiceWorkerRequest& web_request) {
......
...@@ -130,6 +130,11 @@ class ServiceWorkerGlobalScopeProxy final ...@@ -130,6 +130,11 @@ class ServiceWorkerGlobalScopeProxy final
void OnNavigationPreloadError( void OnNavigationPreloadError(
int fetch_event_id, int fetch_event_id,
std::unique_ptr<WebServiceWorkerError>) override; std::unique_ptr<WebServiceWorkerError>) override;
void OnNavigationPreloadComplete(int fetch_event_id,
double completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) override;
// WorkerReportingProxy overrides: // WorkerReportingProxy overrides:
void CountFeature(UseCounter::Feature) override; void CountFeature(UseCounter::Feature) override;
......
...@@ -125,6 +125,11 @@ class WebServiceWorkerContextProxy { ...@@ -125,6 +125,11 @@ class WebServiceWorkerContextProxy {
virtual void OnNavigationPreloadError( virtual void OnNavigationPreloadError(
int fetch_event_id, int fetch_event_id,
std::unique_ptr<WebServiceWorkerError>) = 0; std::unique_ptr<WebServiceWorkerError>) = 0;
virtual void OnNavigationPreloadComplete(int fetch_event_id,
double completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) = 0;
}; };
} // namespace blink } // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment