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