Commit eb39fc23 authored by Mugdha Lakhani's avatar Mugdha Lakhani Committed by Commit Bot

[Background Sync] Move browser wakeup to scheduler.

Before this chance, we were calculating the soonest wakeup_delta across
all storage partitions every time there was a change in state of any
storage partition, to schedule a wakeup task with this delta.

This change builds on the fact that we have running timers representing
delays for each of the storage partitions with active registrations in
the scheduler. I've changed scheduling the wakeup task to a push system.
Each storage partition informs the scheduler of its soonest delay after
there's any change in state. If this requested delay is the smallest of
all the current delays of the timers the scheduler has, it schedules a
wakeup task.

Canceling delayed scheduling causes cancellation of the wakeup task if
none of the storage partitions need it.

The change also removes now unnecessary code.
Unit tests are also added, and integration tests updated.

Bug: 996166
Change-Id: I1e6216ecc7085535a8e0ca0075ddad05085df763
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1834086
Commit-Queue: Mugdha Lakhani <nator@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarRayan Kanso <rayankans@chromium.org>
Auto-Submit: Mugdha Lakhani <nator@chromium.org>
Cr-Commit-Position: refs/heads/master@{#715262}
parent 7a18f0ba
...@@ -11,6 +11,7 @@ import androidx.annotation.IntDef; ...@@ -11,6 +11,7 @@ import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
import org.chromium.base.ObserverList;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask; import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask;
...@@ -26,6 +27,12 @@ import org.chromium.components.background_task_scheduler.TaskInfo; ...@@ -26,6 +27,12 @@ import org.chromium.components.background_task_scheduler.TaskInfo;
* Thread model: This class is to be run on the UI thread only. * Thread model: This class is to be run on the UI thread only.
*/ */
public class BackgroundSyncBackgroundTaskScheduler { public class BackgroundSyncBackgroundTaskScheduler {
/** An observer interface for BackgroundSyncBackgroundTaskScheduler. */
interface Observer {
void oneOffTaskScheduledFor(@BackgroundSyncTask int taskType, long delay);
void oneOffTaskCanceledFor(@BackgroundSyncTask int taskType);
}
/** /**
* Any tasks scheduled using GCMNetworkManager directly to wake up Chrome * Any tasks scheduled using GCMNetworkManager directly to wake up Chrome
* would use this TASK_TAG. We no longer use GCMNetworkManager directly, so * would use this TASK_TAG. We no longer use GCMNetworkManager directly, so
...@@ -59,6 +66,8 @@ public class BackgroundSyncBackgroundTaskScheduler { ...@@ -59,6 +66,8 @@ public class BackgroundSyncBackgroundTaskScheduler {
private static BackgroundSyncBackgroundTaskScheduler sInstance; private static BackgroundSyncBackgroundTaskScheduler sInstance;
private final ObserverList<Observer> mObservers = new ObserverList<>();
@CalledByNative @CalledByNative
public static BackgroundSyncBackgroundTaskScheduler getInstance() { public static BackgroundSyncBackgroundTaskScheduler getInstance() {
if (sInstance == null) sInstance = new BackgroundSyncBackgroundTaskScheduler(); if (sInstance == null) sInstance = new BackgroundSyncBackgroundTaskScheduler();
...@@ -109,6 +118,17 @@ public class BackgroundSyncBackgroundTaskScheduler { ...@@ -109,6 +118,17 @@ public class BackgroundSyncBackgroundTaskScheduler {
} }
} }
/** @param observer The observer to add. */
@VisibleForTesting
public void addObserver(Observer observer) {
mObservers.addObserver(observer);
}
/** @param observer The observer to remove. */
public void removeObserver(Observer observer) {
mObservers.removeObserver(observer);
}
/** /**
* Cancels a Background Sync one-off task, if there's one scheduled. * Cancels a Background Sync one-off task, if there's one scheduled.
* *
...@@ -118,6 +138,10 @@ public class BackgroundSyncBackgroundTaskScheduler { ...@@ -118,6 +138,10 @@ public class BackgroundSyncBackgroundTaskScheduler {
protected void cancelOneOffTask(@BackgroundSyncTask int taskType) { protected void cancelOneOffTask(@BackgroundSyncTask int taskType) {
BackgroundTaskSchedulerFactory.getScheduler().cancel( BackgroundTaskSchedulerFactory.getScheduler().cancel(
ContextUtils.getApplicationContext(), getAppropriateTaskId(taskType)); ContextUtils.getApplicationContext(), getAppropriateTaskId(taskType));
for (Observer observer : mObservers) {
observer.oneOffTaskCanceledFor(taskType);
}
} }
/** /**
...@@ -148,8 +172,14 @@ public class BackgroundSyncBackgroundTaskScheduler { ...@@ -148,8 +172,14 @@ public class BackgroundSyncBackgroundTaskScheduler {
.setExtras(taskExtras) .setExtras(taskExtras)
.build(); .build();
// This will overwrite any existing task with this ID. // This will overwrite any existing task with this ID.
return BackgroundTaskSchedulerFactory.getScheduler().schedule( boolean didSchedule = BackgroundTaskSchedulerFactory.getScheduler().schedule(
ContextUtils.getApplicationContext(), taskInfo); ContextUtils.getApplicationContext(), taskInfo);
for (Observer observer : mObservers) {
observer.oneOffTaskScheduledFor(taskType, minDelayMs);
}
return didSchedule;
} }
/** /**
......
...@@ -4,14 +4,6 @@ ...@@ -4,14 +4,6 @@
package org.chromium.chrome.browser.background_sync; package org.chromium.chrome.browser.background_sync;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.after;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry;
...@@ -23,24 +15,18 @@ import org.junit.Before; ...@@ -23,24 +15,18 @@ import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.chromium.base.ContextUtils;
import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.background_task_scheduler.ChromeBackgroundTaskFactory; import org.chromium.chrome.browser.background_sync.BackgroundSyncBackgroundTaskScheduler.BackgroundSyncTask;
import org.chromium.chrome.browser.externalauth.ExternalAuthUtils; import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.browser.TabTitleObserver; import org.chromium.chrome.test.util.browser.TabTitleObserver;
import org.chromium.chrome.test.util.browser.signin.SigninTestUtil; import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
import org.chromium.components.background_task_scheduler.BackgroundTaskScheduler;
import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory;
import org.chromium.components.background_task_scheduler.TaskInfo;
import org.chromium.content_public.browser.test.NativeLibraryTestRule; import org.chromium.content_public.browser.test.NativeLibraryTestRule;
import org.chromium.content_public.browser.test.util.BackgroundSyncNetworkUtils; import org.chromium.content_public.browser.test.util.BackgroundSyncNetworkUtils;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
...@@ -48,6 +34,8 @@ import org.chromium.net.ConnectionType; ...@@ -48,6 +34,8 @@ import org.chromium.net.ConnectionType;
import org.chromium.net.test.EmbeddedTestServer; import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.net.test.ServerCertificate; import org.chromium.net.test.ServerCertificate;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
/** /**
...@@ -56,9 +44,6 @@ import java.util.concurrent.TimeoutException; ...@@ -56,9 +44,6 @@ import java.util.concurrent.TimeoutException;
@RunWith(ChromeJUnit4ClassRunner.class) @RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public final class BackgroundSyncTest { public final class BackgroundSyncTest {
@Mock
private BackgroundTaskScheduler mTaskScheduler;
@Rule @Rule
public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
new ChromeActivityTestRule<>(ChromeActivity.class); new ChromeActivityTestRule<>(ChromeActivity.class);
...@@ -72,17 +57,15 @@ public final class BackgroundSyncTest { ...@@ -72,17 +57,15 @@ public final class BackgroundSyncTest {
private static final int TITLE_UPDATE_TIMEOUT_SECONDS = (int) scaleTimeout(10); private static final int TITLE_UPDATE_TIMEOUT_SECONDS = (int) scaleTimeout(10);
private static final long WAIT_TIME_MS = scaleTimeout(5000); private static final long WAIT_TIME_MS = scaleTimeout(5000);
private CountDownLatch mScheduleLatch, mCancelLatch;
private BackgroundSyncBackgroundTaskScheduler.Observer mSchedulerObserver;
@Before @Before
public void setUp() throws InterruptedException { public void setUp() throws InterruptedException {
MockitoAnnotations.initMocks(this); addSchedulerObserver();
BackgroundTaskSchedulerFactory.setSchedulerForTesting(mTaskScheduler); // loadNativeLibraryNoBrowserProcess will access AccountManagerFacade, so it should
ChromeBackgroundTaskFactory.setAsDefault();
doReturn(true)
.when(mTaskScheduler)
.schedule(eq(ContextUtils.getApplicationContext()), any(TaskInfo.class));
// loadNativeLibraryAndInitBrowserProcess will access AccountManagerFacade, so it should
// be initialized beforehand. // be initialized beforehand.
SigninTestUtil.setUpAuthForTest(); SigninTestUtil.setUpAuthForTest();
...@@ -108,6 +91,7 @@ public final class BackgroundSyncTest { ...@@ -108,6 +91,7 @@ public final class BackgroundSyncTest {
public void tearDown() { public void tearDown() {
if (mTestServer != null) mTestServer.stopAndDestroyServer(); if (mTestServer != null) mTestServer.stopAndDestroyServer();
SigninTestUtil.tearDownAuthForTest(); SigninTestUtil.tearDownAuthForTest();
BackgroundSyncBackgroundTaskScheduler.getInstance().removeObserver(mSchedulerObserver);
} }
@Test @Test
...@@ -122,25 +106,13 @@ public final class BackgroundSyncTest { ...@@ -122,25 +106,13 @@ public final class BackgroundSyncTest {
// Register Sync. // Register Sync.
runJavaScript("RegisterSyncForTag('tagSucceedsSync');"); runJavaScript("RegisterSyncForTag('tagSucceedsSync');");
assertTitleBecomes("registered sync"); assertTitleBecomes("registered sync");
verify(mTaskScheduler, timeout(WAIT_TIME_MS)) Assert.assertTrue(mScheduleLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
.schedule(eq(ContextUtils.getApplicationContext()),
argThat(taskInfo
-> taskInfo.getBackgroundTaskClass()
== BackgroundSyncBackgroundTask.class));
forceConnectionType(ConnectionType.CONNECTION_WIFI); forceConnectionType(ConnectionType.CONNECTION_WIFI);
assertTitleBecomes("onsync: tagSucceedsSync"); assertTitleBecomes("onsync: tagSucceedsSync");
// Another invocation when all events are firing but haven't completed, to cover the case // Now that sync has completed, browser wakeup should get canceled.
// when the browser is closed mid-event. This one races with the completion of the sync Assert.assertTrue(mCancelLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
// event, and might not happen.
// The wait is to ensure we wait for this invocation to happen, since it happens in
// parallel with dispatching the sync event.
verify(mTaskScheduler, after(WAIT_TIME_MS).atMost(2))
.schedule(eq(ContextUtils.getApplicationContext()),
argThat(taskInfo
-> taskInfo.getBackgroundTaskClass()
== BackgroundSyncBackgroundTask.class));
} }
@Test @Test
...@@ -155,25 +127,11 @@ public final class BackgroundSyncTest { ...@@ -155,25 +127,11 @@ public final class BackgroundSyncTest {
// Register Sync. // Register Sync.
runJavaScript("RegisterSyncForTag('tagFailsSync');"); runJavaScript("RegisterSyncForTag('tagFailsSync');");
assertTitleBecomes("registered sync"); assertTitleBecomes("registered sync");
verify(mTaskScheduler, timeout(WAIT_TIME_MS)) Assert.assertTrue(mScheduleLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
.schedule(eq(ContextUtils.getApplicationContext()),
argThat(taskInfo
-> taskInfo.getBackgroundTaskClass()
== BackgroundSyncBackgroundTask.class));
forceConnectionType(ConnectionType.CONNECTION_WIFI); forceConnectionType(ConnectionType.CONNECTION_WIFI);
// Wait for some time that is less than the retry time period (default 5 minutes). // Browser wakeup must not be canceled.
// One call to schedule wake-up a few minutes after firing the first sync event, to cover Assert.assertFalse(mCancelLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
// our bases if the browser is closed mid-sync. This one races with the completion of the
// sync event, and might not happen.
// Another call to waking up the browser for attempt two after completion of the first
// event. This will always happen.
verify(mTaskScheduler, after(WAIT_TIME_MS).atMost(3))
.schedule(eq(ContextUtils.getApplicationContext()),
argThat(taskInfo
-> taskInfo.getBackgroundTaskClass()
== BackgroundSyncBackgroundTask.class));
} }
/** /**
...@@ -207,4 +165,26 @@ public final class BackgroundSyncTest { ...@@ -207,4 +165,26 @@ public final class BackgroundSyncTest {
/* disabled= */ true); /* disabled= */ true);
}); });
} }
private void addSchedulerObserver() {
mScheduleLatch = new CountDownLatch(1);
mCancelLatch = new CountDownLatch(1);
mSchedulerObserver = new BackgroundSyncBackgroundTaskScheduler.Observer() {
@Override
public void oneOffTaskScheduledFor(@BackgroundSyncTask int taskType, long delay) {
if (taskType == BackgroundSyncTask.ONE_SHOT_SYNC_CHROME_WAKE_UP) {
mScheduleLatch.countDown();
}
}
@Override
public void oneOffTaskCanceledFor(@BackgroundSyncTask int taskType) {
if (taskType == BackgroundSyncTask.ONE_SHOT_SYNC_CHROME_WAKE_UP) {
mCancelLatch.countDown();
}
}
};
BackgroundSyncBackgroundTaskScheduler.getInstance().addObserver(mSchedulerObserver);
}
} }
...@@ -72,17 +72,25 @@ BackgroundSyncLauncherAndroid* BackgroundSyncLauncherAndroid::Get() { ...@@ -72,17 +72,25 @@ BackgroundSyncLauncherAndroid* BackgroundSyncLauncherAndroid::Get() {
} }
// static // static
void BackgroundSyncLauncherAndroid::ScheduleBrowserWakeUp( void BackgroundSyncLauncherAndroid::SetPlayServicesVersionCheckDisabledForTests(
blink::mojom::BackgroundSyncType sync_type) { bool disabled) {
disable_play_services_version_check_for_tests = disabled;
}
// static
void BackgroundSyncLauncherAndroid::ScheduleBrowserWakeUpWithDelay(
blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta delay) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
Get()->ScheduleBrowserWakeUpImpl(sync_type); Get()->ScheduleBrowserWakeUpWithDelayImpl(sync_type, delay);
} }
// static // static
void BackgroundSyncLauncherAndroid::SetPlayServicesVersionCheckDisabledForTests( void BackgroundSyncLauncherAndroid::CancelBrowserWakeup(
bool disabled) { blink::mojom::BackgroundSyncType sync_type) {
disable_play_services_version_check_for_tests = disabled; DCHECK_CURRENTLY_ON(BrowserThread::UI);
Get()->CancelBrowserWakeupImpl(sync_type);
} }
// static // static
...@@ -94,21 +102,7 @@ bool BackgroundSyncLauncherAndroid::ShouldDisableBackgroundSync() { ...@@ -94,21 +102,7 @@ bool BackgroundSyncLauncherAndroid::ShouldDisableBackgroundSync() {
base::android::AttachCurrentThread()); base::android::AttachCurrentThread());
} }
void BackgroundSyncLauncherAndroid::ScheduleBrowserWakeUpImpl( void BackgroundSyncLauncherAndroid::ScheduleBrowserWakeUpWithDelayImpl(
blink::mojom::BackgroundSyncType sync_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* profile = ProfileManager::GetLastUsedProfile();
DCHECK(profile);
content::BackgroundSyncContext::GetSoonestWakeupDeltaAcrossPartitions(
sync_type, profile,
base::BindOnce(&BackgroundSyncLauncherAndroid::
ScheduleBrowserWakeUpWithWakeUpDeltaImpl,
base::Unretained(this), sync_type));
}
void BackgroundSyncLauncherAndroid::ScheduleBrowserWakeUpWithWakeUpDeltaImpl(
blink::mojom::BackgroundSyncType sync_type, blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta soonest_wakeup_delta) { base::TimeDelta soonest_wakeup_delta) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
...@@ -122,6 +116,19 @@ void BackgroundSyncLauncherAndroid::ScheduleBrowserWakeUpWithWakeUpDeltaImpl( ...@@ -122,6 +116,19 @@ void BackgroundSyncLauncherAndroid::ScheduleBrowserWakeUpWithWakeUpDeltaImpl(
min_delay_ms); min_delay_ms);
} }
void BackgroundSyncLauncherAndroid::CancelBrowserWakeupImpl(
blink::mojom::BackgroundSyncType sync_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
JNIEnv* env = base::android::AttachCurrentThread();
// TODO(crbug.com/996166): Add a new method to cancel browser launch.
Java_BackgroundSyncBackgroundTaskScheduler_launchBrowserIfStopped(
env, java_background_sync_background_task_scheduler_launcher_,
GetBackgroundTaskType(sync_type), /* shouldLaunch= */ false,
/* minDelayMs= */ 0);
}
void BackgroundSyncLauncherAndroid::FireBackgroundSyncEvents( void BackgroundSyncLauncherAndroid::FireBackgroundSyncEvents(
blink::mojom::BackgroundSyncType sync_type, blink::mojom::BackgroundSyncType sync_type,
const base::android::JavaParamRef<jobject>& j_runnable) { const base::android::JavaParamRef<jobject>& j_runnable) {
......
...@@ -23,12 +23,17 @@ class BackgroundSyncLauncherAndroid { ...@@ -23,12 +23,17 @@ class BackgroundSyncLauncherAndroid {
public: public:
static BackgroundSyncLauncherAndroid* Get(); static BackgroundSyncLauncherAndroid* Get();
// Calculates the soonest wakeup time across all the storage // Schedules a BackgroundTaskScheduler task for |sync_type| with delay |delay|
// partitions for the non-incognito profile and ensures that the browser // to ensure that the browser is running when the device next goes online
// is running when the device next goes online after that time has passed. // after that time has passed. If |delay| is base::TimeDelta::Max(), the
// If this time is set to base::TimeDelta::Max() across all storage // wake-up task is cancelled.
// partitions, the wake-up task is cancelled. static void ScheduleBrowserWakeUpWithDelay(
static void ScheduleBrowserWakeUp(blink::mojom::BackgroundSyncType sync_type); blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta delay);
// Cancels the BackgroundTaskScheduler task that wakes up the browser to
// process Background Sync registrations of type |sync_type|.
static void CancelBrowserWakeup(blink::mojom::BackgroundSyncType sync_type);
static bool ShouldDisableBackgroundSync(); static bool ShouldDisableBackgroundSync();
...@@ -50,10 +55,10 @@ class BackgroundSyncLauncherAndroid { ...@@ -50,10 +55,10 @@ class BackgroundSyncLauncherAndroid {
BackgroundSyncLauncherAndroid(); BackgroundSyncLauncherAndroid();
~BackgroundSyncLauncherAndroid(); ~BackgroundSyncLauncherAndroid();
void ScheduleBrowserWakeUpImpl(blink::mojom::BackgroundSyncType sync_type); void ScheduleBrowserWakeUpWithDelayImpl(
void ScheduleBrowserWakeUpWithWakeUpDeltaImpl(
blink::mojom::BackgroundSyncType sync_type, blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta soonest_wakeup_delta); base::TimeDelta soonest_wakeup_delta);
void CancelBrowserWakeupImpl(blink::mojom::BackgroundSyncType sync_type);
base::android::ScopedJavaGlobalRef<jobject> base::android::ScopedJavaGlobalRef<jobject>
java_background_sync_background_task_scheduler_launcher_; java_background_sync_background_task_scheduler_launcher_;
......
...@@ -226,7 +226,21 @@ void BackgroundSyncControllerImpl::NotifyPeriodicBackgroundSyncCompleted( ...@@ -226,7 +226,21 @@ void BackgroundSyncControllerImpl::NotifyPeriodicBackgroundSyncCompleted(
origin, status_code, num_attempts, max_attempts); origin, status_code, num_attempts, max_attempts);
} }
void BackgroundSyncControllerImpl::ScheduleBrowserWakeUp( void BackgroundSyncControllerImpl::ScheduleBrowserWakeUpWithDelay(
blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta delay) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (profile_->IsOffTheRecord())
return;
#if defined(OS_ANDROID)
BackgroundSyncLauncherAndroid::ScheduleBrowserWakeUpWithDelay(sync_type,
delay);
#endif
}
void BackgroundSyncControllerImpl::CancelBrowserWakeup(
blink::mojom::BackgroundSyncType sync_type) { blink::mojom::BackgroundSyncType sync_type) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
...@@ -234,7 +248,7 @@ void BackgroundSyncControllerImpl::ScheduleBrowserWakeUp( ...@@ -234,7 +248,7 @@ void BackgroundSyncControllerImpl::ScheduleBrowserWakeUp(
return; return;
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
BackgroundSyncLauncherAndroid::ScheduleBrowserWakeUp(sync_type); BackgroundSyncLauncherAndroid::CancelBrowserWakeup(sync_type);
#endif #endif
} }
......
...@@ -91,8 +91,10 @@ class BackgroundSyncControllerImpl : public content::BackgroundSyncController, ...@@ -91,8 +91,10 @@ class BackgroundSyncControllerImpl : public content::BackgroundSyncController,
blink::ServiceWorkerStatusCode status_code, blink::ServiceWorkerStatusCode status_code,
int num_attempts, int num_attempts,
int max_attempts) override; int max_attempts) override;
void ScheduleBrowserWakeUp( void ScheduleBrowserWakeUpWithDelay(
blink::mojom::BackgroundSyncType sync_type) override; blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta delay) override;
void CancelBrowserWakeup(blink::mojom::BackgroundSyncType sync_type) override;
base::TimeDelta GetNextEventDelay( base::TimeDelta GetNextEventDelay(
const content::BackgroundSyncRegistration& registration, const content::BackgroundSyncRegistration& registration,
......
...@@ -76,12 +76,6 @@ class BackgroundSyncProxy::Core { ...@@ -76,12 +76,6 @@ class BackgroundSyncProxy::Core {
}, },
std::move(delayed_task))); std::move(delayed_task)));
} }
// TODO(crbug.com/996166): Remove this call once the logic to schedule
// browser wakeup has moved to BackgroundTaskScheduler.
auto* controller = browser_context()->GetBackgroundSyncController();
DCHECK(controller);
controller->ScheduleBrowserWakeUp(sync_type);
} }
void SendSuspendedPeriodicSyncOrigins( void SendSuspendedPeriodicSyncOrigins(
......
...@@ -4,11 +4,14 @@ ...@@ -4,11 +4,14 @@
#include "content/browser/background_sync/background_sync_scheduler.h" #include "content/browser/background_sync/background_sync_scheduler.h"
#include <algorithm>
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/supports_user_data.h" #include "base/supports_user_data.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/background_sync_controller.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
namespace { namespace {
...@@ -18,8 +21,8 @@ const char kBackgroundSyncSchedulerKey[] = "background-sync-scheduler"; ...@@ -18,8 +21,8 @@ const char kBackgroundSyncSchedulerKey[] = "background-sync-scheduler";
namespace content { namespace content {
using DelayedProcessingInfo = using DelayedProcessingInfoMap =
std::map<StoragePartition*, std::unique_ptr<base::OneShotTimer>>; std::map<StoragePartitionImpl*, std::unique_ptr<base::OneShotTimer>>;
// static // static
BackgroundSyncScheduler* BackgroundSyncScheduler::GetFor( BackgroundSyncScheduler* BackgroundSyncScheduler::GetFor(
...@@ -51,47 +54,103 @@ BackgroundSyncScheduler::~BackgroundSyncScheduler() { ...@@ -51,47 +54,103 @@ BackgroundSyncScheduler::~BackgroundSyncScheduler() {
} }
void BackgroundSyncScheduler::ScheduleDelayedProcessing( void BackgroundSyncScheduler::ScheduleDelayedProcessing(
StoragePartition* storage_partition, StoragePartitionImpl* storage_partition,
blink::mojom::BackgroundSyncType sync_type, blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta delay, base::TimeDelta delay,
base::OnceClosure delayed_task) { base::OnceClosure delayed_task) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(storage_partition); DCHECK(storage_partition);
auto& delayed_processing_info = GetDelayedProcessingInfo(sync_type); // CancelDelayedProcessing should be called in this case.
DCHECK(!delay.is_max());
auto& delayed_processing_info = GetDelayedProcessingInfoMap(sync_type);
delayed_processing_info.emplace(storage_partition, delayed_processing_info.emplace(storage_partition,
std::make_unique<base::OneShotTimer>()); std::make_unique<base::OneShotTimer>());
if (!delay.is_zero() && !delay.is_max()) { if (!delay.is_zero()) {
delayed_processing_info[storage_partition]->Start(FROM_HERE, delay, delayed_processing_info[storage_partition]->Start(
std::move(delayed_task)); FROM_HERE, delay,
base::BindOnce(&BackgroundSyncScheduler::RunDelayedTaskAndPruneInfoMap,
weak_ptr_factory_.GetWeakPtr(), sync_type,
storage_partition, std::move(delayed_task)));
} }
// TODO(crbug.com/996166) Move logic to schedule a browser wakeup task on #if defined(OS_ANDROID)
// Android from BackgroundSycnProxy to here. ScheduleOrCancelBrowserWakeupForSyncType(sync_type, storage_partition);
#endif
} }
void BackgroundSyncScheduler::CancelDelayedProcessing( void BackgroundSyncScheduler::CancelDelayedProcessing(
StoragePartition* storage_partition, StoragePartitionImpl* storage_partition,
blink::mojom::BackgroundSyncType sync_type) { blink::mojom::BackgroundSyncType sync_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(storage_partition); DCHECK(storage_partition);
auto& delayed_processing_info = GetDelayedProcessingInfo(sync_type); auto& delayed_processing_info = GetDelayedProcessingInfoMap(sync_type);
delayed_processing_info.erase(storage_partition); delayed_processing_info.erase(storage_partition);
// TODO(crbug.com/996166) Move logic to cancel a browser wakeup task on #if defined(OS_ANDROID)
// Android from BackgroundSycnProxy to here. ScheduleOrCancelBrowserWakeupForSyncType(sync_type, storage_partition);
#endif
} }
DelayedProcessingInfo& BackgroundSyncScheduler::GetDelayedProcessingInfo( DelayedProcessingInfoMap& BackgroundSyncScheduler::GetDelayedProcessingInfoMap(
blink::mojom::BackgroundSyncType sync_type) { blink::mojom::BackgroundSyncType sync_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (sync_type == blink::mojom::BackgroundSyncType::ONE_SHOT) if (sync_type == blink::mojom::BackgroundSyncType::ONE_SHOT)
return delayed_processing_info_one_shot_; return delayed_processing_info_one_shot_;
else else
return delayed_processing_info_periodic_; return delayed_processing_info_periodic_;
} }
void BackgroundSyncScheduler::RunDelayedTaskAndPruneInfoMap(
blink::mojom::BackgroundSyncType sync_type,
StoragePartitionImpl* storage_partition,
base::OnceClosure delayed_task) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::move(delayed_task).Run();
auto& delayed_processing_info = GetDelayedProcessingInfoMap(sync_type);
delayed_processing_info.erase(storage_partition);
#if defined(OS_ANDROID)
ScheduleOrCancelBrowserWakeupForSyncType(sync_type, storage_partition);
#endif
}
#if defined(OS_ANDROID)
void BackgroundSyncScheduler::ScheduleOrCancelBrowserWakeupForSyncType(
blink::mojom::BackgroundSyncType sync_type,
StoragePartitionImpl* storage_partition) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* browser_context = storage_partition->browser_context();
DCHECK(browser_context);
auto* controller = browser_context->GetBackgroundSyncController();
DCHECK(controller);
auto& delayed_processing_info = GetDelayedProcessingInfoMap(sync_type);
// If no more scheduled tasks remain, cancel browser wakeup.
// Canceling when there's no task scheduled is a no-op.
if (delayed_processing_info.empty()) {
controller->CancelBrowserWakeup(sync_type);
return;
}
// Schedule browser wakeup with the smallest delay required.
auto& min_info = *std::min_element(
delayed_processing_info.begin(), delayed_processing_info.end(),
[](auto& lhs, auto& rhs) {
return (lhs.second->desired_run_time() - base::TimeTicks::Now()) <
(rhs.second->desired_run_time() - base::TimeTicks::Now());
});
controller->ScheduleBrowserWakeUpWithDelay(
sync_type, min_info.second->desired_run_time() - base::TimeTicks::Now());
}
#endif
} // namespace content } // namespace content
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
...@@ -17,7 +19,7 @@ ...@@ -17,7 +19,7 @@
namespace content { namespace content {
class StoragePartition; class StoragePartitionImpl;
// This contains the logic to schedule delayed processing of (periodic) // This contains the logic to schedule delayed processing of (periodic)
// Background Sync registrations. // Background Sync registrations.
...@@ -36,7 +38,7 @@ class CONTENT_EXPORT BackgroundSyncScheduler ...@@ -36,7 +38,7 @@ class CONTENT_EXPORT BackgroundSyncScheduler
// TODO(crbug.com/996166): Add logic to schedule browser wakeup on Android. // TODO(crbug.com/996166): Add logic to schedule browser wakeup on Android.
// Must be called on the UI thread. // Must be called on the UI thread.
virtual void ScheduleDelayedProcessing( virtual void ScheduleDelayedProcessing(
StoragePartition* storage_partition, StoragePartitionImpl* storage_partition,
blink::mojom::BackgroundSyncType sync_type, blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta delay, base::TimeDelta delay,
base::OnceClosure delayed_task); base::OnceClosure delayed_task);
...@@ -44,7 +46,7 @@ class CONTENT_EXPORT BackgroundSyncScheduler ...@@ -44,7 +46,7 @@ class CONTENT_EXPORT BackgroundSyncScheduler
// Cancels delayed_processing for |sync_type| for |storage_partition|. // Cancels delayed_processing for |sync_type| for |storage_partition|.
// Must be called on the UI thread. // Must be called on the UI thread.
virtual void CancelDelayedProcessing( virtual void CancelDelayedProcessing(
StoragePartition* storage_partition, StoragePartitionImpl* storage_partition,
blink::mojom::BackgroundSyncType sync_type); blink::mojom::BackgroundSyncType sync_type);
private: private:
...@@ -53,14 +55,24 @@ class CONTENT_EXPORT BackgroundSyncScheduler ...@@ -53,14 +55,24 @@ class CONTENT_EXPORT BackgroundSyncScheduler
friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
friend class base::DeleteHelper<BackgroundSyncScheduler>; friend class base::DeleteHelper<BackgroundSyncScheduler>;
std::map<StoragePartition*, std::unique_ptr<base::OneShotTimer>>& std::map<StoragePartitionImpl*, std::unique_ptr<base::OneShotTimer>>&
GetDelayedProcessingInfo(blink::mojom::BackgroundSyncType sync_type); GetDelayedProcessingInfoMap(blink::mojom::BackgroundSyncType sync_type);
void RunDelayedTaskAndPruneInfoMap(blink::mojom::BackgroundSyncType sync_type,
StoragePartitionImpl* storage_partition,
base::OnceClosure delayed_task);
#if defined(OS_ANDROID)
void ScheduleOrCancelBrowserWakeupForSyncType(
blink::mojom::BackgroundSyncType sync_type,
StoragePartitionImpl* storage_partition);
#endif
std::map<StoragePartition*, std::unique_ptr<base::OneShotTimer>> std::map<StoragePartitionImpl*, std::unique_ptr<base::OneShotTimer>>
delayed_processing_info_one_shot_; delayed_processing_info_one_shot_;
std::map<StoragePartition*, std::unique_ptr<base::OneShotTimer>> std::map<StoragePartitionImpl*, std::unique_ptr<base::OneShotTimer>>
delayed_processing_info_periodic_; delayed_processing_info_periodic_;
base::WeakPtrFactory<BackgroundSyncScheduler> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(BackgroundSyncScheduler); DISALLOW_COPY_AND_ASSIGN(BackgroundSyncScheduler);
}; };
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/background_sync/background_sync_scheduler.h" #include "content/browser/background_sync/background_sync_scheduler.h"
#include "content/browser/storage_partition_impl.h" #include "content/browser/storage_partition_impl.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
...@@ -20,6 +21,7 @@ ...@@ -20,6 +21,7 @@
#include "content/public/common/content_client.h" #include "content/public/common/content_client.h"
#include "content/public/test/browser_task_environment.h" #include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_context.h"
#include "content/test/mock_background_sync_controller.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -60,8 +62,9 @@ class BackgroundSyncSchedulerTest : public testing::Test { ...@@ -60,8 +62,9 @@ class BackgroundSyncSchedulerTest : public testing::Test {
base::OnceClosure delayed_task) { base::OnceClosure delayed_task) {
auto* scheduler = BackgroundSyncScheduler::GetFor(&test_browser_context_); auto* scheduler = BackgroundSyncScheduler::GetFor(&test_browser_context_);
DCHECK(scheduler); DCHECK(scheduler);
auto* storage_partition = auto* storage_partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetStoragePartitionForSite(&test_browser_context_, url); BrowserContext::GetStoragePartitionForSite(&test_browser_context_,
url));
DCHECK(storage_partition); DCHECK(storage_partition);
scheduler->ScheduleDelayedProcessing(storage_partition, sync_type, delay, scheduler->ScheduleDelayedProcessing(storage_partition, sync_type, delay,
...@@ -72,13 +75,24 @@ class BackgroundSyncSchedulerTest : public testing::Test { ...@@ -72,13 +75,24 @@ class BackgroundSyncSchedulerTest : public testing::Test {
blink::mojom::BackgroundSyncType sync_type) { blink::mojom::BackgroundSyncType sync_type) {
auto* scheduler = BackgroundSyncScheduler::GetFor(&test_browser_context_); auto* scheduler = BackgroundSyncScheduler::GetFor(&test_browser_context_);
DCHECK(scheduler); DCHECK(scheduler);
auto* storage_partition = auto* storage_partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetStoragePartitionForSite(&test_browser_context_, url); BrowserContext::GetStoragePartitionForSite(&test_browser_context_,
url));
DCHECK(storage_partition); DCHECK(storage_partition);
scheduler->CancelDelayedProcessing(storage_partition, sync_type); scheduler->CancelDelayedProcessing(storage_partition, sync_type);
} }
MockBackgroundSyncController* GetController() {
return static_cast<MockBackgroundSyncController*>(
test_browser_context_.GetBackgroundSyncController());
}
base::TimeDelta GetBrowserWakeupDelay(
blink::mojom::BackgroundSyncType sync_type) {
return GetController()->GetBrowserWakeupDelay(sync_type);
}
void SetUp() override { void SetUp() override {
original_client_ = SetBrowserClientForTesting(&browser_client_); original_client_ = SetBrowserClientForTesting(&browser_client_);
} }
...@@ -111,17 +125,6 @@ TEST_F(BackgroundSyncSchedulerTest, ZeroDelayScheduleDoesNotInvokeCallback) { ...@@ -111,17 +125,6 @@ TEST_F(BackgroundSyncSchedulerTest, ZeroDelayScheduleDoesNotInvokeCallback) {
EXPECT_FALSE(was_called); EXPECT_FALSE(was_called);
} }
TEST_F(BackgroundSyncSchedulerTest, MaxDelayScheduleDoesNotInvokeCallback) {
bool was_called = false;
ScheduleDelayedProcessing(
GURL(kUrl_1), blink::mojom::BackgroundSyncType::ONE_SHOT,
base::TimeDelta::Max(),
base::BindOnce([](bool* was_called) { *was_called = true; },
&was_called));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(was_called);
}
TEST_F(BackgroundSyncSchedulerTest, CancelDoesNotInvokeCallback) { TEST_F(BackgroundSyncSchedulerTest, CancelDoesNotInvokeCallback) {
bool was_called = false; bool was_called = false;
ScheduleDelayedProcessing( ScheduleDelayedProcessing(
...@@ -183,4 +186,112 @@ TEST_F(BackgroundSyncSchedulerTest, ScheduleBothTypesOfSync) { ...@@ -183,4 +186,112 @@ TEST_F(BackgroundSyncSchedulerTest, ScheduleBothTypesOfSync) {
run_loop_2.Run(); run_loop_2.Run();
} }
#if defined(OS_ANDROID)
TEST_F(BackgroundSyncSchedulerTest, BrowserWakeupScheduled) {
ScheduleDelayedProcessing(GURL(kUrl_1),
blink::mojom::BackgroundSyncType::ONE_SHOT,
base::TimeDelta::FromSeconds(1), base::DoNothing());
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromSeconds(1));
ScheduleDelayedProcessing(
GURL(kUrl_2), blink::mojom::BackgroundSyncType::ONE_SHOT,
base::TimeDelta::FromMilliseconds(1), base::DoNothing());
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromMilliseconds(1));
}
TEST_F(BackgroundSyncSchedulerTest,
BrowserWakeupScheduleSecondAfterFirstFinishes) {
base::RunLoop run_loop_1;
ScheduleDelayedProcessing(
GURL(kUrl_1), blink::mojom::BackgroundSyncType::ONE_SHOT,
base::TimeDelta::FromMilliseconds(1), run_loop_1.QuitClosure());
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromMilliseconds(1));
run_loop_1.Run();
ScheduleDelayedProcessing(GURL(kUrl_2),
blink::mojom::BackgroundSyncType::ONE_SHOT,
base::TimeDelta::FromMinutes(1), base::DoNothing());
EXPECT_GT(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromMilliseconds(1));
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromMinutes(1));
}
TEST_F(BackgroundSyncSchedulerTest, BrowserWakeupScheduleOneOfEachType) {
ScheduleDelayedProcessing(GURL(kUrl_1),
blink::mojom::BackgroundSyncType::PERIODIC,
base::TimeDelta::FromSeconds(1), base::DoNothing());
base::RunLoop().RunUntilIdle();
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::PERIODIC),
base::TimeDelta::FromSeconds(1));
ScheduleDelayedProcessing(GURL(kUrl_2),
blink::mojom::BackgroundSyncType::ONE_SHOT,
base::TimeDelta::FromMinutes(1), base::DoNothing());
base::RunLoop().RunUntilIdle();
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromMinutes(1));
}
TEST_F(BackgroundSyncSchedulerTest, BrowserWakeupScheduleThenCancel) {
ScheduleDelayedProcessing(GURL(kUrl_1),
blink::mojom::BackgroundSyncType::PERIODIC,
base::TimeDelta::FromMinutes(1), base::DoNothing());
base::RunLoop().RunUntilIdle();
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::PERIODIC),
base::TimeDelta::FromMinutes(1));
CancelDelayedProcessing(GURL(kUrl_1),
blink::mojom::BackgroundSyncType::PERIODIC);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::PERIODIC),
base::TimeDelta::Max());
}
TEST_F(BackgroundSyncSchedulerTest, CancelingOneTypeDoesNotAffectAnother) {
ScheduleDelayedProcessing(GURL(kUrl_1),
blink::mojom::BackgroundSyncType::PERIODIC,
base::TimeDelta::FromMinutes(1), base::DoNothing());
ScheduleDelayedProcessing(GURL(kUrl_2),
blink::mojom::BackgroundSyncType::ONE_SHOT,
base::TimeDelta::FromSeconds(1), base::DoNothing());
CancelDelayedProcessing(GURL(kUrl_1),
blink::mojom::BackgroundSyncType::PERIODIC);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::PERIODIC),
base::TimeDelta::Max());
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromSeconds(1));
}
TEST_F(BackgroundSyncSchedulerTest,
CancelingProcessingForOneStorageParitionUpdatesBrowserWakeup) {
ScheduleDelayedProcessing(GURL(kUrl_1),
blink::mojom::BackgroundSyncType::ONE_SHOT,
base::TimeDelta::FromMinutes(1), base::DoNothing());
ScheduleDelayedProcessing(GURL(kUrl_2),
blink::mojom::BackgroundSyncType::ONE_SHOT,
base::TimeDelta::FromSeconds(1), base::DoNothing());
base::RunLoop().RunUntilIdle();
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromSeconds(1));
CancelDelayedProcessing(GURL(kUrl_2),
blink::mojom::BackgroundSyncType::ONE_SHOT);
base::RunLoop().RunUntilIdle();
EXPECT_LE(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromMinutes(1));
EXPECT_GT(GetBrowserWakeupDelay(blink::mojom::BackgroundSyncType::ONE_SHOT),
base::TimeDelta::FromSeconds(1));
}
#endif
} // namespace content } // namespace content
...@@ -76,11 +76,16 @@ class CONTENT_EXPORT BackgroundSyncController { ...@@ -76,11 +76,16 @@ class CONTENT_EXPORT BackgroundSyncController {
int num_attempts, int num_attempts,
int max_attempts) {} int max_attempts) {}
// Calculates the soonest wakeup delta across all storage partitions and // Schedules a background task with delay |delay| to wake up the browser to
// schedules a background task to wake up the browser to process // process Background Sync registrations of type |sync_type|.
// Background Sync registrations. virtual void ScheduleBrowserWakeUpWithDelay(
virtual void ScheduleBrowserWakeUp( blink::mojom::BackgroundSyncType sync_type,
blink::mojom::BackgroundSyncType sync_type) {} base::TimeDelta delay) {}
// Cancel the background task that wakes the browser up to process Background
// Sync registrations of type |sync_type|.
virtual void CancelBrowserWakeup(blink::mojom::BackgroundSyncType sync_type) {
}
// Calculates the delay after which the next sync event should be fired // Calculates the delay after which the next sync event should be fired
// for a BackgroundSync registration. The delay is based on the sync_type of // for a BackgroundSync registration. The delay is based on the sync_type of
......
...@@ -30,13 +30,25 @@ void MockBackgroundSyncController::NotifyOneShotBackgroundSyncRegistered( ...@@ -30,13 +30,25 @@ void MockBackgroundSyncController::NotifyOneShotBackgroundSyncRegistered(
registration_origin_ = origin; registration_origin_ = origin;
} }
void MockBackgroundSyncController::ScheduleBrowserWakeUp( void MockBackgroundSyncController::ScheduleBrowserWakeUpWithDelay(
blink::mojom::BackgroundSyncType sync_type) { blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta delay) {
if (sync_type == blink::mojom::BackgroundSyncType::PERIODIC) { if (sync_type == blink::mojom::BackgroundSyncType::PERIODIC) {
run_in_background_for_periodic_sync_count_ += 1; run_in_background_for_periodic_sync_count_ += 1;
periodic_sync_browser_wakeup_delay_ = delay;
return; return;
} }
run_in_background_for_one_shot_sync_count_ += 1; run_in_background_for_one_shot_sync_count_ += 1;
one_shot_sync_browser_wakeup_delay_ = delay;
}
void MockBackgroundSyncController::CancelBrowserWakeup(
blink::mojom::BackgroundSyncType sync_type) {
if (sync_type == blink::mojom::BackgroundSyncType::PERIODIC) {
periodic_sync_browser_wakeup_delay_ = base::TimeDelta::Max();
} else {
one_shot_sync_browser_wakeup_delay_ = base::TimeDelta::Max();
}
} }
void MockBackgroundSyncController::ApplyFieldTrialParamsOverrides() { void MockBackgroundSyncController::ApplyFieldTrialParamsOverrides() {
......
...@@ -27,8 +27,10 @@ class MockBackgroundSyncController : public BackgroundSyncController { ...@@ -27,8 +27,10 @@ class MockBackgroundSyncController : public BackgroundSyncController {
void NotifyOneShotBackgroundSyncRegistered(const url::Origin& origin, void NotifyOneShotBackgroundSyncRegistered(const url::Origin& origin,
bool can_fire, bool can_fire,
bool is_reregistered) override; bool is_reregistered) override;
void ScheduleBrowserWakeUp( void ScheduleBrowserWakeUpWithDelay(
blink::mojom::BackgroundSyncType sync_type) override; blink::mojom::BackgroundSyncType sync_type,
base::TimeDelta delay) override;
void CancelBrowserWakeup(blink::mojom::BackgroundSyncType sync_type) override;
void GetParameterOverrides(BackgroundSyncParameters* parameters) override; void GetParameterOverrides(BackgroundSyncParameters* parameters) override;
base::TimeDelta GetNextEventDelay( base::TimeDelta GetNextEventDelay(
const BackgroundSyncRegistration& registration, const BackgroundSyncRegistration& registration,
...@@ -49,6 +51,15 @@ class MockBackgroundSyncController : public BackgroundSyncController { ...@@ -49,6 +51,15 @@ class MockBackgroundSyncController : public BackgroundSyncController {
int run_in_background_periodic_sync_count() const { int run_in_background_periodic_sync_count() const {
return run_in_background_for_periodic_sync_count_; return run_in_background_for_periodic_sync_count_;
} }
base::TimeDelta GetBrowserWakeupDelay(
blink::mojom::BackgroundSyncType sync_type) const {
if (sync_type == blink::mojom::BackgroundSyncType::ONE_SHOT)
return one_shot_sync_browser_wakeup_delay_;
else
return periodic_sync_browser_wakeup_delay_;
}
BackgroundSyncParameters* background_sync_parameters() { BackgroundSyncParameters* background_sync_parameters() {
return &background_sync_parameters_; return &background_sync_parameters_;
} }
...@@ -64,6 +75,8 @@ class MockBackgroundSyncController : public BackgroundSyncController { ...@@ -64,6 +75,8 @@ class MockBackgroundSyncController : public BackgroundSyncController {
int run_in_background_for_one_shot_sync_count_ = 0; int run_in_background_for_one_shot_sync_count_ = 0;
int run_in_background_for_periodic_sync_count_ = 0; int run_in_background_for_periodic_sync_count_ = 0;
base::TimeDelta periodic_sync_browser_wakeup_delay_;
base::TimeDelta one_shot_sync_browser_wakeup_delay_;
BackgroundSyncParameters background_sync_parameters_; BackgroundSyncParameters background_sync_parameters_;
std::set<url::Origin> suspended_periodic_sync_origins_; std::set<url::Origin> suspended_periodic_sync_origins_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment