blob: efbc1518b7ec0fe4d566e3322859236814ebedd8 [file] [log] [blame]
// Copyright 2015 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 "content/browser/background_sync/background_sync_manager.h"
#include <stdint.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/simple_test_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/background_sync/background_sync_network_observer.h"
#include "content/browser/background_sync/background_sync_status.h"
#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration_object_host.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/background_sync_parameters.h"
#include "content/public/browser/permission_type.h"
#include "content/public/test/background_sync_test_util.h"
#include "content/public/test/mock_permission_manager.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "content/test/mock_background_sync_controller.h"
#include "content/test/test_background_sync_manager.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace content {
namespace {
using ::testing::_;
using ::testing::Return;
const char kScope1[] = "https://example.com/a";
const char kScope2[] = "https://example.com/b";
const char kScript1[] = "https://example.com/a/script.js";
const char kScript2[] = "https://example.com/b/script.js";
void RegisterServiceWorkerCallback(bool* called,
int64_t* store_registration_id,
blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
<< blink::ServiceWorkerStatusToString(status);
*called = true;
*store_registration_id = registration_id;
}
void FindServiceWorkerRegistrationCallback(
scoped_refptr<ServiceWorkerRegistration>* out_registration,
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
<< blink::ServiceWorkerStatusToString(status);
*out_registration = std::move(registration);
}
void UnregisterServiceWorkerCallback(bool* called,
blink::ServiceWorkerStatusCode code) {
EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, code);
*called = true;
}
blink::mojom::BackgroundSyncType GetBackgroundSyncType(
const blink::mojom::SyncRegistrationOptions& options) {
return options.min_interval == -1
? blink::mojom::BackgroundSyncType::ONE_SHOT
: blink::mojom::BackgroundSyncType::PERIODIC;
}
} // namespace
class BackgroundSyncManagerTest
: public testing::Test,
public DevToolsBackgroundServicesContextImpl::EventObserver {
public:
BackgroundSyncManagerTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
sync_options_1_.tag = "foo";
sync_options_2_.tag = "bar";
}
void SetUp() override {
// Don't let the tests be confused by the real-world device connectivity
background_sync_test_util::SetIgnoreNetworkChanges(true);
// TODO(jkarlin): Create a new object with all of the necessary SW calls
// so that we can inject test versions instead of bringing up all of this
// extra SW stuff.
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
std::unique_ptr<MockPermissionManager> mock_permission_manager(
new testing::NiceMock<MockPermissionManager>());
ON_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::BACKGROUND_SYNC, _, _))
.WillByDefault(Return(blink::mojom::PermissionStatus::GRANTED));
ON_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::PERIODIC_BACKGROUND_SYNC, _, _))
.WillByDefault(Return(blink::mojom::PermissionStatus::GRANTED));
helper_->browser_context()->SetPermissionControllerDelegate(
std::move(mock_permission_manager));
// Create a StoragePartition with the correct BrowserContext so that the
// BackgroundSyncManager can find the BrowserContext through it.
storage_partition_impl_ = StoragePartitionImpl::Create(
helper_->browser_context(), /* in_memory= */ true, base::FilePath(),
/* partition_domain= */ "");
helper_->context_wrapper()->set_storage_partition(
storage_partition_impl_.get());
SetMaxSyncAttemptsAndRestartManager(1);
// Wait for storage to finish initializing before registering service
// workers.
base::RunLoop().RunUntilIdle();
RegisterServiceWorkers();
storage_partition_impl_->GetDevToolsBackgroundServicesContext()
->AddObserver(this);
}
void TearDown() override {
storage_partition_impl_->GetDevToolsBackgroundServicesContext()
->RemoveObserver(this);
// Restore the network observer functionality for subsequent tests.
background_sync_test_util::SetIgnoreNetworkChanges(false);
}
void RegisterServiceWorkers() {
bool called_1 = false;
bool called_2 = false;
blink::mojom::ServiceWorkerRegistrationOptions options1;
options1.scope = GURL(kScope1);
blink::mojom::ServiceWorkerRegistrationOptions options2;
options2.scope = GURL(kScope2);
helper_->context()->RegisterServiceWorker(
GURL(kScript1), options1,
base::BindOnce(&RegisterServiceWorkerCallback, &called_1,
&sw_registration_id_1_));
helper_->context()->RegisterServiceWorker(
GURL(kScript2), options2,
base::BindOnce(&RegisterServiceWorkerCallback, &called_2,
&sw_registration_id_2_));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called_1);
EXPECT_TRUE(called_2);
// Hang onto the registrations as they need to be "live" when
// calling BackgroundSyncManager::Register.
helper_->context_wrapper()->FindReadyRegistrationForId(
sw_registration_id_1_, GURL(kScope1).GetOrigin(),
base::BindOnce(FindServiceWorkerRegistrationCallback,
&sw_registration_1_));
helper_->context_wrapper()->FindReadyRegistrationForId(
sw_registration_id_2_, GURL(kScope1).GetOrigin(),
base::BindOnce(FindServiceWorkerRegistrationCallback,
&sw_registration_2_));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(sw_registration_1_);
EXPECT_TRUE(sw_registration_2_);
}
void SetNetwork(network::mojom::ConnectionType connection_type) {
network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType(
connection_type);
if (test_background_sync_manager_) {
BackgroundSyncNetworkObserver* network_observer =
test_background_sync_manager_->GetNetworkObserverForTesting();
network_observer->NotifyManagerIfConnectionChangedForTesting(
connection_type);
base::RunLoop().RunUntilIdle();
}
}
void StatusAndOneShotSyncRegistrationCallback(
bool* was_called,
BackgroundSyncStatus status,
std::unique_ptr<BackgroundSyncRegistration> registration) {
*was_called = true;
one_shot_sync_callback_status_ = status;
callback_one_shot_sync_registration_ = std::move(registration);
}
void StatusAndPeriodicSyncRegistrationCallback(
bool* was_called,
BackgroundSyncStatus status,
std::unique_ptr<BackgroundSyncRegistration> registration) {
*was_called = true;
periodic_sync_callback_status_ = status;
callback_periodic_sync_registration_ = std::move(registration);
}
void StatusAndOneShotSyncRegistrationsCallback(
bool* was_called,
BackgroundSyncStatus status,
std::vector<std::unique_ptr<BackgroundSyncRegistration>> registrations) {
*was_called = true;
one_shot_sync_callback_status_ = status;
callback_one_shot_sync_registrations_ = std::move(registrations);
}
void StatusAndPeriodicSyncRegistrationsCallback(
bool* was_called,
BackgroundSyncStatus status,
std::vector<std::unique_ptr<BackgroundSyncRegistration>> registrations) {
*was_called = true;
periodic_sync_callback_status_ = status;
callback_periodic_sync_registrations_ = std::move(registrations);
}
void StatusCallback(bool* was_called, BackgroundSyncStatus status) {
*was_called = true;
callback_status_ = status;
}
base::TimeDelta GetSoonestWakeupDelta(
blink::mojom::BackgroundSyncType sync_type) {
return test_background_sync_manager_->GetSoonestWakeupDelta(sync_type);
}
protected:
MOCK_METHOD1(OnEventReceived,
void(const devtools::proto::BackgroundServiceEvent&));
MOCK_METHOD2(OnRecordingStateChanged,
void(bool, devtools::proto::BackgroundService));
void CreateBackgroundSyncManager() {
background_sync_manager_ = std::make_unique<TestBackgroundSyncManager>(
helper_->context_wrapper(),
storage_partition_impl_->GetDevToolsBackgroundServicesContext());
test_background_sync_manager_ =
static_cast<TestBackgroundSyncManager*>(background_sync_manager_.get());
background_sync_manager_->set_clock(&test_clock_);
// Many tests do not expect the sync event to fire immediately after
// register (and cleanup up the sync registrations). Tests can control when
// the sync event fires by manipulating the network state as needed.
// NOTE: The setup of the network connection must happen after the
// BackgroundSyncManager has been created.
SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
}
void InitBackgroundSyncManager() {
test_background_sync_manager_->DoInit();
base::RunLoop().RunUntilIdle();
}
void SetupBackgroundSyncManager() {
CreateBackgroundSyncManager();
InitBackgroundSyncManager();
}
void SetupCorruptBackgroundSyncManager() {
CreateBackgroundSyncManager();
test_background_sync_manager_->set_corrupt_backend(true);
InitBackgroundSyncManager();
}
void SetupDelayedBackgroundSyncManager() {
CreateBackgroundSyncManager();
test_background_sync_manager_->set_delay_backend(true);
InitBackgroundSyncManager();
}
void DeleteBackgroundSyncManager() {
background_sync_manager_.reset();
test_background_sync_manager_ = nullptr;
}
bool Register(blink::mojom::SyncRegistrationOptions sync_options) {
return RegisterWithServiceWorkerId(sw_registration_id_1_,
std::move(sync_options));
}
bool Unregister(blink::mojom::SyncRegistrationOptions sync_options) {
return UnregisterWithServiceWorkerId(sw_registration_id_1_,
std::move(sync_options));
}
bool RegisterWithServiceWorkerId(
int64_t sw_registration_id,
blink::mojom::SyncRegistrationOptions options) {
bool was_called = false;
BackgroundSyncStatus* callback_status;
if (GetBackgroundSyncType(options) ==
blink::mojom::BackgroundSyncType::ONE_SHOT) {
background_sync_manager_->Register(
sw_registration_id, std::move(options),
base::BindOnce(&BackgroundSyncManagerTest::
StatusAndOneShotSyncRegistrationCallback,
base::Unretained(this), &was_called));
callback_status = &one_shot_sync_callback_status_;
} else {
background_sync_manager_->Register(
sw_registration_id, std::move(options),
base::BindOnce(&BackgroundSyncManagerTest::
StatusAndPeriodicSyncRegistrationCallback,
base::Unretained(this), &was_called));
callback_status = &periodic_sync_callback_status_;
}
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
// Mock the client receiving the response and calling
// DidResolveRegistration.
if (*callback_status == BACKGROUND_SYNC_STATUS_OK) {
background_sync_manager_->DidResolveRegistration(
blink::mojom::BackgroundSyncRegistrationInfo::New(
sw_registration_id, options.tag, GetBackgroundSyncType(options)));
base::RunLoop().RunUntilIdle();
}
return *callback_status == BACKGROUND_SYNC_STATUS_OK;
}
bool UnregisterWithServiceWorkerId(
int64_t sw_registration_id,
blink::mojom::SyncRegistrationOptions options) {
if (GetBackgroundSyncType(options) ==
blink::mojom::BackgroundSyncType::ONE_SHOT) {
// Not supported for one-shot sync.
return false;
}
bool was_called = false;
background_sync_manager_->UnregisterPeriodicSync(
sw_registration_id, options.tag,
base::BindOnce(&BackgroundSyncManagerTest::StatusCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
return callback_status_ == BACKGROUND_SYNC_STATUS_OK;
}
MockPermissionManager* GetPermissionControllerDelegate() {
return static_cast<MockPermissionManager*>(
helper_->browser_context()->GetPermissionControllerDelegate());
}
bool GetRegistration(
blink::mojom::SyncRegistrationOptions registration_options) {
if (GetBackgroundSyncType(registration_options) ==
blink::mojom::BackgroundSyncType::ONE_SHOT) {
return GetOneShotSyncRegistrationWithServiceWorkerId(
sw_registration_id_1_, std::move(registration_options));
}
return GetPeriodicSyncRegistrationWithServiceWorkerId(
sw_registration_id_1_, std::move(registration_options));
}
bool GetOneShotSyncRegistrationWithServiceWorkerId(
int64_t sw_registration_id,
blink::mojom::SyncRegistrationOptions registration_options) {
bool was_called = false;
background_sync_manager_->GetOneShotSyncRegistrations(
sw_registration_id,
base::BindOnce(&BackgroundSyncManagerTest::
StatusAndOneShotSyncRegistrationsCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
if (one_shot_sync_callback_status_ == BACKGROUND_SYNC_STATUS_OK) {
for (auto& one_shot_sync_registration :
callback_one_shot_sync_registrations_) {
if (one_shot_sync_registration->options()->Equals(
registration_options)) {
// Transfer the matching registration out of the vector into
// |callback_one_shot_sync_registration_| for testing.
callback_one_shot_sync_registration_ =
std::move(one_shot_sync_registration);
base::Erase(callback_one_shot_sync_registrations_,
one_shot_sync_registration);
return true;
}
}
}
return false;
}
bool GetPeriodicSyncRegistrationWithServiceWorkerId(
int64_t sw_registration_id,
blink::mojom::SyncRegistrationOptions registration_options) {
bool was_called = false;
background_sync_manager_->GetPeriodicSyncRegistrations(
sw_registration_id,
base::BindOnce(&BackgroundSyncManagerTest::
StatusAndPeriodicSyncRegistrationsCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
if (periodic_sync_callback_status_ == BACKGROUND_SYNC_STATUS_OK) {
for (auto& periodic_sync_registration :
callback_periodic_sync_registrations_) {
if (periodic_sync_registration->options()->Equals(
registration_options)) {
// Transfer the matching registration out of the vector into
// |callback_periodic_sync_registration_| for testing.
callback_periodic_sync_registration_ =
std::move(periodic_sync_registration);
base::Erase(callback_periodic_sync_registrations_,
periodic_sync_registration);
return true;
}
}
}
return false;
}
bool GetOneShotSyncRegistrations() {
bool was_called = false;
background_sync_manager_->GetOneShotSyncRegistrations(
sw_registration_id_1_,
base::BindOnce(&BackgroundSyncManagerTest::
StatusAndOneShotSyncRegistrationsCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
return one_shot_sync_callback_status_ == BACKGROUND_SYNC_STATUS_OK;
}
bool GetPeriodicSyncRegistrations() {
bool was_called = false;
background_sync_manager_->GetPeriodicSyncRegistrations(
sw_registration_id_1_,
base::BindOnce(&BackgroundSyncManagerTest::
StatusAndPeriodicSyncRegistrationsCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
return periodic_sync_callback_status_ == BACKGROUND_SYNC_STATUS_OK;
}
MockBackgroundSyncController* GetController() {
return static_cast<MockBackgroundSyncController*>(
helper_->browser_context()->GetBackgroundSyncController());
}
void StorageRegistrationCallback(blink::ServiceWorkerStatusCode result) {
callback_sw_status_code_ = result;
}
void UnregisterServiceWorker(uint64_t sw_registration_id) {
bool called = false;
helper_->context()->UnregisterServiceWorker(
ScopeForSWId(sw_registration_id),
base::BindOnce(&UnregisterServiceWorkerCallback, &called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
}
GURL ScopeForSWId(int64_t sw_id) {
EXPECT_TRUE(sw_id == sw_registration_id_1_ ||
sw_id == sw_registration_id_2_);
return sw_id == sw_registration_id_1_ ? GURL(kScope1) : GURL(kScope2);
}
void SetupForSyncEvent(
const TestBackgroundSyncManager::DispatchSyncCallback& callback) {
test_background_sync_manager_->set_dispatch_sync_callback(callback);
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
}
void SetupForPeriodicSyncEvent(
const TestBackgroundSyncManager::DispatchSyncCallback& callback) {
test_background_sync_manager_->set_dispatch_periodic_sync_callback(
callback);
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
}
void DispatchSyncStatusCallback(
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerVersion> active_version,
ServiceWorkerVersion::StatusCallback callback) {
sync_events_called_++;
std::move(callback).Run(status);
}
void DispatchPeriodicSyncStatusCallback(
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerVersion> active_version,
ServiceWorkerVersion::StatusCallback callback) {
periodic_sync_events_called_++;
std::move(callback).Run(status);
}
void InitSyncEventTest() {
SetupForSyncEvent(base::BindRepeating(
&BackgroundSyncManagerTest::DispatchSyncStatusCallback,
base::Unretained(this), blink::ServiceWorkerStatusCode::kOk));
}
void InitPeriodicSyncEventTest() {
SetupForPeriodicSyncEvent(base::BindRepeating(
&BackgroundSyncManagerTest::DispatchPeriodicSyncStatusCallback,
base::Unretained(this), blink::ServiceWorkerStatusCode::kOk));
}
void InitFailedSyncEventTest() {
SetupForSyncEvent(base::BindRepeating(
&BackgroundSyncManagerTest::DispatchSyncStatusCallback,
base::Unretained(this),
blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected));
}
void DispatchSyncDelayedCallback(
scoped_refptr<ServiceWorkerVersion> active_version,
ServiceWorkerVersion::StatusCallback callback) {
sync_events_called_++;
sync_fired_callback_ = std::move(callback);
}
void InitDelayedSyncEventTest() {
SetupForSyncEvent(base::BindRepeating(
&BackgroundSyncManagerTest::DispatchSyncDelayedCallback,
base::Unretained(this)));
}
void RegisterAndVerifySyncEventDelayed(
blink::mojom::SyncRegistrationOptions sync_options) {
int count_sync_events = sync_events_called_;
EXPECT_FALSE(sync_fired_callback_);
EXPECT_TRUE(Register(sync_options));
EXPECT_EQ(count_sync_events + 1, sync_events_called_);
EXPECT_TRUE(GetRegistration(std::move(sync_options)));
EXPECT_TRUE(sync_fired_callback_);
}
void DeleteServiceWorkerAndStartOver() {
helper_->context()->ScheduleDeleteAndStartOver();
content::RunAllTasksUntilIdle();
}
int MaxTagLength() const { return BackgroundSyncManager::kMaxTagLength; }
void SetMaxSyncAttemptsAndRestartManager(int max_sync_attempts) {
BackgroundSyncParameters* parameters =
GetController()->background_sync_parameters();
parameters->max_sync_attempts = max_sync_attempts;
// Restart the BackgroundSyncManager so that it updates its parameters.
SetupBackgroundSyncManager();
}
void FireReadyEvents() { background_sync_manager_->OnNetworkChanged(); }
bool AreOptionConditionsMet() {
return background_sync_manager_->AreOptionConditionsMet();
}
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
std::unique_ptr<BackgroundSyncManager> background_sync_manager_;
std::unique_ptr<StoragePartitionImpl> storage_partition_impl_;
TestBackgroundSyncManager* test_background_sync_manager_ = nullptr;
base::SimpleTestClock test_clock_;
int64_t sw_registration_id_1_;
int64_t sw_registration_id_2_;
scoped_refptr<ServiceWorkerRegistration> sw_registration_1_;
scoped_refptr<ServiceWorkerRegistration> sw_registration_2_;
blink::mojom::SyncRegistrationOptions sync_options_1_;
blink::mojom::SyncRegistrationOptions sync_options_2_;
// Callback values.
BackgroundSyncStatus one_shot_sync_callback_status_ =
BACKGROUND_SYNC_STATUS_OK;
BackgroundSyncStatus periodic_sync_callback_status_ =
BACKGROUND_SYNC_STATUS_OK;
BackgroundSyncStatus callback_status_ = BACKGROUND_SYNC_STATUS_OK;
std::unique_ptr<BackgroundSyncRegistration>
callback_one_shot_sync_registration_;
std::unique_ptr<BackgroundSyncRegistration>
callback_periodic_sync_registration_;
std::vector<std::unique_ptr<BackgroundSyncRegistration>>
callback_one_shot_sync_registrations_;
std::vector<std::unique_ptr<BackgroundSyncRegistration>>
callback_periodic_sync_registrations_;
blink::ServiceWorkerStatusCode callback_sw_status_code_ =
blink::ServiceWorkerStatusCode::kOk;
int sync_events_called_ = 0;
int periodic_sync_events_called_ = 0;
ServiceWorkerVersion::StatusCallback sync_fired_callback_;
};
TEST_F(BackgroundSyncManagerTest, Register) {
EXPECT_TRUE(Register(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, FailToRegisterWithInvalidOptions) {
sync_options_1_.min_interval = -2000;
EXPECT_FALSE(Register(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, Unregister) {
// Not supported for One-shot syncs.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_FALSE(Unregister(sync_options_1_));
sync_options_1_.min_interval = 36000;
EXPECT_TRUE(Register(sync_options_1_));
// Don't fail for non-existent Periodic Sync registrations.
sync_options_2_.min_interval = 36000;
EXPECT_TRUE(Unregister(sync_options_2_));
// Unregistering one periodic sync doesn't affect another.
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_TRUE(Unregister(sync_options_1_));
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_2_));
// Disable manager. Unregister should fail.
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_FALSE(Unregister(sync_options_2_));
SetupBackgroundSyncManager();
EXPECT_TRUE(Unregister(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, UnregistrationStopsPeriodicTasks) {
InitPeriodicSyncEventTest();
int thirteen_hours_ms = 13 * 60 * 60 * 1000;
sync_options_2_.min_interval = thirteen_hours_ms;
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_EQ(0, periodic_sync_events_called_);
// Advance clock.
test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
FireReadyEvents();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, periodic_sync_events_called_);
EXPECT_TRUE(Unregister(sync_options_2_));
// Advance clock. Expect no increase in periodicSync events fired.
test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
FireReadyEvents();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, periodic_sync_events_called_);
}
TEST_F(BackgroundSyncManagerTest, RegisterAndWaitToFireUntilResolved) {
InitSyncEventTest();
bool was_called = false;
background_sync_manager_->Register(
sw_registration_id_1_, sync_options_1_,
base::BindOnce(
&BackgroundSyncManagerTest::StatusAndOneShotSyncRegistrationCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
// Verify that the sync event hasn't fired yet, as it should wait for the
// client to acknowledge with DidResolveRegistration.
EXPECT_EQ(0, sync_events_called_);
background_sync_manager_->DidResolveRegistration(
blink::mojom::BackgroundSyncRegistrationInfo::New(
sw_registration_id_1_, sync_options_1_.tag,
GetBackgroundSyncType(sync_options_1_)));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, sync_events_called_);
}
TEST_F(BackgroundSyncManagerTest, ResolveInvalidRegistration) {
InitSyncEventTest();
bool was_called = false;
background_sync_manager_->Register(
sw_registration_id_1_, sync_options_1_,
base::BindOnce(
&BackgroundSyncManagerTest::StatusAndOneShotSyncRegistrationCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
// Verify that the sync event hasn't fired yet, as it should wait for the
// client to acknowledge with DidResolveRegistration.
EXPECT_EQ(0, sync_events_called_);
// Resolve a non-existing registration.
background_sync_manager_->DidResolveRegistration(
blink::mojom::BackgroundSyncRegistrationInfo::New(
sw_registration_id_1_, "unknown_tag",
GetBackgroundSyncType(sync_options_1_)));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, sync_events_called_);
}
TEST_F(BackgroundSyncManagerTest, RegistrationIntact) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(sync_options_1_.tag,
callback_one_shot_sync_registration_->options()->tag);
sync_options_2_.min_interval = 3600;
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_EQ(sync_options_2_.tag,
callback_periodic_sync_registration_->options()->tag);
}
TEST_F(BackgroundSyncManagerTest, RegisterWithoutLiveSWRegistration) {
// Get a provider host which is used to install the service worker.
ASSERT_TRUE(sw_registration_1_->active_version());
ASSERT_FALSE(sw_registration_1_->waiting_version());
ASSERT_FALSE(sw_registration_1_->installing_version());
ServiceWorkerProviderHost* provider_host =
sw_registration_1_->active_version()->provider_host();
ASSERT_TRUE(provider_host);
// Remove the registration object host.
provider_host->registration_object_hosts_.clear();
// Ensure |sw_registration_1_| is the last reference to the registration.
ASSERT_TRUE(sw_registration_1_->HasOneRef());
sw_registration_1_ = nullptr;
EXPECT_FALSE(Register(sync_options_1_));
EXPECT_EQ(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
one_shot_sync_callback_status_);
}
TEST_F(BackgroundSyncManagerTest, RegisterWithoutActiveSWRegistration) {
sw_registration_1_->UnsetVersion(sw_registration_1_->active_version());
EXPECT_FALSE(Register(sync_options_1_));
EXPECT_EQ(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
one_shot_sync_callback_status_);
}
TEST_F(BackgroundSyncManagerTest, RegisterBadBackend) {
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_FALSE(Register(sync_options_1_));
test_background_sync_manager_->set_corrupt_backend(false);
EXPECT_FALSE(Register(sync_options_1_));
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, RegisterPermissionDenied) {
GURL expected_origin = GURL(kScope1).GetOrigin();
MockPermissionManager* mock_permission_manager =
GetPermissionControllerDelegate();
EXPECT_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::BACKGROUND_SYNC,
expected_origin, expected_origin))
.WillOnce(testing::Return(blink::mojom::PermissionStatus::DENIED));
EXPECT_FALSE(Register(sync_options_1_));
sync_options_2_.min_interval = 36000;
EXPECT_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::PERIODIC_BACKGROUND_SYNC,
expected_origin, expected_origin))
.WillOnce(testing::Return(blink::mojom::PermissionStatus::DENIED));
EXPECT_FALSE(Register(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, RegisterPermissionGranted) {
GURL expected_origin = GURL(kScope1).GetOrigin();
MockPermissionManager* mock_permission_manager =
GetPermissionControllerDelegate();
EXPECT_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::BACKGROUND_SYNC,
expected_origin, expected_origin))
.WillOnce(testing::Return(blink::mojom::PermissionStatus::GRANTED));
EXPECT_TRUE(Register(sync_options_1_));
sync_options_2_.min_interval = 36000;
EXPECT_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::PERIODIC_BACKGROUND_SYNC,
expected_origin, expected_origin))
.WillOnce(testing::Return(blink::mojom::PermissionStatus::GRANTED));
EXPECT_TRUE(Register(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, TwoRegistrations) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationNonExisting) {
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationExisting) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_FALSE(GetRegistration(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationBadBackend) {
EXPECT_TRUE(Register(sync_options_1_));
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_FALSE(Register(sync_options_2_));
// Registration should have discovered the bad backend and disabled the
// BackgroundSyncManager.
EXPECT_FALSE(GetRegistration(sync_options_1_));
test_background_sync_manager_->set_corrupt_backend(false);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsZero) {
EXPECT_TRUE(GetOneShotSyncRegistrations());
EXPECT_EQ(0u, callback_one_shot_sync_registrations_.size());
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsOne) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetOneShotSyncRegistrations());
ASSERT_EQ(1u, callback_one_shot_sync_registrations_.size());
sync_options_1_.Equals(*callback_one_shot_sync_registrations_[0]->options());
sync_options_1_.min_interval = 3600;
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetPeriodicSyncRegistrations());
ASSERT_EQ(1u, callback_periodic_sync_registrations_.size());
sync_options_1_.Equals(*callback_periodic_sync_registrations_[0]->options());
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsTwo) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_TRUE(GetOneShotSyncRegistrations());
ASSERT_EQ(2u, callback_one_shot_sync_registrations_.size());
sync_options_1_.Equals(*callback_one_shot_sync_registrations_[0]->options());
sync_options_2_.Equals(*callback_one_shot_sync_registrations_[1]->options());
sync_options_1_.min_interval = 3600;
sync_options_2_.min_interval = 3600;
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_TRUE(GetPeriodicSyncRegistrations());
ASSERT_EQ(2u, callback_periodic_sync_registrations_.size());
sync_options_1_.Equals(*callback_periodic_sync_registrations_[0]->options());
sync_options_2_.Equals(*callback_periodic_sync_registrations_[1]->options());
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsBadBackend) {
EXPECT_TRUE(Register(sync_options_1_));
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_TRUE(GetOneShotSyncRegistrations());
EXPECT_FALSE(Register(sync_options_2_));
// Registration should have discovered the bad backend and disabled the
// BackgroundSyncManager.
EXPECT_FALSE(GetOneShotSyncRegistrations());
test_background_sync_manager_->set_corrupt_backend(false);
EXPECT_FALSE(GetOneShotSyncRegistrations());
}
TEST_F(BackgroundSyncManagerTest, Reregister) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, ReregisterSecond) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_TRUE(Register(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, RegisterMaxTagLength) {
sync_options_1_.tag = std::string(MaxTagLength(), 'a');
EXPECT_TRUE(Register(sync_options_1_));
sync_options_2_.tag = std::string(MaxTagLength() + 1, 'b');
EXPECT_FALSE(Register(sync_options_2_));
EXPECT_EQ(BACKGROUND_SYNC_STATUS_NOT_ALLOWED, one_shot_sync_callback_status_);
}
TEST_F(BackgroundSyncManagerTest, RebootRecovery) {
EXPECT_TRUE(Register(sync_options_1_));
SetupBackgroundSyncManager();
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_FALSE(GetRegistration(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, RebootRecoveryTwoServiceWorkers) {
EXPECT_TRUE(
RegisterWithServiceWorkerId(sw_registration_id_1_, sync_options_1_));
EXPECT_TRUE(
RegisterWithServiceWorkerId(sw_registration_id_2_, sync_options_2_));
SetupBackgroundSyncManager();
EXPECT_TRUE(GetOneShotSyncRegistrationWithServiceWorkerId(
sw_registration_id_1_, sync_options_1_));
EXPECT_FALSE(GetOneShotSyncRegistrationWithServiceWorkerId(
sw_registration_id_1_, sync_options_2_));
EXPECT_FALSE(GetOneShotSyncRegistrationWithServiceWorkerId(
sw_registration_id_2_, sync_options_1_));
EXPECT_TRUE(GetOneShotSyncRegistrationWithServiceWorkerId(
sw_registration_id_2_, sync_options_2_));
EXPECT_TRUE(GetOneShotSyncRegistrationWithServiceWorkerId(
sw_registration_id_1_, sync_options_1_));
EXPECT_TRUE(GetOneShotSyncRegistrationWithServiceWorkerId(
sw_registration_id_2_, sync_options_2_));
EXPECT_TRUE(
RegisterWithServiceWorkerId(sw_registration_id_1_, sync_options_2_));
EXPECT_TRUE(
RegisterWithServiceWorkerId(sw_registration_id_2_, sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, InitWithBadBackend) {
SetupCorruptBackgroundSyncManager();
EXPECT_FALSE(Register(sync_options_1_));
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, SequentialOperations) {
// Schedule Init and all of the operations on a delayed backend. Verify that
// the operations complete sequentially.
SetupDelayedBackgroundSyncManager();
bool register_called = false;
bool get_registrations_called = false;
test_background_sync_manager_->Register(
sw_registration_id_1_, sync_options_1_,
base::BindOnce(
&BackgroundSyncManagerTest::StatusAndOneShotSyncRegistrationCallback,
base::Unretained(this), &register_called));
test_background_sync_manager_->GetOneShotSyncRegistrations(
sw_registration_id_1_,
base::BindOnce(
&BackgroundSyncManagerTest::StatusAndOneShotSyncRegistrationsCallback,
base::Unretained(this), &get_registrations_called));
base::RunLoop().RunUntilIdle();
// Init should be blocked while loading from the backend.
EXPECT_FALSE(register_called);
EXPECT_FALSE(get_registrations_called);
test_background_sync_manager_->ResumeBackendOperation();
base::RunLoop().RunUntilIdle();
// Register should be blocked while storing to the backend.
EXPECT_FALSE(register_called);
EXPECT_FALSE(get_registrations_called);
test_background_sync_manager_->ResumeBackendOperation();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(register_called);
EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, one_shot_sync_callback_status_);
// GetRegistrations should run immediately as it doesn't write to disk.
EXPECT_TRUE(get_registrations_called);
}
TEST_F(BackgroundSyncManagerTest, UnregisterServiceWorker) {
EXPECT_TRUE(Register(sync_options_1_));
UnregisterServiceWorker(sw_registration_id_1_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest,
UnregisterServiceWorkerDuringSyncRegistration) {
EXPECT_TRUE(Register(sync_options_1_));
sync_options_2_.min_interval = 3600;
test_background_sync_manager_->set_delay_backend(true);
bool callback_called = false;
test_background_sync_manager_->Register(
sw_registration_id_1_, sync_options_2_,
base::BindOnce(
&BackgroundSyncManagerTest::StatusAndPeriodicSyncRegistrationCallback,
base::Unretained(this), &callback_called));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(callback_called);
UnregisterServiceWorker(sw_registration_id_1_);
test_background_sync_manager_->ResumeBackendOperation();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback_called);
EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
periodic_sync_callback_status_);
test_background_sync_manager_->set_delay_backend(false);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, DeleteAndStartOverServiceWorkerContext) {
EXPECT_TRUE(Register(sync_options_1_));
DeleteServiceWorkerAndStartOver();
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, DisabledManagerWorksAfterBrowserRestart) {
EXPECT_TRUE(Register(sync_options_1_));
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_FALSE(Register(sync_options_2_));
// The manager is now disabled and not accepting new requests until browser
// restart or notification that the storage has been wiped.
test_background_sync_manager_->set_corrupt_backend(false);
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_FALSE(Register(sync_options_2_));
// Simulate restarting the browser by creating a new BackgroundSyncManager.
SetupBackgroundSyncManager();
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, DisabledManagerWorksAfterDeleteAndStartOver) {
EXPECT_TRUE(Register(sync_options_1_));
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_FALSE(Register(sync_options_2_));
// The manager is now disabled and not accepting new requests until browser
// restart or notification that the storage has been wiped.
test_background_sync_manager_->set_corrupt_backend(false);
DeleteServiceWorkerAndStartOver();
RegisterServiceWorkers();
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, RegistrationEqualsTag) {
BackgroundSyncRegistration reg_1;
BackgroundSyncRegistration reg_2;
EXPECT_TRUE(reg_1.Equals(reg_2));
reg_2.options()->tag = "bar";
EXPECT_FALSE(reg_1.Equals(reg_2));
}
TEST_F(BackgroundSyncManagerTest, StoreAndRetrievePreservesValues) {
InitDelayedSyncEventTest();
blink::mojom::SyncRegistrationOptions options;
// Set non-default values for each field.
options.tag = "foo";
// Store the registration.
EXPECT_TRUE(Register(options));
// Simulate restarting the sync manager, forcing the next read to come from
// disk.
SetupBackgroundSyncManager();
EXPECT_TRUE(GetRegistration(options));
EXPECT_TRUE(options.Equals(*callback_one_shot_sync_registration_->options()));
}
TEST_F(BackgroundSyncManagerTest, EmptyTagSupported) {
sync_options_1_.tag = "";
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(
sync_options_1_.Equals(*callback_one_shot_sync_registration_->options()));
}
TEST_F(BackgroundSyncManagerTest, PeriodicSyncOptions) {
sync_options_1_.min_interval = 2;
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(
sync_options_1_.Equals(*callback_periodic_sync_registration_->options()));
}
TEST_F(BackgroundSyncManagerTest, BothTypesOfSyncShareATag) {
sync_options_1_.tag = "foo";
sync_options_2_.tag = "foo";
// Make the registration periodic.
sync_options_2_.min_interval = 36000;
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_EQ(callback_one_shot_sync_registration_->options()->tag, "foo");
EXPECT_TRUE(
sync_options_1_.Equals(*callback_one_shot_sync_registration_->options()));
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_TRUE(GetRegistration(sync_options_2_));
EXPECT_TRUE(
sync_options_2_.Equals(*callback_periodic_sync_registration_->options()));
EXPECT_EQ(callback_periodic_sync_registration_->options()->tag, "foo");
}
TEST_F(BackgroundSyncManagerTest, FiresOnRegistration) {
InitSyncEventTest();
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, PeriodicSyncFiresWhenExpected) {
InitPeriodicSyncEventTest();
int thirteen_hours_ms = 13 * 60 * 60 * 1000;
sync_options_2_.min_interval = thirteen_hours_ms;
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_EQ(0, periodic_sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_2_));
// Advance clock.
test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
FireReadyEvents();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, periodic_sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptFails) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
// Reregister the event mid-sync
EXPECT_TRUE(Register(sync_options_1_));
// The first sync attempt fails.
ASSERT_TRUE(sync_fired_callback_);
std::move(sync_fired_callback_)
.Run(blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected);
base::RunLoop().RunUntilIdle();
// It should fire again since it was reregistered mid-sync.
EXPECT_TRUE(GetRegistration(sync_options_1_));
ASSERT_TRUE(sync_fired_callback_);
std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptSucceeds) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
// Reregister the event mid-sync
EXPECT_TRUE(Register(sync_options_1_));
// The first sync event succeeds.
ASSERT_TRUE(sync_fired_callback_);
std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
// It should fire again since it was reregistered mid-sync.
EXPECT_TRUE(GetRegistration(sync_options_1_));
ASSERT_TRUE(sync_fired_callback_);
std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, OverwritePendingRegistration) {
InitFailedSyncEventTest();
// Prevent the first sync from running so that it stays in a pending state.
SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
// Overwrite the first sync. It should still be pending.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
// Verify that it only gets to run once.
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, DisableWhilePending) {
InitDelayedSyncEventTest();
SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
// Corrupting the backend should result in the manager disabling itself on the
// next operation.
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_FALSE(Register(sync_options_2_));
test_background_sync_manager_->set_corrupt_backend(false);
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, sync_events_called_);
}
TEST_F(BackgroundSyncManagerTest, DisableWhileFiring) {
InitDelayedSyncEventTest();
// Register a one-shot that pauses mid-fire.
RegisterAndVerifySyncEventDelayed(sync_options_1_);
// Corrupting the backend should result in the manager disabling itself on the
// next operation.
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_FALSE(Register(sync_options_2_));
test_background_sync_manager_->set_corrupt_backend(false);
// Successfully complete the firing event. We can't verify that it actually
// completed but at least we can test that it doesn't crash.
ASSERT_TRUE(sync_fired_callback_);
std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
}
TEST_F(BackgroundSyncManagerTest, FiresOnNetworkChange) {
InitSyncEventTest();
SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_1_));
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, MultipleRegistrationsFireOnNetworkChange) {
InitSyncEventTest();
SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_2_));
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
EXPECT_EQ(2, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_FALSE(GetRegistration(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, FiresOnManagerRestart) {
InitSyncEventTest();
// Initially the event won't run because there is no network.
SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_1_));
// Simulate closing the browser.
DeleteBackgroundSyncManager();
// The next time the manager is started, the network is good.
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
SetupBackgroundSyncManager();
InitSyncEventTest();
// The event should have fired.
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, FailedRegistrationShouldBeRemoved) {
InitFailedSyncEventTest();
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, FailedRegistrationReregisteredAndFires) {
InitFailedSyncEventTest();
// The initial sync event fails.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
InitSyncEventTest();
// Reregistering should cause the sync event to fire again, this time
// succeeding.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(2, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, DelayMidSync) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
// Finish firing the event and verify that the registration is removed.
ASSERT_TRUE(sync_fired_callback_);
std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, BadBackendMidSync) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
test_background_sync_manager_->set_corrupt_backend(true);
ASSERT_TRUE(sync_fired_callback_);
std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
// The backend should now be disabled because it couldn't unregister the
// one-shot.
EXPECT_FALSE(Register(sync_options_2_));
EXPECT_FALSE(
RegisterWithServiceWorkerId(sw_registration_id_2_, sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, UnregisterServiceWorkerMidSync) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
UnregisterServiceWorker(sw_registration_id_1_);
ASSERT_TRUE(sync_fired_callback_);
std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
// The backend isn't disabled, but the first service worker registration is
// gone.
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_FALSE(Register(sync_options_1_));
EXPECT_TRUE(
RegisterWithServiceWorkerId(sw_registration_id_2_, sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, KillManagerMidSync) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
// Create a new manager which should fire the sync again on init.
SetupBackgroundSyncManager();
InitSyncEventTest();
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_EQ(2, sync_events_called_);
}
TEST_F(BackgroundSyncManagerTest, RegisterWithoutMainFrame) {
test_background_sync_manager_->set_has_main_frame_provider_host(false);
EXPECT_FALSE(Register(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, RegisterExistingWithoutMainFrame) {
EXPECT_TRUE(Register(sync_options_1_));
test_background_sync_manager_->set_has_main_frame_provider_host(false);
EXPECT_FALSE(Register(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, DefaultParameters) {
*GetController()->background_sync_parameters() = BackgroundSyncParameters();
// Restart the BackgroundSyncManager so that it updates its parameters.
SetupBackgroundSyncManager();
EXPECT_EQ(BackgroundSyncParameters(),
*test_background_sync_manager_->background_sync_parameters());
}
TEST_F(BackgroundSyncManagerTest, OverrideParameters) {
BackgroundSyncParameters* parameters =
GetController()->background_sync_parameters();
parameters->disable = true;
parameters->max_sync_attempts = 100;
parameters->initial_retry_delay = base::TimeDelta::FromMinutes(200);
parameters->retry_delay_factor = 300;
parameters->min_sync_recovery_time = base::TimeDelta::FromMinutes(400);
parameters->max_sync_event_duration = base::TimeDelta::FromMinutes(500);
// Restart the BackgroundSyncManager so that it updates its parameters.
SetupBackgroundSyncManager();
// Check that the manager is disabled
EXPECT_FALSE(Register(sync_options_1_));
EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
one_shot_sync_callback_status_);
const BackgroundSyncParameters* manager_parameters =
test_background_sync_manager_->background_sync_parameters();
EXPECT_EQ(*parameters, *manager_parameters);
}
TEST_F(BackgroundSyncManagerTest, DisablingFromControllerKeepsRegistrations) {
EXPECT_TRUE(Register(sync_options_1_));
BackgroundSyncParameters* parameters =
GetController()->background_sync_parameters();
parameters->disable = true;
// Restart the BackgroundSyncManager so that it updates its parameters.
SetupBackgroundSyncManager();
EXPECT_FALSE(GetRegistration(sync_options_1_)); // fails because disabled
// Reenable the BackgroundSyncManager on next launch
parameters->disable = false;
// Restart the BackgroundSyncManager so that it updates its parameters.
SetupBackgroundSyncManager();
EXPECT_TRUE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, DisabledPermanently) {
BackgroundSyncParameters* parameters =
GetController()->background_sync_parameters();
parameters->disable = true;
// Restart the BackgroundSyncManager so that it updates its parameters.
SetupBackgroundSyncManager();
// Check that the manager is disabled
EXPECT_FALSE(Register(sync_options_1_));
EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
one_shot_sync_callback_status_);
// If the service worker is wiped and the manager is restarted, the manager
// should stay disabled.
DeleteServiceWorkerAndStartOver();
RegisterServiceWorkers();
EXPECT_FALSE(Register(sync_options_1_));
EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
one_shot_sync_callback_status_);
}
TEST_F(BackgroundSyncManagerTest, NotifyBackgroundSyncRegistered) {
// Verify that the BackgroundSyncController is informed of registrations.
EXPECT_EQ(0, GetController()->registration_count());
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(1, GetController()->registration_count());
EXPECT_EQ(url::Origin::Create(GURL(kScope1)),
GetController()->registration_origin());
}
TEST_F(BackgroundSyncManagerTest, WakeBrowserCalled) {
SetupBackgroundSyncManager();
InitDelayedSyncEventTest();
// The BackgroundSyncManager should declare in initialization
// that it doesn't need to be woken up since it has no registrations.
EXPECT_LT(0, GetController()->run_in_background_count());
EXPECT_FALSE(test_background_sync_manager_->IsBrowserWakeupScheduled());
SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_FALSE(test_background_sync_manager_->IsBrowserWakeupScheduled());
// Register a one-shot but it can't fire due to lack of network, wake up is
// required.
Register(sync_options_1_);
EXPECT_TRUE(test_background_sync_manager_->IsBrowserWakeupScheduled());
// Start the event but it will pause mid-sync due to
// InitDelayedSyncEventTest() above.
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
EXPECT_TRUE(test_background_sync_manager_->IsBrowserWakeupScheduled());
EXPECT_TRUE(test_background_sync_manager_->EqualsSoonestOneShotWakeupDelta(
test_background_sync_manager_->background_sync_parameters()
->min_sync_recovery_time));
// Finish the sync.
ASSERT_TRUE(sync_fired_callback_);
std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(test_background_sync_manager_->IsBrowserWakeupScheduled());
}
TEST_F(BackgroundSyncManagerTest, GetSoonestWakeupDeltaConsidersSyncType) {
// Register a one-shot sync.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
// Also register a Periodic sync.
sync_options_2_.min_interval = 13 * 60 * 60 * 1000;
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_TRUE(GetRegistration(sync_options_2_));
EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta());
EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC),
base::TimeDelta::FromMilliseconds(sync_options_2_.min_interval));
}
TEST_F(BackgroundSyncManagerTest, SoonestWakeupDeltaDecreasesWithTime) {
// Register a periodic sync.
int thirteen_hours_ms = 13 * 60 * 60 * 1000;
sync_options_2_.min_interval = thirteen_hours_ms * 4;
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_TRUE(GetRegistration(sync_options_2_));
base::TimeDelta soonest_wakeup_delta_1 =
GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC);
test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
base::TimeDelta soonest_wakeup_delta_2 =
GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC);
test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
base::TimeDelta soonest_wakeup_delta_3 =
GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC);
test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
base::TimeDelta soonest_wakeup_delta_4 =
GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC);
EXPECT_GT(soonest_wakeup_delta_1, soonest_wakeup_delta_2);
EXPECT_GT(soonest_wakeup_delta_2, soonest_wakeup_delta_3);
EXPECT_GT(soonest_wakeup_delta_3, soonest_wakeup_delta_4);
}
TEST_F(BackgroundSyncManagerTest, OneAttempt) {
SetMaxSyncAttemptsAndRestartManager(1);
InitFailedSyncEventTest();
// It should permanently fail after failing once.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, TwoAttempts) {
SetMaxSyncAttemptsAndRestartManager(2);
InitFailedSyncEventTest();
// The first run will fail but it will setup a timer to try again.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(test_background_sync_manager_->IsDelayedTaskScheduled());
// Make sure the delay is reasonable.
EXPECT_LT(base::TimeDelta::FromMinutes(1),
test_background_sync_manager_->delayed_task_delta());
EXPECT_GT(base::TimeDelta::FromHours(1),
test_background_sync_manager_->delayed_task_delta());
// Fire again and this time it should permanently fail.
test_clock_.Advance(test_background_sync_manager_->delayed_task_delta());
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, ThreeAttempts) {
SetMaxSyncAttemptsAndRestartManager(3);
InitFailedSyncEventTest();
// The first run will fail but it will setup a timer to try again.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(test_background_sync_manager_->IsDelayedTaskScheduled());
// The second run will fail but it will setup a timer to try again.
base::TimeDelta first_delta =
test_background_sync_manager_->delayed_task_delta();
test_clock_.Advance(test_background_sync_manager_->delayed_task_delta());
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(GetRegistration(sync_options_1_));
// Verify that the delta grows for each attempt.
EXPECT_LT(first_delta, test_background_sync_manager_->delayed_task_delta());
// The third run will permanently fail.
test_clock_.Advance(test_background_sync_manager_->delayed_task_delta());
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, WaitsFullDelayTime) {
SetMaxSyncAttemptsAndRestartManager(2);
InitFailedSyncEventTest();
// The first run will fail but it will setup a timer to try again.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(test_background_sync_manager_->IsDelayedTaskScheduled());
// Fire again one second before it's ready to retry. Expect it to reschedule
// the delay timer for one more second.
test_clock_.Advance(test_background_sync_manager_->delayed_task_delta() -
base::TimeDelta::FromSeconds(1));
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_EQ(base::TimeDelta::FromSeconds(1),
test_background_sync_manager_->delayed_task_delta());
// Fire one second later and it should fail permanently.
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, RetryOnBrowserRestart) {
SetMaxSyncAttemptsAndRestartManager(2);
InitFailedSyncEventTest();
// The first run will fail but it will setup a timer to try again.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
// Simulate restarting the browser after sufficient time has passed.
base::TimeDelta delta = test_background_sync_manager_->delayed_task_delta();
CreateBackgroundSyncManager();
InitFailedSyncEventTest();
test_clock_.Advance(delta);
InitBackgroundSyncManager();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, RescheduleOnBrowserRestart) {
SetMaxSyncAttemptsAndRestartManager(2);
InitFailedSyncEventTest();
// The first run will fail but it will setup a timer to try again.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
// Simulate restarting the browser before the retry timer has expired.
base::TimeDelta delta = test_background_sync_manager_->delayed_task_delta();
CreateBackgroundSyncManager();
InitFailedSyncEventTest();
test_clock_.Advance(delta - base::TimeDelta::FromSeconds(1));
InitBackgroundSyncManager();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_EQ(base::TimeDelta::FromSeconds(1),
test_background_sync_manager_->delayed_task_delta());
}
TEST_F(BackgroundSyncManagerTest, RetryIfClosedMidSync) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
// The time delta is the recovery timer.
base::TimeDelta delta = test_background_sync_manager_->delayed_task_delta();
// Simulate restarting the browser after the recovery time, the event should
// fire once and then fail permanently.
CreateBackgroundSyncManager();
InitFailedSyncEventTest();
test_clock_.Advance(delta);
InitBackgroundSyncManager();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, AllTestsEventuallyFire) {
SetMaxSyncAttemptsAndRestartManager(3);
InitFailedSyncEventTest();
// The first run will fail but it will setup a timer to try again.
EXPECT_TRUE(Register(sync_options_1_));
// Run it a second time.
test_clock_.Advance(test_background_sync_manager_->delayed_task_delta());
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
base::TimeDelta delay_delta =
test_background_sync_manager_->delayed_task_delta();
// Create a second registration, which will fail and setup a timer.
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_GT(delay_delta, test_background_sync_manager_->delayed_task_delta());
while (test_background_sync_manager_->IsDelayedTaskScheduled()) {
test_clock_.Advance(test_background_sync_manager_->delayed_task_delta());
test_background_sync_manager_->RunDelayedTask();
EXPECT_FALSE(test_background_sync_manager_->IsDelayedTaskScheduled());
base::RunLoop().RunUntilIdle();
}
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_FALSE(GetRegistration(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, LastChance) {
SetMaxSyncAttemptsAndRestartManager(2);
InitFailedSyncEventTest();
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_FALSE(test_background_sync_manager_->last_chance());
EXPECT_TRUE(GetRegistration(sync_options_1_));
// Run it again.
test_clock_.Advance(test_background_sync_manager_->delayed_task_delta());
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_TRUE(test_background_sync_manager_->last_chance());
}
TEST_F(BackgroundSyncManagerTest, EmulateOfflineSingleClient) {
InitSyncEventTest();
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
true);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_1_));
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
false);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_EQ(2, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, EmulateOfflineMultipleClients) {
InitSyncEventTest();
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
true);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_1_));
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
true);
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_2_));
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
false);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_2_));
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
false);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
EXPECT_FALSE(GetRegistration(sync_options_2_));
}
static void EmulateDispatchSyncEventCallback(
bool* was_called,
blink::ServiceWorkerStatusCode* code,
blink::ServiceWorkerStatusCode status_code) {
*was_called = true;
*code = status_code;
}
TEST_F(BackgroundSyncManagerTest, EmulateDispatchSyncEvent) {
InitSyncEventTest();
bool was_called = false;
blink::ServiceWorkerStatusCode code =
blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected;
background_sync_manager_->EmulateDispatchSyncEvent(
"emulated_tag", sw_registration_1_->active_version(), false,
base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, code);
EXPECT_EQ(1, sync_events_called_);
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
true);
was_called = false;
background_sync_manager_->EmulateDispatchSyncEvent(
"emulated_tag", sw_registration_1_->active_version(), false,
base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, code);
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
false);
SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
was_called = false;
code = blink::ServiceWorkerStatusCode::kOk;
background_sync_manager_->EmulateDispatchSyncEvent(
"emulated_tag", sw_registration_1_->active_version(), false,
base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, code);
SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
was_called = false;
background_sync_manager_->EmulateDispatchSyncEvent(
"emulated_tag", sw_registration_1_->active_version(), false,
base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, code);
EXPECT_EQ(2, sync_events_called_);
}
TEST_F(BackgroundSyncManagerTest, DispatchPeriodicSyncEvent) {
InitPeriodicSyncEventTest();
EXPECT_TRUE(AreOptionConditionsMet());
bool was_called = false;
blink::ServiceWorkerStatusCode code =
blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected;
test_background_sync_manager_->DispatchPeriodicSyncEvent(
"test_tag", sw_registration_1_->active_version(),
base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, code);
EXPECT_EQ(1, periodic_sync_events_called_);
}
TEST_F(BackgroundSyncManagerTest, EventsLoggedForRegistration) {
// Note that the dispatch is mocked out, so those events are not registered
// by these tests.
storage_partition_impl_->GetDevToolsBackgroundServicesContext()
->StartRecording(devtools::proto::BACKGROUND_SYNC);
SetMaxSyncAttemptsAndRestartManager(3);
InitFailedSyncEventTest();
{
// We expect a "Registered" event and a "Fail" event.
EXPECT_CALL(*this, OnEventReceived(_)).Times(2);
// The first run will fail but it will setup a timer to try again.
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(test_background_sync_manager_->IsDelayedTaskScheduled());
}
test_clock_.Advance(test_background_sync_manager_->delayed_task_delta());
{
// Expect another "Fail" event.
EXPECT_CALL(*this, OnEventReceived(_)).Times(1);
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(GetRegistration(sync_options_1_));
}
// The event should succeed now.
InitSyncEventTest();
test_clock_.Advance(test_background_sync_manager_->delayed_task_delta());
{
// Expect a "Completion" event.
EXPECT_CALL(*this, OnEventReceived(_)).Times(1);
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
}
TEST_F(BackgroundSyncManagerTest, UkmRecordedAtCompletion) {
InitSyncEventTest();
{
base::HistogramTester histogram_tester;
EXPECT_TRUE(Register(sync_options_1_));
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_1_));
histogram_tester.ExpectBucketCount(
"BackgroundSync.Registration.OneShot.EventSucceededAtCompletion", true,
1);
histogram_tester.ExpectBucketCount(
"BackgroundSync.Registration.OneShot.NumAttemptsForSuccessfulEvent", 1,
1);
}
SetMaxSyncAttemptsAndRestartManager(1);
InitFailedSyncEventTest();
{
base::HistogramTester histogram_tester;
EXPECT_TRUE(Register(sync_options_2_));
test_background_sync_manager_->RunDelayedTask();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_2_));
histogram_tester.ExpectBucketCount(
"BackgroundSync.Registration.OneShot.EventSucceededAtCompletion", false,
1);
histogram_tester.ExpectBucketCount(
"BackgroundSync.Registration.OneShot.NumAttemptsForSuccessfulEvent", 1,
0);
}
}
} // namespace content