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/background_sync/background_sync_base_browsertest.h"
6
7 #include <memory>
8 #include <set>
9 #include <vector>
10 #include "base/metrics/field_trial_param_associator.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/task/post_task.h"
13 #include "content/browser/background_sync/background_sync_manager.h"
14 #include "content/browser/storage_partition_impl.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/browser_task_traits.h"
17 #include "content/public/browser/service_worker_context.h"
18 #include "content/public/test/background_sync_test_util.h"
19 #include "content/public/test/content_browser_test_utils.h"
20 #include "content/shell/browser/shell.h"
21 #include "content/test/mock_background_sync_controller.h"
22
23 namespace content {
24
BackgroundSyncBaseBrowserTest()25 BackgroundSyncBaseBrowserTest::BackgroundSyncBaseBrowserTest() {}
~BackgroundSyncBaseBrowserTest()26 BackgroundSyncBaseBrowserTest::~BackgroundSyncBaseBrowserTest() {}
27
BuildScriptString(const std::string & function,const std::string & argument)28 std::string BackgroundSyncBaseBrowserTest::BuildScriptString(
29 const std::string& function,
30 const std::string& argument) {
31 return base::StringPrintf("%s('%s');", function.c_str(), argument.c_str());
32 }
33
BuildExpectedResult(const std::string & tag,const std::string & action)34 std::string BackgroundSyncBaseBrowserTest::BuildExpectedResult(
35 const std::string& tag,
36 const std::string& action) {
37 return base::StringPrintf("%s%s %s", kSuccessfulOperationPrefix, tag.c_str(),
38 action.c_str());
39 }
40
RegistrationPending(const std::string & tag)41 bool BackgroundSyncBaseBrowserTest::RegistrationPending(
42 const std::string& tag) {
43 bool is_pending;
44 base::RunLoop run_loop;
45
46 StoragePartitionImpl* storage = GetStorage();
47 BackgroundSyncContextImpl* sync_context = storage->GetBackgroundSyncContext();
48 ServiceWorkerContextWrapper* service_worker_context =
49 static_cast<ServiceWorkerContextWrapper*>(
50 storage->GetServiceWorkerContext());
51
52 auto callback = base::BindOnce(
53 &BackgroundSyncBaseBrowserTest::RegistrationPendingCallback,
54 base::Unretained(this), run_loop.QuitClosure(),
55 base::ThreadTaskRunnerHandle::Get(), &is_pending);
56
57 RunOrPostTaskOnThread(
58 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
59 base::BindOnce(
60 &BackgroundSyncBaseBrowserTest::RegistrationPendingOnCoreThread,
61 base::Unretained(this), base::WrapRefCounted(sync_context),
62 base::WrapRefCounted(service_worker_context), tag,
63 https_server_->GetURL(kDefaultTestURL), std::move(callback)));
64
65 run_loop.Run();
66
67 return is_pending;
68 }
69
CompleteDelayedSyncEvent()70 bool BackgroundSyncBaseBrowserTest::CompleteDelayedSyncEvent() {
71 std::string script_result;
72 EXPECT_TRUE(RunScript("completeDelayedSyncEvent()", &script_result));
73 return script_result == BuildExpectedResult("delay", "completing");
74 }
75
RegistrationPendingCallback(base::OnceClosure quit,const scoped_refptr<base::SingleThreadTaskRunner> & task_runner,bool * result_out,bool result)76 void BackgroundSyncBaseBrowserTest::RegistrationPendingCallback(
77 base::OnceClosure quit,
78 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
79 bool* result_out,
80 bool result) {
81 *result_out = result;
82 task_runner->PostTask(FROM_HERE, std::move(quit));
83 }
84
RegistrationPendingDidGetSyncRegistration(const std::string & tag,base::OnceCallback<void (bool)> callback,BackgroundSyncStatus error_type,std::vector<std::unique_ptr<BackgroundSyncRegistration>> registrations)85 void BackgroundSyncBaseBrowserTest::RegistrationPendingDidGetSyncRegistration(
86 const std::string& tag,
87 base::OnceCallback<void(bool)> callback,
88 BackgroundSyncStatus error_type,
89 std::vector<std::unique_ptr<BackgroundSyncRegistration>> registrations) {
90 ASSERT_EQ(BACKGROUND_SYNC_STATUS_OK, error_type);
91 // Find the right registration in the list and check its status.
92 for (const auto& registration : registrations) {
93 if (registration->options()->tag == tag) {
94 std::move(callback).Run(registration->sync_state() ==
95 blink::mojom::BackgroundSyncState::PENDING);
96 return;
97 }
98 }
99 ADD_FAILURE() << "Registration should exist";
100 }
101
RegistrationPendingDidGetSWRegistration(const scoped_refptr<BackgroundSyncContextImpl> sync_context,const std::string & tag,base::OnceCallback<void (bool)> callback,blink::ServiceWorkerStatusCode status,scoped_refptr<ServiceWorkerRegistration> registration)102 void BackgroundSyncBaseBrowserTest::RegistrationPendingDidGetSWRegistration(
103 const scoped_refptr<BackgroundSyncContextImpl> sync_context,
104 const std::string& tag,
105 base::OnceCallback<void(bool)> callback,
106 blink::ServiceWorkerStatusCode status,
107 scoped_refptr<ServiceWorkerRegistration> registration) {
108 ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
109 int64_t service_worker_id = registration->id();
110 BackgroundSyncManager* sync_manager = sync_context->background_sync_manager();
111 sync_manager->GetOneShotSyncRegistrations(
112 service_worker_id,
113 base::BindOnce(&BackgroundSyncBaseBrowserTest::
114 RegistrationPendingDidGetSyncRegistration,
115 base::Unretained(this), tag, std::move(callback)));
116 }
117
RegistrationPendingOnCoreThread(const scoped_refptr<BackgroundSyncContextImpl> sync_context,const scoped_refptr<ServiceWorkerContextWrapper> sw_context,const std::string & tag,const GURL & url,base::OnceCallback<void (bool)> callback)118 void BackgroundSyncBaseBrowserTest::RegistrationPendingOnCoreThread(
119 const scoped_refptr<BackgroundSyncContextImpl> sync_context,
120 const scoped_refptr<ServiceWorkerContextWrapper> sw_context,
121 const std::string& tag,
122 const GURL& url,
123 base::OnceCallback<void(bool)> callback) {
124 sw_context->FindReadyRegistrationForClientUrl(
125 url, base::BindOnce(&BackgroundSyncBaseBrowserTest::
126 RegistrationPendingDidGetSWRegistration,
127 base::Unretained(this), sync_context, tag,
128 std::move(callback)));
129 }
130
SetTestClockOnCoreThread(BackgroundSyncContextImpl * sync_context,base::SimpleTestClock * clock)131 void BackgroundSyncBaseBrowserTest::SetTestClockOnCoreThread(
132 BackgroundSyncContextImpl* sync_context,
133 base::SimpleTestClock* clock) {
134 DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
135 DCHECK(clock);
136
137 BackgroundSyncManager* background_sync_manager =
138 sync_context->background_sync_manager();
139 background_sync_manager->set_clock(clock);
140 }
141
SetUp()142 void BackgroundSyncBaseBrowserTest::SetUp() {
143 const char kTrialName[] = "BackgroundSync";
144 const char kGroupName[] = "BackgroundSync";
145 const char kFeatureName[] = "PeriodicBackgroundSync";
146 scoped_refptr<base::FieldTrial> trial =
147 base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
148 std::map<std::string, std::string> params;
149 params["max_sync_attempts"] = "1";
150 params["min_periodic_sync_events_interval_sec"] = "5";
151 base::FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
152 kTrialName, kGroupName, params);
153 std::unique_ptr<base::FeatureList> feature_list(
154 std::make_unique<base::FeatureList>());
155 feature_list->RegisterFieldTrialOverride(
156 kFeatureName, base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
157 scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
158
159 background_sync_test_util::SetIgnoreNetworkChanges(true);
160 ContentBrowserTest::SetUp();
161 }
162
SetIncognitoMode(bool incognito)163 void BackgroundSyncBaseBrowserTest::SetIncognitoMode(bool incognito) {
164 shell_ = incognito ? CreateOffTheRecordBrowser() : shell();
165 // Let any async shell creation logic finish.
166 base::RunLoop().RunUntilIdle();
167 }
168
GetStorage()169 StoragePartitionImpl* BackgroundSyncBaseBrowserTest::GetStorage() {
170 WebContents* web_contents = shell_->web_contents();
171 return static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
172 web_contents->GetBrowserContext(), web_contents->GetSiteInstance()));
173 }
174
web_contents()175 WebContents* BackgroundSyncBaseBrowserTest::web_contents() {
176 return shell_->web_contents();
177 }
178
SetUpOnMainThread()179 void BackgroundSyncBaseBrowserTest::SetUpOnMainThread() {
180 https_server_ = std::make_unique<net::EmbeddedTestServer>(
181 net::EmbeddedTestServer::TYPE_HTTPS);
182 https_server_->ServeFilesFromSourceDirectory(GetTestDataFilePath());
183 ASSERT_TRUE(https_server_->Start());
184
185 SetIncognitoMode(false);
186 background_sync_test_util::SetOnline(web_contents(), true);
187 ASSERT_TRUE(LoadTestPage(kDefaultTestURL));
188
189 ContentBrowserTest::SetUpOnMainThread();
190 }
191
TearDownOnMainThread()192 void BackgroundSyncBaseBrowserTest::TearDownOnMainThread() {
193 https_server_.reset();
194 }
195
LoadTestPage(const std::string & path)196 bool BackgroundSyncBaseBrowserTest::LoadTestPage(const std::string& path) {
197 return NavigateToURL(shell_, https_server_->GetURL(path));
198 }
199
RunScript(const std::string & script,std::string * result)200 bool BackgroundSyncBaseBrowserTest::RunScript(const std::string& script,
201 std::string* result) {
202 return content::ExecuteScriptAndExtractString(web_contents(), script, result);
203 }
204
SetTestClock(base::SimpleTestClock * clock)205 void BackgroundSyncBaseBrowserTest::SetTestClock(base::SimpleTestClock* clock) {
206 StoragePartitionImpl* storage = GetStorage();
207 BackgroundSyncContextImpl* sync_context = storage->GetBackgroundSyncContext();
208
209 // TODO(crbug.com/824858): Remove the else branch after the feature is
210 // enabled. Also, try to make a RunOrPostTaskOnThreadAndReply() function so
211 // the if/else isn't needed.
212 if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
213 SetTestClockOnCoreThread(sync_context, clock);
214 } else {
215 base::RunLoop run_loop;
216 base::PostTaskAndReply(
217 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
218 base::BindOnce(&BackgroundSyncBaseBrowserTest::SetTestClockOnCoreThread,
219 base::Unretained(this), base::Unretained(sync_context),
220 clock),
221 run_loop.QuitClosure());
222 run_loop.Run();
223 }
224 }
225
ClearStoragePartitionData()226 void BackgroundSyncBaseBrowserTest::ClearStoragePartitionData() {
227 // Clear data from the storage partition. Parameters are set to clear data
228 // for service workers, for all origins, for an unbounded time range.
229 StoragePartitionImpl* storage = GetStorage();
230
231 uint32_t storage_partition_mask =
232 StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
233 uint32_t quota_storage_mask =
234 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
235 GURL delete_origin = GURL();
236 const base::Time delete_begin = base::Time();
237 base::Time delete_end = base::Time::Max();
238
239 base::RunLoop run_loop;
240
241 storage->ClearData(storage_partition_mask, quota_storage_mask, delete_origin,
242 delete_begin, delete_end, run_loop.QuitClosure());
243
244 run_loop.Run();
245 }
246
PopConsoleString()247 std::string BackgroundSyncBaseBrowserTest::PopConsoleString() {
248 std::string script_result;
249 EXPECT_TRUE(RunScript("resultQueue.pop()", &script_result));
250 return script_result;
251 }
252
PopConsole(const std::string & expected_msg)253 bool BackgroundSyncBaseBrowserTest::PopConsole(
254 const std::string& expected_msg) {
255 std::string script_result = PopConsoleString();
256 return script_result == expected_msg;
257 }
258
RegisterServiceWorker()259 bool BackgroundSyncBaseBrowserTest::RegisterServiceWorker() {
260 std::string script_result;
261 EXPECT_TRUE(RunScript("registerServiceWorker()", &script_result));
262 return script_result == BuildExpectedResult("service worker", "registered");
263 }
264
265 } // namespace content
266