1 // Copyright 2015 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.
9 #include "base/command_line.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/task_runner_util.h"
13 #include "content/browser/background_sync/background_sync_manager.h"
14 #include "content/browser/background_sync/background_sync_status.h"
15 #include "content/browser/service_worker/service_worker_context_wrapper.h"
16 #include "content/browser/service_worker/service_worker_registration.h"
17 #include "content/public/browser/background_sync_context.h"
18 #include "content/public/browser/browser_context.h"
19 #include "content/public/browser/storage_partition.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "content/public/test/content_browser_test.h"
24 #include "content/public/test/content_browser_test_utils.h"
25 #include "content/public/test/test_utils.h"
26 #include "content/shell/browser/shell.h"
27 #include "net/base/network_change_notifier.h"
28 #include "testing/gtest/include/gtest/gtest.h"
30 using net::NetworkChangeNotifier
;
36 const char kDefaultTestURL
[] = "files/background_sync/test.html";
38 const char kSuccessfulOperationPrefix
[] = "ok - ";
40 std::string
BuildScriptString(const std::string
& function
,
41 const std::string
& argument
) {
42 return base::StringPrintf("%s('%s');", function
.c_str(), argument
.c_str());
45 std::string
BuildExpectedResult(const std::string
& tag
,
46 const std::string
& action
) {
47 return base::StringPrintf("%s%s %s", kSuccessfulOperationPrefix
, tag
.c_str(),
51 void OneShotPendingCallback(
52 const base::Closure
& quit
,
53 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
57 task_runner
->PostTask(FROM_HERE
, quit
);
60 void OneShotPendingDidGetSyncRegistration(
61 const base::Callback
<void(bool)>& callback
,
62 BackgroundSyncStatus error_type
,
63 const BackgroundSyncRegistration
& registration
) {
64 ASSERT_EQ(BACKGROUND_SYNC_STATUS_OK
, error_type
);
65 callback
.Run(registration
.sync_state() == SYNC_STATE_PENDING
);
68 void OneShotPendingDidGetSWRegistration(
69 const scoped_refptr
<BackgroundSyncContext
> sync_context
,
70 const std::string
& tag
,
71 const base::Callback
<void(bool)>& callback
,
72 ServiceWorkerStatusCode status
,
73 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
74 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
75 int64 service_worker_id
= registration
->id();
76 BackgroundSyncManager
* sync_manager
= sync_context
->background_sync_manager();
77 sync_manager
->GetRegistration(
78 service_worker_id
, tag
, SYNC_ONE_SHOT
,
79 base::Bind(&OneShotPendingDidGetSyncRegistration
, callback
));
82 void OneShotPendingOnIOThread(
83 const scoped_refptr
<BackgroundSyncContext
> sync_context
,
84 const scoped_refptr
<ServiceWorkerContextWrapper
> sw_context
,
85 const std::string
& tag
,
87 const base::Callback
<void(bool)>& callback
) {
88 sw_context
->FindRegistrationForDocument(
89 url
, base::Bind(&OneShotPendingDidGetSWRegistration
, sync_context
, tag
,
93 class BackgroundSyncBrowserTest
: public ContentBrowserTest
{
95 BackgroundSyncBrowserTest() {}
96 ~BackgroundSyncBrowserTest() override
{}
98 void SetUp() override
{
99 NetworkChangeNotifier::SetTestNotificationsOnly(true);
101 #if defined(OS_CHROMEOS)
102 // ChromeOS's NetworkChangeNotifier doesn't get created in
103 // content_browsertests, so make one now.
104 net::NetworkChangeNotifier::CreateMock();
107 ContentBrowserTest::SetUp();
110 void SetIncognitoMode(bool incognito
) {
111 shell_
= incognito
? CreateOffTheRecordBrowser() : shell();
114 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
115 // TODO(jkarlin): Remove this once background sync is no longer
117 command_line
->AppendSwitch(
118 switches::kEnableExperimentalWebPlatformFeatures
);
121 void SetUpOnMainThread() override
{
122 https_server_
.reset(new net::SpawnedTestServer(
123 net::SpawnedTestServer::TYPE_HTTPS
,
124 net::BaseTestServer::SSLOptions(
125 net::BaseTestServer::SSLOptions::CERT_OK
),
126 base::FilePath(FILE_PATH_LITERAL("content/test/data/"))));
127 ASSERT_TRUE(https_server_
->Start());
131 SetIncognitoMode(false);
133 ASSERT_TRUE(LoadTestPage(kDefaultTestURL
));
135 ContentBrowserTest::SetUpOnMainThread();
138 void TearDownOnMainThread() override
{ https_server_
.reset(); }
140 bool LoadTestPage(const std::string
& path
) {
141 return NavigateToURL(shell_
, https_server_
->GetURL(path
));
144 bool RunScript(const std::string
& script
, std::string
* result
) {
145 return content::ExecuteScriptAndExtractString(shell_
->web_contents(),
149 void SetOnline(bool online
);
151 // Returns true if the one-shot sync with tag is currently pending. Fails
152 // (assertion failure) if the tag isn't registered.
153 bool OneShotPending(const std::string
& tag
);
155 bool PopConsole(const std::string
& expected_msg
);
156 bool RegisterServiceWorker();
157 bool RegisterOneShot(const std::string
& tag
);
158 bool GetRegistrationOneShot(const std::string
& tag
);
159 bool GetRegistrationsOneShot(const std::vector
<std::string
>& expected_tags
);
160 bool CompleteDelayedOneShot();
161 bool RejectDelayedOneShot();
164 scoped_ptr
<net::SpawnedTestServer
> https_server_
;
165 Shell
* shell_
= nullptr;
167 DISALLOW_COPY_AND_ASSIGN(BackgroundSyncBrowserTest
);
170 void BackgroundSyncBrowserTest::SetOnline(bool online
) {
172 NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
173 NetworkChangeNotifier::CONNECTION_WIFI
);
175 NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
176 NetworkChangeNotifier::CONNECTION_NONE
);
178 base::RunLoop().RunUntilIdle();
181 bool BackgroundSyncBrowserTest::OneShotPending(const std::string
& tag
) {
183 base::RunLoop run_loop
;
185 StoragePartition
* storage
= BrowserContext::GetDefaultStoragePartition(
186 shell_
->web_contents()->GetBrowserContext());
187 BackgroundSyncContext
* sync_context
= storage
->GetBackgroundSyncContext();
188 ServiceWorkerContextWrapper
* service_worker_context
=
189 static_cast<ServiceWorkerContextWrapper
*>(
190 storage
->GetServiceWorkerContext());
192 base::Callback
<void(bool)> callback
=
193 base::Bind(&OneShotPendingCallback
, run_loop
.QuitClosure(),
194 base::ThreadTaskRunnerHandle::Get(), &is_pending
);
196 BrowserThread::PostTask(
197 BrowserThread::IO
, FROM_HERE
,
198 base::Bind(&OneShotPendingOnIOThread
, make_scoped_refptr(sync_context
),
199 make_scoped_refptr(service_worker_context
), tag
,
200 https_server_
->GetURL(kDefaultTestURL
), callback
));
207 bool BackgroundSyncBrowserTest::PopConsole(const std::string
& expected_msg
) {
208 std::string script_result
;
209 EXPECT_TRUE(RunScript("resultQueue.pop()", &script_result
));
210 return script_result
== expected_msg
;
213 bool BackgroundSyncBrowserTest::RegisterServiceWorker() {
214 std::string script_result
;
215 EXPECT_TRUE(RunScript("registerServiceWorker()", &script_result
));
216 return script_result
== BuildExpectedResult("service worker", "registered");
219 bool BackgroundSyncBrowserTest::RegisterOneShot(const std::string
& tag
) {
220 std::string script_result
;
222 RunScript(BuildScriptString("registerOneShot", tag
), &script_result
));
223 return script_result
== BuildExpectedResult(tag
, "registered");
226 bool BackgroundSyncBrowserTest::GetRegistrationOneShot(const std::string
& tag
) {
227 std::string script_result
;
228 EXPECT_TRUE(RunScript(BuildScriptString("getRegistrationOneShot", tag
),
230 return script_result
== BuildExpectedResult(tag
, "found");
233 bool BackgroundSyncBrowserTest::GetRegistrationsOneShot(
234 const std::vector
<std::string
>& expected_tags
) {
235 std::string script_result
;
236 EXPECT_TRUE(RunScript("getRegistrationsOneShot()", &script_result
));
238 EXPECT_TRUE(base::StartsWith(script_result
, kSuccessfulOperationPrefix
,
239 base::CompareCase::INSENSITIVE_ASCII
));
240 script_result
= script_result
.substr(strlen(kSuccessfulOperationPrefix
));
241 std::vector
<std::string
> result_tags
= base::SplitString(
242 script_result
, ",", base::KEEP_WHITESPACE
, base::SPLIT_WANT_ALL
);
244 return std::set
<std::string
>(expected_tags
.begin(), expected_tags
.end()) ==
245 std::set
<std::string
>(result_tags
.begin(), result_tags
.end());
248 bool BackgroundSyncBrowserTest::CompleteDelayedOneShot() {
249 std::string script_result
;
250 EXPECT_TRUE(RunScript("completeDelayedOneShot()", &script_result
));
251 return script_result
== BuildExpectedResult("delay", "completing");
254 bool BackgroundSyncBrowserTest::RejectDelayedOneShot() {
255 std::string script_result
;
256 EXPECT_TRUE(RunScript("rejectDelayedOneShot()", &script_result
));
257 return script_result
== BuildExpectedResult("delay", "rejecting");
260 IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest
, OneShotFires
) {
261 EXPECT_TRUE(RegisterServiceWorker());
262 EXPECT_TRUE(LoadTestPage(kDefaultTestURL
)); // Control the page.
264 EXPECT_TRUE(RegisterOneShot("foo"));
265 EXPECT_TRUE(PopConsole("foo fired"));
266 EXPECT_FALSE(GetRegistrationOneShot("foo"));
269 IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest
, OneShotDelaysForNetwork
) {
270 EXPECT_TRUE(RegisterServiceWorker());
271 EXPECT_TRUE(LoadTestPage(kDefaultTestURL
)); // Control the page.
273 // Prevent firing by going offline.
275 EXPECT_TRUE(RegisterOneShot("foo"));
276 EXPECT_TRUE(GetRegistrationOneShot("foo"));
277 EXPECT_TRUE(OneShotPending("foo"));
279 // Resume firing by going online.
281 EXPECT_TRUE(PopConsole("foo fired"));
282 EXPECT_FALSE(GetRegistrationOneShot("foo"));
285 IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest
, WaitUntil
) {
286 EXPECT_TRUE(RegisterServiceWorker());
287 EXPECT_TRUE(LoadTestPage(kDefaultTestURL
)); // Control the page.
290 EXPECT_TRUE(RegisterOneShot("delay"));
292 // Verify that it is firing.
293 EXPECT_TRUE(GetRegistrationOneShot("delay"));
294 EXPECT_FALSE(OneShotPending("delay"));
296 // Complete the task.
297 EXPECT_TRUE(CompleteDelayedOneShot());
298 EXPECT_TRUE(PopConsole("ok - delay completed"));
300 // Verify that it finished firing.
301 // TODO(jkarlin): Use registration.done to verify that the event actually
302 // completed successfully.
303 EXPECT_FALSE(GetRegistrationOneShot("delay"));
306 IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest
, WaitUntilReject
) {
307 EXPECT_TRUE(RegisterServiceWorker());
308 EXPECT_TRUE(LoadTestPage(kDefaultTestURL
)); // Control the page.
311 EXPECT_TRUE(RegisterOneShot("delay"));
313 // Verify that it is firing.
314 EXPECT_TRUE(GetRegistrationOneShot("delay"));
315 EXPECT_FALSE(OneShotPending("delay"));
317 // Complete the task.
318 EXPECT_TRUE(RejectDelayedOneShot());
319 EXPECT_TRUE(PopConsole("ok - delay rejected"));
321 // Since the event failed the registration should still be there.
322 // TODO(jkarlin): Use registration.done to verify that the event actually
324 EXPECT_TRUE(GetRegistrationOneShot("delay"));
327 IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest
, Incognito
) {
328 EXPECT_TRUE(RegisterServiceWorker());
329 EXPECT_TRUE(LoadTestPage(kDefaultTestURL
)); // Control the page.
332 EXPECT_TRUE(RegisterOneShot("normal"));
333 EXPECT_TRUE(OneShotPending("normal"));
335 // Go incognito and verify that incognito doesn't see the registration.
336 SetIncognitoMode(true);
338 // Tell the new network observer that we're offline (it initializes from
339 // NetworkChangeNotifier::GetCurrentConnectionType() which is not mocked out
343 EXPECT_TRUE(LoadTestPage(kDefaultTestURL
));
344 EXPECT_TRUE(RegisterServiceWorker());
345 EXPECT_TRUE(LoadTestPage(kDefaultTestURL
)); // Control the page.
347 EXPECT_FALSE(GetRegistrationOneShot("normal"));
349 EXPECT_TRUE(RegisterOneShot("incognito"));
350 EXPECT_TRUE(OneShotPending("incognito"));
352 // Switch back and make sure the registration is still there.
353 SetIncognitoMode(false);
354 EXPECT_TRUE(LoadTestPage(kDefaultTestURL
)); // Should be controlled.
356 EXPECT_TRUE(GetRegistrationOneShot("normal"));
357 EXPECT_FALSE(GetRegistrationOneShot("incognito"));
360 IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest
, GetRegistrations
) {
361 EXPECT_TRUE(RegisterServiceWorker());
362 EXPECT_TRUE(LoadTestPage(kDefaultTestURL
)); // Control the page.
364 std::vector
<std::string
> registered_tags
;
365 EXPECT_TRUE(GetRegistrationsOneShot(registered_tags
));
368 registered_tags
.push_back("foo");
369 registered_tags
.push_back("bar");
371 for (const std::string
& tag
: registered_tags
)
372 EXPECT_TRUE(RegisterOneShot(tag
));
374 EXPECT_TRUE(GetRegistrationsOneShot(registered_tags
));
379 } // namespace content