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

Side by Side Diff: content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java

Issue 2049843004: Upstream: Renderers are running in WebAPKs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Always check command line flags in getNum(Class)ofService(). Created 4 years, 5 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 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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.app; 5 package org.chromium.content.app;
6 6
7 import android.app.Service;
8 import android.content.Context; 7 import android.content.Context;
9 import android.content.Intent; 8 import android.content.Intent;
10 import android.graphics.SurfaceTexture; 9 import android.graphics.SurfaceTexture;
11 import android.os.Bundle; 10 import android.os.Bundle;
12 import android.os.IBinder; 11 import android.os.IBinder;
13 import android.os.Parcelable; 12 import android.os.Parcelable;
14 import android.os.Process; 13 import android.os.Process;
15 import android.os.RemoteException; 14 import android.os.RemoteException;
16 import android.view.Surface; 15 import android.view.Surface;
17 16
18 import org.chromium.base.BaseSwitches; 17 import org.chromium.base.BaseSwitches;
19 import org.chromium.base.CommandLine; 18 import org.chromium.base.CommandLine;
20 import org.chromium.base.ContextUtils; 19 import org.chromium.base.ContextUtils;
21 import org.chromium.base.Log; 20 import org.chromium.base.Log;
22 import org.chromium.base.annotations.CalledByNative; 21 import org.chromium.base.annotations.CalledByNative;
23 import org.chromium.base.annotations.JNINamespace; 22 import org.chromium.base.annotations.JNINamespace;
24 import org.chromium.base.annotations.SuppressFBWarnings; 23 import org.chromium.base.annotations.SuppressFBWarnings;
25 import org.chromium.base.library_loader.LibraryLoader; 24 import org.chromium.base.library_loader.LibraryLoader;
26 import org.chromium.base.library_loader.Linker; 25 import org.chromium.base.library_loader.Linker;
27 import org.chromium.base.library_loader.ProcessInitException; 26 import org.chromium.base.library_loader.ProcessInitException;
28 import org.chromium.content.browser.ChildProcessConstants; 27 import org.chromium.content.browser.ChildProcessConstants;
29 import org.chromium.content.browser.ChildProcessCreationParams; 28 import org.chromium.content.browser.ChildProcessCreationParams;
30 import org.chromium.content.browser.ChildProcessLauncher;
31 import org.chromium.content.browser.FileDescriptorInfo; 29 import org.chromium.content.browser.FileDescriptorInfo;
32 import org.chromium.content.common.ContentSwitches; 30 import org.chromium.content.common.ContentSwitches;
33 import org.chromium.content.common.IChildProcessCallback; 31 import org.chromium.content.common.IChildProcessCallback;
34 import org.chromium.content.common.IChildProcessService; 32 import org.chromium.content.common.IChildProcessService;
35 import org.chromium.content.common.SurfaceWrapper; 33 import org.chromium.content.common.SurfaceWrapper;
36 34
37 import java.util.concurrent.Semaphore; 35 import java.util.concurrent.Semaphore;
38 import java.util.concurrent.atomic.AtomicReference; 36 import java.util.concurrent.atomic.AtomicReference;
39 37
40 /** 38 /**
41 * This is the base class for child services; the [Non]SandboxedProcessService0, 1.. etc 39 * This class implements all of the functionality for {@link ChildProcessService } which owns an
42 * subclasses provide the concrete service entry points, to enable the browser t o connect 40 * object of {@link ChildProcessServiceImpl}.
43 * to more than one distinct process (i.e. one process per service number, up to limit of N). 41 * It makes possible that WebAPK's ChildProcessService owns a ChildProcessServic eImpl object
44 * The embedding application must declare these service instances in the applica tion section 42 * and uses the same functionalities to create renderer process for WebAPKs when "--enable-webapk"
45 * of its AndroidManifest.xml, for example with N entries of the form:- 43 * flag is turned on.
46 * <service android:name="org.chromium.content.app.[Non]SandboxedProcessServ iceX"
47 * android:process=":[non]sandboxed_processX" />
48 * for X in 0...N-1 (where N is {@link ChildProcessLauncher#MAX_REGISTERED_SERVI CES})
49 */ 44 */
50 @JNINamespace("content") 45 @JNINamespace("content")
51 @SuppressWarnings("SynchronizeOnNonFinalField") 46 @SuppressWarnings("SynchronizeOnNonFinalField")
52 public class ChildProcessService extends Service { 47 public class ChildProcessServiceImpl {
53 private static final String MAIN_THREAD_NAME = "ChildProcessMain"; 48 private static final String MAIN_THREAD_NAME = "ChildProcessMain";
54 private static final String TAG = "ChildProcessService"; 49 private static final String TAG = "ChildProcessService";
55 protected static final FileDescriptorInfo[] EMPTY_FILE_DESCRIPTOR_INFO = {}; 50 protected static final FileDescriptorInfo[] EMPTY_FILE_DESCRIPTOR_INFO = {};
56 private IChildProcessCallback mCallback; 51 private IChildProcessCallback mCallback;
57 52
58 // This is the native "Main" thread for the renderer / utility process. 53 // This is the native "Main" thread for the renderer / utility process.
59 private Thread mMainThread; 54 private Thread mMainThread;
60 // Parameters received via IPC, only accessed while holding the mMainThread monitor. 55 // Parameters received via IPC, only accessed while holding the mMainThread monitor.
61 private String[] mCommandLineParams; 56 private String[] mCommandLineParams;
62 private int mCpuCount; 57 private int mCpuCount;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 getServiceInfo(args); 92 getServiceInfo(args);
98 return Process.myPid(); 93 return Process.myPid();
99 } 94 }
100 95
101 @Override 96 @Override
102 public void crashIntentionallyForTesting() { 97 public void crashIntentionallyForTesting() {
103 Process.killProcess(Process.myPid()); 98 Process.killProcess(Process.myPid());
104 } 99 }
105 }; 100 };
106 101
107 @Override 102 // The ClassLoader for the host browser context.
108 public void onCreate() { 103 private ClassLoader mHostClassLoader;
104
105 /* package */ static Context getContext() {
106 return sContext.get();
107 }
108
109 /**
110 * Loads Chrome's native libraries and initializes a ChildProcessServiceImpl .
111 * @param context The application context.
112 * @param hostBrowserContext The context of the host browser (i.e. Chrome).
113 */
114 public void create(final Context context, final Context hostBrowserContext) {
115 mHostClassLoader = hostBrowserContext.getClassLoader();
109 Log.i(TAG, "Creating new ChildProcessService pid=%d", Process.myPid()); 116 Log.i(TAG, "Creating new ChildProcessService pid=%d", Process.myPid());
110 if (sContext.get() != null) { 117 if (sContext.get() != null) {
111 throw new RuntimeException("Illegal child process reuse."); 118 throw new RuntimeException("Illegal child process reuse.");
112 } 119 }
113 sContext.set(this); 120 sContext.set(context);
114 super.onCreate();
115 121
116 ContextUtils.initApplicationContext(getApplicationContext()); 122 // Initialize the context for the application that owns this ChildProces sServiceImpl object.
123 ContextUtils.initApplicationContext(context);
117 124
118 mMainThread = new Thread(new Runnable() { 125 mMainThread = new Thread(new Runnable() {
119 @Override 126 @Override
120 @SuppressFBWarnings("DM_EXIT") 127 @SuppressFBWarnings("DM_EXIT")
121 public void run() { 128 public void run() {
122 try { 129 try {
123 // CommandLine must be initialized before everything else. 130 // CommandLine must be initialized before everything else.
124 synchronized (mMainThread) { 131 synchronized (mMainThread) {
125 while (mCommandLineParams == null) { 132 while (mCommandLineParams == null) {
126 mMainThread.wait(); 133 mMainThread.wait();
(...skipping 18 matching lines...) Expand all
145 } 152 }
146 } 153 }
147 boolean isLoaded = false; 154 boolean isLoaded = false;
148 if (CommandLine.getInstance().hasSwitch( 155 if (CommandLine.getInstance().hasSwitch(
149 BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER)) { 156 BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER)) {
150 android.os.Debug.waitForDebugger(); 157 android.os.Debug.waitForDebugger();
151 } 158 }
152 159
153 boolean loadAtFixedAddressFailed = false; 160 boolean loadAtFixedAddressFailed = false;
154 try { 161 try {
155 LibraryLoader.get(mLibraryProcessType).loadNow(getApplic ationContext()); 162 LibraryLoader.get(mLibraryProcessType).loadNow(hostBrows erContext);
156 isLoaded = true; 163 isLoaded = true;
157 } catch (ProcessInitException e) { 164 } catch (ProcessInitException e) {
158 if (requestedSharedRelro) { 165 if (requestedSharedRelro) {
159 Log.w(TAG, "Failed to load native library with share d RELRO, " 166 Log.w(TAG, "Failed to load native library with share d RELRO, "
160 + "retrying without"); 167 + "retrying without");
161 loadAtFixedAddressFailed = true; 168 loadAtFixedAddressFailed = true;
162 } else { 169 } else {
163 Log.e(TAG, "Failed to load native library", e); 170 Log.e(TAG, "Failed to load native library", e);
164 } 171 }
165 } 172 }
166 if (!isLoaded && requestedSharedRelro) { 173 if (!isLoaded && requestedSharedRelro) {
167 linker.disableSharedRelros(); 174 linker.disableSharedRelros();
168 try { 175 try {
169 LibraryLoader.get(mLibraryProcessType).loadNow(getAp plicationContext()); 176 LibraryLoader.get(mLibraryProcessType).loadNow(hostB rowserContext);
170 isLoaded = true; 177 isLoaded = true;
171 } catch (ProcessInitException e) { 178 } catch (ProcessInitException e) {
172 Log.e(TAG, "Failed to load native library on retry", e); 179 Log.e(TAG, "Failed to load native library on retry", e);
173 } 180 }
174 } 181 }
175 if (!isLoaded) { 182 if (!isLoaded) {
176 System.exit(-1); 183 System.exit(-1);
177 } 184 }
178 LibraryLoader.get(mLibraryProcessType) 185 LibraryLoader.get(mLibraryProcessType)
179 .registerRendererProcessHistogram(requestedSharedRel ro, 186 .registerRendererProcessHistogram(requestedSharedRel ro,
180 loadAtFixedAddressFailed); 187 loadAtFixedAddressFailed);
181 LibraryLoader.get(mLibraryProcessType).initialize(); 188 LibraryLoader.get(mLibraryProcessType).initialize();
182 synchronized (mMainThread) { 189 synchronized (mMainThread) {
183 mLibraryInitialized = true; 190 mLibraryInitialized = true;
184 mMainThread.notifyAll(); 191 mMainThread.notifyAll();
185 while (mFdInfos == null) { 192 while (mFdInfos == null) {
186 mMainThread.wait(); 193 mMainThread.wait();
187 } 194 }
188 } 195 }
189 for (FileDescriptorInfo fdInfo : mFdInfos) { 196 for (FileDescriptorInfo fdInfo : mFdInfos) {
190 nativeRegisterGlobalFileDescriptor( 197 nativeRegisterGlobalFileDescriptor(
191 fdInfo.mId, fdInfo.mFd.detachFd(), fdInfo.mOffse t, fdInfo.mSize); 198 fdInfo.mId, fdInfo.mFd.detachFd(), fdInfo.mOffse t, fdInfo.mSize);
192 } 199 }
193 nativeInitChildProcess(ChildProcessService.this, mCpuCount, mCpuFeatures); 200 nativeInitChildProcessImpl(ChildProcessServiceImpl.this, mCp uCount,
201 mCpuFeatures);
194 if (mActivitySemaphore.tryAcquire()) { 202 if (mActivitySemaphore.tryAcquire()) {
195 ContentMain.start(); 203 ContentMain.start();
196 nativeExitChildProcess(); 204 nativeExitChildProcess();
197 } 205 }
198 } catch (InterruptedException e) { 206 } catch (InterruptedException e) {
199 Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e); 207 Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e);
200 } catch (ProcessInitException e) { 208 } catch (ProcessInitException e) {
201 Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e); 209 Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e);
202 } 210 }
203 } 211 }
204 }, MAIN_THREAD_NAME); 212 }, MAIN_THREAD_NAME);
205 mMainThread.start(); 213 mMainThread.start();
206 } 214 }
207 215
208 @Override
209 @SuppressFBWarnings("DM_EXIT") 216 @SuppressFBWarnings("DM_EXIT")
210 public void onDestroy() { 217 public void destroy() {
211 Log.i(TAG, "Destroying ChildProcessService pid=%d", Process.myPid()); 218 Log.i(TAG, "Destroying ChildProcessService pid=%d", Process.myPid());
212 super.onDestroy();
213 if (mActivitySemaphore.tryAcquire()) { 219 if (mActivitySemaphore.tryAcquire()) {
214 // TODO(crbug.com/457406): This is a bit hacky, but there is no know n better solution 220 // TODO(crbug.com/457406): This is a bit hacky, but there is no know n better solution
215 // as this service will get reused (at least if not sandboxed). 221 // as this service will get reused (at least if not sandboxed).
216 // In fact, we might really want to always exit() from onDestroy(), not just from 222 // In fact, we might really want to always exit() from onDestroy(), not just from
217 // the early return here. 223 // the early return here.
218 System.exit(0); 224 System.exit(0);
219 return; 225 return;
220 } 226 }
221 synchronized (mMainThread) { 227 synchronized (mMainThread) {
222 try { 228 try {
223 while (!mLibraryInitialized) { 229 while (!mLibraryInitialized) {
224 // Avoid a potential race in calling through to native code before the library 230 // Avoid a potential race in calling through to native code before the library
225 // has loaded. 231 // has loaded.
226 mMainThread.wait(); 232 mMainThread.wait();
227 } 233 }
228 } catch (InterruptedException e) { 234 } catch (InterruptedException e) {
229 // Ignore 235 // Ignore
230 } 236 }
231 } 237 }
232 // Try to shutdown the MainThread gracefully, but it might not 238 // Try to shutdown the MainThread gracefully, but it might not
233 // have chance to exit normally. 239 // have chance to exit normally.
234 nativeShutdownMainThread(); 240 nativeShutdownMainThread();
235 } 241 }
236 242
237 @Override 243 public IBinder bind(Intent intent) {
238 public IBinder onBind(Intent intent) {
239 // We call stopSelf() to request that this service be stopped as soon as the client
240 // unbinds. Otherwise the system may keep it around and available for a reconnect. The
241 // child processes do not currently support reconnect; they must be init ialized from
242 // scratch every time.
243 stopSelf();
244 initializeParams(intent); 244 initializeParams(intent);
245 return mBinder; 245 return mBinder;
246 } 246 }
247 247
248 /** 248 void initializeParams(Intent intent) {
249 * Helper method to initialize the params from intent.
250 * @param intent Intent to launch the service.
251 */
252 protected void initializeParams(Intent intent) {
253 synchronized (mMainThread) { 249 synchronized (mMainThread) {
254 mCommandLineParams = 250 mCommandLineParams =
255 intent.getStringArrayExtra(ChildProcessConstants.EXTRA_COMMA ND_LINE); 251 intent.getStringArrayExtra(ChildProcessConstants.EXTRA_COMMA ND_LINE);
256 // mLinkerParams is never used if Linker.isUsed() returns false. 252 // mLinkerParams is never used if Linker.isUsed() returns false.
257 // See onCreate(). 253 // See onCreate().
258 mLinkerParams = new ChromiumLinkerParams(intent); 254 mLinkerParams = new ChromiumLinkerParams(intent);
259 mLibraryProcessType = ChildProcessCreationParams.getLibraryProcessTy pe(intent); 255 mLibraryProcessType = ChildProcessCreationParams.getLibraryProcessTy pe(intent);
260 mIsBound = true; 256 mIsBound = true;
261 mMainThread.notifyAll(); 257 mMainThread.notifyAll();
262 } 258 }
263 } 259 }
264 260
265 /**
266 * Helper method to get the information about the service from a given bundl e.
267 * @param bundle Bundle that contains the information to start the service.
268 */
269 void getServiceInfo(Bundle bundle) { 261 void getServiceInfo(Bundle bundle) {
270 // Required to unparcel FileDescriptorInfo. 262 // Required to unparcel FileDescriptorInfo.
271 bundle.setClassLoader(getClassLoader()); 263 bundle.setClassLoader(mHostClassLoader);
272 synchronized (mMainThread) { 264 synchronized (mMainThread) {
273 // Allow the command line to be set via bind() intent or setupConnec tion, but 265 // Allow the command line to be set via bind() intent or setupConnec tion, but
274 // the FD can only be transferred here. 266 // the FD can only be transferred here.
275 if (mCommandLineParams == null) { 267 if (mCommandLineParams == null) {
276 mCommandLineParams = 268 mCommandLineParams =
277 bundle.getStringArray(ChildProcessConstants.EXTRA_COMMAN D_LINE); 269 bundle.getStringArray(ChildProcessConstants.EXTRA_COMMAN D_LINE);
278 } 270 }
279 // We must have received the command line by now 271 // We must have received the command line by now
280 assert mCommandLineParams != null; 272 assert mCommandLineParams != null;
281 mCpuCount = bundle.getInt(ChildProcessConstants.EXTRA_CPU_COUNT); 273 mCpuCount = bundle.getInt(ChildProcessConstants.EXTRA_CPU_COUNT);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 * This includes the IPC channel, the crash dump signals and resource relate d 408 * This includes the IPC channel, the crash dump signals and resource relate d
417 * files. 409 * files.
418 */ 410 */
419 private static native void nativeRegisterGlobalFileDescriptor( 411 private static native void nativeRegisterGlobalFileDescriptor(
420 int id, int fd, long offset, long size); 412 int id, int fd, long offset, long size);
421 413
422 /** 414 /**
423 * The main entry point for a child process. This should be called from a ne w thread since 415 * The main entry point for a child process. This should be called from a ne w thread since
424 * it will not return until the child process exits. See child_process_servi ce.{h,cc} 416 * it will not return until the child process exits. See child_process_servi ce.{h,cc}
425 * 417 *
426 * @param service The current ChildProcessService object. 418 * @param serviceImpl The current ChildProcessServiceImpl object.
427 * renderer. 419 * renderer.
428 */ 420 */
429 private static native void nativeInitChildProcess( 421 private static native void nativeInitChildProcessImpl(
430 ChildProcessService service, int cpuCount, long cpuFeatures); 422 ChildProcessServiceImpl serviceImpl, int cpuCount, long cpuFeatures) ;
431 423
432 /** 424 /**
433 * Force the child process to exit. 425 * Force the child process to exit.
434 */ 426 */
435 private static native void nativeExitChildProcess(); 427 private static native void nativeExitChildProcess();
436 428
437 private native void nativeShutdownMainThread(); 429 private native void nativeShutdownMainThread();
438 } 430 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698