blob: 53e73fa7dfc21c265b88c407f4a486b7ed9e843a [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/strings/stringprintf.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
#include "content/browser/background_sync/background_sync_base_browsertest.h"
#include "content/browser/background_sync/background_sync_manager.h"
#include "content/public/common/content_features.h"
#include "content/public/test/background_sync_test_util.h"
#include "content/public/test/browser_test.h"
namespace {
constexpr base::TimeDelta kMinGapBetweenPeriodicSyncEvents =
base::TimeDelta::FromSeconds(5);
} // namespace
namespace content {
class PeriodicBackgroundSyncBrowserTest : public BackgroundSyncBaseBrowserTest {
public:
PeriodicBackgroundSyncBrowserTest() {}
~PeriodicBackgroundSyncBrowserTest() override {}
bool Register(const std::string& tag, int min_interval_ms);
bool RegisterFromIFrame(const std::string& tag, int min_interval_ms);
bool RegisterNoMinInterval(const std::string& tag);
bool RegisterFromServiceWorker(const std::string& tag, int min_interval_ms);
std::string RegisterFromCrossOriginFrame(const std::string& frame_url);
bool RegisterFromServiceWorkerNoMinInterval(const std::string& tag);
bool HasTag(const std::string& tag);
bool HasTagFromServiceWorker(const std::string& tag);
bool Unregister(const std::string& tag);
bool UnregisterFromServiceWorker(const std::string& tag);
int GetNumPeriodicSyncEvents();
protected:
base::SimpleTestClock clock_;
private:
DISALLOW_COPY_AND_ASSIGN(PeriodicBackgroundSyncBrowserTest);
};
bool PeriodicBackgroundSyncBrowserTest::Register(const std::string& tag,
int min_interval_ms) {
std::string script_result = RunScript(base::StringPrintf(
"%s('%s', %d);", "registerPeriodicSync", tag.c_str(), min_interval_ms));
return script_result == BuildExpectedResult(tag, "registered");
}
bool PeriodicBackgroundSyncBrowserTest::RegisterFromIFrame(
const std::string& tag,
int min_interval_ms) {
std::string script_result = RunScript(
base::StringPrintf("%s('%s', %d);", "registerPeriodicSyncFromIFrame",
tag.c_str(), min_interval_ms));
return script_result == BuildExpectedResult(tag, "registered");
}
std::string PeriodicBackgroundSyncBrowserTest::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("registerPeriodicSyncFromCrossOriginFrame",
url.spec()));
}
bool PeriodicBackgroundSyncBrowserTest::RegisterNoMinInterval(
const std::string& tag) {
std::string script_result = RunScript(
base::StringPrintf("%s('%s');", "registerPeriodicSync", tag.c_str()));
return script_result == BuildExpectedResult(tag, "registered");
}
bool PeriodicBackgroundSyncBrowserTest::RegisterFromServiceWorker(
const std::string& tag,
int min_interval_ms) {
std::string script_result = RunScript(base::StringPrintf(
"%s('%s', %d);", "registerPeriodicSyncFromServiceWorker", tag.c_str(),
min_interval_ms));
return script_result == BuildExpectedResult(tag, "register sent to SW");
}
bool PeriodicBackgroundSyncBrowserTest::RegisterFromServiceWorkerNoMinInterval(
const std::string& tag) {
std::string script_result = RunScript(
BuildScriptString("registerPeriodicSyncFromServiceWorker", tag));
return script_result == BuildExpectedResult(tag, "register sent to SW");
}
bool PeriodicBackgroundSyncBrowserTest::HasTag(const std::string& tag) {
std::string script_result =
RunScript(BuildScriptString("hasPeriodicSyncTag", tag));
return script_result == BuildExpectedResult(tag, "found");
}
bool PeriodicBackgroundSyncBrowserTest::HasTagFromServiceWorker(
const std::string& tag) {
std::string script_result =
RunScript(BuildScriptString("hasPeriodicSyncTagFromServiceWorker", tag));
return (script_result == "ok - hasTag sent to SW");
}
bool PeriodicBackgroundSyncBrowserTest::Unregister(const std::string& tag) {
std::string script_result = RunScript(BuildScriptString("unregister", tag));
return script_result == BuildExpectedResult(tag, "unregistered");
}
bool PeriodicBackgroundSyncBrowserTest::UnregisterFromServiceWorker(
const std::string& tag) {
std::string script_result =
RunScript(BuildScriptString("unregisterFromServiceWorker", tag));
return script_result == BuildExpectedResult(tag, "unregister sent to SW");
}
int PeriodicBackgroundSyncBrowserTest::GetNumPeriodicSyncEvents() {
std::string script_result = RunScript("getNumPeriodicSyncEvents()");
int num_periodic_sync_events = -1;
bool converted =
base::StringToInt(PopConsoleString(), &num_periodic_sync_events);
DCHECK(converted);
return num_periodic_sync_events;
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
RegisterFromControlledDocument) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 1000));
EXPECT_TRUE(Unregister("foo"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
RegisterNoMinInterval) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(RegisterNoMinInterval("foo"));
EXPECT_TRUE(Unregister("foo"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
RegisterFromIFrameWithTopLevelFrameForOrigin) {
GURL url = https_server()->GetURL(kEmptyURL);
std::string script_result = RunScript(
BuildScriptString("registerPeriodicSyncFromLocalFrame", url.spec()));
// This succeeds because there's a top level frame for the origin.
EXPECT_EQ(BuildExpectedResult("iframe", "registered periodicSync"),
script_result);
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
RegisterFromIFrameWithoutTopLevelFrameForOrigin) {
std::string script_result =
RegisterFromCrossOriginFrame(kRegisterPeriodicSyncFromIFrameURL);
// This fails because there's no top level frame open for the origin.
EXPECT_EQ(BuildExpectedResult("frame", "failed to register periodicSync"),
script_result);
}
// Verify that Register works in a service worker
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
RegisterFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
EXPECT_TRUE(RegisterFromServiceWorker("foo_sw", /* min_interval_ms= */ 10));
EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
EXPECT_TRUE(Unregister("foo"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
RegisterFromServiceWorkerNoMinInterval) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
EXPECT_TRUE(RegisterFromServiceWorkerNoMinInterval("foo_sw"));
EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
EXPECT_TRUE(Unregister("foo"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest, FindATag) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 1000));
EXPECT_TRUE(HasTag("foo"));
EXPECT_TRUE(Unregister("foo"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
FindATagFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 1000));
EXPECT_TRUE(HasTagFromServiceWorker("foo"));
EXPECT_TRUE(PopConsole("ok - foo found in SW"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
UnregisterFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
EXPECT_TRUE(RegisterNoMinInterval("foo"));
EXPECT_TRUE(HasTag("foo"));
EXPECT_TRUE(UnregisterFromServiceWorker("foo"));
EXPECT_TRUE(PopConsole("ok - foo unregistered in SW"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
FirePeriodicSyncOnConnectivity) {
SetTestClock(&clock_);
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
// Prevent firing by going offline.
background_sync_test_util::SetOnline(web_contents(), false);
EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 10));
EXPECT_TRUE(HasTag("foo"));
int initial_periodic_sync_events = GetNumPeriodicSyncEvents();
ASSERT_EQ(initial_periodic_sync_events, 0);
clock_.Advance(kMinGapBetweenPeriodicSyncEvents);
EXPECT_EQ(GetNumPeriodicSyncEvents(), initial_periodic_sync_events);
// Resume firing by going online.
background_sync_test_util::SetOnline(web_contents(), true);
EXPECT_TRUE(PopConsole("foo fired"));
EXPECT_EQ(GetNumPeriodicSyncEvents(), initial_periodic_sync_events + 1);
EXPECT_TRUE(HasTag("foo"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest, MultipleEventsFired) {
SetTestClock(&clock_);
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 10));
clock_.Advance(kMinGapBetweenPeriodicSyncEvents);
EXPECT_TRUE(PopConsole("foo fired"));
EXPECT_TRUE(HasTag("foo"));
clock_.Advance(kMinGapBetweenPeriodicSyncEvents);
EXPECT_TRUE(PopConsole("foo fired"));
EXPECT_TRUE(HasTag("foo"));
EXPECT_TRUE(Unregister("foo"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
MultipleMinIntervalsAndTags) {
SetTestClock(&clock_);
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 10));
EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 200));
EXPECT_TRUE(HasTag("foo"));
EXPECT_TRUE(Register("bar", /* min_interval_ms= */ 50));
EXPECT_TRUE(HasTag("bar"));
clock_.Advance(kMinGapBetweenPeriodicSyncEvents);
// Ordering is important here.
EXPECT_TRUE(PopConsole("bar fired"));
EXPECT_TRUE(PopConsole("foo fired"));
EXPECT_TRUE(Unregister("foo"));
EXPECT_FALSE(HasTag("foo"));
EXPECT_TRUE(HasTag("bar"));
clock_.Advance(kMinGapBetweenPeriodicSyncEvents);
EXPECT_TRUE(PopConsole("bar fired"));
EXPECT_TRUE(Unregister("bar"));
}
IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest, WaitUntil) {
SetTestClock(&clock_);
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
background_sync_test_util::SetOnline(web_contents(), false);
EXPECT_TRUE(Register("delay", /* min_interval_ms= */ 10));
ASSERT_TRUE(HasTag("delay"));
clock_.Advance(kMinGapBetweenPeriodicSyncEvents);
background_sync_test_util::SetOnline(web_contents(), true);
base::RunLoop().RunUntilIdle();
int num_periodicsync_events_fired = GetNumPeriodicSyncEvents();
// Complete the task.
EXPECT_TRUE(CompleteDelayedSyncEvent());
EXPECT_TRUE(PopConsole("ok - delay completed"));
EXPECT_EQ(GetNumPeriodicSyncEvents(), num_periodicsync_events_fired + 1);
EXPECT_TRUE(HasTag("delay"));
EXPECT_TRUE(Unregister("delay"));
}
} // namespace content