| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/run_loop.h" |
| #include "base/threading/thread_restrictions.h" |
| #include "base/time/time.h" |
| #include "build/build_config.h" |
| #include "components/background_sync/background_sync_controller_impl.h" |
| #include "components/content_settings/core/browser/host_content_settings_map.h" |
| #include "components/content_settings/core/common/content_settings.h" |
| #include "content/public/browser/background_sync_parameters.h" |
| #include "content/public/test/background_sync_test_util.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "net/test/embedded_test_server/http_request.h" |
| #include "net/test/embedded_test_server/http_response.h" |
| #include "weblayer/browser/background_sync/background_sync_controller_factory.h" |
| #include "weblayer/browser/background_sync/background_sync_delegate_impl.h" |
| #include "weblayer/browser/host_content_settings_map_factory.h" |
| #include "weblayer/browser/tab_impl.h" |
| #include "weblayer/shell/browser/shell.h" |
| #include "weblayer/test/weblayer_browser_test.h" |
| #include "weblayer/test/weblayer_browser_test_utils.h" |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| #include "components/keep_alive_registry/keep_alive_registry.h" |
| #include "components/keep_alive_registry/keep_alive_state_observer.h" |
| |
| namespace { |
| class TestKeepAliveStateObserver : public KeepAliveStateObserver { |
| public: |
| TestKeepAliveStateObserver() { |
| KeepAliveRegistry::GetInstance()->AddObserver(this); |
| } |
| |
| ~TestKeepAliveStateObserver() override { |
| KeepAliveRegistry::GetInstance()->RemoveObserver(this); |
| } |
| |
| void OnKeepAliveStateChanged(bool is_keeping_alive) override { |
| if (is_keeping_alive_loop_ && !is_keeping_alive) |
| is_keeping_alive_loop_->Quit(); |
| } |
| |
| void OnKeepAliveRestartStateChanged(bool can_restart) override {} |
| |
| void WaitUntilNoKeepAlives() { |
| if (!KeepAliveRegistry::GetInstance()->IsKeepingAlive()) |
| return; |
| is_keeping_alive_loop_ = std::make_unique<base::RunLoop>(); |
| is_keeping_alive_loop_->Run(); |
| is_keeping_alive_loop_ = nullptr; |
| CHECK(!KeepAliveRegistry::GetInstance()->IsKeepingAlive()); |
| } |
| |
| private: |
| std::unique_ptr<base::RunLoop> is_keeping_alive_loop_; |
| }; |
| } // namespace |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| namespace { |
| const char kExampleUrl[] = "https://www.example.com/"; |
| const char kTag[] = "test_tag"; |
| } // namespace |
| |
| namespace weblayer { |
| |
| class BackgroundSyncBrowserTest : public WebLayerBrowserTest { |
| public: |
| BackgroundSyncBrowserTest() = default; |
| ~BackgroundSyncBrowserTest() override = default; |
| |
| void SetUpOnMainThread() override { |
| sync_event_received_ = std::make_unique<base::RunLoop>(); |
| content::background_sync_test_util::SetIgnoreNetworkChanges( |
| /* ignore= */ true); |
| |
| https_server_ = std::make_unique<net::EmbeddedTestServer>( |
| net::EmbeddedTestServer::TYPE_HTTPS); |
| https_server_->RegisterRequestHandler(base::BindRepeating( |
| &BackgroundSyncBrowserTest::HandleRequest, base::Unretained(this))); |
| https_server_->AddDefaultHandlers( |
| base::FilePath(FILE_PATH_LITERAL("weblayer/test/data"))); |
| ASSERT_TRUE(https_server_->Start()); |
| } |
| |
| // Intercepts all requests. |
| std::unique_ptr<net::test_server::HttpResponse> HandleRequest( |
| const net::test_server::HttpRequest& request) { |
| if (request.GetURL().query() == "syncreceived") { |
| if (sync_event_received_) |
| sync_event_received_->Quit(); |
| } |
| |
| // The default handlers will take care of this request. |
| return nullptr; |
| } |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| void PostRunTestOnMainThread() override { |
| keep_alive_observer_.WaitUntilNoKeepAlives(); |
| WebLayerBrowserTest::PostRunTestOnMainThread(); |
| } |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| protected: |
| content::WebContents* web_contents() { |
| return static_cast<TabImpl*>(shell()->tab())->web_contents(); |
| } |
| |
| std::unique_ptr<base::RunLoop> sync_event_received_; |
| std::unique_ptr<net::EmbeddedTestServer> https_server_; |
| #if !BUILDFLAG(IS_ANDROID) |
| TestKeepAliveStateObserver keep_alive_observer_; |
| #endif // !BUILDFLAG(IS_ANDROID) |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, GetBackgroundSyncController) { |
| EXPECT_TRUE(BackgroundSyncControllerFactory::GetForBrowserContext( |
| GetBrowserContext())); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, ZeroSiteEngagementPenalty) { |
| // TODO(crbug.com/1091211): Update when we add support for Periodic Background |
| // Sync. |
| auto* controller = BackgroundSyncControllerFactory::GetForBrowserContext( |
| GetBrowserContext()); |
| ASSERT_TRUE(controller); |
| |
| url::Origin origin = url::Origin::Create(GURL(kExampleUrl)); |
| content::BackgroundSyncRegistration registration; |
| registration.set_origin(origin); |
| |
| // min interval >=0 implies Periodic Background Sync. |
| blink::mojom::SyncRegistrationOptions options( |
| kTag, |
| /* min_interval= */ base::Hours(12).InMilliseconds()); |
| *registration.options() = std::move(options); |
| // First attempt. |
| registration.set_num_attempts(0); |
| |
| content::BackgroundSyncParameters parameters; |
| |
| base::TimeDelta delay = controller->GetNextEventDelay( |
| registration, ¶meters, |
| /* time_till_soonest_scheduled_event_for_origin= */ |
| base::TimeDelta::Max()); |
| EXPECT_EQ(delay, base::TimeDelta::Max()); |
| } |
| |
| #if BUILDFLAG(IS_ANDROID) |
| // TODO(crbug.com/1154332): Fix flaky test. |
| IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, |
| DISABLED_BackgroundSyncNotDisabled) { |
| auto* controller = BackgroundSyncControllerFactory::GetForBrowserContext( |
| GetBrowserContext()); |
| ASSERT_TRUE(controller); |
| |
| // TODO(crbug.com/1087486, 1091211): Update logic here if we need to support |
| // Android L when we add browser wakeup logic. |
| content::BackgroundSyncParameters parameters; |
| controller->GetParameterOverrides(¶meters); |
| EXPECT_FALSE(parameters.disable); |
| } |
| #endif // defined (OS_ANDROID) |
| |
| IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, ContentSettings) { |
| auto* browser_context = GetBrowserContext(); |
| auto* controller = |
| BackgroundSyncControllerFactory::GetForBrowserContext(browser_context); |
| ASSERT_TRUE(controller); |
| |
| url::Origin origin = url::Origin::Create(GURL(kExampleUrl)); |
| controller->AddToTrackedOrigins(origin); |
| ASSERT_TRUE(controller->IsOriginTracked(origin)); |
| |
| auto* host_content_settings_map = |
| HostContentSettingsMapFactory::GetForBrowserContext(browser_context); |
| ASSERT_TRUE(host_content_settings_map); |
| |
| host_content_settings_map->SetContentSettingDefaultScope( |
| /* primary_url= */ GURL(kExampleUrl), |
| /* secondary_url= */ GURL(kExampleUrl), |
| ContentSettingsType::BACKGROUND_SYNC, CONTENT_SETTING_BLOCK); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_FALSE(controller->IsOriginTracked(origin)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, NormalProfile) { |
| // TODO(crbug.com/1087486, 1091211): Make this use |
| // BackgroundSyncController::ScheduleBrowserWakeup() once we support waking |
| // the browser up. |
| auto delegate = |
| std::make_unique<BackgroundSyncDelegateImpl>(GetBrowserContext()); |
| ASSERT_TRUE(delegate); |
| EXPECT_FALSE(delegate->IsProfileOffTheRecord()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, SyncEventFired) { |
| content::background_sync_test_util::SetOnline(web_contents(), false); |
| NavigateAndWaitForCompletion( |
| https_server_->GetURL("/background_sync_browsertest.html"), shell()); |
| content::background_sync_test_util::SetOnline(web_contents(), true); |
| sync_event_received_->Run(); |
| } |
| |
| class IncognitoBackgroundSyncBrowserTest : public BackgroundSyncBrowserTest { |
| public: |
| IncognitoBackgroundSyncBrowserTest() { SetShellStartsInIncognitoMode(); } |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(IncognitoBackgroundSyncBrowserTest, |
| OffTheRecordProfile) { |
| base::ScopedAllowBlockingForTesting allow_blocking; |
| |
| // TODO(crbug.com/1087486, 1091211): Make this use |
| // BackgroundSyncController::ScheduleBrowserWakeup() once we support waking |
| // the browser up. |
| auto delegate = |
| std::make_unique<BackgroundSyncDelegateImpl>(GetBrowserContext()); |
| EXPECT_TRUE(delegate->IsProfileOffTheRecord()); |
| } |
| |
| } // namespace weblayer |