Commit ee805c1e authored by qinmin's avatar qinmin Committed by Commit bot

Introduce background Download process to android

This change adds a new download process to android.
This process will handle download in the background and may outlive chrome
Unlike other ChildProcessService, DownloadProcessService is a started service as it manage its own lifecycle:
When a download started, the download service will start running
When all download finishes, the Download service will be stopped

BUG=545640

Review URL: https://codereview.chromium.org/1622743005

Cr-Commit-Position: refs/heads/master@{#373608}
parent 371faba5
...@@ -643,6 +643,17 @@ android:value="true" /> ...@@ -643,6 +643,17 @@ android:value="true" />
android:exported="false" /> android:exported="false" />
{% endfor %} {% endfor %}
<!-- Background download process, it may outlive chrome if download does not finish
when user kills chrome. Once created, the process will manage its own lifecycle.
To work around an issue in earlier android versions that a bound service will
get killed when chrome goes away, this service will only communicate with the
browser process through callbacks. -->
<service android:name="org.chromium.content.app.DownloadProcessService"
android:process=":download"
android:permission="{{ manifest_package }}.permission.CHILD_SERVICE"
android:isolatedProcess="false"
android:exported="false"/>
<receiver android:name="org.chromium.chrome.browser.download.DownloadBroadcastReceiver" <receiver android:name="org.chromium.chrome.browser.download.DownloadBroadcastReceiver"
android:exported="false"> android:exported="false">
<intent-filter> <intent-filter>
......
...@@ -12,6 +12,7 @@ content_app_sources = [ ...@@ -12,6 +12,7 @@ content_app_sources = [
"android/content_jni_onload.cc", "android/content_jni_onload.cc",
"android/content_main.cc", "android/content_main.cc",
"android/content_main.h", "android/content_main.h",
"android/download_main.cc",
"android/library_loader_hooks.cc", "android/library_loader_hooks.cc",
"android/library_loader_hooks.h", "android/library_loader_hooks.h",
"content_main.cc", "content_main.cc",
......
// Copyright 2016 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 "base/message_loop/message_loop.h"
#include "base/threading/platform_thread.h"
#include "content/public/common/main_function_params.h"
namespace content {
// Mainline routine for running as the download process.
int DownloadMain(const MainFunctionParams& parameters) {
// The main message loop of the utility process.
base::MessageLoop main_message_loop;
base::PlatformThread::SetName("CrDownloadMain");
base::MessageLoop::current()->Run();
return 0;
}
} // namespace content
...@@ -121,6 +121,9 @@ extern int PpapiBrokerMain(const MainFunctionParams&); ...@@ -121,6 +121,9 @@ extern int PpapiBrokerMain(const MainFunctionParams&);
#endif #endif
extern int RendererMain(const content::MainFunctionParams&); extern int RendererMain(const content::MainFunctionParams&);
extern int UtilityMain(const MainFunctionParams&); extern int UtilityMain(const MainFunctionParams&);
#if defined(OS_ANDROID)
extern int DownloadMain(const MainFunctionParams&);
#endif
} // namespace content } // namespace content
namespace content { namespace content {
...@@ -343,6 +346,9 @@ int RunNamedProcessTypeMain( ...@@ -343,6 +346,9 @@ int RunNamedProcessTypeMain(
{ switches::kUtilityProcess, UtilityMain }, { switches::kUtilityProcess, UtilityMain },
{ switches::kRendererProcess, RendererMain }, { switches::kRendererProcess, RendererMain },
{ switches::kGpuProcess, GpuMain }, { switches::kGpuProcess, GpuMain },
#if defined(OS_ANDROID)
{ switches::kDownloadProcess, DownloadMain},
#endif
#endif // !CHROME_MULTIPLE_DLL_BROWSER #endif // !CHROME_MULTIPLE_DLL_BROWSER
}; };
......
...@@ -13,12 +13,16 @@ ...@@ -13,12 +13,16 @@
#include "base/android/jni_array.h" #include "base/android/jni_array.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "content/browser/file_descriptor_info_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/media/android/browser_media_player_manager.h" #include "content/browser/media/android/browser_media_player_manager.h"
#include "content/browser/media/android/media_web_contents_observer_android.h" #include "content/browser/media/android/media_web_contents_observer_android.h"
#include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "jni/ChildProcessLauncher_jni.h" #include "jni/ChildProcessLauncher_jni.h"
#include "media/base/android/media_player_android.h" #include "media/base/android/media_player_android.h"
...@@ -84,6 +88,21 @@ static void SetSurfacePeer( ...@@ -84,6 +88,21 @@ static void SetSurfacePeer(
} }
} }
void LaunchDownloadProcess(base::CommandLine* cmd_line) {
scoped_ptr<base::CommandLine> cmd_line_deleter(cmd_line);
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
// Create the Command line String[]
ScopedJavaLocalRef<jobjectArray> j_argv =
ToJavaArrayOfStrings(env, cmd_line->argv());
// TODO(qinmin): pass download parameters here.
Java_ChildProcessLauncher_startDownloadProcessIfNecessary(
env, base::android::GetApplicationContext(), j_argv.obj());
}
} // anonymous namespace } // anonymous namespace
// Called from ChildProcessLauncher.java when the ChildProcess was // Called from ChildProcessLauncher.java when the ChildProcess was
...@@ -103,6 +122,32 @@ static void OnChildProcessStarted(JNIEnv*, ...@@ -103,6 +122,32 @@ static void OnChildProcessStarted(JNIEnv*,
delete callback; delete callback;
} }
void StartDownloadProcessIfNecessary() {
base::FilePath exe_path = content::ChildProcessHost::GetChildPath(
content::ChildProcessHost::CHILD_NORMAL);
if (exe_path.empty()) {
NOTREACHED() << "Unable to get download process binary name.";
return;
}
base::CommandLine* cmd_line = new base::CommandLine(exe_path);
cmd_line->AppendSwitchASCII(switches::kProcessType,
switches::kDownloadProcess);
cmd_line->AppendSwitch(switches::kNoSandbox);
const base::CommandLine browser_command_line =
*base::CommandLine::ForCurrentProcess();
static const char* kForwardSwitches[] = {
switches::kDisableLogging,
switches::kEnableLogging,
switches::kLoggingLevel,
};
cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
arraysize(kForwardSwitches));
CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
base::Bind(&LaunchDownloadProcess, cmd_line));
}
void StartChildProcess( void StartChildProcess(
const base::CommandLine::StringVector& argv, const base::CommandLine::StringVector& argv,
int child_process_id, int child_process_id,
......
...@@ -29,6 +29,10 @@ void StartChildProcess( ...@@ -29,6 +29,10 @@ void StartChildProcess(
const std::map<int, base::MemoryMappedFile::Region>& regions, const std::map<int, base::MemoryMappedFile::Region>& regions,
const StartChildProcessCallback& callback); const StartChildProcessCallback& callback);
// Starts the background download process if it hasn't been started.
// TODO(qinmin): pass the download parameters here and pass it to java side.
void StartDownloadProcessIfNecessary();
// Stops a child process based on the handle returned form // Stops a child process based on the handle returned form
// StartChildProcess. // StartChildProcess.
void StopChildProcess(base::ProcessHandle handle); void StopChildProcess(base::ProcessHandle handle);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
'app/android/content_jni_onload.cc', 'app/android/content_jni_onload.cc',
'app/android/content_main.cc', 'app/android/content_main.cc',
'app/android/content_main.h', 'app/android/content_main.h',
'app/android/download_main.cc',
'app/android/library_loader_hooks.cc', 'app/android/library_loader_hooks.cc',
'app/android/library_loader_hooks.h', 'app/android/library_loader_hooks.h',
'app/content_main.cc', 'app/content_main.cc',
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016 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.
-->
<resources>
<!-- Download service notification -->
<item type="id" name="download_service_notification" />
</resources>
...@@ -27,8 +27,8 @@ import org.chromium.base.library_loader.LibraryProcessType; ...@@ -27,8 +27,8 @@ import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.Linker; import org.chromium.base.library_loader.Linker;
import org.chromium.base.library_loader.ProcessInitException; import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.content.browser.ChildProcessConstants; import org.chromium.content.browser.ChildProcessConstants;
import org.chromium.content.browser.ChildProcessLauncher;
import org.chromium.content.browser.FileDescriptorInfo; import org.chromium.content.browser.FileDescriptorInfo;
import org.chromium.content.common.ContentSwitches;
import org.chromium.content.common.IChildProcessCallback; import org.chromium.content.common.IChildProcessCallback;
import org.chromium.content.common.IChildProcessService; import org.chromium.content.common.IChildProcessService;
import org.chromium.content.common.SurfaceWrapper; import org.chromium.content.common.SurfaceWrapper;
...@@ -51,6 +51,7 @@ import java.util.concurrent.atomic.AtomicReference; ...@@ -51,6 +51,7 @@ import java.util.concurrent.atomic.AtomicReference;
public class ChildProcessService extends Service { public class ChildProcessService extends Service {
private static final String MAIN_THREAD_NAME = "ChildProcessMain"; private static final String MAIN_THREAD_NAME = "ChildProcessMain";
private static final String TAG = "ChildProcessService"; private static final String TAG = "ChildProcessService";
protected static final FileDescriptorInfo[] EMPTY_FILE_DESCRIPTOR_INFO = {};
private IChildProcessCallback mCallback; private IChildProcessCallback mCallback;
// This is the native "Main" thread for the renderer / utility process. // This is the native "Main" thread for the renderer / utility process.
...@@ -289,10 +290,10 @@ public class ChildProcessService extends Service { ...@@ -289,10 +290,10 @@ public class ChildProcessService extends Service {
mFdInfos = new FileDescriptorInfo[fdInfosAsParcelable.length]; mFdInfos = new FileDescriptorInfo[fdInfosAsParcelable.length];
System.arraycopy(fdInfosAsParcelable, 0, mFdInfos, 0, fdInfosAsParcelable.length); System.arraycopy(fdInfosAsParcelable, 0, mFdInfos, 0, fdInfosAsParcelable.length);
} else { } else {
// TODO(qinmin): On earlier androird versions, a started service running in another String processType = ContentSwitches.getSwitchValue(
// process can get killed after Chrome is killed. To work around this issue, client mCommandLineParams, ContentSwitches.SWITCH_PROCESS_TYPE);
// will never bind to the service. As a result, the file descriptors needs to be assert ContentSwitches.SWITCH_DOWNLOAD_PROCESS.equals(processType);
// passed through an intent when starting the service. mFdInfos = EMPTY_FILE_DESCRIPTOR_INFO;
} }
Bundle sharedRelros = bundle.getBundle(Linker.EXTRA_LINKER_SHARED_RELROS); Bundle sharedRelros = bundle.getBundle(Linker.EXTRA_LINKER_SHARED_RELROS);
if (sharedRelros != null) { if (sharedRelros != null) {
......
// Copyright 2016 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.content.app;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import org.chromium.base.Log;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.content.R;
import org.chromium.content.browser.ChildProcessConstants;
import org.chromium.content.common.IChildProcessCallback;
/**
* Background download process for handling all transferable downloads.
*/
@JNINamespace("content")
public class DownloadProcessService extends ChildProcessService {
private static final String TAG = "DownloadProcess";
private long mClientContext;
private IChildProcessCallback mCallback;
private int mDownloadCount;
@Override
public void onCreate() {
super.onCreate();
// TODO(qinmin): Use the first pending download as notification, or
// get a more proper notification for this.
startForeground(R.id.download_service_notification, new Notification());
}
@Override
@SuppressLint("NewApi")
public int onStartCommand(Intent intent, int flags, int startId) {
assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
initializeParams(intent);
Bundle bundle = intent.getExtras();
if (bundle != null) {
IBinder binder = bundle.getBinder(ChildProcessConstants.EXTRA_CHILD_PROCESS_CALLBACK);
mCallback = IChildProcessCallback.Stub.asInterface(binder);
getServiceInfo(bundle);
}
return START_STICKY;
}
/**
* Will be called by the native side when a download starts or is rejected.
*
* @CalledByNative
*/
private void onDownloadStarted(boolean started, int downloadId) {
if (mCallback != null) {
try {
mCallback.onDownloadStarted(started, downloadId);
} catch (RemoteException e) {
Log.e(TAG, "Unable to callback the browser process.", e);
}
}
if (started) mDownloadCount++;
}
/**
* Will be called by the native side when a download completes.
*
* @CalledByNative
*/
private void onDownloadCompleted(boolean success) {
mDownloadCount--;
if (mDownloadCount == 0) stopSelf();
}
}
\ No newline at end of file
...@@ -13,12 +13,10 @@ import android.os.DeadObjectException; ...@@ -13,12 +13,10 @@ import android.os.DeadObjectException;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import org.chromium.base.CpuFeatures;
import org.chromium.base.Log; import org.chromium.base.Log;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent; import org.chromium.base.TraceEvent;
import org.chromium.base.VisibleForTesting; import org.chromium.base.VisibleForTesting;
import org.chromium.base.library_loader.Linker;
import org.chromium.content.app.ChildProcessService; import org.chromium.content.app.ChildProcessService;
import org.chromium.content.app.ChromiumLinkerParams; import org.chromium.content.app.ChromiumLinkerParams;
import org.chromium.content.common.IChildProcessCallback; import org.chromium.content.common.IChildProcessCallback;
...@@ -331,16 +329,9 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection { ...@@ -331,16 +329,9 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
assert mServiceConnectComplete && mService != null; assert mServiceConnectComplete && mService != null;
assert mConnectionParams != null; assert mConnectionParams != null;
Bundle bundle = new Bundle(); Bundle bundle =
bundle.putStringArray( ChildProcessLauncher.createsServiceBundle(mConnectionParams.mCommandLine,
ChildProcessConstants.EXTRA_COMMAND_LINE, mConnectionParams.mCommandLine); mConnectionParams.mFilesToBeMapped, mConnectionParams.mSharedRelros);
bundle.putParcelableArray(
ChildProcessConstants.EXTRA_FILES, mConnectionParams.mFilesToBeMapped);
// Add the CPU properties now.
bundle.putInt(ChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCount());
bundle.putLong(ChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.getMask());
bundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS,
mConnectionParams.mSharedRelros);
try { try {
mPid = mService.setupConnection(bundle, mConnectionParams.mCallback); mPid = mService.setupConnection(bundle, mConnectionParams.mCallback);
assert mPid != 0 : "Child service claims to be run by a process of pid=0."; assert mPid != 0 : "Child service claims to be run by a process of pid=0.";
......
...@@ -19,4 +19,11 @@ public class ChildProcessConstants { ...@@ -19,4 +19,11 @@ public class ChildProcessConstants {
// Used to pass the CPU features mask to child processes. // Used to pass the CPU features mask to child processes.
public static final String EXTRA_CPU_FEATURES = public static final String EXTRA_CPU_FEATURES =
"com.google.android.apps.chrome.extra.cpu_features"; "com.google.android.apps.chrome.extra.cpu_features";
// Used to pass the IChildProcessCallback to a child process. For a started service,
// file descriptors cannot be passed in the intent that starts the service. As a result,
// a Binder object needs to be passed through which the child process can retrieve the file
// descriptors.
public static final String EXTRA_CHILD_PROCESS_CALLBACK =
"com.google.android.apps.chrome.extra.child_process_callback";
} }
...@@ -4,10 +4,14 @@ ...@@ -4,10 +4,14 @@
package org.chromium.content.browser; package org.chromium.content.browser;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.RemoteException; import android.os.RemoteException;
import android.text.TextUtils; import android.text.TextUtils;
...@@ -15,6 +19,7 @@ import android.util.Pair; ...@@ -15,6 +19,7 @@ import android.util.Pair;
import android.view.Surface; import android.view.Surface;
import org.chromium.base.CommandLine; import org.chromium.base.CommandLine;
import org.chromium.base.CpuFeatures;
import org.chromium.base.Log; import org.chromium.base.Log;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent; import org.chromium.base.TraceEvent;
...@@ -24,8 +29,10 @@ import org.chromium.base.annotations.JNINamespace; ...@@ -24,8 +29,10 @@ import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.library_loader.Linker; import org.chromium.base.library_loader.Linker;
import org.chromium.content.app.ChildProcessService; import org.chromium.content.app.ChildProcessService;
import org.chromium.content.app.ChromiumLinkerParams; import org.chromium.content.app.ChromiumLinkerParams;
import org.chromium.content.app.DownloadProcessService;
import org.chromium.content.app.PrivilegedProcessService; import org.chromium.content.app.PrivilegedProcessService;
import org.chromium.content.app.SandboxedProcessService; import org.chromium.content.app.SandboxedProcessService;
import org.chromium.content.common.ContentSwitches;
import org.chromium.content.common.IChildProcessCallback; import org.chromium.content.common.IChildProcessCallback;
import org.chromium.content.common.SurfaceWrapper; import org.chromium.content.common.SurfaceWrapper;
...@@ -47,11 +54,7 @@ public class ChildProcessLauncher { ...@@ -47,11 +54,7 @@ public class ChildProcessLauncher {
static final int CALLBACK_FOR_GPU_PROCESS = 1; static final int CALLBACK_FOR_GPU_PROCESS = 1;
static final int CALLBACK_FOR_RENDERER_PROCESS = 2; static final int CALLBACK_FOR_RENDERER_PROCESS = 2;
static final int CALLBACK_FOR_UTILITY_PROCESS = 3; static final int CALLBACK_FOR_UTILITY_PROCESS = 3;
static final int CALLBACK_FOR_DOWNLOAD_PROCESS = 4;
private static final String SWITCH_PROCESS_TYPE = "type";
private static final String SWITCH_RENDERER_PROCESS = "renderer";
private static final String SWITCH_UTILITY_PROCESS = "utility";
private static final String SWITCH_GPU_PROCESS = "gpu-process";
/** /**
* Allows specifying the package name for looking up child services * Allows specifying the package name for looking up child services
...@@ -110,7 +113,7 @@ public class ChildProcessLauncher { ...@@ -110,7 +113,7 @@ public class ChildProcessLauncher {
mFreeConnectionIndices.add(i); mFreeConnectionIndices.add(i);
} }
mChildClass = mChildClass =
inSandbox ? SandboxedProcessService.class : PrivilegedProcessService.class; inSandbox ? SandboxedProcessService.class : PrivilegedProcessService.class;
mInSandbox = inSandbox; mInSandbox = inSandbox;
} }
...@@ -567,20 +570,6 @@ public class ChildProcessLauncher { ...@@ -567,20 +570,6 @@ public class ChildProcessLauncher {
} }
} }
private static String getSwitchValue(final String[] commandLine, String switchKey) {
if (commandLine == null || switchKey == null) {
return null;
}
// This format should be matched with the one defined in command_line.h.
final String switchKeyPrefix = "--" + switchKey + "=";
for (String command : commandLine) {
if (command != null && command.startsWith(switchKeyPrefix)) {
return command.substring(switchKeyPrefix.length());
}
}
return null;
}
@CalledByNative @CalledByNative
private static FileDescriptorInfo makeFdInfo( private static FileDescriptorInfo makeFdInfo(
int id, int fd, boolean autoClose, long offset, long size) { int id, int fd, boolean autoClose, long offset, long size) {
...@@ -617,13 +606,14 @@ public class ChildProcessLauncher { ...@@ -617,13 +606,14 @@ public class ChildProcessLauncher {
int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS; int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS;
boolean inSandbox = true; boolean inSandbox = true;
String processType = getSwitchValue(commandLine, SWITCH_PROCESS_TYPE); String processType =
if (SWITCH_RENDERER_PROCESS.equals(processType)) { ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWITCH_PROCESS_TYPE);
if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) {
callbackType = CALLBACK_FOR_RENDERER_PROCESS; callbackType = CALLBACK_FOR_RENDERER_PROCESS;
} else if (SWITCH_GPU_PROCESS.equals(processType)) { } else if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) {
callbackType = CALLBACK_FOR_GPU_PROCESS; callbackType = CALLBACK_FOR_GPU_PROCESS;
inSandbox = false; inSandbox = false;
} else if (SWITCH_UTILITY_PROCESS.equals(processType)) { } else if (ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType)) {
// We only support sandboxed right now. // We only support sandboxed right now.
callbackType = CALLBACK_FOR_UTILITY_PROCESS; callbackType = CALLBACK_FOR_UTILITY_PROCESS;
} else { } else {
...@@ -634,6 +624,39 @@ public class ChildProcessLauncher { ...@@ -634,6 +624,39 @@ public class ChildProcessLauncher {
callbackType, inSandbox); callbackType, inSandbox);
} }
/**
* Spawns a background download process if it hasn't been started. The download process will
* manage its own lifecyle and can outlive chrome.
*
* @param context Context used to obtain the application context.
* @param commandLine The child process command line argv.
*/
@SuppressLint("NewApi")
@CalledByNative
private static void startDownloadProcessIfNecessary(
Context context, final String[] commandLine) {
assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
String processType =
ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWITCH_PROCESS_TYPE);
assert ContentSwitches.SWITCH_DOWNLOAD_PROCESS.equals(processType);
Intent intent = new Intent();
intent.setClass(context, DownloadProcessService.class);
intent.setPackage(context.getPackageName());
intent.putExtra(ChildProcessConstants.EXTRA_COMMAND_LINE, commandLine);
Bundle bundle =
createsServiceBundle(commandLine, null, Linker.getInstance().getSharedRelros());
// Pid doesn't matter for download process.
bundle.putBinder(ChildProcessConstants.EXTRA_CHILD_PROCESS_CALLBACK,
createCallback(0, CALLBACK_FOR_DOWNLOAD_PROCESS).asBinder());
intent.putExtras(bundle);
ChromiumLinkerParams linkerParams = getLinkerParamsForNewConnection();
if (linkerParams != null) {
linkerParams.addIntentExtras(intent);
}
context.startService(intent);
}
private static void startInternal( private static void startInternal(
Context context, Context context,
final String[] commandLine, final String[] commandLine,
...@@ -675,6 +698,23 @@ public class ChildProcessLauncher { ...@@ -675,6 +698,23 @@ public class ChildProcessLauncher {
} }
} }
/**
* Create the common bundle to be passed to child processes.
* @param context Application context.
* @param commandLine Command line params to be passed to the service.
* @param linkerParams Linker params to start the service.
*/
protected static Bundle createsServiceBundle(
String[] commandLine, FileDescriptorInfo[] filesToBeMapped, Bundle sharedRelros) {
Bundle bundle = new Bundle();
bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, commandLine);
bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, filesToBeMapped);
bundle.putInt(ChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCount());
bundle.putLong(ChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.getMask());
bundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS, sharedRelros);
return bundle;
}
@VisibleForTesting @VisibleForTesting
static void triggerConnectionSetup( static void triggerConnectionSetup(
final ChildProcessConnection connection, final ChildProcessConnection connection,
...@@ -806,6 +846,15 @@ public class ChildProcessLauncher { ...@@ -806,6 +846,15 @@ public class ChildProcessLauncher {
return ChildProcessLauncher.getSurfaceTextureSurface(surfaceTextureId, return ChildProcessLauncher.getSurfaceTextureSurface(surfaceTextureId,
childProcessId); childProcessId);
} }
@Override
public void onDownloadStarted(boolean started, int downloadId) {
// TODO(qinmin): call native to cancel or proceed with the download.
if (callbackType != CALLBACK_FOR_DOWNLOAD_PROCESS) {
Log.e(TAG, "Illegal callback for non-download process.");
return;
}
}
}; };
} }
......
...@@ -72,6 +72,35 @@ public abstract class ContentSwitches { ...@@ -72,6 +72,35 @@ public abstract class ContentSwitches {
// Native switch kIPCSyncCompositing // Native switch kIPCSyncCompositing
public static final String IPC_SYNC_COMPOSITING = "ipc-sync-compositing"; public static final String IPC_SYNC_COMPOSITING = "ipc-sync-compositing";
// Native switch kProcessType
public static final String SWITCH_PROCESS_TYPE = "type";
// Native switch kRendererProcess
public static final String SWITCH_RENDERER_PROCESS = "renderer";
// Native switch kUtilityProcess
public static final String SWITCH_UTILITY_PROCESS = "utility";
// Native switch kGPUProcess
public static final String SWITCH_GPU_PROCESS = "gpu-process";
// Native switch kDownloadProcess
public static final String SWITCH_DOWNLOAD_PROCESS = "download";
// Prevent instantiation. // Prevent instantiation.
private ContentSwitches() {} private ContentSwitches() {}
public static String getSwitchValue(final String[] commandLine, String switchKey) {
if (commandLine == null || switchKey == null) {
return null;
}
// This format should be matched with the one defined in command_line.h.
final String switchKeyPrefix = "--" + switchKey + "=";
for (String command : commandLine) {
if (command != null && command.startsWith(switchKeyPrefix)) {
return command.substring(switchKeyPrefix.length());
}
}
return null;
}
} }
...@@ -21,4 +21,8 @@ interface IChildProcessCallback { ...@@ -21,4 +21,8 @@ interface IChildProcessCallback {
void unregisterSurfaceTextureSurface(int surfaceTextureId, int clientId); void unregisterSurfaceTextureSurface(int surfaceTextureId, int clientId);
SurfaceWrapper getSurfaceTextureSurface(int surfaceTextureId); SurfaceWrapper getSurfaceTextureSurface(int surfaceTextureId);
// Callback to inform native that the download service has accepted or
// rejected the download.
void onDownloadStarted(boolean started, int downloadId);
} }
...@@ -298,6 +298,9 @@ const char kDisableZeroCopy[] = "disable-zero-copy"; ...@@ -298,6 +298,9 @@ const char kDisableZeroCopy[] = "disable-zero-copy";
// based tests. // based tests.
const char kDomAutomationController[] = "dom-automation"; const char kDomAutomationController[] = "dom-automation";
// Causes the process to run as a download subprocess.
const char kDownloadProcess[] = "download";
// Enable antialiasing on 2d canvas clips (as opposed to draw operations) // Enable antialiasing on 2d canvas clips (as opposed to draw operations)
const char kEnable2dCanvasClipAntialiasing[] = "enable-2d-canvas-clip-aa"; const char kEnable2dCanvasClipAntialiasing[] = "enable-2d-canvas-clip-aa";
......
...@@ -96,6 +96,7 @@ CONTENT_EXPORT extern const char kDisableWebSecurity[]; ...@@ -96,6 +96,7 @@ CONTENT_EXPORT extern const char kDisableWebSecurity[];
extern const char kDisableXSSAuditor[]; extern const char kDisableXSSAuditor[];
CONTENT_EXPORT extern const char kDisableZeroCopy[]; CONTENT_EXPORT extern const char kDisableZeroCopy[];
CONTENT_EXPORT extern const char kDomAutomationController[]; CONTENT_EXPORT extern const char kDomAutomationController[];
CONTENT_EXPORT extern const char kDownloadProcess[];
extern const char kEnable2dCanvasClipAntialiasing[]; extern const char kEnable2dCanvasClipAntialiasing[];
CONTENT_EXPORT extern const char kEnableAggressiveDOMStorageFlushing[]; CONTENT_EXPORT extern const char kEnableAggressiveDOMStorageFlushing[];
CONTENT_EXPORT extern const char kEnableAudioSupportForDesktopShare[]; CONTENT_EXPORT extern const char kEnableAudioSupportForDesktopShare[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment