summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqinmin <qinmin@chromium.org>2016-02-04 12:37:54 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-04 20:38:44 +0000
commitee805c1eeab8ed56cdac0020ba41948279bdbd05 (patch)
treec86af7f0f5b6b4786899972ca1d1f1afd60388ba
parent371faba5e24c2baebe69dc7105ac80ad132d9c20 (diff)
downloadchromium_src-ee805c1eeab8ed56cdac0020ba41948279bdbd05.zip
chromium_src-ee805c1eeab8ed56cdac0020ba41948279bdbd05.tar.gz
chromium_src-ee805c1eeab8ed56cdac0020ba41948279bdbd05.tar.bz2
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}
-rw-r--r--chrome/android/java/AndroidManifest.xml11
-rw-r--r--content/app/BUILD.gn1
-rw-r--r--content/app/android/download_main.cc21
-rw-r--r--content/app/content_main_runner.cc6
-rw-r--r--content/browser/android/child_process_launcher_android.cc45
-rw-r--r--content/browser/android/child_process_launcher_android.h4
-rw-r--r--content/content_app.gypi1
-rw-r--r--content/public/android/java/res/values/ids.xml12
-rw-r--r--content/public/android/java/src/org/chromium/content/app/ChildProcessService.java11
-rw-r--r--content/public/android/java/src/org/chromium/content/app/DownloadProcessService.java78
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java15
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ChildProcessConstants.java7
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java97
-rw-r--r--content/public/android/java/src/org/chromium/content/common/ContentSwitches.java29
-rw-r--r--content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl4
-rw-r--r--content/public/common/content_switches.cc3
-rw-r--r--content/public/common/content_switches.h1
17 files changed, 305 insertions, 41 deletions
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 29430e8..914ef9a 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -643,6 +643,17 @@ android:value="true" />
android:exported="false" />
{% 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"
android:exported="false">
<intent-filter>
diff --git a/content/app/BUILD.gn b/content/app/BUILD.gn
index c65a9be5..f3d476c 100644
--- a/content/app/BUILD.gn
+++ b/content/app/BUILD.gn
@@ -12,6 +12,7 @@ content_app_sources = [
"android/content_jni_onload.cc",
"android/content_main.cc",
"android/content_main.h",
+ "android/download_main.cc",
"android/library_loader_hooks.cc",
"android/library_loader_hooks.h",
"content_main.cc",
diff --git a/content/app/android/download_main.cc b/content/app/android/download_main.cc
new file mode 100644
index 0000000..3280e29
--- /dev/null
+++ b/content/app/android/download_main.cc
@@ -0,0 +1,21 @@
+// 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
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index a8235c3..e8d31b0 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -121,6 +121,9 @@ extern int PpapiBrokerMain(const MainFunctionParams&);
#endif
extern int RendererMain(const content::MainFunctionParams&);
extern int UtilityMain(const MainFunctionParams&);
+#if defined(OS_ANDROID)
+extern int DownloadMain(const MainFunctionParams&);
+#endif
} // namespace content
namespace content {
@@ -343,6 +346,9 @@ int RunNamedProcessTypeMain(
{ switches::kUtilityProcess, UtilityMain },
{ switches::kRendererProcess, RendererMain },
{ switches::kGpuProcess, GpuMain },
+#if defined(OS_ANDROID)
+ { switches::kDownloadProcess, DownloadMain},
+#endif
#endif // !CHROME_MULTIPLE_DLL_BROWSER
};
diff --git a/content/browser/android/child_process_launcher_android.cc b/content/browser/android/child_process_launcher_android.cc
index a396580..11bb6de 100644
--- a/content/browser/android/child_process_launcher_android.cc
+++ b/content/browser/android/child_process_launcher_android.cc
@@ -13,12 +13,16 @@
#include "base/android/jni_array.h"
#include "base/logging.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/media/android/browser_media_player_manager.h"
#include "content/browser/media/android/media_web_contents_observer_android.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/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "jni/ChildProcessLauncher_jni.h"
#include "media/base/android/media_player_android.h"
@@ -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
// Called from ChildProcessLauncher.java when the ChildProcess was
@@ -103,6 +122,32 @@ static void OnChildProcessStarted(JNIEnv*,
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(
const base::CommandLine::StringVector& argv,
int child_process_id,
diff --git a/content/browser/android/child_process_launcher_android.h b/content/browser/android/child_process_launcher_android.h
index ea806ac..3f09ad0 100644
--- a/content/browser/android/child_process_launcher_android.h
+++ b/content/browser/android/child_process_launcher_android.h
@@ -29,6 +29,10 @@ void StartChildProcess(
const std::map<int, base::MemoryMappedFile::Region>& regions,
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
// StartChildProcess.
void StopChildProcess(base::ProcessHandle handle);
diff --git a/content/content_app.gypi b/content/content_app.gypi
index ad82f48..293781b 100644
--- a/content/content_app.gypi
+++ b/content/content_app.gypi
@@ -25,6 +25,7 @@
'app/android/content_jni_onload.cc',
'app/android/content_main.cc',
'app/android/content_main.h',
+ 'app/android/download_main.cc',
'app/android/library_loader_hooks.cc',
'app/android/library_loader_hooks.h',
'app/content_main.cc',
diff --git a/content/public/android/java/res/values/ids.xml b/content/public/android/java/res/values/ids.xml
new file mode 100644
index 0000000..e9481bb
--- /dev/null
+++ b/content/public/android/java/res/values/ids.xml
@@ -0,0 +1,12 @@
+<?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>
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
index 849f9c7..ce9eccc 100644
--- a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
+++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
@@ -27,8 +27,8 @@ import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.Linker;
import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.content.browser.ChildProcessConstants;
-import org.chromium.content.browser.ChildProcessLauncher;
import org.chromium.content.browser.FileDescriptorInfo;
+import org.chromium.content.common.ContentSwitches;
import org.chromium.content.common.IChildProcessCallback;
import org.chromium.content.common.IChildProcessService;
import org.chromium.content.common.SurfaceWrapper;
@@ -51,6 +51,7 @@ import java.util.concurrent.atomic.AtomicReference;
public class ChildProcessService extends Service {
private static final String MAIN_THREAD_NAME = "ChildProcessMain";
private static final String TAG = "ChildProcessService";
+ protected static final FileDescriptorInfo[] EMPTY_FILE_DESCRIPTOR_INFO = {};
private IChildProcessCallback mCallback;
// This is the native "Main" thread for the renderer / utility process.
@@ -289,10 +290,10 @@ public class ChildProcessService extends Service {
mFdInfos = new FileDescriptorInfo[fdInfosAsParcelable.length];
System.arraycopy(fdInfosAsParcelable, 0, mFdInfos, 0, fdInfosAsParcelable.length);
} else {
- // TODO(qinmin): On earlier androird versions, a started service running in another
- // process can get killed after Chrome is killed. To work around this issue, client
- // will never bind to the service. As a result, the file descriptors needs to be
- // passed through an intent when starting the service.
+ String processType = ContentSwitches.getSwitchValue(
+ mCommandLineParams, ContentSwitches.SWITCH_PROCESS_TYPE);
+ assert ContentSwitches.SWITCH_DOWNLOAD_PROCESS.equals(processType);
+ mFdInfos = EMPTY_FILE_DESCRIPTOR_INFO;
}
Bundle sharedRelros = bundle.getBundle(Linker.EXTRA_LINKER_SHARED_RELROS);
if (sharedRelros != null) {
diff --git a/content/public/android/java/src/org/chromium/content/app/DownloadProcessService.java b/content/public/android/java/src/org/chromium/content/app/DownloadProcessService.java
new file mode 100644
index 0000000..7ea954b
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/app/DownloadProcessService.java
@@ -0,0 +1,78 @@
+// 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
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java
index 3243a69..257ebb7 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java
@@ -13,12 +13,10 @@ import android.os.DeadObjectException;
import android.os.IBinder;
import android.os.RemoteException;
-import org.chromium.base.CpuFeatures;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent;
import org.chromium.base.VisibleForTesting;
-import org.chromium.base.library_loader.Linker;
import org.chromium.content.app.ChildProcessService;
import org.chromium.content.app.ChromiumLinkerParams;
import org.chromium.content.common.IChildProcessCallback;
@@ -331,16 +329,9 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
assert mServiceConnectComplete && mService != null;
assert mConnectionParams != null;
- Bundle bundle = new Bundle();
- bundle.putStringArray(
- ChildProcessConstants.EXTRA_COMMAND_LINE, mConnectionParams.mCommandLine);
- 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);
+ Bundle bundle =
+ ChildProcessLauncher.createsServiceBundle(mConnectionParams.mCommandLine,
+ mConnectionParams.mFilesToBeMapped, mConnectionParams.mSharedRelros);
try {
mPid = mService.setupConnection(bundle, mConnectionParams.mCallback);
assert mPid != 0 : "Child service claims to be run by a process of pid=0.";
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConstants.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConstants.java
index d4eb121..4d0fbcb 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConstants.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConstants.java
@@ -19,4 +19,11 @@ public class ChildProcessConstants {
// Used to pass the CPU features mask to child processes.
public static final String 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";
}
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
index 8654cc5..6a300d9 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
@@ -4,10 +4,14 @@
package org.chromium.content.browser;
+import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture;
+import android.os.Build;
+import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.text.TextUtils;
@@ -15,6 +19,7 @@ import android.util.Pair;
import android.view.Surface;
import org.chromium.base.CommandLine;
+import org.chromium.base.CpuFeatures;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent;
@@ -24,8 +29,10 @@ import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.library_loader.Linker;
import org.chromium.content.app.ChildProcessService;
import org.chromium.content.app.ChromiumLinkerParams;
+import org.chromium.content.app.DownloadProcessService;
import org.chromium.content.app.PrivilegedProcessService;
import org.chromium.content.app.SandboxedProcessService;
+import org.chromium.content.common.ContentSwitches;
import org.chromium.content.common.IChildProcessCallback;
import org.chromium.content.common.SurfaceWrapper;
@@ -47,11 +54,7 @@ public class ChildProcessLauncher {
static final int CALLBACK_FOR_GPU_PROCESS = 1;
static final int CALLBACK_FOR_RENDERER_PROCESS = 2;
static final int CALLBACK_FOR_UTILITY_PROCESS = 3;
-
- 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";
+ static final int CALLBACK_FOR_DOWNLOAD_PROCESS = 4;
/**
* Allows specifying the package name for looking up child services
@@ -110,7 +113,7 @@ public class ChildProcessLauncher {
mFreeConnectionIndices.add(i);
}
mChildClass =
- inSandbox ? SandboxedProcessService.class : PrivilegedProcessService.class;
+ inSandbox ? SandboxedProcessService.class : PrivilegedProcessService.class;
mInSandbox = inSandbox;
}
@@ -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
private static FileDescriptorInfo makeFdInfo(
int id, int fd, boolean autoClose, long offset, long size) {
@@ -617,13 +606,14 @@ public class ChildProcessLauncher {
int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS;
boolean inSandbox = true;
- String processType = getSwitchValue(commandLine, SWITCH_PROCESS_TYPE);
- if (SWITCH_RENDERER_PROCESS.equals(processType)) {
+ String processType =
+ ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWITCH_PROCESS_TYPE);
+ if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) {
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;
inSandbox = false;
- } else if (SWITCH_UTILITY_PROCESS.equals(processType)) {
+ } else if (ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType)) {
// We only support sandboxed right now.
callbackType = CALLBACK_FOR_UTILITY_PROCESS;
} else {
@@ -634,6 +624,39 @@ public class ChildProcessLauncher {
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(
Context context,
final String[] commandLine,
@@ -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
static void triggerConnectionSetup(
final ChildProcessConnection connection,
@@ -806,6 +846,15 @@ public class ChildProcessLauncher {
return ChildProcessLauncher.getSurfaceTextureSurface(surfaceTextureId,
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;
+ }
+ }
};
}
diff --git a/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java b/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java
index 8fc8302..899d48f 100644
--- a/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java
+++ b/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java
@@ -72,6 +72,35 @@ public abstract class ContentSwitches {
// Native switch kIPCSyncCompositing
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.
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;
+ }
}
diff --git a/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl b/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl
index 0600a4d..36983b0 100644
--- a/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl
+++ b/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl
@@ -21,4 +21,8 @@ interface IChildProcessCallback {
void unregisterSurfaceTextureSurface(int surfaceTextureId, int clientId);
SurfaceWrapper getSurfaceTextureSurface(int surfaceTextureId);
+
+ // Callback to inform native that the download service has accepted or
+ // rejected the download.
+ void onDownloadStarted(boolean started, int downloadId);
}
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 7e2f2ca..b68e1dd 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -298,6 +298,9 @@ const char kDisableZeroCopy[] = "disable-zero-copy";
// based tests.
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)
const char kEnable2dCanvasClipAntialiasing[] = "enable-2d-canvas-clip-aa";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index d201530..8a7736a0 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -96,6 +96,7 @@ CONTENT_EXPORT extern const char kDisableWebSecurity[];
extern const char kDisableXSSAuditor[];
CONTENT_EXPORT extern const char kDisableZeroCopy[];
CONTENT_EXPORT extern const char kDomAutomationController[];
+CONTENT_EXPORT extern const char kDownloadProcess[];
extern const char kEnable2dCanvasClipAntialiasing[];
CONTENT_EXPORT extern const char kEnableAggressiveDOMStorageFlushing[];
CONTENT_EXPORT extern const char kEnableAudioSupportForDesktopShare[];