blob: 7136e261e7f8eb4cf2e320447c2eb123b65e1bc6 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// 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_launcher.h"
#include <map>
#include <vector>
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/content_export.h"
#include "content/public/browser/background_sync_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/run_loop.h"
#endif
namespace content {
namespace {
const char kUrl_1[] = "https://example.com";
const char kUrl_2[] = "https://whereswaldo.com";
class TestBrowserClient : public ContentBrowserClient {
public:
TestBrowserClient() = default;
~TestBrowserClient() override = default;
StoragePartitionConfig GetStoragePartitionConfigForSite(
BrowserContext* browser_context,
const GURL& site) override {
DCHECK(browser_context);
auto partition_num = base::NumberToString(++partition_count_);
return StoragePartitionConfig::Create(
browser_context, std::string("PartitionDomain") + partition_num,
std::string("Partition") + partition_num, false /* in_memory */);
}
private:
int partition_count_ = 0;
};
} // namespace
class BackgroundSyncLauncherTest : public testing::Test {
public:
BackgroundSyncLauncherTest()
: task_environment_(BrowserTaskEnvironment::MainThreadType::UI) {}
void SetUpBrowserContext(const std::vector<GURL>& urls,
blink::mojom::BackgroundSyncType sync_type,
const std::map<GURL, int>& wakeup_deltas = {}) {
DCHECK(!urls.empty());
for (const auto& url : urls) {
auto* storage_partition =
test_browser_context_.GetStoragePartitionForUrl(url);
auto iter = wakeup_deltas.find(url);
if (iter == wakeup_deltas.end())
continue;
static_cast<StoragePartitionImpl*>(storage_partition)
->GetBackgroundSyncContext()
->set_wakeup_delta_for_testing(sync_type,
base::Milliseconds(iter->second));
}
}
void SetUp() override {
original_client_ = SetBrowserClientForTesting(&browser_client_);
}
void TearDown() override { SetBrowserClientForTesting(original_client_); }
base::TimeDelta GetSoonestWakeupDelta(
blink::mojom::BackgroundSyncType sync_type) {
return BackgroundSyncLauncher::GetSoonestWakeupDelta(
sync_type, &test_browser_context_);
}
#if BUILDFLAG(IS_ANDROID)
void FireBackgroundSyncEventsForAllPartitions() {
num_invocations_fire_background_sync_events_ = 0;
auto done_closure = base::BindLambdaForTesting(
[&]() { num_invocations_fire_background_sync_events_++; });
test_browser_context_.ForEachLoadedStoragePartition(
[&](StoragePartition* storage_partition) {
BackgroundSyncContext* sync_context =
storage_partition->GetBackgroundSyncContext();
sync_context->FireBackgroundSyncEvents(
blink::mojom::BackgroundSyncType::ONE_SHOT, done_closure);
});
task_environment_.RunUntilIdle();
}
int NumInvocationsOfFireBackgroundSyncEvents() {
return num_invocations_fire_background_sync_events_;
}
#endif
protected:
void DidFireBackgroundSyncEvents() {
num_invocations_fire_background_sync_events_++;
}
BrowserTaskEnvironment task_environment_;
TestBrowserClient browser_client_;
raw_ptr<ContentBrowserClient> original_client_;
TestBrowserContext test_browser_context_;
int num_invocations_fire_background_sync_events_ = 0;
};
// Tests that we pick the correct wake up delta for the one-shot Background
// Sync wake up task, across all storage partitions.
TEST_F(BackgroundSyncLauncherTest, CorrectSoonestWakeupDeltaIsPicked) {
std::vector<GURL> urls = {GURL(kUrl_1), GURL(kUrl_2)};
// Add two storage partitions. Verify that we set the soonest wake up delta
// to base::TimeDelta::Max(). This will cause cancellation of the wakeup
// task.
SetUpBrowserContext(urls, blink::mojom::BackgroundSyncType::ONE_SHOT);
EXPECT_TRUE(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::ONE_SHOT)
.is_max());
// Add two more storage partitions, this time with wakeup_deltas.
// Verify that we pick the smaller of the two.
int delta_ms = 0;
std::map<GURL, int> wakeup_deltas;
for (const auto& url : urls)
wakeup_deltas[url] = delta_ms += 1000;
SetUpBrowserContext(urls, blink::mojom::BackgroundSyncType::ONE_SHOT,
wakeup_deltas);
EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::ONE_SHOT)
.InMilliseconds(),
1000);
}
// Tests that we pick the correct wake up delta for the correct Background Sync
// wake up task, across all storage partitions.
TEST_F(BackgroundSyncLauncherTest, SoonestWakeupDeltaIsPickedForTheRightTask) {
std::vector<GURL> urls = {GURL(kUrl_1), GURL(kUrl_2)};
// Add two storage partitions with wakeup_deltas, both of the same sync type.
// Verify that we pick the smaller of the two.
int delta_ms = 0;
std::map<GURL, int> wakeup_deltas;
for (const auto& url : urls)
wakeup_deltas[url] = delta_ms += 1000;
SetUpBrowserContext(urls, blink::mojom::BackgroundSyncType::ONE_SHOT,
wakeup_deltas);
EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::ONE_SHOT)
.InMilliseconds(),
1000);
EXPECT_TRUE(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC)
.is_max());
// Add some more wakeup_deltas now for Periodic Background Sync.
wakeup_deltas.clear();
wakeup_deltas[GURL(kUrl_1)] = 500;
SetUpBrowserContext(urls, blink::mojom::BackgroundSyncType::PERIODIC,
wakeup_deltas);
EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::ONE_SHOT)
.InMilliseconds(),
1000);
EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC)
.InMilliseconds(),
500);
}
#if BUILDFLAG(IS_ANDROID)
TEST_F(BackgroundSyncLauncherTest, FireBackgroundSyncEvents) {
std::vector<GURL> urls = {GURL(kUrl_1), GURL(kUrl_2)};
SetUpBrowserContext(urls, blink::mojom::BackgroundSyncType::ONE_SHOT);
ASSERT_NO_FATAL_FAILURE(FireBackgroundSyncEventsForAllPartitions());
EXPECT_EQ(NumInvocationsOfFireBackgroundSyncEvents(), 2);
}
#endif
} // namespace content