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 | } |