Commit f9a98b3a authored by Asami Doi's avatar Asami Doi Committed by Commit Bot

ServiceWorker: Consider sites that take more than the timeout as offline capable.

When a timeout happens in ServiceWorkerEventQueue, the error status
transfers to ServiceWorkerFetchDispatcher::OnFetchEventFinished(), but
the callback of an offline capability checker
(ServiceWorkerOfflineCapabilityChecker::OnFetchResult) can't catch the
error status.

This CL set a flag `is_timeout_event_` when the timeout happens and if
the flag is set, call DidFail() with the error status instead of
DidFinish() which is called in a successful case.

Bug: 965802
Change-Id: I9b38c8332f3bfc539d16b0f101143e7af3db66f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2437081
Commit-Queue: Asami Doi <asamidoi@chromium.org>
Reviewed-by: default avatarMakoto Shimazu <shimazu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823905}
parent 3a30346d
...@@ -623,6 +623,7 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() { ...@@ -623,6 +623,7 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
version_->endpoint()->DispatchFetchEventForMainResource( version_->endpoint()->DispatchFetchEventForMainResource(
std::move(params), std::move(pending_response_callback), std::move(params), std::move(pending_response_callback),
base::BindOnce(&ServiceWorkerFetchDispatcher::OnFetchEventFinished, base::BindOnce(&ServiceWorkerFetchDispatcher::OnFetchEventFinished,
weak_factory_.GetWeakPtr(),
base::Unretained(version_.get()), event_finish_id, base::Unretained(version_.get()), event_finish_id,
url_loader_assets_)); url_loader_assets_));
} }
...@@ -781,12 +782,14 @@ bool ServiceWorkerFetchDispatcher::IsEventDispatched() const { ...@@ -781,12 +782,14 @@ bool ServiceWorkerFetchDispatcher::IsEventDispatched() const {
return request_.is_null(); return request_.is_null();
} }
// static
void ServiceWorkerFetchDispatcher::OnFetchEventFinished( void ServiceWorkerFetchDispatcher::OnFetchEventFinished(
ServiceWorkerVersion* version, ServiceWorkerVersion* version,
int event_finish_id, int event_finish_id,
scoped_refptr<URLLoaderAssets> url_loader_assets, scoped_refptr<URLLoaderAssets> url_loader_assets,
blink::mojom::ServiceWorkerEventStatus status) { blink::mojom::ServiceWorkerEventStatus status) {
if (status == blink::mojom::ServiceWorkerEventStatus::TIMEOUT) {
DidFail(blink::ServiceWorkerStatusCode::kErrorTimeout);
}
version->FinishRequest( version->FinishRequest(
event_finish_id, event_finish_id,
status != blink::mojom::ServiceWorkerEventStatus::ABORTED); status != blink::mojom::ServiceWorkerEventStatus::ABORTED);
......
...@@ -101,11 +101,10 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher { ...@@ -101,11 +101,10 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
// are settled. This function is called once the renderer signals that // are settled. This function is called once the renderer signals that
// happened. |fetch_callback_| can run before this, once respondWith() is // happened. |fetch_callback_| can run before this, once respondWith() is
// settled. // settled.
static void OnFetchEventFinished( void OnFetchEventFinished(ServiceWorkerVersion* version,
ServiceWorkerVersion* version, int event_finish_id,
int event_finish_id, scoped_refptr<URLLoaderAssets> url_loader_assets,
scoped_refptr<URLLoaderAssets> url_loader_assets, blink::mojom::ServiceWorkerEventStatus status);
blink::mojom::ServiceWorkerEventStatus status);
ServiceWorkerMetrics::EventType GetEventType() const; ServiceWorkerMetrics::EventType GetEventType() const;
......
...@@ -677,6 +677,24 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerOfflineCapabilityCheckBrowserTest, ...@@ -677,6 +677,24 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerOfflineCapabilityCheckBrowserTest,
EXPECT_EQ(OfflineCapability::kUnsupported, EXPECT_EQ(OfflineCapability::kUnsupported,
CheckOfflineCapability("/service_worker/empty.html?cache_add")); CheckOfflineCapability("/service_worker/empty.html?cache_add"));
EXPECT_EQ(
OfflineCapability::kSupported,
CheckOfflineCapability("/service_worker/empty.html?sleep_then_offline"));
// Site that takes more than the timeout is considered as "offline capable".
EXPECT_EQ(OfflineCapability::kSupported,
CheckOfflineCapability(
"/service_worker/empty.html?sleep_then_offline&sleep=20000"));
EXPECT_EQ(
OfflineCapability::kUnsupported,
CheckOfflineCapability("/service_worker/empty.html?sleep_then_fetch"));
// Site that takes more than the timeout is considered as "offline capable".
EXPECT_EQ(OfflineCapability::kSupported,
CheckOfflineCapability(
"/service_worker/empty.html?sleep_then_fetch&sleep=20000"));
} }
// Sites with a service worker which is not activated yet are identified as // Sites with a service worker which is not activated yet are identified as
......
...@@ -130,15 +130,18 @@ void ServiceWorkerOfflineCapabilityChecker::OnFetchResult( ...@@ -130,15 +130,18 @@ void ServiceWorkerOfflineCapabilityChecker::OnFetchResult(
blink::mojom::ServiceWorkerStreamHandlePtr /* stream */, blink::mojom::ServiceWorkerStreamHandlePtr /* stream */,
blink::mojom::ServiceWorkerFetchEventTimingPtr /* timing */, blink::mojom::ServiceWorkerFetchEventTimingPtr /* timing */,
scoped_refptr<ServiceWorkerVersion> version) { scoped_refptr<ServiceWorkerVersion> version) {
if (status == blink::ServiceWorkerStatusCode::kOk && // The sites are considered as "offline capable" when the response finished
result == ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse && // successfully and returns 200 or the timeout happens.
// TODO(hayato): Investigate whether any 2xx should be accepted or not. if ((status == blink::ServiceWorkerStatusCode::kOk &&
response->status_code == 200) { result == ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse &&
// TODO(hayato): Investigate whether any 2xx should be accepted or not.
response->status_code == 200) ||
status == blink::ServiceWorkerStatusCode::kErrorTimeout) {
std::move(callback_).Run(OfflineCapability::kSupported, std::move(callback_).Run(OfflineCapability::kSupported,
version->registration_id()); version->registration_id());
} else { } else {
// TODO(hayato): At present, we return kUnsupported even if the detection // TODO(hayato): At present, we return kUnsupported even if the detection
// failed due to internal errors (disk fialures, timeout, etc). In the // failed due to internal errors except timeout (disk fialures, etc). In the
// future, we might want to return another enum value so that the callside // future, we might want to return another enum value so that the callside
// can know whether internal errors happened or not. // can know whether internal errors happened or not.
std::move(callback_).Run(OfflineCapability::kUnsupported, std::move(callback_).Run(OfflineCapability::kUnsupported,
......
...@@ -33,13 +33,13 @@ self.addEventListener("fetch", event => { ...@@ -33,13 +33,13 @@ self.addEventListener("fetch", event => {
); );
} else if (param.has("sleep_then_fetch")) { } else if (param.has("sleep_then_fetch")) {
event.respondWith( event.respondWith(
sleep(param.get("sleep") || 0, event.request.url).then(() => { sleep(param.get("sleep") || 0).then(() => {
return fetch(event.request.url); return fetch(event.request.url);
}) })
); );
} else if (param.has("sleep_then_offline")) { } else if (param.has("sleep_then_offline")) {
event.respondWith( event.respondWith(
sleep(param.get("sleep") || 0, event.request.url).then(() => { sleep(param.get("sleep") || 0).then(() => {
return new Response("Hello Offline page"); return new Response("Hello Offline page");
}) })
); );
......
...@@ -1952,9 +1952,9 @@ void ServiceWorkerGlobalScope::DispatchFetchEventForMainResource( ...@@ -1952,9 +1952,9 @@ void ServiceWorkerGlobalScope::DispatchFetchEventForMainResource(
DCHECK(IsContextThread()); DCHECK(IsContextThread());
// The timeout for offline events in a service worker. The default value is // The timeout for offline events in a service worker. The default value is
// the same as the default timeout (5 mins) of all events. // the same as the update interval value in the event queue.
static const base::FeatureParam<int> kCustomTimeoutForOfflineEvent{ static const base::FeatureParam<int> kCustomTimeoutForOfflineEvent{
&features::kCheckOfflineCapability, "timeout_second", 5 * 60}; &features::kCheckOfflineCapability, "timeout_second", 10};
const int event_id = event_queue_->NextEventId(); const int event_id = event_queue_->NextEventId();
fetch_event_callbacks_.Set(event_id, std::move(callback)); fetch_event_callbacks_.Set(event_id, std::move(callback));
......
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