Commit 12e095b7 authored by Asami Doi's avatar Asami Doi Committed by Commit Bot

ServiceWorker: Add browser tests to make sure the implementation

to use an existing script on offline is correct or not.

The goal is to import and evaluate as a module script at ServiceWorker.
Users can use it by adding type 'module' when register a service
worker script.

The reason why I use browser tests instead of WPT tests is I want to
make sure an installed script works well offline. There is no way to
terminate a worker from WPT tests. These new tests are for 'classic'
and 'module' scripts.

Change-Id: I17f201080eeced93b8dccb8a3867721798b3699c
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Bug: 824647
Reviewed-on: https://chromium-review.googlesource.com/c/1276046
Commit-Queue: Asami Doi <asamidoi@google.com>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Reviewed-by: default avatarHiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601465}
parent c9dd6b7d
......@@ -582,9 +582,12 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
}
void InstallTestHelper(const std::string& worker_url,
blink::ServiceWorkerStatusCode expected_status) {
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
base::Unretained(this), worker_url));
blink::ServiceWorkerStatusCode expected_status,
blink::mojom::ScriptType script_type =
blink::mojom::ScriptType::kClassic) {
RunOnIOThread(
base::BindOnce(&self::SetUpRegistrationWithScriptTypeOnIOThread,
base::Unretained(this), worker_url, script_type));
// Dispatch install on a worker.
base::Optional<blink::ServiceWorkerStatusCode> status;
......@@ -605,8 +608,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
stop_run_loop.Run();
}
void ActivateTestHelper(const std::string& worker_url,
blink::ServiceWorkerStatusCode expected_status) {
void ActivateTestHelper(blink::ServiceWorkerStatusCode expected_status) {
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop run_loop;
base::PostTaskWithTraits(
......@@ -641,10 +643,18 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
}
void SetUpRegistrationOnIOThread(const std::string& worker_url) {
SetUpRegistrationWithScriptTypeOnIOThread(
worker_url, blink::mojom::ScriptType::kClassic);
}
void SetUpRegistrationWithScriptTypeOnIOThread(
const std::string& worker_url,
blink::mojom::ScriptType script_type) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
const GURL scope = embedded_test_server()->GetURL("/service_worker/");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = scope;
options.type = script_type;
registration_ = new ServiceWorkerRegistration(
options, wrapper()->context()->storage()->NewRegistrationId(),
wrapper()->context()->AsWeakPtr());
......@@ -654,10 +664,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
version_ = new ServiceWorkerVersion(
registration_.get(), embedded_test_server()->GetURL(worker_url),
blink::mojom::ScriptType::kClassic,
wrapper()->context()->storage()->NewVersionId(),
script_type, wrapper()->context()->storage()->NewVersionId(),
wrapper()->context()->AsWeakPtr());
// Make the registration findable via storage functions.
wrapper()->context()->storage()->NotifyInstallingRegistration(
registration_.get());
......@@ -1130,8 +1138,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
// Create a registration and active version.
InstallTestHelper("/service_worker/worker.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper("/service_worker/worker.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper(blink::ServiceWorkerStatusCode::kOk);
ASSERT_TRUE(registration_->active_version());
// Give the version a controllee.
......@@ -1213,8 +1220,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
StartServerAndNavigateToSetup();
InstallTestHelper("/service_worker/worker.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper("/service_worker/worker.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper(blink::ServiceWorkerStatusCode::kOk);
ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
}
......@@ -1223,7 +1229,6 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
InstallTestHelper("/service_worker/worker_activate_rejected.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper(
"/service_worker/worker_activate_rejected.js",
blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected);
}
......@@ -1268,6 +1273,44 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
&console_listener));
}
// Tests starting an installed classic service worker while offline.
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
StartInstalledClassicScriptWhileOffline) {
StartServerAndNavigateToSetup();
// Install a service worker.
InstallTestHelper("/service_worker/worker_with_one_import.js",
blink::ServiceWorkerStatusCode::kOk,
blink::mojom::ScriptType::kClassic);
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
// Emulate offline by stopping the test server.
EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
EXPECT_FALSE(embedded_test_server()->Started());
// Restart the worker while offline.
StartWorker(blink::ServiceWorkerStatusCode::kOk);
}
// Tests starting an installed module service worker while offline.
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
StartInstalledModuleScriptWhileOffline) {
StartServerAndNavigateToSetup();
// Install a service worker.
InstallTestHelper("/service_worker/static_import_worker.js",
blink::ServiceWorkerStatusCode::kOk,
blink::mojom::ScriptType::kModule);
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
// Emulate offline by stopping the test server.
EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
EXPECT_FALSE(embedded_test_server()->Started());
// Restart the worker while offline.
StartWorker(blink::ServiceWorkerStatusCode::kOk);
}
class WaitForLoaded : public EmbeddedWorkerInstance::Listener {
public:
explicit WaitForLoaded(base::OnceClosure quit) : quit_(std::move(quit)) {}
......@@ -1362,8 +1405,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
InstallTestHelper("/service_worker/fetch_event.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper("/service_worker/fetch_event.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper(blink::ServiceWorkerStatusCode::kOk);
FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
......@@ -1391,8 +1433,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
const base::Time start_time(base::Time::Now());
InstallTestHelper("/service_worker/fetch_event_response_via_cache.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper("/service_worker/fetch_event_response_via_cache.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper(blink::ServiceWorkerStatusCode::kOk);
FetchOnRegisteredWorker(&result, &response1, &blob_data_handle);
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
......@@ -1423,8 +1464,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
InstallTestHelper("/service_worker/fetch_event_rejected.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper("/service_worker/fetch_event_rejected.js",
blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper(blink::ServiceWorkerStatusCode::kOk);
ConsoleListener console_listener;
RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver,
......
......@@ -37,9 +37,25 @@ ServiceWorkerReadFromCacheJob::ServiceWorkerReadFromCacheJob(
version_(version),
weak_factory_(this) {
DCHECK(version_);
DCHECK(resource_type_ == RESOURCE_TYPE_SCRIPT ||
(resource_type_ == RESOURCE_TYPE_SERVICE_WORKER &&
version_->script_url() == request_->url()));
#if DCHECK_IS_ON()
switch (version_->script_type()) {
case blink::mojom::ScriptType::kClassic:
// For classic scripts, the main service worker script should have the
// "service worker" resource type and imported scripts should have the
// "script" resource type.
DCHECK(resource_type_ == RESOURCE_TYPE_SCRIPT ||
(resource_type_ == RESOURCE_TYPE_SERVICE_WORKER &&
version_->script_url() == request_->url()));
break;
case blink::mojom::ScriptType::kModule:
// For module scripts, both the main service worker script and
// static-imported scripts should have the "service worker" resource type
// because static import inherits the resource type of the top-level
// module script.
DCHECK_EQ(RESOURCE_TYPE_SERVICE_WORKER, resource_type_);
break;
}
#endif // DCHECK_IS_ON()
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker",
"ServiceWorkerReadFromCacheJob", this,
"URL", request_->url().spec());
......
......@@ -408,6 +408,14 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
set_new_version(new ServiceWorkerVersion(
registration(), script_url_, worker_script_type_, version_id, context_));
new_version()->set_force_bypass_cache_for_scripts(force_bypass_cache_);
// Module service workers don't support pause after download so we can't
// perform script comparison.
// TODO(asamidoi): Support pause after download in module workers.
if (worker_script_type_ == blink::mojom::ScriptType::kModule) {
skip_script_comparison_ = true;
}
if (registration()->has_installed_version() && !skip_script_comparison_) {
new_version()->SetToPauseAfterDownload(
base::BindOnce(&ServiceWorkerRegisterJob::OnPausedAfterDownload,
......
......@@ -814,6 +814,8 @@ void ServiceWorkerVersion::Doom() {
}
void ServiceWorkerVersion::SetToPauseAfterDownload(base::OnceClosure callback) {
// TODO(asamidoi): Support pause after download in module workers.
DCHECK_EQ(blink::mojom::ScriptType::kClassic, script_type_);
pause_after_download_callback_ = std::move(callback);
}
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as module from './worker.js';
......@@ -265,7 +265,13 @@ std::unique_ptr<WebURLLoader> WorkerFetchContext::CreateURLLoader(
->CreateURLLoader(wrapped, CreateResourceLoadingTaskRunnerHandle());
}
if (request.GetRequestContext() == mojom::RequestContextType::SCRIPT) {
// Use |script_loader_factory_| to load types SCRIPT (classic imported
// scripts) and SERVICE_WORKER (module main scripts and module imported
// scripts). Note that classic main scripts are also SERVICE_WORKER but loaded
// by the shadow page on the main thread, not here.
if (request.GetRequestContext() == mojom::RequestContextType::SCRIPT ||
request.GetRequestContext() ==
mojom::RequestContextType::SERVICE_WORKER) {
if (!script_loader_factory_)
script_loader_factory_ = web_context_->CreateScriptLoaderFactory();
if (script_loader_factory_) {
......
......@@ -309,6 +309,13 @@ void WebEmbeddedWorkerImpl::OnShadowPageInitialized() {
return;
}
// If this is a module service worker, start the worker thread now. The worker
// thread will fetch the script.
if (worker_start_data_.script_type == mojom::ScriptType::kModule) {
StartWorkerThread();
return;
}
// Note: We only get here if this is a new (i.e., not installed) service
// worker.
DCHECK(!main_script_loader_);
......
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