blob: a6dd4b947afd9ac0f50f8a1ab94c8c0a2898f38b [file] [log] [blame]
// Copyright 2019 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_launcher.h"
#include <algorithm>
#include <utility>
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/public/browser/background_sync_context.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#if defined(OS_ANDROID)
#include "base/android/callback_android.h"
#endif
namespace content {
namespace {
base::LazyInstance<BackgroundSyncLauncher>::DestructorAtExit
g_background_sync_launcher = LAZY_INSTANCE_INITIALIZER;
unsigned int GetStoragePartitionCount(BrowserContext* browser_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(browser_context);
int num_partitions = 0;
BrowserContext::ForEachStoragePartition(
browser_context,
base::BindRepeating(
[](int* num_partitions, StoragePartition* storage_partition) {
(*num_partitions)++;
},
&num_partitions));
// It's valid for a profile to not have any storage partitions. This DCHECK
// is to ensure that we're not waking up Chrome for no reason, because that's
// expensive and unnecessary.
DCHECK(num_partitions);
return num_partitions;
}
} // namespace
// static
BackgroundSyncLauncher* BackgroundSyncLauncher::Get() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return g_background_sync_launcher.Pointer();
}
// static
void BackgroundSyncLauncher::GetSoonestWakeupDelta(
BrowserContext* browser_context,
base::OnceCallback<void(base::TimeDelta)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
Get()->GetSoonestWakeupDeltaImpl(browser_context, std::move(callback));
}
// static
#if defined(OS_ANDROID)
void BackgroundSyncLauncher::FireBackgroundSyncEvents(
BrowserContext* browser_context,
const base::android::JavaParamRef<jobject>& j_runnable) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(browser_context);
base::RepeatingClosure done_closure = base::BarrierClosure(
GetStoragePartitionCount(browser_context),
base::BindOnce(base::android::RunRunnableAndroid,
base::android::ScopedJavaGlobalRef<jobject>(j_runnable)));
BrowserContext::ForEachStoragePartition(
browser_context,
base::BindRepeating(
[](base::OnceClosure done_closure,
StoragePartition* storage_partition) {
BackgroundSyncContext* sync_context =
storage_partition->GetBackgroundSyncContext();
DCHECK(sync_context);
sync_context->FireBackgroundSyncEvents(std::move(done_closure));
},
std::move(done_closure)));
}
#endif
BackgroundSyncLauncher::BackgroundSyncLauncher() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
BackgroundSyncLauncher::~BackgroundSyncLauncher() = default;
void BackgroundSyncLauncher::GetSoonestWakeupDeltaImpl(
BrowserContext* browser_context,
base::OnceCallback<void(base::TimeDelta)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::RepeatingClosure done_closure = base::BarrierClosure(
GetStoragePartitionCount(browser_context),
base::BindOnce(&BackgroundSyncLauncher::SendSoonestWakeupDelta,
base::Unretained(this), std::move(callback)));
soonest_wakeup_delta_ = base::TimeDelta::Max();
BrowserContext::ForEachStoragePartition(
browser_context,
base::BindRepeating(
&BackgroundSyncLauncher::GetSoonestWakeupDeltaForStoragePartition,
base::Unretained(this), std::move(done_closure)));
}
void BackgroundSyncLauncher::GetSoonestWakeupDeltaForStoragePartition(
base::OnceClosure done_closure,
StoragePartition* storage_partition) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BackgroundSyncContext* sync_context =
storage_partition->GetBackgroundSyncContext();
DCHECK(sync_context);
sync_context->GetSoonestWakeupDelta(base::BindOnce(
[](base::OnceClosure done_closure, base::TimeDelta* soonest_wakeup_delta,
base::TimeDelta wakeup_delta) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
*soonest_wakeup_delta = std::min(*soonest_wakeup_delta, wakeup_delta);
std::move(done_closure).Run();
},
std::move(done_closure), &soonest_wakeup_delta_));
}
void BackgroundSyncLauncher::SendSoonestWakeupDelta(
base::OnceCallback<void(base::TimeDelta)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::move(callback).Run(soonest_wakeup_delta_);
}
} // namespace content