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 "base/bind.h"
8 #include "base/macros.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_split.h"
11 #include "base/task/post_task.h"
12 #include "base/task_runner_util.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "content/browser/background_sync/background_sync_manager.h"
15 #include "content/browser/background_sync/background_sync_network_observer.h"
16 #include "content/browser/service_worker/service_worker_context_wrapper.h"
17 #include "content/browser/storage_partition_impl.h"
18 #include "content/public/browser/browser_context.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/test/background_sync_test_util.h"
23 #include "content/public/test/browser_test.h"
24 #include "content/public/test/browser_test_utils.h"
25 #include "content/public/test/content_browser_test.h"
26 #include "content/public/test/test_utils.h"
27 #include "content/shell/browser/shell.h"
28 #include "net/base/network_change_notifier.h"
29 #include "net/test/embedded_test_server/embedded_test_server.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 namespace content {
33
34 class OneShotBackgroundSyncBrowserTest : public BackgroundSyncBaseBrowserTest {
35 public:
OneShotBackgroundSyncBrowserTest()36 OneShotBackgroundSyncBrowserTest() {}
~OneShotBackgroundSyncBrowserTest()37 ~OneShotBackgroundSyncBrowserTest() override {}
38
39 bool Register(const std::string& tag);
40 bool RegisterFromServiceWorker(const std::string& tag);
41 bool RegisterFromCrossOriginFrame(const std::string& frame_url,
42 std::string* script_result);
43 void WaitForTagRemoval(const std::string& tag, int64_t pauses_ms = 5);
44 bool HasTag(const std::string& tag);
45 bool HasTagFromServiceWorker(const std::string& tag);
46 bool MatchTags(const std::string& script_result,
47 const std::vector<std::string>& expected_tags);
48 bool GetTags(const std::vector<std::string>& expected_tags);
49 bool GetTagsFromServiceWorker(const std::vector<std::string>& expected_tags);
50 bool RejectDelayedSyncEvent();
51
52 private:
53 DISALLOW_COPY_AND_ASSIGN(OneShotBackgroundSyncBrowserTest);
54 };
55
Register(const std::string & tag)56 bool OneShotBackgroundSyncBrowserTest::Register(const std::string& tag) {
57 std::string script_result;
58 EXPECT_TRUE(
59 RunScript(BuildScriptString("registerOneShotSync", tag), &script_result));
60 return script_result == BuildExpectedResult(tag, "registered");
61 }
62
RegisterFromServiceWorker(const std::string & tag)63 bool OneShotBackgroundSyncBrowserTest::RegisterFromServiceWorker(
64 const std::string& tag) {
65 std::string script_result;
66 EXPECT_TRUE(
67 RunScript(BuildScriptString("registerOneShotSyncFromServiceWorker", tag),
68 &script_result));
69 return script_result == BuildExpectedResult(tag, "register sent to SW");
70 }
71
RegisterFromCrossOriginFrame(const std::string & frame_url,std::string * script_result)72 bool OneShotBackgroundSyncBrowserTest::RegisterFromCrossOriginFrame(
73 const std::string& frame_url,
74 std::string* script_result) {
75 // Start a second https server to use as a second origin.
76 net::EmbeddedTestServer alt_server(net::EmbeddedTestServer::TYPE_HTTPS);
77 alt_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
78 EXPECT_TRUE(alt_server.Start());
79
80 GURL url = alt_server.GetURL(frame_url);
81 return RunScript(
82 BuildScriptString("registerOneShotSyncFromCrossOriginFrame", url.spec()),
83 script_result);
84 }
85
WaitForTagRemoval(const std::string & tag,int64_t pauses_ms)86 void OneShotBackgroundSyncBrowserTest::WaitForTagRemoval(const std::string& tag,
87 int64_t pauses_ms) {
88 while (HasTag(tag)) {
89 base::RunLoop run_loop;
90 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
91 FROM_HERE, run_loop.QuitClosure(),
92 base::TimeDelta::FromMilliseconds(pauses_ms));
93 run_loop.Run();
94 }
95 }
96
HasTag(const std::string & tag)97 bool OneShotBackgroundSyncBrowserTest::HasTag(const std::string& tag) {
98 std::string script_result;
99 EXPECT_TRUE(
100 RunScript(BuildScriptString("hasOneShotSyncTag", tag), &script_result));
101 return script_result == BuildExpectedResult(tag, "found");
102 }
103
HasTagFromServiceWorker(const std::string & tag)104 bool OneShotBackgroundSyncBrowserTest::HasTagFromServiceWorker(
105 const std::string& tag) {
106 std::string script_result;
107 EXPECT_TRUE(
108 RunScript(BuildScriptString("hasOneShotSyncTagFromServiceWorker", tag),
109 &script_result));
110 EXPECT_TRUE(script_result == "ok - hasTag sent to SW");
111
112 return PopConsole(BuildExpectedResult(tag, "found"));
113 }
114
MatchTags(const std::string & script_result,const std::vector<std::string> & expected_tags)115 bool OneShotBackgroundSyncBrowserTest::MatchTags(
116 const std::string& script_result,
117 const std::vector<std::string>& expected_tags) {
118 EXPECT_TRUE(base::StartsWith(script_result, kSuccessfulOperationPrefix,
119 base::CompareCase::INSENSITIVE_ASCII));
120 std::string tag_string =
121 script_result.substr(strlen(kSuccessfulOperationPrefix));
122 std::vector<std::string> result_tags = base::SplitString(
123 tag_string, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
124
125 return std::set<std::string>(expected_tags.begin(), expected_tags.end()) ==
126 std::set<std::string>(result_tags.begin(), result_tags.end());
127 }
128
GetTags(const std::vector<std::string> & expected_tags)129 bool OneShotBackgroundSyncBrowserTest::GetTags(
130 const std::vector<std::string>& expected_tags) {
131 std::string script_result;
132 EXPECT_TRUE(RunScript("getOneShotSyncTags()", &script_result));
133
134 return MatchTags(script_result, expected_tags);
135 }
136
GetTagsFromServiceWorker(const std::vector<std::string> & expected_tags)137 bool OneShotBackgroundSyncBrowserTest::GetTagsFromServiceWorker(
138 const std::vector<std::string>& expected_tags) {
139 std::string script_result;
140 EXPECT_TRUE(
141 RunScript("getOneShotSyncTagsFromServiceWorker()", &script_result));
142 EXPECT_TRUE(script_result == "ok - getTags sent to SW");
143
144 return MatchTags(PopConsoleString(), expected_tags);
145 }
146
RejectDelayedSyncEvent()147 bool OneShotBackgroundSyncBrowserTest::RejectDelayedSyncEvent() {
148 std::string script_result;
149 EXPECT_TRUE(RunScript("rejectDelayedSyncEvent()", &script_result));
150 return script_result == BuildExpectedResult("delay", "rejecting");
151 }
152
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,RegisterFromControlledDocument)153 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
154 RegisterFromControlledDocument) {
155 EXPECT_TRUE(RegisterServiceWorker());
156 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
157
158 EXPECT_TRUE(Register("foo"));
159 EXPECT_TRUE(PopConsole("foo fired"));
160 WaitForTagRemoval("foo");
161 }
162
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,RegisterFromUncontrolledDocument)163 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
164 RegisterFromUncontrolledDocument) {
165 EXPECT_TRUE(RegisterServiceWorker());
166
167 EXPECT_TRUE(Register("foo"));
168 EXPECT_TRUE(PopConsole("foo fired"));
169 WaitForTagRemoval("foo");
170 }
171
172 // Verify that Register works in a service worker
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,RegisterFromServiceWorker)173 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
174 RegisterFromServiceWorker) {
175 EXPECT_TRUE(RegisterServiceWorker());
176 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
177
178 EXPECT_TRUE(RegisterFromServiceWorker("foo_sw"));
179 EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
180 EXPECT_TRUE(PopConsole("foo_sw fired"));
181 WaitForTagRemoval("foo_sw");
182 }
183
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,RegistrationDelaysForNetwork)184 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
185 RegistrationDelaysForNetwork) {
186 EXPECT_TRUE(RegisterServiceWorker());
187 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
188
189 // Prevent firing by going offline.
190 background_sync_test_util::SetOnline(web_contents(), false);
191 EXPECT_TRUE(Register("foo"));
192 EXPECT_TRUE(HasTag("foo"));
193 EXPECT_TRUE(RegistrationPending("foo"));
194
195 // Resume firing by going online.
196 background_sync_test_util::SetOnline(web_contents(), true);
197 EXPECT_TRUE(PopConsole("foo fired"));
198 WaitForTagRemoval("foo");
199 }
200
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,WaitUntil)201 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest, WaitUntil) {
202 EXPECT_TRUE(RegisterServiceWorker());
203 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
204
205 background_sync_test_util::SetOnline(web_contents(), true);
206 EXPECT_TRUE(Register("delay"));
207
208 // Verify that it is firing.
209 EXPECT_TRUE(HasTag("delay"));
210 EXPECT_FALSE(RegistrationPending("delay"));
211
212 // Complete the task.
213 EXPECT_TRUE(CompleteDelayedSyncEvent());
214 EXPECT_TRUE(PopConsole("ok - delay completed"));
215
216 // Verify that it finished firing.
217 WaitForTagRemoval("delay");
218 }
219
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,WaitUntilReject)220 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest, WaitUntilReject) {
221 EXPECT_TRUE(RegisterServiceWorker());
222 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
223
224 background_sync_test_util::SetOnline(web_contents(), true);
225 EXPECT_TRUE(Register("delay"));
226
227 // Verify that it is firing.
228 EXPECT_TRUE(HasTag("delay"));
229 EXPECT_FALSE(RegistrationPending("delay"));
230
231 // Complete the task.
232 EXPECT_TRUE(RejectDelayedSyncEvent());
233 EXPECT_TRUE(PopConsole("ok - delay rejected"));
234 WaitForTagRemoval("delay");
235 }
236
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,Incognito)237 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest, Incognito) {
238 EXPECT_TRUE(RegisterServiceWorker());
239 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
240
241 background_sync_test_util::SetOnline(web_contents(), false);
242 EXPECT_TRUE(Register("normal"));
243 EXPECT_TRUE(RegistrationPending("normal"));
244
245 // Go incognito and verify that incognito doesn't see the registration.
246 SetIncognitoMode(true);
247
248 // Tell the new network observer that we're offline (it initializes from
249 // NetworkChangeNotifier::GetCurrentConnectionType() which is not mocked out
250 // in this test).
251 background_sync_test_util::SetOnline(web_contents(), false);
252
253 EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
254 EXPECT_TRUE(RegisterServiceWorker());
255
256 EXPECT_FALSE(HasTag("normal"));
257
258 EXPECT_TRUE(Register("incognito"));
259 EXPECT_TRUE(RegistrationPending("incognito"));
260
261 // Switch back and make sure the registration is still there.
262 SetIncognitoMode(false);
263 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Should be controlled.
264
265 EXPECT_TRUE(HasTag("normal"));
266 EXPECT_FALSE(HasTag("incognito"));
267 }
268
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,GetTags)269 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest, GetTags) {
270 EXPECT_TRUE(RegisterServiceWorker());
271 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
272
273 std::vector<std::string> registered_tags;
274 EXPECT_TRUE(GetTags(registered_tags));
275
276 background_sync_test_util::SetOnline(web_contents(), false);
277 registered_tags.push_back("foo");
278 registered_tags.push_back("bar");
279
280 for (const std::string& tag : registered_tags)
281 EXPECT_TRUE(Register(tag));
282
283 EXPECT_TRUE(GetTags(registered_tags));
284 }
285
286 // Verify that GetOneShotSyncRegistrations works in a service worker
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,GetRegistrationsFromServiceWorker)287 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
288 GetRegistrationsFromServiceWorker) {
289 EXPECT_TRUE(RegisterServiceWorker());
290 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
291
292 std::vector<std::string> registered_tags;
293 EXPECT_TRUE(GetTags(registered_tags));
294
295 background_sync_test_util::SetOnline(web_contents(), false);
296 registered_tags.push_back("foo_sw");
297 registered_tags.push_back("bar_sw");
298
299 for (const std::string& tag : registered_tags) {
300 EXPECT_TRUE(RegisterFromServiceWorker(tag));
301 EXPECT_TRUE(PopConsole(BuildExpectedResult(tag, "registered in SW")));
302 }
303
304 EXPECT_TRUE(GetTagsFromServiceWorker(registered_tags));
305 }
306
307 // Verify that GetOneShotSyncRegistration works in a service worker
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,HasTagFromServiceWorker)308 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
309 HasTagFromServiceWorker) {
310 EXPECT_TRUE(RegisterServiceWorker());
311 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
312
313 std::vector<std::string> registered_tags;
314 EXPECT_TRUE(GetTags(registered_tags));
315
316 background_sync_test_util::SetOnline(web_contents(), false);
317
318 EXPECT_TRUE(RegisterFromServiceWorker("foo_sw"));
319 EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
320 EXPECT_TRUE(HasTagFromServiceWorker("foo_sw"));
321 }
322
323 // Verify that a background sync registration is deleted when site data is
324 // cleared.
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,SyncRegistrationDeletedWhenClearingSiteData)325 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
326 SyncRegistrationDeletedWhenClearingSiteData) {
327 EXPECT_TRUE(RegisterServiceWorker());
328 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
329
330 // Prevent firing by going offline.
331 background_sync_test_util::SetOnline(web_contents(), false);
332 EXPECT_TRUE(Register("foo"));
333 EXPECT_TRUE(HasTag("foo"));
334 EXPECT_TRUE(RegistrationPending("foo"));
335
336 // Simulate a user clearing site data (including Service Workers, crucially),
337 // by clearing data from the storage partition.
338 ClearStoragePartitionData();
339
340 EXPECT_FALSE(HasTag("foo"));
341 }
342
343 // Verify that a background sync registration, from a service worker, is deleted
344 // when site data is cleared.
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,SyncRegistrationFromSWDeletedWhenClearingSiteData)345 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
346 SyncRegistrationFromSWDeletedWhenClearingSiteData) {
347 EXPECT_TRUE(RegisterServiceWorker());
348 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
349
350 std::vector<std::string> registered_tags;
351 EXPECT_TRUE(GetTags(registered_tags));
352
353 background_sync_test_util::SetOnline(web_contents(), false);
354
355 EXPECT_TRUE(RegisterFromServiceWorker("foo_sw"));
356 EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
357 EXPECT_TRUE(HasTagFromServiceWorker("foo_sw"));
358
359 // Simulate a user clearing site data (including Service Workers, crucially),
360 // by clearing data from the storage partition.
361 ClearStoragePartitionData();
362
363 // Use HasTag() instead of HasTagServiceWorker() because clearing site data
364 // immediately terminates the service worker when removing it from the
365 // registration.
366 EXPECT_FALSE(HasTag("foo"));
367 }
368
369 // Verify that multiple background sync registrations are deleted when site
370 // data is cleared.
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,SyncRegistrationsDeletedWhenClearingSiteData)371 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
372 SyncRegistrationsDeletedWhenClearingSiteData) {
373 EXPECT_TRUE(RegisterServiceWorker());
374 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
375
376 std::vector<std::string> registered_tags;
377 EXPECT_TRUE(GetTags(registered_tags));
378
379 background_sync_test_util::SetOnline(web_contents(), false);
380 registered_tags.push_back("foo");
381 registered_tags.push_back("bar");
382
383 for (const std::string& tag : registered_tags)
384 EXPECT_TRUE(Register(tag));
385
386 EXPECT_TRUE(GetTags(registered_tags));
387
388 for (const std::string& tag : registered_tags)
389 EXPECT_TRUE(RegistrationPending(tag));
390
391 // Simulate a user clearing site data (including Service Workers, crucially),
392 // by clearing data from the storage partition.
393 ClearStoragePartitionData();
394
395 for (const std::string& tag : registered_tags)
396 EXPECT_FALSE(HasTag(tag));
397 }
398
399 // Verify that a sync event that is currently firing is deleted when site
400 // data is cleared.
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,FiringSyncEventDeletedWhenClearingSiteData)401 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
402 FiringSyncEventDeletedWhenClearingSiteData) {
403 EXPECT_TRUE(RegisterServiceWorker());
404 EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
405
406 background_sync_test_util::SetOnline(web_contents(), true);
407 EXPECT_TRUE(Register("delay"));
408
409 // Verify that it is firing.
410 EXPECT_TRUE(HasTag("delay"));
411 EXPECT_FALSE(RegistrationPending("delay"));
412
413 // Simulate a user clearing site data (including Service Workers, crucially),
414 // by clearing data from the storage partition.
415 ClearStoragePartitionData();
416
417 // Verify that it was deleted.
418 EXPECT_FALSE(HasTag("delay"));
419 }
420
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,RegisterFromIFrameWithMainFrameHost)421 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
422 RegisterFromIFrameWithMainFrameHost) {
423 std::string script_result;
424 GURL url = https_server()->GetURL(kEmptyURL);
425 EXPECT_TRUE(RunScript(
426 BuildScriptString("registerOneShotSyncFromLocalFrame", url.spec()),
427 &script_result));
428 EXPECT_EQ(BuildExpectedResult("iframe", "registered sync"), script_result);
429 }
430
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,RegisterFromIFrameWithoutMainFrameHost)431 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
432 RegisterFromIFrameWithoutMainFrameHost) {
433 std::string script_result;
434 EXPECT_TRUE(
435 RegisterFromCrossOriginFrame(kRegisterSyncFromIFrameURL, &script_result));
436 EXPECT_EQ(BuildExpectedResult("frame", "failed to register sync"),
437 script_result);
438 }
439
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,RegisterFromServiceWorkerWithoutMainFrameHost)440 IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
441 RegisterFromServiceWorkerWithoutMainFrameHost) {
442 std::string script_result;
443 EXPECT_TRUE(
444 RegisterFromCrossOriginFrame(kRegisterSyncFromSWURL, &script_result));
445 EXPECT_EQ(BuildExpectedResult("frame", "failed to register sync"),
446 script_result);
447 }
448
449 } // namespace content
450