[Background Sync] Allow native processing to finish

sending any pending Background Sync events, before exiting the
background task that woke up the browser.

Bug: 924490
Change-Id: Id63b2d9edeb6e9255dff616ea06f02c9f77cc0d3
Reviewed-on: https://chromium-review.googlesource.com/c/1477707
Commit-Queue: Mugdha Lakhani <[email protected]>
Reviewed-by: Peter Beverloo <[email protected]>
Reviewed-by: Rayan Kanso <[email protected]>
Reviewed-by: Dmitry Gozman <[email protected]>
Reviewed-by: David Trainor <[email protected]>
Cr-Commit-Position: refs/heads/master@{#636034}
diff --git a/chrome/browser/android/background_sync_launcher_android.cc b/chrome/browser/android/background_sync_launcher_android.cc
index 7b182c6..8eaedf25 100644
--- a/chrome/browser/android/background_sync_launcher_android.cc
+++ b/chrome/browser/android/background_sync_launcher_android.cc
@@ -4,10 +4,19 @@
 
 #include "chrome/browser/android/background_sync_launcher_android.h"
 
+#include <utility>
+
+#include "base/android/callback_android.h"
+#include "base/barrier_closure.h"
 #include "base/feature_list.h"
 #include "chrome/browser/android/chrome_feature_list.h"
+#include "chrome/browser/profiles/profile_manager.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"
 #include "jni/BackgroundSyncBackgroundTaskScheduler_jni.h"
+#include "jni/BackgroundSyncBackgroundTask_jni.h"
 #include "jni/BackgroundSyncLauncher_jni.h"
 
 using content::BrowserThread;
@@ -24,6 +33,18 @@
 }  // namespace
 
 // static
+void JNI_BackgroundSyncBackgroundTask_FireBackgroundSyncEvents(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& j_runnable) {
+  if (!base::FeatureList::IsEnabled(
+          chrome::android::kBackgroundTaskSchedulerForBackgroundSync)) {
+    return;
+  }
+
+  BackgroundSyncLauncherAndroid::Get()->FireBackgroundSyncEvents(j_runnable);
+}
+
+// static
 BackgroundSyncLauncherAndroid* BackgroundSyncLauncherAndroid::Get() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
@@ -39,6 +60,22 @@
   Get()->LaunchBrowserIfStoppedImpl(launch_when_next_online, min_delay_ms);
 }
 
+// static
+void BackgroundSyncLauncherAndroid::SetPlayServicesVersionCheckDisabledForTests(
+    bool disabled) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  disable_play_services_version_check_for_tests = disabled;
+}
+
+// static
+bool BackgroundSyncLauncherAndroid::ShouldDisableBackgroundSync() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (disable_play_services_version_check_for_tests)
+    return false;
+  return Java_BackgroundSyncLauncher_shouldDisableBackgroundSync(
+      base::android::AttachCurrentThread());
+}
+
 void BackgroundSyncLauncherAndroid::LaunchBrowserIfStoppedImpl(
     bool launch_when_next_online,
     int64_t min_delay_ms) {
@@ -59,21 +96,57 @@
       launch_when_next_online, min_delay_ms);
 }
 
-// static
-void BackgroundSyncLauncherAndroid::SetPlayServicesVersionCheckDisabledForTests(
-    bool disabled) {
+void BackgroundSyncLauncherAndroid::FireBackgroundSyncEvents(
+    const base::android::JavaParamRef<jobject>& j_runnable) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  disable_play_services_version_check_for_tests = disabled;
+
+  auto* profile = ProfileManager::GetLastUsedProfile();
+  DCHECK(profile);
+
+  int num_partitions = 0;
+  content::BrowserContext::ForEachStoragePartition(
+      profile, base::BindRepeating(
+                   [](int* num_partitions,
+                      content::StoragePartition* storage_partition) {
+                     (*num_partitions)++;
+                   },
+                   &num_partitions));
+
+  // This class is a singleton, which is only destructed on program exit.
+  // Therefore, use of base::Unretained(this) is safe.
+  base::RepeatingClosure done_closure = base::BarrierClosure(
+      num_partitions,
+      base::BindOnce(base::android::RunRunnableAndroid,
+                     base::android::ScopedJavaGlobalRef<jobject>(j_runnable)));
+
+  content::BrowserContext::ForEachStoragePartition(
+      profile,
+      base::BindRepeating(&BackgroundSyncLauncherAndroid::
+                              FireBackgroundSyncEventsForStoragePartition,
+                          base::Unretained(this), done_closure));
 }
 
-// static
-bool BackgroundSyncLauncherAndroid::ShouldDisableBackgroundSync() {
+void BackgroundSyncLauncherAndroid::FireBackgroundSyncEventsForStoragePartition(
+    base::OnceClosure done_closure,
+    content::StoragePartition* storage_partition) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (disable_play_services_version_check_for_tests) {
-    return false;
+
+  content::BackgroundSyncContext* sync_context =
+      storage_partition->GetBackgroundSyncContext();
+  if (!sync_context) {
+    std::move(done_closure).Run();
+    return;
   }
-  return Java_BackgroundSyncLauncher_shouldDisableBackgroundSync(
-      base::android::AttachCurrentThread());
+
+  sync_context->FireBackgroundSyncEventsForStoragePartition(
+      storage_partition, std::move(done_closure));
+}
+
+void BackgroundSyncLauncherAndroid::OnFiredBackgroundSyncEvents(
+    base::android::ScopedJavaGlobalRef<jobject> j_runnable) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  base::android::RunRunnableAndroid(j_runnable);
 }
 
 BackgroundSyncLauncherAndroid::BackgroundSyncLauncherAndroid() {