| // 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), ®ister_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 |