blob: 81dd6cbc67e6dbc3f7fae9e4d1d398e34c484cf6 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/background_sync/background_sync_base_browsertest.h"
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/background_sync/background_sync_network_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/background_sync_test_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "net/base/network_change_notifier.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
class OneShotBackgroundSyncBrowserTest : public BackgroundSyncBaseBrowserTest {
public:
OneShotBackgroundSyncBrowserTest() {}
OneShotBackgroundSyncBrowserTest(const OneShotBackgroundSyncBrowserTest&) =
delete;
OneShotBackgroundSyncBrowserTest& operator=(
const OneShotBackgroundSyncBrowserTest&) = delete;
~OneShotBackgroundSyncBrowserTest() override {}
bool Register(const std::string& tag);
bool RegisterFromServiceWorker(const std::string& tag);
std::string RegisterFromCrossOriginFrame(const std::string& frame_url);
void WaitForTagRemoval(const std::string& tag, int64_t pauses_ms = 5);
bool HasTag(const std::string& tag);
bool HasTagFromServiceWorker(const std::string& tag);
bool MatchTags(const std::string& script_result,
const std::vector<std::string>& expected_tags);
bool GetTags(const std::vector<std::string>& expected_tags);
bool GetTagsFromServiceWorker(const std::vector<std::string>& expected_tags);
bool RejectDelayedSyncEvent();
};
bool OneShotBackgroundSyncBrowserTest::Register(const std::string& tag) {
std::string script_result =
RunScript(BuildScriptString("registerOneShotSync", tag));
return script_result == BuildExpectedResult(tag, "registered");
}
bool OneShotBackgroundSyncBrowserTest::RegisterFromServiceWorker(
const std::string& tag) {
std::string script_result =
RunScript(BuildScriptString("registerOneShotSyncFromServiceWorker", tag));
return script_result == BuildExpectedResult(tag, "register sent to SW");
}
std::string OneShotBackgroundSyncBrowserTest::RegisterFromCrossOriginFrame(
const std::string& frame_url) {
// Start a second https server to use as a second origin.
net::EmbeddedTestServer alt_server(net::EmbeddedTestServer::TYPE_HTTPS);
alt_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
EXPECT_TRUE(alt_server.Start());
GURL url = alt_server.GetURL(frame_url);
return RunScript(
BuildScriptString("registerOneShotSyncFromCrossOriginFrame", url.spec()));
}
void OneShotBackgroundSyncBrowserTest::WaitForTagRemoval(const std::string& tag,
int64_t pauses_ms) {
while (HasTag(tag)) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(pauses_ms));
run_loop.Run();
}
}
bool OneShotBackgroundSyncBrowserTest::HasTag(const std::string& tag) {
std::string script_result =
RunScript(BuildScriptString("hasOneShotSyncTag", tag));
return script_result == BuildExpectedResult(tag, "found");
}
bool OneShotBackgroundSyncBrowserTest::HasTagFromServiceWorker(
const std::string& tag) {
std::string script_result =
RunScript(BuildScriptString("hasOneShotSyncTagFromServiceWorker", tag));
EXPECT_TRUE(script_result == "ok - hasTag sent to SW");
return PopConsole(BuildExpectedResult(tag, "found"));
}
bool OneShotBackgroundSyncBrowserTest::MatchTags(
const std::string& script_result,
const std::vector<std::string>& expected_tags) {
EXPECT_TRUE(base::StartsWith(script_result, kSuccessfulOperationPrefix,
base::CompareCase::INSENSITIVE_ASCII));
std::string tag_string =
script_result.substr(strlen(kSuccessfulOperationPrefix));
std::vector<std::string> result_tags = base::SplitString(
tag_string, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
return std::set<std::string>(expected_tags.begin(), expected_tags.end()) ==
std::set<std::string>(result_tags.begin(), result_tags.end());
}
bool OneShotBackgroundSyncBrowserTest::GetTags(
const std::vector<std::string>& expected_tags) {
std::string script_result = RunScript("getOneShotSyncTags()");
return MatchTags(script_result, expected_tags);
}
bool OneShotBackgroundSyncBrowserTest::GetTagsFromServiceWorker(
const std::vector<std::string>& expected_tags) {
std::string script_result =
RunScript("getOneShotSyncTagsFromServiceWorker()");
EXPECT_TRUE(script_result == "ok - getTags sent to SW");
return MatchTags(PopConsoleString(), expected_tags);
}
bool OneShotBackgroundSyncBrowserTest::RejectDelayedSyncEvent() {
std::string script_result = RunScript("rejectDelayedSyncEvent()");
return script_result == BuildExpectedResult("delay", "rejecting");
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
RegisterFromControlledDocument) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
EXPECT_TRUE(Register("foo"));
EXPECT_TRUE(PopConsole("foo fired"));
WaitForTagRemoval("foo");
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
RegisterFromUncontrolledDocument) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(Register("foo"));
EXPECT_TRUE(PopConsole("foo fired"));
WaitForTagRemoval("foo");
}
// Verify that Register works in a service worker
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
RegisterFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
EXPECT_TRUE(RegisterFromServiceWorker("foo_sw"));
EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
EXPECT_TRUE(PopConsole("foo_sw fired"));
WaitForTagRemoval("foo_sw");
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
RegistrationDelaysForNetwork) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
// Prevent firing by going offline.
background_sync_test_util::SetOnline(web_contents(), false);
EXPECT_TRUE(Register("foo"));
EXPECT_TRUE(HasTag("foo"));
EXPECT_TRUE(RegistrationPending("foo"));
// Resume firing by going online.
background_sync_test_util::SetOnline(web_contents(), true);
EXPECT_TRUE(PopConsole("foo fired"));
WaitForTagRemoval("foo");
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest, WaitUntil) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
background_sync_test_util::SetOnline(web_contents(), true);
EXPECT_TRUE(Register("delay"));
// Verify that it is firing.
EXPECT_TRUE(HasTag("delay"));
EXPECT_FALSE(RegistrationPending("delay"));
// Complete the task.
EXPECT_TRUE(CompleteDelayedSyncEvent());
EXPECT_TRUE(PopConsole("ok - delay completed"));
// Verify that it finished firing.
WaitForTagRemoval("delay");
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest, WaitUntilReject) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
background_sync_test_util::SetOnline(web_contents(), true);
EXPECT_TRUE(Register("delay"));
// Verify that it is firing.
EXPECT_TRUE(HasTag("delay"));
EXPECT_FALSE(RegistrationPending("delay"));
// Complete the task.
EXPECT_TRUE(RejectDelayedSyncEvent());
EXPECT_TRUE(PopConsole("ok - delay rejected"));
WaitForTagRemoval("delay");
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest, Incognito) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
background_sync_test_util::SetOnline(web_contents(), false);
EXPECT_TRUE(Register("normal"));
EXPECT_TRUE(RegistrationPending("normal"));
// Go incognito and verify that incognito doesn't see the registration.
SetIncognitoMode(true);
// Tell the new network observer that we're offline (it initializes from
// NetworkChangeNotifier::GetCurrentConnectionType() which is not mocked out
// in this test).
background_sync_test_util::SetOnline(web_contents(), false);
EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_FALSE(HasTag("normal"));
EXPECT_TRUE(Register("incognito"));
EXPECT_TRUE(RegistrationPending("incognito"));
// Switch back and make sure the registration is still there.
SetIncognitoMode(false);
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Should be controlled.
EXPECT_TRUE(HasTag("normal"));
EXPECT_FALSE(HasTag("incognito"));
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest, GetTags) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
registered_tags.push_back("foo");
registered_tags.push_back("bar");
for (const std::string& tag : registered_tags)
EXPECT_TRUE(Register(tag));
EXPECT_TRUE(GetTags(registered_tags));
}
// Verify that GetOneShotSyncRegistrations works in a service worker
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
GetRegistrationsFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
registered_tags.push_back("foo_sw");
registered_tags.push_back("bar_sw");
for (const std::string& tag : registered_tags) {
EXPECT_TRUE(RegisterFromServiceWorker(tag));
EXPECT_TRUE(PopConsole(BuildExpectedResult(tag, "registered in SW")));
}
EXPECT_TRUE(GetTagsFromServiceWorker(registered_tags));
}
// Verify that GetOneShotSyncRegistration works in a service worker
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
HasTagFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
EXPECT_TRUE(RegisterFromServiceWorker("foo_sw"));
EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
EXPECT_TRUE(HasTagFromServiceWorker("foo_sw"));
}
// Verify that a background sync registration is deleted when site data is
// cleared.
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
SyncRegistrationDeletedWhenClearingSiteData) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
// Prevent firing by going offline.
background_sync_test_util::SetOnline(web_contents(), false);
EXPECT_TRUE(Register("foo"));
EXPECT_TRUE(HasTag("foo"));
EXPECT_TRUE(RegistrationPending("foo"));
// Simulate a user clearing site data (including Service Workers, crucially),
// by clearing data from the storage partition.
ClearStoragePartitionData();
EXPECT_FALSE(HasTag("foo"));
}
// Verify that a background sync registration, from a service worker, is deleted
// when site data is cleared.
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
SyncRegistrationFromSWDeletedWhenClearingSiteData) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
EXPECT_TRUE(RegisterFromServiceWorker("foo_sw"));
EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
EXPECT_TRUE(HasTagFromServiceWorker("foo_sw"));
// Simulate a user clearing site data (including Service Workers, crucially),
// by clearing data from the storage partition.
ClearStoragePartitionData();
// Use HasTag() instead of HasTagServiceWorker() because clearing site data
// immediately terminates the service worker when removing it from the
// registration.
EXPECT_FALSE(HasTag("foo"));
}
// Verify that multiple background sync registrations are deleted when site
// data is cleared.
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
SyncRegistrationsDeletedWhenClearingSiteData) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
registered_tags.push_back("foo");
registered_tags.push_back("bar");
for (const std::string& tag : registered_tags)
EXPECT_TRUE(Register(tag));
EXPECT_TRUE(GetTags(registered_tags));
for (const std::string& tag : registered_tags)
EXPECT_TRUE(RegistrationPending(tag));
// Simulate a user clearing site data (including Service Workers, crucially),
// by clearing data from the storage partition.
ClearStoragePartitionData();
for (const std::string& tag : registered_tags)
EXPECT_FALSE(HasTag(tag));
}
// Verify that a sync event that is currently firing is deleted when site
// data is cleared.
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
FiringSyncEventDeletedWhenClearingSiteData) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
background_sync_test_util::SetOnline(web_contents(), true);
EXPECT_TRUE(Register("delay"));
// Verify that it is firing.
EXPECT_TRUE(HasTag("delay"));
EXPECT_FALSE(RegistrationPending("delay"));
// Simulate a user clearing site data (including Service Workers, crucially),
// by clearing data from the storage partition.
ClearStoragePartitionData();
// Verify that it was deleted.
EXPECT_FALSE(HasTag("delay"));
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
RegisterFromIFrameWithMainFrameHost) {
GURL url = https_server()->GetURL(kEmptyURL);
EXPECT_EQ(BuildExpectedResult("iframe", "registered sync"),
RunScript(BuildScriptString("registerOneShotSyncFromLocalFrame",
url.spec())));
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
RegisterFromIFrameWithoutMainFrameHost) {
EXPECT_EQ(BuildExpectedResult("frame", "failed to register sync"),
RegisterFromCrossOriginFrame(kRegisterSyncFromIFrameURL));
}
IN_PROC_BROWSER_TEST_F(OneShotBackgroundSyncBrowserTest,
RegisterFromServiceWorkerWithoutMainFrameHost) {
EXPECT_EQ(BuildExpectedResult("frame", "failed to register sync"),
RegisterFromCrossOriginFrame(kRegisterSyncFromSWURL));
}
} // namespace content