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