1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/browsing_data/browsing_data_browsertest_utils.h"
6
7 #include <memory>
8 #include <string>
9 #include <utility>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/run_loop.h"
14 #include "base/task/post_task.h"
15 #include "components/network_session_configurator/common/network_switches.h"
16 #include "content/browser/browsing_data/browsing_data_test_utils.h"
17 #include "content/public/browser/browser_task_traits.h"
18 #include "content/public/browser/network_service_instance.h"
19 #include "content/public/browser/service_worker_context.h"
20 #include "content/public/browser/storage_partition.h"
21 #include "content/public/browser/storage_usage_info.h"
22 #include "content/public/common/content_switches.h"
23 #include "content/public/common/network_service_util.h"
24 #include "content/public/test/content_browser_test_utils.h"
25 #include "mojo/public/cpp/bindings/remote.h"
26 #include "net/base/url_util.h"
27 #include "net/test/embedded_test_server/http_response.h"
28 #include "services/network/public/mojom/network_service.mojom.h"
29 #include "services/network/public/mojom/network_service_test.mojom.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 namespace content {
33
34 namespace browsing_data_browsertest_utils {
35
36 namespace {
37
AddServiceWorkerCallback(bool success)38 void AddServiceWorkerCallback(bool success) {
39 ASSERT_TRUE(success);
40 }
41
GetServiceWorkersCallback(base::OnceClosure callback,std::vector<StorageUsageInfo> * out_service_workers,const std::vector<StorageUsageInfo> & service_workers)42 void GetServiceWorkersCallback(
43 base::OnceClosure callback,
44 std::vector<StorageUsageInfo>* out_service_workers,
45 const std::vector<StorageUsageInfo>& service_workers) {
46 *out_service_workers = service_workers;
47 std::move(callback).Run();
48 }
49
50 } // namespace
51
SignalActivation(ServiceWorkerContextWrapper * context,base::OnceClosure callback)52 void ServiceWorkerActivationObserver::SignalActivation(
53 ServiceWorkerContextWrapper* context,
54 base::OnceClosure callback) {
55 new ServiceWorkerActivationObserver(context, std::move(callback));
56 }
57
ServiceWorkerActivationObserver(ServiceWorkerContextWrapper * context,base::OnceClosure callback)58 ServiceWorkerActivationObserver::ServiceWorkerActivationObserver(
59 ServiceWorkerContextWrapper* context,
60 base::OnceClosure callback)
61 : context_(context),
62 scoped_observer_(this),
63 callback_(std::move(callback)) {
64 scoped_observer_.Add(context);
65 }
66
~ServiceWorkerActivationObserver()67 ServiceWorkerActivationObserver::~ServiceWorkerActivationObserver() {}
68
OnVersionStateChanged(int64_t version_id,const GURL & scope,ServiceWorkerVersion::Status)69 void ServiceWorkerActivationObserver::OnVersionStateChanged(
70 int64_t version_id,
71 const GURL& scope,
72 ServiceWorkerVersion::Status) {
73 if (context_->GetLiveVersion(version_id)->status() ==
74 ServiceWorkerVersion::ACTIVATED) {
75 std::move(callback_).Run();
76 delete this;
77 }
78 }
79
SetIgnoreCertificateErrors(base::CommandLine * command_line)80 void SetIgnoreCertificateErrors(base::CommandLine* command_line) {
81 if (IsOutOfProcessNetworkService()) {
82 // |MockCertVerifier| only seems to work when Network Service was enabled.
83 command_line->AppendSwitch(switches::kUseMockCertVerifierForTesting);
84 } else {
85 // We're redirecting all hosts to localhost even on HTTPS, so we'll get
86 // certificate errors.
87 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
88 }
89 }
90
AddServiceWorker(const std::string & origin,StoragePartition * storage_partition,net::EmbeddedTestServer * https_server)91 void AddServiceWorker(const std::string& origin,
92 StoragePartition* storage_partition,
93 net::EmbeddedTestServer* https_server) {
94 DCHECK_CURRENTLY_ON(BrowserThread::UI);
95 ServiceWorkerContextWrapper* service_worker_context =
96 static_cast<ServiceWorkerContextWrapper*>(
97 storage_partition->GetServiceWorkerContext());
98
99 GURL scope_url = https_server->GetURL(origin, "/");
100 GURL js_url = https_server->GetURL(origin, "/?file=worker.js");
101
102 // Register the worker.
103 blink::mojom::ServiceWorkerRegistrationOptions options(
104 scope_url, blink::mojom::ScriptType::kClassic,
105 blink::mojom::ServiceWorkerUpdateViaCache::kImports);
106 RunOrPostTaskOnThread(
107 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
108 base::BindOnce(&ServiceWorkerContextWrapper::RegisterServiceWorker,
109 base::Unretained(service_worker_context), js_url, options,
110 base::BindOnce(&AddServiceWorkerCallback)));
111
112 // Wait for its activation.
113 base::RunLoop run_loop;
114 RunOrPostTaskOnThread(
115 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
116 base::BindOnce(&ServiceWorkerActivationObserver::SignalActivation,
117 base::Unretained(service_worker_context),
118 run_loop.QuitClosure()));
119 run_loop.Run();
120 }
121
GetServiceWorkers(StoragePartition * storage_partition)122 std::vector<StorageUsageInfo> GetServiceWorkers(
123 StoragePartition* storage_partition) {
124 DCHECK_CURRENTLY_ON(BrowserThread::UI);
125 ServiceWorkerContextWrapper* service_worker_context =
126 static_cast<ServiceWorkerContextWrapper*>(
127 storage_partition->GetServiceWorkerContext());
128
129 std::vector<StorageUsageInfo> service_workers;
130 base::RunLoop run_loop;
131
132 RunOrPostTaskOnThread(
133 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
134 base::BindOnce(
135 &ServiceWorkerContextWrapper::GetAllOriginsInfo,
136 base::Unretained(service_worker_context),
137 base::BindOnce(&GetServiceWorkersCallback, run_loop.QuitClosure(),
138 base::Unretained(&service_workers))));
139 run_loop.Run();
140
141 return service_workers;
142 }
143
SetResponseContent(const GURL & url,std::string * value,net::test_server::BasicHttpResponse * response)144 void SetResponseContent(const GURL& url,
145 std::string* value,
146 net::test_server::BasicHttpResponse* response) {
147 if (net::GetValueForKeyInQuery(url, "file", value)) {
148 base::FilePath path(GetTestFilePath("browsing_data", value->c_str()));
149 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
150 EXPECT_TRUE(file.IsValid());
151 int64_t length = file.GetLength();
152 EXPECT_GE(length, 0);
153 std::unique_ptr<char[]> buffer(new char[length + 1]);
154 file.Read(0, buffer.get(), length);
155 buffer[length] = '\0';
156
157 if (path.Extension() == FILE_PATH_LITERAL(".js"))
158 response->set_content_type("application/javascript");
159 else if (path.Extension() == FILE_PATH_LITERAL(".html"))
160 response->set_content_type("text/html");
161 else
162 NOTREACHED();
163
164 response->set_content(buffer.get());
165 }
166 }
167
SetUpMockCertVerifier(int32_t default_result)168 void SetUpMockCertVerifier(int32_t default_result) {
169 mojo::Remote<network::mojom::NetworkServiceTest> network_service_test;
170 GetNetworkService()->BindTestInterface(
171 network_service_test.BindNewPipeAndPassReceiver());
172
173 base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
174 network_service_test->MockCertVerifierSetDefaultResult(
175 default_result, run_loop.QuitClosure());
176 run_loop.Run();
177 }
178
179 } // namespace browsing_data_browsertest_utils
180
181 } // namespace content
182