| // 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/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/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/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_dispatcher_host.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 "net/base/network_change_notifier.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" |
| #include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| using ::testing::Return; |
| using ::testing::_; |
| |
| const char kPattern1[] = "https://example.com/a"; |
| const char kPattern2[] = "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, |
| ServiceWorkerStatusCode status, |
| const std::string& status_message, |
| int64_t registration_id) { |
| EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status); |
| *called = true; |
| *store_registration_id = registration_id; |
| } |
| |
| void FindServiceWorkerRegistrationCallback( |
| scoped_refptr<ServiceWorkerRegistration>* out_registration, |
| ServiceWorkerStatusCode status, |
| scoped_refptr<ServiceWorkerRegistration> registration) { |
| EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status); |
| *out_registration = std::move(registration); |
| } |
| |
| void UnregisterServiceWorkerCallback(bool* called, |
| ServiceWorkerStatusCode code) { |
| EXPECT_EQ(SERVICE_WORKER_OK, code); |
| *called = true; |
| } |
| |
| } // namespace |
| |
| class BackgroundSyncManagerTest : public testing::Test { |
| public: |
| BackgroundSyncManagerTest() |
| : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), |
| network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) { |
| sync_options_1_.tag = "foo"; |
| sync_options_1_.network_state = NETWORK_STATE_ONLINE; |
| |
| sync_options_2_.tag = "bar"; |
| sync_options_2_.network_state = NETWORK_STATE_ONLINE; |
| } |
| |
| void SetUp() override { |
| // Don't let the tests be confused by the real-world device connectivity |
| background_sync_test_util::SetIgnoreNetworkChangeNotifier(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)); |
| helper_->browser_context()->SetPermissionManager( |
| 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_.reset(new StoragePartitionImpl( |
| helper_->browser_context(), base::FilePath(), nullptr)); |
| 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(); |
| } |
| |
| void TearDown() override { |
| // Restore the network observer functionality for subsequent tests |
| background_sync_test_util::SetIgnoreNetworkChangeNotifier(false); |
| } |
| |
| void RegisterServiceWorkers() { |
| bool called_1 = false; |
| bool called_2 = false; |
| blink::mojom::ServiceWorkerRegistrationOptions options1; |
| options1.scope = GURL(kPattern1); |
| blink::mojom::ServiceWorkerRegistrationOptions options2; |
| options2.scope = GURL(kPattern2); |
| helper_->context()->RegisterServiceWorker( |
| GURL(kScript1), options1, |
| base::AdaptCallbackForRepeating( |
| base::BindOnce(&RegisterServiceWorkerCallback, &called_1, |
| &sw_registration_id_1_))); |
| |
| helper_->context()->RegisterServiceWorker( |
| GURL(kScript2), options2, |
| base::AdaptCallbackForRepeating( |
| 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(kPattern1).GetOrigin(), |
| base::AdaptCallbackForRepeating(base::BindOnce( |
| FindServiceWorkerRegistrationCallback, &sw_registration_1_))); |
| |
| helper_->context_wrapper()->FindReadyRegistrationForId( |
| sw_registration_id_2_, GURL(kPattern1).GetOrigin(), |
| base::AdaptCallbackForRepeating(base::BindOnce( |
| FindServiceWorkerRegistrationCallback, &sw_registration_2_))); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(sw_registration_1_); |
| EXPECT_TRUE(sw_registration_2_); |
| } |
| |
| void SetNetwork(net::NetworkChangeNotifier::ConnectionType connection_type) { |
| net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( |
| connection_type); |
| if (test_background_sync_manager_) { |
| BackgroundSyncNetworkObserver* network_observer = |
| test_background_sync_manager_->GetNetworkObserverForTesting(); |
| network_observer->NotifyManagerIfNetworkChangedForTesting( |
| connection_type); |
| base::RunLoop().RunUntilIdle(); |
| } |
| } |
| |
| void StatusAndRegistrationCallback( |
| bool* was_called, |
| BackgroundSyncStatus status, |
| std::unique_ptr<BackgroundSyncRegistration> registration) { |
| *was_called = true; |
| callback_status_ = status; |
| callback_registration_ = std::move(registration); |
| } |
| |
| void StatusAndRegistrationsCallback( |
| bool* was_called, |
| BackgroundSyncStatus status, |
| std::vector<std::unique_ptr<BackgroundSyncRegistration>> registrations) { |
| *was_called = true; |
| callback_status_ = status; |
| callback_registrations_ = std::move(registrations); |
| } |
| |
| void StatusCallback(bool* was_called, BackgroundSyncStatus status) { |
| *was_called = true; |
| callback_status_ = status; |
| } |
| |
| protected: |
| void CreateBackgroundSyncManager() { |
| test_background_sync_manager_ = |
| new TestBackgroundSyncManager(helper_->context_wrapper()); |
| background_sync_manager_.reset(test_background_sync_manager_); |
| |
| 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(net::NetworkChangeNotifier::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(const BackgroundSyncRegistrationOptions& sync_options) { |
| return RegisterWithServiceWorkerId(sw_registration_id_1_, sync_options); |
| } |
| |
| bool RegisterWithServiceWorkerId( |
| int64_t sw_registration_id, |
| const BackgroundSyncRegistrationOptions& options) { |
| bool was_called = false; |
| background_sync_manager_->Register( |
| sw_registration_id, options, |
| base::BindOnce( |
| &BackgroundSyncManagerTest::StatusAndRegistrationCallback, |
| base::Unretained(this), &was_called)); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(was_called); |
| return callback_status_ == BACKGROUND_SYNC_STATUS_OK; |
| } |
| |
| MockPermissionManager* GetPermissionManager() { |
| return static_cast<MockPermissionManager*>( |
| helper_->browser_context()->GetPermissionManager()); |
| } |
| |
| bool GetRegistration( |
| const BackgroundSyncRegistrationOptions& registration_options) { |
| return GetRegistrationWithServiceWorkerId(sw_registration_id_1_, |
| registration_options); |
| } |
| |
| bool GetRegistrationWithServiceWorkerId( |
| int64_t sw_registration_id, |
| const BackgroundSyncRegistrationOptions& registration_options) { |
| bool was_called = false; |
| background_sync_manager_->GetRegistrations( |
| sw_registration_id, |
| base::BindOnce( |
| &BackgroundSyncManagerTest::StatusAndRegistrationsCallback, |
| base::Unretained(this), &was_called)); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(was_called); |
| |
| if (callback_status_ == BACKGROUND_SYNC_STATUS_OK) { |
| for (auto iter = callback_registrations_.begin(); |
| iter < callback_registrations_.end(); ++iter) { |
| if ((*iter)->options()->tag == registration_options.tag) { |
| // Transfer the matching registration out of the vector into |
| // callback_registration_ for testing. |
| callback_registration_ = std::move(*iter); |
| callback_registrations_.erase(iter); |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| bool GetRegistrations() { |
| return GetRegistrationsWithServiceWorkerId(sw_registration_id_1_); |
| } |
| |
| bool GetRegistrationsWithServiceWorkerId(int64_t sw_registration_id) { |
| bool was_called = false; |
| background_sync_manager_->GetRegistrations( |
| sw_registration_id, |
| base::BindOnce( |
| &BackgroundSyncManagerTest::StatusAndRegistrationsCallback, |
| base::Unretained(this), &was_called)); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(was_called); |
| |
| return callback_status_ == BACKGROUND_SYNC_STATUS_OK; |
| } |
| |
| MockBackgroundSyncController* GetController() { |
| return static_cast<MockBackgroundSyncController*>( |
| helper_->browser_context()->GetBackgroundSyncController()); |
| } |
| |
| void StorageRegistrationCallback(ServiceWorkerStatusCode result) { |
| callback_sw_status_code_ = result; |
| } |
| |
| void UnregisterServiceWorker(uint64_t sw_registration_id) { |
| bool called = false; |
| helper_->context()->UnregisterServiceWorker( |
| PatternForSWId(sw_registration_id), |
| base::AdaptCallbackForRepeating( |
| base::BindOnce(&UnregisterServiceWorkerCallback, &called))); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(called); |
| } |
| |
| GURL PatternForSWId(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(kPattern1) : GURL(kPattern2); |
| } |
| |
| void SetupForSyncEvent( |
| const TestBackgroundSyncManager::DispatchSyncCallback& callback) { |
| test_background_sync_manager_->set_dispatch_sync_callback(callback); |
| SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI); |
| } |
| |
| void DispatchSyncStatusCallback( |
| ServiceWorkerStatusCode status, |
| scoped_refptr<ServiceWorkerVersion> active_version, |
| ServiceWorkerVersion::StatusCallback callback) { |
| sync_events_called_++; |
| std::move(callback).Run(status); |
| } |
| |
| void InitSyncEventTest() { |
| SetupForSyncEvent(base::BindRepeating( |
| &BackgroundSyncManagerTest::DispatchSyncStatusCallback, |
| base::Unretained(this), SERVICE_WORKER_OK)); |
| } |
| |
| void InitFailedSyncEventTest() { |
| SetupForSyncEvent(base::BindRepeating( |
| &BackgroundSyncManagerTest::DispatchSyncStatusCallback, |
| base::Unretained(this), SERVICE_WORKER_ERROR_FAILED)); |
| } |
| |
| 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( |
| const BackgroundSyncRegistrationOptions& sync_options) { |
| int sync_events_called = sync_events_called_; |
| EXPECT_FALSE(sync_fired_callback_); |
| |
| EXPECT_TRUE(Register(sync_options)); |
| |
| EXPECT_EQ(sync_events_called + 1, sync_events_called_); |
| EXPECT_TRUE(GetRegistration(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(); |
| } |
| |
| TestBrowserThreadBundle browser_thread_bundle_; |
| std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; |
| 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_; |
| |
| BackgroundSyncRegistrationOptions sync_options_1_; |
| BackgroundSyncRegistrationOptions sync_options_2_; |
| |
| // Callback values. |
| BackgroundSyncStatus callback_status_ = BACKGROUND_SYNC_STATUS_OK; |
| std::unique_ptr<BackgroundSyncRegistration> callback_registration_; |
| std::vector<std::unique_ptr<BackgroundSyncRegistration>> |
| callback_registrations_; |
| ServiceWorkerStatusCode callback_sw_status_code_ = SERVICE_WORKER_OK; |
| int sync_events_called_ = 0; |
| ServiceWorkerVersion::StatusCallback sync_fired_callback_; |
| }; |
| |
| TEST_F(BackgroundSyncManagerTest, Register) { |
| EXPECT_TRUE(Register(sync_options_1_)); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, RegistrationIntact) { |
| EXPECT_TRUE(Register(sync_options_1_)); |
| EXPECT_STREQ(sync_options_1_.tag.c_str(), |
| callback_registration_->options()->tag.c_str()); |
| EXPECT_TRUE(callback_registration_->IsValid()); |
| } |
| |
| 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, 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, 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(kPattern1).GetOrigin(); |
| MockPermissionManager* mock_permission_manager = GetPermissionManager(); |
| |
| 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_)); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, RegisterPermissionGranted) { |
| GURL expected_origin = GURL(kPattern1).GetOrigin(); |
| MockPermissionManager* mock_permission_manager = GetPermissionManager(); |
| |
| 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_)); |
| } |
| |
| 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(GetRegistrations()); |
| EXPECT_EQ(0u, callback_registrations_.size()); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, GetRegistrationsOne) { |
| EXPECT_TRUE(Register(sync_options_1_)); |
| EXPECT_TRUE(GetRegistrations()); |
| |
| EXPECT_EQ(1u, callback_registrations_.size()); |
| sync_options_1_.Equals(*callback_registrations_[0]->options()); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, GetRegistrationsTwo) { |
| EXPECT_TRUE(Register(sync_options_1_)); |
| EXPECT_TRUE(Register(sync_options_2_)); |
| EXPECT_TRUE(GetRegistrations()); |
| |
| EXPECT_EQ(2u, callback_registrations_.size()); |
| sync_options_1_.Equals(*callback_registrations_[0]->options()); |
| sync_options_2_.Equals(*callback_registrations_[1]->options()); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, GetRegistrationsBadBackend) { |
| EXPECT_TRUE(Register(sync_options_1_)); |
| test_background_sync_manager_->set_corrupt_backend(true); |
| EXPECT_TRUE(GetRegistrations()); |
| EXPECT_FALSE(Register(sync_options_2_)); |
| // Registration should have discovered the bad backend and disabled the |
| // BackgroundSyncManager. |
| EXPECT_FALSE(GetRegistrations()); |
| test_background_sync_manager_->set_corrupt_backend(false); |
| EXPECT_FALSE(GetRegistrations()); |
| } |
| |
| |
| 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, callback_status_); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, RegistrationIncreasesId) { |
| EXPECT_TRUE(Register(sync_options_1_)); |
| BackgroundSyncRegistration::RegistrationId cur_id = |
| callback_registration_->id(); |
| |
| EXPECT_TRUE(GetRegistration(sync_options_1_)); |
| EXPECT_TRUE(Register(sync_options_2_)); |
| EXPECT_LT(cur_id, callback_registration_->id()); |
| } |
| |
| 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(GetRegistrationWithServiceWorkerId(sw_registration_id_1_, |
| sync_options_1_)); |
| EXPECT_FALSE(GetRegistrationWithServiceWorkerId(sw_registration_id_1_, |
| sync_options_2_)); |
| EXPECT_FALSE(GetRegistrationWithServiceWorkerId(sw_registration_id_2_, |
| sync_options_1_)); |
| EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_2_, |
| sync_options_2_)); |
| |
| EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_1_, |
| sync_options_1_)); |
| EXPECT_TRUE(GetRegistrationWithServiceWorkerId(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::AdaptCallbackForRepeating(base::BindOnce( |
| &BackgroundSyncManagerTest::StatusAndRegistrationCallback, |
| base::Unretained(this), ®ister_called))); |
| test_background_sync_manager_->GetRegistrations( |
| sw_registration_id_1_, |
| base::AdaptCallbackForRepeating(base::BindOnce( |
| &BackgroundSyncManagerTest::StatusAndRegistrationsCallback, |
| 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, 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_)); |
| |
| 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::AdaptCallbackForRepeating(base::BindOnce( |
| &BackgroundSyncManagerTest::StatusAndRegistrationCallback, |
| 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, 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, RegistrationEqualsId) { |
| BackgroundSyncRegistration reg_1; |
| BackgroundSyncRegistration reg_2; |
| |
| EXPECT_TRUE(reg_1.Equals(reg_2)); |
| reg_2.set_id(reg_1.id() + 1); |
| EXPECT_TRUE(reg_1.Equals(reg_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, RegistrationEqualsNetworkState) { |
| BackgroundSyncRegistration reg_1; |
| BackgroundSyncRegistration reg_2; |
| EXPECT_TRUE(reg_1.Equals(reg_2)); |
| reg_1.options()->network_state = NETWORK_STATE_ANY; |
| reg_2.options()->network_state = NETWORK_STATE_ONLINE; |
| EXPECT_FALSE(reg_1.Equals(reg_2)); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, StoreAndRetrievePreservesValues) { |
| InitDelayedSyncEventTest(); |
| BackgroundSyncRegistrationOptions options; |
| |
| // Set non-default values for each field. |
| options.tag = "foo"; |
| EXPECT_NE(NETWORK_STATE_AVOID_CELLULAR, options.network_state); |
| options.network_state = NETWORK_STATE_AVOID_CELLULAR; |
| |
| // 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_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_registration_->options())); |
| } |
| |
| 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, 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(SERVICE_WORKER_ERROR_FAILED); |
| 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(SERVICE_WORKER_OK); |
| 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(SERVICE_WORKER_OK); |
| 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(SERVICE_WORKER_OK); |
| 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(net::NetworkChangeNotifier::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(net::NetworkChangeNotifier::CONNECTION_WIFI); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, sync_events_called_); |
| EXPECT_FALSE(GetRegistration(sync_options_1_)); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, DisableWhilePending) { |
| InitDelayedSyncEventTest(); |
| SetNetwork(net::NetworkChangeNotifier::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(net::NetworkChangeNotifier::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(SERVICE_WORKER_OK); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, FiresOnNetworkChange) { |
| InitSyncEventTest(); |
| |
| SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE); |
| EXPECT_TRUE(Register(sync_options_1_)); |
| EXPECT_EQ(0, sync_events_called_); |
| EXPECT_TRUE(GetRegistration(sync_options_1_)); |
| |
| SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, sync_events_called_); |
| EXPECT_FALSE(GetRegistration(sync_options_1_)); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, MultipleRegistrationsFireOnNetworkChange) { |
| InitSyncEventTest(); |
| |
| SetNetwork(net::NetworkChangeNotifier::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(net::NetworkChangeNotifier::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(net::NetworkChangeNotifier::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(net::NetworkChangeNotifier::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(SERVICE_WORKER_OK); |
| 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(SERVICE_WORKER_OK); |
| 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(SERVICE_WORKER_OK); |
| |
| // 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, 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, 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, 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(GURL(kPattern1).GetOrigin().spec(), |
| GetController()->registration_origin().spec()); |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, WakeBrowserCalled) { |
| 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(GetController()->run_in_background_enabled()); |
| |
| SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE); |
| EXPECT_FALSE(GetController()->run_in_background_enabled()); |
| |
| // Register a one-shot but it can't fire due to lack of network, wake up is |
| // required. |
| Register(sync_options_1_); |
| EXPECT_TRUE(GetController()->run_in_background_enabled()); |
| |
| // Start the event but it will pause mid-sync due to |
| // InitDelayedSyncEventTest() above. |
| SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI); |
| EXPECT_TRUE(GetController()->run_in_background_enabled()); |
| EXPECT_EQ(test_background_sync_manager_->background_sync_parameters() |
| ->min_sync_recovery_time, |
| base::TimeDelta::FromMilliseconds( |
| GetController()->run_in_background_min_ms())); |
| |
| // Finish the sync. |
| ASSERT_TRUE(sync_fired_callback_); |
| std::move(sync_fired_callback_).Run(SERVICE_WORKER_OK); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_FALSE(GetController()->run_in_background_enabled()); |
| } |
| |
| 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, |
| ServiceWorkerStatusCode* code, |
| ServiceWorkerStatusCode status_code) { |
| *was_called = true; |
| *code = status_code; |
| } |
| |
| TEST_F(BackgroundSyncManagerTest, EmulateDispatchSyncEvent) { |
| InitSyncEventTest(); |
| bool was_called = false; |
| ServiceWorkerStatusCode code = SERVICE_WORKER_ERROR_MAX_VALUE; |
| 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(SERVICE_WORKER_OK, code); |
| |
| EXPECT_EQ(1, sync_events_called_); |
| |
| background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_, |
| true); |
| |
| was_called = false; |
| code = SERVICE_WORKER_ERROR_MAX_VALUE; |
| 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(SERVICE_WORKER_ERROR_NETWORK, code); |
| |
| background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_, |
| false); |
| |
| SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE); |
| was_called = false; |
| code = SERVICE_WORKER_ERROR_MAX_VALUE; |
| 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(SERVICE_WORKER_ERROR_NETWORK, code); |
| |
| SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI); |
| was_called = false; |
| code = SERVICE_WORKER_ERROR_MAX_VALUE; |
| 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(SERVICE_WORKER_OK, code); |
| |
| EXPECT_EQ(2, sync_events_called_); |
| } |
| } // namespace content |