Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java

Issue 2882823002: Moving some CPL logic to CPLH. (Closed)
Patch Set: Fixed warm-up and tests. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.content.browser; 5 package org.chromium.content.browser;
6 6
7 import android.content.Context; 7 import android.content.Context;
8 import android.os.Bundle;
9 import android.os.IBinder;
8 import android.os.ParcelFileDescriptor; 10 import android.os.ParcelFileDescriptor;
9 11
10 import org.chromium.base.ContextUtils; 12 import org.chromium.base.ContextUtils;
13 import org.chromium.base.CpuFeatures;
11 import org.chromium.base.Log; 14 import org.chromium.base.Log;
15 import org.chromium.base.VisibleForTesting;
12 import org.chromium.base.annotations.CalledByNative; 16 import org.chromium.base.annotations.CalledByNative;
13 import org.chromium.base.annotations.JNINamespace; 17 import org.chromium.base.annotations.JNINamespace;
18 import org.chromium.base.library_loader.Linker;
14 import org.chromium.base.process_launcher.ChildProcessCreationParams; 19 import org.chromium.base.process_launcher.ChildProcessCreationParams;
15 import org.chromium.base.process_launcher.FileDescriptorInfo; 20 import org.chromium.base.process_launcher.FileDescriptorInfo;
21 import org.chromium.content.app.ChromiumLinkerParams;
22 import org.chromium.content.common.ContentSwitches;
16 23
17 import java.io.IOException; 24 import java.io.IOException;
18 25
19 /** 26 /**
20 * This is the java counterpart to ChildProcessLauncherHelper. It is owned by na tive side and 27 * This is the java counterpart to ChildProcessLauncherHelper. It is owned by na tive side and
21 * has an explicit destroy method. 28 * has an explicit destroy method.
22 * Each public or jni methods should have explicit documentation on what threads they are called. 29 * Each public or jni methods should have explicit documentation on what threads they are called.
23 */ 30 */
24 @JNINamespace("content::internal") 31 @JNINamespace("content::internal")
25 class ChildProcessLauncherHelper { 32 public class ChildProcessLauncherHelper {
26 private static final String TAG = "ChildProcLH"; 33 private static final String TAG = "ChildProcLH";
27 34
28 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle. 35 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle.
29 private static final int NULL_PROCESS_HANDLE = 0; 36 private static final int NULL_PROCESS_HANDLE = 0;
30 37
38 // The IBinder provided to the created service.
39 private final IBinder mIBinderCallback;
40
31 // Note native pointer is only guaranteed live until nativeOnChildProcessSta rted. 41 // Note native pointer is only guaranteed live until nativeOnChildProcessSta rted.
32 private long mNativeChildProcessLauncherHelper; 42 private long mNativeChildProcessLauncherHelper;
43
44 // The actual service connection. Set once we have connected to the service.
33 private ChildProcessConnection mChildProcessConnection; 45 private ChildProcessConnection mChildProcessConnection;
34 46
35 @CalledByNative 47 @CalledByNative
36 private static FileDescriptorInfo makeFdInfo( 48 private static FileDescriptorInfo makeFdInfo(
37 int id, int fd, boolean autoClose, long offset, long size) { 49 int id, int fd, boolean autoClose, long offset, long size) {
38 assert LauncherThread.runningOnLauncherThread(); 50 assert LauncherThread.runningOnLauncherThread();
39 ParcelFileDescriptor pFd; 51 ParcelFileDescriptor pFd;
40 if (autoClose) { 52 if (autoClose) {
41 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor. 53 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor.
42 pFd = ParcelFileDescriptor.adoptFd(fd); 54 pFd = ParcelFileDescriptor.adoptFd(fd);
43 } else { 55 } else {
44 try { 56 try {
45 pFd = ParcelFileDescriptor.fromFd(fd); 57 pFd = ParcelFileDescriptor.fromFd(fd);
46 } catch (IOException e) { 58 } catch (IOException e) {
47 Log.e(TAG, "Invalid FD provided for process connection, aborting connection.", e); 59 Log.e(TAG, "Invalid FD provided for process connection, aborting connection.", e);
48 return null; 60 return null;
49 } 61 }
50 } 62 }
51 return new FileDescriptorInfo(id, pFd, offset, size); 63 return new FileDescriptorInfo(id, pFd, offset, size);
52 } 64 }
53 65
66 @VisibleForTesting
54 @CalledByNative 67 @CalledByNative
55 private static ChildProcessLauncherHelper create(long nativePointer, int par amId, 68 public static ChildProcessLauncherHelper createAndStart(long nativePointer, int paramId,
56 final String[] commandLine, FileDescriptorInfo[] filesToBeMapped) { 69 final String[] commandLine, FileDescriptorInfo[] filesToBeMapped) {
57 assert LauncherThread.runningOnLauncherThread(); 70 assert LauncherThread.runningOnLauncherThread();
58 return new ChildProcessLauncherHelper(nativePointer, paramId, commandLin e, filesToBeMapped); 71 String processType =
72 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE);
73
74 ChildProcessCreationParams params = ChildProcessCreationParams.get(param Id);
75 if (paramId != ChildProcessCreationParams.DEFAULT_ID && params == null) {
76 throw new RuntimeException("CreationParams id " + paramId + " not fo und");
77 }
78
79 Context context = ContextUtils.getApplicationContext();
80 boolean sandboxed = true;
81 boolean alwaysInForeground = false;
82 if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) {
83 if (params != null && !params.getPackageName().equals(context.getPac kageName())) {
84 // WebViews and WebAPKs have renderer processes running in their applications.
85 // When launching these renderer processes, {@link ManagedChildP rocessConnection}
86 // requires the package name of the application which holds the renderer process.
87 // Therefore, the package name in ChildProcessCreationParams cou ld be the package
88 // name of WebViews, WebAPKs, or Chrome, depending on the host a pplication.
89 // Except renderer process, all other child processes should use Chrome's package
90 // name. In WebAPK, ChildProcessCreationParams are initialized w ith WebAPK's
91 // package name. Make a copy of the WebAPK's params, but replace the package with
92 // Chrome's package to use when initializing a non-renderer proc esses.
93 // TODO(boliu): Should fold into |paramId|. Investigate why this is needed.
94 params = new ChildProcessCreationParams(context.getPackageName() ,
95 params.getIsExternalService(), params.getLibraryProcessT ype(),
96 params.getBindToCallerCheck());
97 }
98 if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) {
99 sandboxed = false;
100 alwaysInForeground = true;
101 } else {
102 // We only support sandboxed utility processes now.
103 assert ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType );
104 }
105 }
106
107 ChildProcessLauncherHelper process_launcher =
108 new ChildProcessLauncherHelper(nativePointer, processType);
109 process_launcher.start(
110 context, commandLine, filesToBeMapped, params, sandboxed, always InForeground);
111 return process_launcher;
59 } 112 }
60 113
61 private ChildProcessLauncherHelper(long nativePointer, int paramId, final St ring[] commandLine, 114 private ChildProcessLauncherHelper(long nativePointer, String processType) {
62 FileDescriptorInfo[] filesToBeMapped) {
63 assert LauncherThread.runningOnLauncherThread(); 115 assert LauncherThread.runningOnLauncherThread();
64 mNativeChildProcessLauncherHelper = nativePointer; 116 mNativeChildProcessLauncherHelper = nativePointer;
117 mIBinderCallback = ContentSwitches.SWITCH_GPU_PROCESS.equals(processType )
118 ? new GpuProcessCallback()
119 : null;
120 initLinker();
121 }
65 122
66 ChildProcessLauncher.start(ContextUtils.getApplicationContext(), paramId , commandLine, 123 private void start(Context context, String[] commandLine,
67 filesToBeMapped, new ChildProcessLauncher.LaunchCallback() { 124 final FileDescriptorInfo[] filesToBeMapped, ChildProcessCreationPara ms params,
125 boolean sandboxed, boolean alwaysInForeground) {
126 boolean bindToCallerCheck = params == null ? false : params.getBindToCal lerCheck();
127 Bundle serviceBundle = createServiceBundle(bindToCallerCheck);
128 onBeforeConnectionAllocated(serviceBundle);
129
130 Bundle connectionBundle = createConnectionBundle(commandLine, filesToBeM apped);
131 ChildProcessLauncher.start(context, serviceBundle,
132 connectionBundle, new ChildProcessLauncher.LaunchCallback() {
68 @Override 133 @Override
69 public void onChildProcessStarted(ChildProcessConnection con nection) { 134 public void onChildProcessStarted(ChildProcessConnection con nection) {
70 mChildProcessConnection = connection; 135 mChildProcessConnection = connection;
136
137 // Proactively close the FDs rather than waiting for the GC to do it.
138 try {
139 for (FileDescriptorInfo fileInfo : filesToBeMapped) {
140 fileInfo.fd.close();
141 }
142 } catch (IOException ioe) {
143 Log.w(TAG, "Failed to close FD.", ioe);
144 }
145
71 if (mNativeChildProcessLauncherHelper != 0) { 146 if (mNativeChildProcessLauncherHelper != 0) {
72 nativeOnChildProcessStarted( 147 nativeOnChildProcessStarted(
73 mNativeChildProcessLauncherHelper, getPid()) ; 148 mNativeChildProcessLauncherHelper, getPid()) ;
74 } 149 }
75 mNativeChildProcessLauncherHelper = 0; 150 mNativeChildProcessLauncherHelper = 0;
76 } 151 }
77 }); 152 }, getIBinderCallback(), sandboxed, alwaysInForeground, params);
78 } 153 }
79 154
80 private int getPid() { 155 private int getPid() {
81 return mChildProcessConnection == null ? NULL_PROCESS_HANDLE 156 return mChildProcessConnection == null ? NULL_PROCESS_HANDLE
82 : mChildProcessConnection.getPid( ); 157 : mChildProcessConnection.getPid( );
83 } 158 }
84 159
85 // Called on client (UI or IO) thread. 160 // Called on client (UI or IO) thread.
86 @CalledByNative 161 @CalledByNative
87 private boolean isOomProtected() { 162 private boolean isOomProtected() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 } catch (RuntimeException e) { 198 } catch (RuntimeException e) {
124 // Unittest packages do not declare services. Some tests require a r ealistic number 199 // Unittest packages do not declare services. Some tests require a r ealistic number
125 // to test child process policies, so pick a high-ish number here. 200 // to test child process policies, so pick a high-ish number here.
126 return 65535; 201 return 65535;
127 } 202 }
128 } 203 }
129 204
130 // Can be called on a number of threads, including launcher, and binder. 205 // Can be called on a number of threads, including launcher, and binder.
131 private static native void nativeOnChildProcessStarted( 206 private static native void nativeOnChildProcessStarted(
132 long nativeChildProcessLauncherHelper, int pid); 207 long nativeChildProcessLauncherHelper, int pid);
208
209 private static boolean sLinkerInitialized;
210 private static long sLinkerLoadAddress;
211 @VisibleForTesting
212 static void initLinker() {
213 assert LauncherThread.runningOnLauncherThread();
214 if (sLinkerInitialized) return;
215 if (Linker.isUsed()) {
216 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress();
217 if (sLinkerLoadAddress == 0) {
218 Log.i(TAG, "Shared RELRO support disabled!");
219 }
220 }
221 sLinkerInitialized = true;
222 }
223
224 private static ChromiumLinkerParams getLinkerParamsForNewConnection() {
225 assert LauncherThread.runningOnLauncherThread();
226 assert sLinkerInitialized;
227
228 if (sLinkerLoadAddress == 0) return null;
229
230 // Always wait for the shared RELROs in service processes.
231 final boolean waitForSharedRelros = true;
232 if (Linker.areTestsEnabled()) {
233 Linker linker = Linker.getInstance();
234 return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRel ros,
235 linker.getTestRunnerClassNameForTesting(),
236 linker.getImplementationForTesting());
237 } else {
238 return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRel ros);
239 }
240 }
241
242 /**
243 * Creates the common bundle to be passed to child processes through the ser vice binding intent.
244 * If the service gets recreated by the framework the intent will be reused, so these parameters
245 * should be common to all processes of that type.
246 *
247 * @param commandLine Command line params to be passed to the service.
248 * @param linkerParams Linker params to start the service.
249 */
250 // TODO(jcivelli): make private once warmup connection code is move from Chi ldProcessLauncher to
251 // this class and remove initLinker call.
252 static Bundle createServiceBundle(boolean bindToCallerCheck) {
253 initLinker();
254 Bundle bundle = new Bundle();
255 bundle.putBoolean(ChildProcessConstants.EXTRA_BIND_TO_CALLER, bindToCall erCheck);
256 bundle.putParcelable(
257 ChildProcessConstants.EXTRA_LINKER_PARAMS, getLinkerParamsForNew Connection());
258 return bundle;
259 }
260
261 @VisibleForTesting
262 public static Bundle createConnectionBundle(
263 String[] commandLine, FileDescriptorInfo[] filesToBeMapped) {
264 assert sLinkerInitialized;
265
266 Bundle bundle = new Bundle();
267 bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, commandL ine);
268 bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, filesToBeMa pped);
269 // content specific parameters.
270 bundle.putInt(ChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCoun t());
271 bundle.putLong(ChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.get Mask());
272 bundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS, Linker.getInstance() .getSharedRelros());
273 return bundle;
274 }
275
276 // Below are methods that will eventually be moved to a content delegate cla ss.
277
278 private void onBeforeConnectionAllocated(Bundle commonParameters) {
279 // TODO(jcivelli): move createServiceBundle in there.
280 }
281
282 private IBinder getIBinderCallback() {
283 return mIBinderCallback;
284 }
285
286 // Testing only related methods.
287 @VisibleForTesting
288 public static ChildProcessLauncherHelper createAndStartForTesting(long nativ ePointer,
289 String[] commandLine, FileDescriptorInfo[] filesToBeMapped,
290 ChildProcessCreationParams creationParams, boolean sandboxed,
291 boolean alwaysInForeground) {
292 String processType =
293 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE);
294 ChildProcessLauncherHelper launcherHelper =
295 new ChildProcessLauncherHelper(nativePointer, processType);
296 launcherHelper.start(ContextUtils.getApplicationContext(), commandLine, filesToBeMapped,
297 creationParams, sandboxed, alwaysInForeground);
298 return launcherHelper;
299 }
300
301 @VisibleForTesting
302 public ChildProcessConnection getChildProcessConnection() {
303 return mChildProcessConnection;
304 }
133 } 305 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698