Allow native code running in reduced mode to launch full browser

This cl implements NativeStartupBridge which allows native code running
in reduced mode to interface with java and launch full browser. The
first client of this is DownloadService which is being refactored into
being able to run in reduced mode but may require launching full browser
if needed.

Change-Id: I27d2d7cb4a7d89fa376698e7773a6d41b5daf4d3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1572529
Reviewed-by: David Trainor <dtrainor@chromium.org>
Reviewed-by: Steven Holte <holte@chromium.org>
Commit-Queue: Mohamed Heikal <mheikal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#653060}
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 3f4dafb..99d9d51 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2405,6 +2405,7 @@
     "java/src/org/chromium/chrome/browser/infobar/SurveyInfoBar.java",
     "java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java",
     "java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java",
+    "java/src/org/chromium/chrome/browser/init/NativeStartupBridge.java",
     "java/src/org/chromium/chrome/browser/instantapps/InstantAppsSettings.java",
     "java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java",
     "java/src/org/chromium/chrome/browser/jsdialog/JavascriptAppModalDialog.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index c69b7eab9..1f9f85a 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -863,6 +863,7 @@
   "java/src/org/chromium/chrome/browser/init/EmptyBrowserParts.java",
   "java/src/org/chromium/chrome/browser/init/InvalidStartupDialog.java",
   "java/src/org/chromium/chrome/browser/init/NativeInitializationController.java",
+  "java/src/org/chromium/chrome/browser/init/NativeStartupBridge.java",
   "java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java",
   "java/src/org/chromium/chrome/browser/init/ServiceManagerStartupUtils.java",
   "java/src/org/chromium/chrome/browser/init/SingleWindowKeyboardVisibilityDelegate.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/NativeStartupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/init/NativeStartupBridge.java
new file mode 100644
index 0000000..17557de
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/NativeStartupBridge.java
@@ -0,0 +1,47 @@
+// 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.
+
+package org.chromium.chrome.browser.init;
+
+import org.chromium.base.Log;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.base.library_loader.ProcessInitException;
+import org.chromium.base.task.PostTask;
+import org.chromium.content_public.browser.BrowserStartupController;
+import org.chromium.content_public.browser.UiThreadTaskTraits;
+
+/**
+ * A class for native code to request full browser start when running in service manager only mode.
+ */
+public class NativeStartupBridge {
+    private static final String TAG = "NativeStartupBridge";
+
+    @CalledByNative
+    private static void loadFullBrowser() {
+        if (BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
+                        .isStartupSuccessfullyCompleted()) {
+            return;
+        }
+        final BrowserParts parts = new EmptyBrowserParts() {
+            @Override
+            public boolean startServiceManagerOnly() {
+                return false;
+            }
+        };
+
+        PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    ChromeBrowserInitializer.getInstance().handlePreNativeStartup(parts);
+                    ChromeBrowserInitializer.getInstance().handlePostNativeStartup(
+                            true /* isAsync */, parts);
+                } catch (ProcessInitException e) {
+                    Log.e(TAG, "ProcessInitException while starting the browser process.");
+                }
+            }
+        });
+    }
+}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 97a16df..54162b8 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2510,6 +2510,8 @@
       "android/signin/signin_utils.cc",
       "android/signin/signin_utils.h",
       "android/signin/unified_consent_service_bridge.cc",
+      "android/startup_bridge.cc",
+      "android/startup_bridge.h",
       "android/subresource_filter/test_subresource_filter_publisher.cc",
       "android/tab_android.cc",
       "android/tab_android.h",
diff --git a/chrome/browser/android/startup_bridge.cc b/chrome/browser/android/startup_bridge.cc
new file mode 100644
index 0000000..d92c449
--- /dev/null
+++ b/chrome/browser/android/startup_bridge.cc
@@ -0,0 +1,25 @@
+// 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 "chrome/browser/android/startup_bridge.h"
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/metrics/histogram_macros.h"
+#include "chrome/browser/browser_process.h"
+#include "jni/NativeStartupBridge_jni.h"
+
+namespace android_startup {
+
+void LoadFullBrowser() {
+  if (g_browser_process)
+    return;
+  UMA_HISTOGRAM_BOOLEAN("Android.NativeStartupBridge.LoadFullBrowser",
+                        true /*requested*/);
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_NativeStartupBridge_loadFullBrowser(env);
+}
+
+}  // namespace android_startup
diff --git a/chrome/browser/android/startup_bridge.h b/chrome/browser/android/startup_bridge.h
new file mode 100644
index 0000000..913cef9
--- /dev/null
+++ b/chrome/browser/android/startup_bridge.h
@@ -0,0 +1,12 @@
+// 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.
+
+#ifndef CHROME_BROWSER_ANDROID_STARTUP_BRIDGE_H_
+#define CHROME_BROWSER_ANDROID_STARTUP_BRIDGE_H_
+
+namespace android_startup {
+extern void LoadFullBrowser();
+}
+
+#endif  // CHROME_BROWSER_ANDROID_STARTUP_BRIDGE_H_
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 2f93e51..336d30ce 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -2527,6 +2527,17 @@
   </summary>
 </histogram>
 
+<histogram name="Android.NativeStartupBridge.LoadFullBrowser"
+    enum="BooleanRequested" expires_after="2020-06-01">
+  <owner>mheikal@chromium.org</owner>
+  <owner>hnakashima@chromium.org</owner>
+  <owner>hanxi@chromium.org</owner>
+  <summary>
+    The number of times full-browser mode is requested to be loaded from native
+    code (running in reduced mode).
+  </summary>
+</histogram>
+
 <histogram name="Android.NTP.Impression" enum="NTPImpressionType">
   <owner>finkm@chromium.org</owner>
   <summary>