| 1 | // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | package org.chromium.content.browser; |
| 6 | |
| 7 | import android.app.ActivityManager; |
| 8 | import android.content.Context; |
| 9 | import android.util.Log; |
| 10 | |
| 11 | import org.chromium.base.JNINamespace; |
| 12 | import org.chromium.content.app.ContentMain; |
| 13 | import org.chromium.content.app.LibraryLoader; |
| 14 | import org.chromium.content.common.ProcessInitException; |
| 15 | |
| 16 | @JNINamespace("content") |
| 17 | // TODO(nyquist) Remove this class, and move the functionality to BrowserStartupController. |
| 18 | public class AndroidBrowserProcess { |
| 19 | private static final String TAG = "BrowserProcessMain"; |
| 20 | |
| 21 | // Prevents initializing the process more than once. |
| 22 | private static boolean sInitialized = false; |
| 23 | |
| 24 | // Use single-process mode that runs the renderer on a separate thread in the main application. |
| 25 | public static final int MAX_RENDERERS_SINGLE_PROCESS = 0; |
| 26 | |
| 27 | // Cap on the maximum number of renderer processes that can be requested. |
| 28 | // This is currently set to account for: |
| 29 | // 13: The maximum number of sandboxed processes we have available |
| 30 | // - 1: The regular New Tab Page |
| 31 | // - 1: The incognito New Tab Page |
| 32 | // - 1: A regular incognito tab |
| 33 | // - 1: Safety buffer (http://crbug.com/251279) |
| 34 | public static final int MAX_RENDERERS_LIMIT = |
| 35 | ChildProcessLauncher.MAX_REGISTERED_SANDBOXED_SERVICES - 4; |
| 36 | |
| 37 | /** |
| 38 | * Initialize the process as a ContentView host. This must be called from the main UI thread. |
| 39 | * This should be called by the ContentView constructor to prepare this process for ContentView |
| 40 | * use outside of the browser. In the case where ContentView is used in the browser then |
| 41 | * initBrowserProcess() should already have been called and this is a no-op. |
| 42 | * |
| 43 | * @param context Context used to obtain the application context. |
| 44 | * @param maxRendererProcesses Limit on the number of renderers to use. Each tab runs in its own |
| 45 | * process until the maximum number of processes is reached. The special value of |
| 46 | * MAX_RENDERERS_SINGLE_PROCESS requests single-process mode where the renderer will run in the |
| 47 | * application process in a separate thread. The maximum number of allowed renderers is capped |
| 48 | * by MAX_RENDERERS_LIMIT. |
| 49 | * |
| 50 | * @return Whether the process actually needed to be initialized (false if already running). |
| 51 | */ |
| 52 | public static boolean init(Context context, int maxRendererProcesses) |
| 53 | throws ProcessInitException { |
| 54 | assert maxRendererProcesses >= 0; |
| 55 | assert maxRendererProcesses <= MAX_RENDERERS_LIMIT; |
| 56 | if (sInitialized) return false; |
| 57 | sInitialized = true; |
| 58 | Log.i(TAG, "Initializing chromium process, renderers=" + maxRendererProcesses); |
| 59 | |
| 60 | // Normally Main.java will have kicked this off asynchronously for Chrome. But other |
| 61 | // ContentView apps like tests also need them so we make sure we've extracted resources |
| 62 | // here. We can still make it a little async (wait until the library is loaded). |
| 63 | ResourceExtractor resourceExtractor = ResourceExtractor.get(context); |
| 64 | resourceExtractor.startExtractingResources(); |
| 65 | |
| 66 | // Normally Main.java will have already loaded the library asynchronously, we only need to |
| 67 | // load it here if we arrived via another flow, e.g. bookmark access & sync setup. |
| 68 | LibraryLoader.ensureInitialized(); |
| 69 | // TODO(yfriedman): Remove dependency on a command line flag for this. |
| 70 | DeviceUtils.addDeviceSpecificUserAgentSwitch(context); |
| 71 | |
| 72 | Context appContext = context.getApplicationContext(); |
| 73 | // Now we really need to have the resources ready. |
| 74 | resourceExtractor.waitForCompletion(); |
| 75 | |
| 76 | nativeSetCommandLineFlags(maxRendererProcesses, |
| 77 | nativeIsPluginEnabled() ? getPlugins(context) : null); |
| 78 | ContentMain.initApplicationContext(appContext); |
| 79 | int result = ContentMain.start(); |
| 80 | if (result > 0) throw new ProcessInitException(result); |
| 81 | return true; |
| 82 | } |
| 83 | |
| 84 | /** |
| 85 | * Initialization needed for tests. Mainly used by content browsertests. |
| 86 | */ |
| 87 | public static void initChromiumBrowserProcessForTests(Context context) { |
| 88 | ResourceExtractor resourceExtractor = ResourceExtractor.get(context); |
| 89 | resourceExtractor.startExtractingResources(); |
| 90 | resourceExtractor.waitForCompletion(); |
| 91 | |
| 92 | // Having a single renderer should be sufficient for tests. We can't have more than |
| 93 | // MAX_RENDERERS_LIMIT. |
| 94 | nativeSetCommandLineFlags(1 /* maxRenderers */, null); |
| 95 | } |
| 96 | |
| 97 | private static String getPlugins(final Context context) { |
| 98 | return PepperPluginManager.getPlugins(context); |
| 99 | } |
| 100 | |
| 101 | private static native void nativeSetCommandLineFlags(int maxRenderProcesses, |
| 102 | String pluginDescriptor); |
| 103 | |
| 104 | // Is this an official build of Chrome? Only native code knows for sure. Official build |
| 105 | // knowledge is needed very early in process startup. |
| 106 | private static native boolean nativeIsOfficialBuild(); |
| 107 | |
| 108 | private static native boolean nativeIsPluginEnabled(); |
| 109 | } |