summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorjcivelli@chromium.org <jcivelli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-25 00:20:08 +0000
committerjcivelli@chromium.org <jcivelli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-25 00:20:08 +0000
commitc7abd4296309d21002aebb32edf8333ada4f74db (patch)
treec066a73babc0d66174b9c4828c8726086053bbc3 /content
parent7c6e9a625f39fe59ff6d846dac353688aa669fee (diff)
downloadchromium_src-c7abd4296309d21002aebb32edf8333ada4f74db.zip
chromium_src-c7abd4296309d21002aebb32edf8333ada4f74db.tar.gz
chromium_src-c7abd4296309d21002aebb32edf8333ada4f74db.tar.bz2
Close leaking FDs.
When starting a SandboxedProcess the resource file descriptors were leaked in the browser process, eventually causing crashers. BUG=None TEST=When using the Android content shell for a long time, it should not crash. Review URL: https://chromiumcodereview.appspot.com/10949027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@158456 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/app/android/sandboxed_process_service.cc40
-rw-r--r--content/browser/android/sandboxed_process_launcher.cc52
-rw-r--r--content/browser/android/sandboxed_process_launcher.h5
-rw-r--r--content/browser/child_process_launcher.cc33
-rw-r--r--content/browser/zygote_host/zygote_host_impl_linux.cc19
-rw-r--r--content/browser/zygote_host/zygote_host_impl_linux.h4
-rw-r--r--content/content_browser.gypi1
-rw-r--r--content/public/android/java/src/org/chromium/content/app/SandboxedProcessService.java41
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/FileDescriptorInfo.java20
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/SandboxedProcessConnection.java67
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/SandboxedProcessLauncher.java19
-rw-r--r--content/public/browser/content_browser_client.h3
-rw-r--r--content/public/browser/file_descriptor_info.h29
-rw-r--r--content/shell/shell_content_browser_client.cc7
-rw-r--r--content/shell/shell_content_browser_client.h2
15 files changed, 206 insertions, 136 deletions
diff --git a/content/app/android/sandboxed_process_service.cc b/content/app/android/sandboxed_process_service.cc
index 291748f..eb3c299 100644
--- a/content/app/android/sandboxed_process_service.cc
+++ b/content/app/android/sandboxed_process_service.cc
@@ -50,22 +50,18 @@ class SurfaceTexturePeerSandboxedImpl : public content::SurfaceTexturePeer {
// Chrome actually uses the renderer code path for all of its sandboxed
// processes such as renderers, plugins, etc.
-void InternalInitSandboxedProcess(int ipc_fd,
- const std::vector<int>& extra_file_ids,
- const std::vector<int>& extra_file_fds,
+void InternalInitSandboxedProcess(const std::vector<int>& file_ids,
+ const std::vector<int>& file_fds,
JNIEnv* env,
jclass clazz,
jobject context,
jobject service) {
- // Set up the IPC file descriptor mapping.
- base::GlobalDescriptors::GetInstance()->Set(kPrimaryIPCChannel, ipc_fd);
- // Register the extra file descriptors.
- // This usually include the crash dump signals and resource related files.
- DCHECK(extra_file_fds.size() == extra_file_ids.size());
- for (size_t i = 0; i < extra_file_ids.size(); ++i) {
- base::GlobalDescriptors::GetInstance()->Set(extra_file_ids[i],
- extra_file_fds[i]);
- }
+ // Register the file descriptors.
+ // This includes the IPC channel, the crash dump signals and resource related
+ // files.
+ DCHECK(file_fds.size() == file_ids.size());
+ for (size_t i = 0; i < file_ids.size(); ++i)
+ base::GlobalDescriptors::GetInstance()->Set(file_ids[i], file_fds[i]);
content::SurfaceTexturePeer::InitInstance(
new SurfaceTexturePeerSandboxedImpl(service));
@@ -80,17 +76,15 @@ void InitSandboxedProcess(JNIEnv* env,
jclass clazz,
jobject context,
jobject service,
- jint ipc_fd,
- jintArray j_extra_file_ids,
- jintArray j_extra_file_fds) {
- std::vector<int> extra_file_ids;
- std::vector<int> extra_file_fds;
- JavaIntArrayToIntVector(env, j_extra_file_ids, &extra_file_ids);
- JavaIntArrayToIntVector(env, j_extra_file_fds, &extra_file_fds);
-
- InternalInitSandboxedProcess(static_cast<int>(ipc_fd),
- extra_file_ids, extra_file_fds,
- env, clazz, context, service);
+ jintArray j_file_ids,
+ jintArray j_file_fds) {
+ std::vector<int> file_ids;
+ std::vector<int> file_fds;
+ JavaIntArrayToIntVector(env, j_file_ids, &file_ids);
+ JavaIntArrayToIntVector(env, j_file_fds, &file_fds);
+
+ InternalInitSandboxedProcess(
+ file_ids, file_fds, env, clazz, context, service);
}
void ExitSandboxedProcess(JNIEnv* env, jclass clazz) {
diff --git a/content/browser/android/sandboxed_process_launcher.cc b/content/browser/android/sandboxed_process_launcher.cc
index 04d3512..0bdd88a 100644
--- a/content/browser/android/sandboxed_process_launcher.cc
+++ b/content/browser/android/sandboxed_process_launcher.cc
@@ -13,7 +13,6 @@
using base::android::AttachCurrentThread;
using base::android::ToJavaArrayOfStrings;
using base::android::ScopedJavaLocalRef;
-using base::GlobalDescriptors;
using content::StartSandboxedProcessCallback;
namespace content {
@@ -37,8 +36,7 @@ static void OnSandboxedProcessStarted(JNIEnv*,
void StartSandboxedProcess(
const CommandLine::StringVector& argv,
- int ipc_fd,
- const GlobalDescriptors::Mapping& files_to_register,
+ const std::vector<content::FileDescriptorInfo>& files_to_register,
const StartSandboxedProcessCallback& callback) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
@@ -46,24 +44,40 @@ void StartSandboxedProcess(
// Create the Command line String[]
ScopedJavaLocalRef<jobjectArray> j_argv = ToJavaArrayOfStrings(env, argv);
- ScopedJavaLocalRef<jintArray> j_file_to_register_id_files(env,
- env->NewIntArray(files_to_register.size() * 2));
- scoped_array<jint> file_to_register_id_files(
- new jint[files_to_register.size() * 2]);
- for (size_t i = 0; i < files_to_register.size(); ++i) {
- const GlobalDescriptors::KeyFDPair& id_file = files_to_register[i];
- file_to_register_id_files[2 * i] = id_file.first;
- file_to_register_id_files[(2 * i) + 1] = id_file.second;
+ size_t file_count = files_to_register.size();
+ DCHECK(file_count > 0);
+
+ ScopedJavaLocalRef<jintArray> j_file_ids(env, env->NewIntArray(file_count));
+ base::android::CheckException(env);
+ jint* file_ids = env->GetIntArrayElements(j_file_ids.obj(), NULL);
+ base::android::CheckException(env);
+ ScopedJavaLocalRef<jintArray> j_file_fds(env, env->NewIntArray(file_count));
+ base::android::CheckException(env);
+ jint* file_fds = env->GetIntArrayElements(j_file_fds.obj(), NULL);
+ base::android::CheckException(env);
+ ScopedJavaLocalRef<jbooleanArray> j_file_auto_close(
+ env, env->NewBooleanArray(file_count));
+ base::android::CheckException(env);
+ jboolean* file_auto_close =
+ env->GetBooleanArrayElements(j_file_auto_close.obj(), NULL);
+ base::android::CheckException(env);
+ for (size_t i = 0; i < file_count; ++i) {
+ const content::FileDescriptorInfo& fd_info = files_to_register[i];
+ file_ids[i] = fd_info.id;
+ file_fds[i] = fd_info.fd.fd;
+ file_auto_close[i] = fd_info.fd.auto_close;
}
- env->SetIntArrayRegion(j_file_to_register_id_files.obj(),
- 0, files_to_register.size() * 2,
- file_to_register_id_files.get());
+ env->ReleaseIntArrayElements(j_file_ids.obj(), file_ids, 0);
+ env->ReleaseIntArrayElements(j_file_fds.obj(), file_fds, 0);
+ env->ReleaseBooleanArrayElements(j_file_auto_close.obj(), file_auto_close, 0);
+
Java_SandboxedProcessLauncher_start(env,
- base::android::GetApplicationContext(),
- static_cast<jobjectArray>(j_argv.obj()),
- static_cast<jint>(ipc_fd),
- j_file_to_register_id_files.obj(),
- reinterpret_cast<jint>(new StartSandboxedProcessCallback(callback)));
+ base::android::GetApplicationContext(),
+ j_argv.obj(),
+ j_file_ids.obj(),
+ j_file_fds.obj(),
+ j_file_auto_close.obj(),
+ reinterpret_cast<jint>(new StartSandboxedProcessCallback(callback)));
}
void StopSandboxedProcess(base::ProcessHandle handle) {
diff --git a/content/browser/android/sandboxed_process_launcher.h b/content/browser/android/sandboxed_process_launcher.h
index 13b36da..64deaac 100644
--- a/content/browser/android/sandboxed_process_launcher.h
+++ b/content/browser/android/sandboxed_process_launcher.h
@@ -9,9 +9,9 @@
#include "base/callback.h"
#include "base/command_line.h"
-#include "base/global_descriptors_posix.h"
#include "base/platform_file.h"
#include "base/process.h"
+#include "content/public/browser/file_descriptor_info.h"
namespace content {
@@ -22,8 +22,7 @@ typedef base::Callback<void(base::ProcessHandle)> StartSandboxedProcessCallback;
// retuned if the process could not be created.
void StartSandboxedProcess(
const CommandLine::StringVector& argv,
- int ipc_fd,
- const base::GlobalDescriptors::Mapping& files_to_register,
+ const std::vector<FileDescriptorInfo>& files_to_register,
const StartSandboxedProcessCallback& callback);
// Stops a sandboxed process based on the handle returned form
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc
index f7cf772..0bbc035 100644
--- a/content/browser/child_process_launcher.cc
+++ b/content/browser/child_process_launcher.cc
@@ -166,28 +166,31 @@ class ChildProcessLauncher::Context
#elif defined(OS_ANDROID)
std::string process_type =
cmd_line->GetSwitchValueASCII(switches::kProcessType);
- base::GlobalDescriptors::Mapping files_to_register;
- files_to_register.push_back(std::pair<base::GlobalDescriptors::Key, int>(
- kPrimaryIPCChannel, ipcfd));
+ std::vector<content::FileDescriptorInfo> files_to_register;
+ files_to_register.push_back(
+ content::FileDescriptorInfo(kPrimaryIPCChannel,
+ base::FileDescriptor(ipcfd, false)));
+
content::GetContentClient()->browser()->
GetAdditionalMappedFilesForChildProcess(*cmd_line, &files_to_register);
- content::StartSandboxedProcess(cmd_line->argv(),
- ipcfd, files_to_register,
+ content::StartSandboxedProcess(cmd_line->argv(), files_to_register,
base::Bind(&ChildProcessLauncher::Context::OnSandboxedProcessStarted,
this_object, client_thread_id));
#elif defined(OS_POSIX)
base::ProcessHandle handle = base::kNullProcessHandle;
- // We need to close the client end of the IPC channel
- // to reliably detect child termination.
+ // We need to close the client end of the IPC channel to reliably detect
+ // child termination.
file_util::ScopedFD ipcfd_closer(&ipcfd);
std::string process_type =
cmd_line->GetSwitchValueASCII(switches::kProcessType);
- base::GlobalDescriptors::Mapping files_to_register;
- files_to_register.push_back(std::pair<base::GlobalDescriptors::Key, int>(
- kPrimaryIPCChannel, ipcfd));
+ std::vector<content::FileDescriptorInfo> files_to_register;
+ files_to_register.push_back(
+ content::FileDescriptorInfo(kPrimaryIPCChannel,
+ base::FileDescriptor(ipcfd, false)));
+
#if !defined(OS_MACOSX)
content::GetContentClient()->browser()->
GetAdditionalMappedFilesForChildProcess(*cmd_line, &files_to_register);
@@ -201,12 +204,12 @@ class ChildProcessLauncher::Context
{
// Convert FD mapping to FileHandleMappingVector
base::FileHandleMappingVector fds_to_map;
- for (size_t i = 0; i < files_to_register.size(); ++i) {
- const base::GlobalDescriptors::KeyFDPair& id_file =
- files_to_register[i];
+ for (std::vector<content::FileDescriptorInfo>::const_iterator
+ i = files_to_register.begin(); i != files_to_register.end(); ++i) {
+ const content::FileDescriptorInfo& fd_info = *i;
fds_to_map.push_back(std::make_pair(
- id_file.second,
- id_file.first + base::GlobalDescriptors::kBaseDescriptor));
+ fd_info.fd.fd,
+ fd_info.id + base::GlobalDescriptors::kBaseDescriptor));
}
#if !defined(OS_MACOSX)
diff --git a/content/browser/zygote_host/zygote_host_impl_linux.cc b/content/browser/zygote_host/zygote_host_impl_linux.cc
index 6ef5487..7d084ac 100644
--- a/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ b/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -16,6 +16,7 @@
#include "base/file_util.h"
#include "base/linux_util.h"
#include "base/logging.h"
+#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
@@ -238,7 +239,7 @@ ssize_t ZygoteHostImpl::ReadReply(void* buf, size_t buf_len) {
pid_t ZygoteHostImpl::ForkRequest(
const std::vector<std::string>& argv,
- const base::GlobalDescriptors::Mapping& mapping,
+ const std::vector<content::FileDescriptorInfo>& mapping,
const std::string& process_type) {
DCHECK(init_);
Pickle pickle;
@@ -253,10 +254,20 @@ pid_t ZygoteHostImpl::ForkRequest(
pickle.WriteInt(mapping.size());
std::vector<int> fds;
- for (base::GlobalDescriptors::Mapping::const_iterator
+ // Scoped pointers cannot be stored in containers, so we have to use a
+ // linked_ptr.
+ std::vector<linked_ptr<file_util::ScopedFD> > autodelete_fds;
+ for (std::vector<content::FileDescriptorInfo>::const_iterator
i = mapping.begin(); i != mapping.end(); ++i) {
- pickle.WriteUInt32(i->first);
- fds.push_back(i->second);
+ pickle.WriteUInt32(i->id);
+ fds.push_back(i->fd.fd);
+ if (i->fd.auto_close) {
+ // Auto-close means we need to close the FDs after they habe been passed
+ // to the other process.
+ linked_ptr<file_util::ScopedFD> ptr(
+ new file_util::ScopedFD(&(fds.back())));
+ autodelete_fds.push_back(ptr);
+ }
}
pid_t pid;
diff --git a/content/browser/zygote_host/zygote_host_impl_linux.h b/content/browser/zygote_host/zygote_host_impl_linux.h
index 17a6b35..460abc5 100644
--- a/content/browser/zygote_host/zygote_host_impl_linux.h
+++ b/content/browser/zygote_host/zygote_host_impl_linux.h
@@ -8,9 +8,9 @@
#include <string>
#include <vector>
-#include "base/global_descriptors_posix.h"
#include "base/process_util.h"
#include "base/synchronization/lock.h"
+#include "content/public/browser/file_descriptor_info.h"
#include "content/public/browser/zygote_host_linux.h"
template<typename Type>
@@ -27,7 +27,7 @@ class CONTENT_EXPORT ZygoteHostImpl : public content::ZygoteHost {
// Returns its pid on success, otherwise
// base::kNullProcessHandle;
pid_t ForkRequest(const std::vector<std::string>& command_line,
- const base::GlobalDescriptors::Mapping& mapping,
+ const std::vector<content::FileDescriptorInfo>& mapping,
const std::string& process_type);
void EnsureProcessTerminated(pid_t process);
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 1d01015..ed37f1b 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -75,6 +75,7 @@
'public/browser/download_url_parameters.h',
'public/browser/favicon_status.cc',
'public/browser/favicon_status.h',
+ 'public/browser/file_descriptor_info.h',
'public/browser/font_list_async.h',
'public/browser/geolocation.h',
'public/browser/geolocation_permission_context.h',
diff --git a/content/public/android/java/src/org/chromium/content/app/SandboxedProcessService.java b/content/public/android/java/src/org/chromium/content/app/SandboxedProcessService.java
index 4ce68ed..5917736 100644
--- a/content/public/android/java/src/org/chromium/content/app/SandboxedProcessService.java
+++ b/content/public/android/java/src/org/chromium/content/app/SandboxedProcessService.java
@@ -47,10 +47,9 @@ public class SandboxedProcessService extends Service {
// Parameters received via IPC, only accessed while holding the mSandboxMainThread monitor.
private String mNativeLibraryName; // Must be passed in via the bind command.
private String[] mCommandLineParams;
- private ParcelFileDescriptor mIPCFd;
// Pairs IDs and file descriptors that should be registered natively.
- private ArrayList<Integer> mExtraFileIds;
- private ArrayList<ParcelFileDescriptor> mExtraFileFds;
+ private ArrayList<Integer> mFileIds;
+ private ArrayList<ParcelFileDescriptor> mFileFds;
private static Context sContext = null;
private boolean mLibraryInitialized = false;
@@ -70,9 +69,8 @@ public class SandboxedProcessService extends Service {
}
// We must have received the command line by now
assert mCommandLineParams != null;
- mIPCFd = args.getParcelable(SandboxedProcessConnection.EXTRA_IPC_FD);
- mExtraFileIds = new ArrayList<Integer>();
- mExtraFileFds = new ArrayList<ParcelFileDescriptor>();
+ mFileIds = new ArrayList<Integer>();
+ mFileFds = new ArrayList<ParcelFileDescriptor>();
for (int i = 0;; i++) {
String fdName = SandboxedProcessConnection.EXTRA_FILES_PREFIX + i
+ SandboxedProcessConnection.EXTRA_FILES_FD_SUFFIX;
@@ -81,10 +79,10 @@ public class SandboxedProcessService extends Service {
// End of the file list.
break;
}
- mExtraFileFds.add(parcel);
+ mFileFds.add(parcel);
String idName = SandboxedProcessConnection.EXTRA_FILES_PREFIX + i
+ SandboxedProcessConnection.EXTRA_FILES_ID_SUFFIX;
- mExtraFileIds.add(args.getInt(idName));
+ mFileIds.add(args.getInt(idName));
}
mSandboxMainThread.notifyAll();
}
@@ -127,21 +125,20 @@ public class SandboxedProcessService extends Service {
synchronized (mSandboxMainThread) {
mLibraryInitialized = true;
mSandboxMainThread.notifyAll();
- while (mIPCFd == null) {
+ while (mFileIds == null) {
mSandboxMainThread.wait();
}
}
- assert mExtraFileIds.size() == mExtraFileFds.size();
- int[] extraFileIds = new int[mExtraFileIds.size()];
- int[] extraFileFds = new int[mExtraFileFds.size()];
- for (int i = 0; i < mExtraFileIds.size(); ++i) {
- extraFileIds[i] = mExtraFileIds.get(i);
- extraFileFds[i] = mExtraFileFds.get(i).detachFd();
+ assert mFileIds.size() == mFileFds.size();
+ int[] fileIds = new int[mFileIds.size()];
+ int[] fileFds = new int[mFileFds.size()];
+ for (int i = 0; i < mFileIds.size(); ++i) {
+ fileIds[i] = mFileIds.get(i);
+ fileFds[i] = mFileFds.get(i).detachFd();
}
ContentMain.initApplicationContext(sContext.getApplicationContext());
nativeInitSandboxedProcess(sContext.getApplicationContext(),
- SandboxedProcessService.this, mIPCFd.detachFd(),
- extraFileIds, extraFileFds);
+ SandboxedProcessService.this, fileIds, fileFds);
ContentMain.start();
nativeExitSandboxedProcess();
} catch (InterruptedException e) {
@@ -246,14 +243,12 @@ public class SandboxedProcessService extends Service {
*
* @param applicationContext The Application Context of the current process.
* @param service The current SandboxedProcessService object.
- * @param ipcFd File descriptor to use for ipc.
- * @param extraFileIds (Optional) A list of pair of file IDs that should be registered for
- * access by the renderer.
- * @param extraFileFds (Optional) A list of pair of file descriptors that should be registered
- * for access by the renderer.
+ * @param fileIds A list of file IDs that should be registered for access by the renderer.
+ * @param fileFds A list of file descriptors that should be registered for access by the
+ * renderer.
*/
private static native void nativeInitSandboxedProcess(Context applicationContext,
- SandboxedProcessService service, int ipcFd, int[] extraFileIds, int[] extraFileFds);
+ SandboxedProcessService service, int[] extraFileIds, int[] extraFileFds);
/**
* Force the sandboxed process to exit.
diff --git a/content/public/android/java/src/org/chromium/content/browser/FileDescriptorInfo.java b/content/public/android/java/src/org/chromium/content/browser/FileDescriptorInfo.java
new file mode 100644
index 0000000..a0db0b9
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/FileDescriptorInfo.java
@@ -0,0 +1,20 @@
+// Copyright (c) 2012 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.browser;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+
+class FileDescriptorInfo {
+ public int mId;
+ public int mFd;
+ public boolean mAutoClose;
+
+ FileDescriptorInfo(int id, int fd, boolean autoClose) {
+ mId = id;
+ mFd = fd;
+ mAutoClose = autoClose;
+ }
+} \ No newline at end of file
diff --git a/content/public/android/java/src/org/chromium/content/browser/SandboxedProcessConnection.java b/content/public/android/java/src/org/chromium/content/browser/SandboxedProcessConnection.java
index e6376b8..d334751 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SandboxedProcessConnection.java
+++ b/content/public/android/java/src/org/chromium/content/browser/SandboxedProcessConnection.java
@@ -36,8 +36,7 @@ public class SandboxedProcessConnection implements ServiceConnection {
"com.google.android.apps.chrome.extra.sandbox_command_line";
public static final String EXTRA_NATIVE_LIBRARY_NAME =
"com.google.android.apps.chrome.extra.sandbox_native_library_name";
- // Note the FD may only be passed in the connection bundle.
- public static final String EXTRA_IPC_FD = "com.google.android.apps.chrome.extra.sandbox_ipcFd";
+ // Note the FDs may only be passed in the connection bundle.
public static final String EXTRA_FILES_PREFIX =
"com.google.android.apps.chrome.extra.sandbox_extraFile_";
public static final String EXTRA_FILES_ID_SUFFIX = "_id";
@@ -61,20 +60,17 @@ public class SandboxedProcessConnection implements ServiceConnection {
private static class ConnectionParams {
final String[] mCommandLine;
- final int mIpcFd;
- final int[] mExtraFileIdsAndFds;
+ final FileDescriptorInfo[] mFilesToBeMapped;
final ISandboxedProcessCallback mCallback;
final Runnable mOnConnectionCallback;
ConnectionParams(
String[] commandLine,
- int ipcFd,
- int[] idsAndFds,
+ FileDescriptorInfo[] filesToBeMapped,
ISandboxedProcessCallback callback,
Runnable onConnectionCallback) {
mCommandLine = commandLine;
- mIpcFd = ipcFd;
- mExtraFileIdsAndFds = idsAndFds;
+ mFilesToBeMapped = filesToBeMapped;
mCallback = callback;
mOnConnectionCallback = onConnectionCallback;
}
@@ -139,21 +135,18 @@ public class SandboxedProcessConnection implements ServiceConnection {
*
* This establishes the parameters that were not already supplied in bind.
* @param commandLine (Optional) will be ignored if the command line was already sent in bind()
- * @param ipcFd The file descriptor that will be used by the sandbox process for IPC.
- * @param fileToRegisterIdFds (Optional) a list of pair of IDs and FDs that should be
- * registered
+ * @param fileToBeMapped a list of file descriptors that should be registered
* @param callback Used for status updates regarding this process connection.
* @param onConnectionCallback will be run when the connection is setup and ready to use.
*/
synchronized void setupConnection(
String[] commandLine,
- int ipcFd,
- int[] fileToRegisterIdFds,
+ FileDescriptorInfo[] filesToBeMapped,
ISandboxedProcessCallback callback,
Runnable onConnectionCallback) {
TraceEvent.begin();
assert mConnectionParams == null;
- mConnectionParams = new ConnectionParams(commandLine, ipcFd, fileToRegisterIdFds, callback,
+ mConnectionParams = new ConnectionParams(commandLine, filesToBeMapped, callback,
onConnectionCallback);
if (mServiceConnectComplete) {
doConnectionSetup();
@@ -213,43 +206,43 @@ public class SandboxedProcessConnection implements ServiceConnection {
if (onConnectionCallback == null) {
unbind();
} else if (mService != null) {
- ParcelFileDescriptor ipcFdParcel;
- try {
- ipcFdParcel = ParcelFileDescriptor.fromFd(mConnectionParams.mIpcFd);
- } catch(IOException e) {
- Log.e(TAG, "Invalid IPC FD, aborting connection.", e);
- return;
- }
Bundle bundle = new Bundle();
bundle.putStringArray(EXTRA_COMMAND_LINE, mConnectionParams.mCommandLine);
- bundle.putParcelable(EXTRA_IPC_FD, ipcFdParcel);
- int[] idsAndFds = mConnectionParams.mExtraFileIdsAndFds;
- assert idsAndFds.length % 2 == 0;
- int pairLength = idsAndFds.length / 2;
- for (int i = 0; i < pairLength; i++) {
+ FileDescriptorInfo[] fileInfos = mConnectionParams.mFilesToBeMapped;
+ ParcelFileDescriptor[] parcelFiles = new ParcelFileDescriptor[fileInfos.length];
+ for (int i = 0; i < fileInfos.length; i++) {
String idName = EXTRA_FILES_PREFIX + i + EXTRA_FILES_ID_SUFFIX;
String fdName = EXTRA_FILES_PREFIX + i + EXTRA_FILES_FD_SUFFIX;
- ParcelFileDescriptor parcelFile;
- try {
- parcelFile = ParcelFileDescriptor.fromFd(idsAndFds[(2 * i) + 1]);
- bundle.putParcelable(fdName, parcelFile);
- bundle.putInt(idName, idsAndFds[2 * i]);
- } catch (IOException e) {
- Log.e(TAG, "Invalid extra file FD: id=" + idsAndFds[ 2 * i] + " fd="
- + idsAndFds[(2 * i) + 1]);
+ if (fileInfos[i].mAutoClose) {
+ // Adopt the FD, it will be closed when we close the ParcelFileDescriptor.
+ parcelFiles[i] = ParcelFileDescriptor.adoptFd(fileInfos[i].mFd);
+ } else {
+ try {
+ parcelFiles[i] = ParcelFileDescriptor.fromFd(fileInfos[i].mFd);
+ } catch(IOException e) {
+ Log.e(TAG,
+ "Invalid FD provided for process connection, aborting connection.",
+ e);
+ return;
+ }
+
}
+ bundle.putParcelable(fdName, parcelFiles[i]);
+ bundle.putInt(idName, fileInfos[i].mId);
}
try {
mPID = mService.setupConnection(bundle, mConnectionParams.mCallback);
} catch (android.os.RemoteException re) {
Log.e(TAG, "Failed to setup connection.", re);
}
+ // We proactivley close the FDs rather than wait for GC & finalizer.
try {
- // We proactivley close now rather than wait for GC & finalizer.
- ipcFdParcel.close();
+ for (ParcelFileDescriptor parcelFile : parcelFiles) {
+ if (parcelFile != null) parcelFile.close();
+ }
} catch (IOException ioe) {
- Log.w(TAG, "Failed to close IPC FD.", ioe);
+ Log.w(TAG, "Failed to close FD.", ioe);
}
}
mConnectionParams = null;
diff --git a/content/public/android/java/src/org/chromium/content/browser/SandboxedProcessLauncher.java b/content/public/android/java/src/org/chromium/content/browser/SandboxedProcessLauncher.java
index f1913ff..766eca3 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SandboxedProcessLauncher.java
+++ b/content/public/android/java/src/org/chromium/content/browser/SandboxedProcessLauncher.java
@@ -161,16 +161,26 @@ public class SandboxedProcessLauncher {
*
* @param context Context used to obtain the application context.
* @param commandLine The sandboxed process command line argv.
- * @param ipcFd File descriptor used to set up IPC.
+ * @param file_ids The ID that should be used when mapping files in the created process.
+ * @param file_fds The file descriptors that should be mapped in the created process.
+ * @param file_auto_close Whether the file descriptors should be closed once they were passed to
+ * the created process.
* @param clientContext Arbitrary parameter used by the client to distinguish this connection.
*/
@CalledByNative
static void start(
Context context,
final String[] commandLine,
- int ipcFd,
- int[] fileToRegisterIdFds,
+ int[] fileIds,
+ int[] fileFds,
+ boolean[] fileAutoClose,
final int clientContext) {
+ assert fileIds.length == fileFds.length && fileFds.length == fileAutoClose.length;
+ FileDescriptorInfo[] filesToBeMapped = new FileDescriptorInfo[fileFds.length];
+ for (int i = 0; i < fileFds.length; i++) {
+ filesToBeMapped[i] =
+ new FileDescriptorInfo(fileIds[i], fileFds[i], fileAutoClose[i]);
+ }
assert clientContext != 0;
SandboxedProcessConnection allocatedConnection;
synchronized (SandboxedProcessLauncher.class) {
@@ -201,8 +211,7 @@ public class SandboxedProcessLauncher {
nativeOnSandboxedProcessStarted(clientContext, pid);
}
};
- connection.setupConnection(commandLine, ipcFd, fileToRegisterIdFds, createCallback(),
- onConnect);
+ connection.setupConnection(commandLine, filesToBeMapped, createCallback(), onConnect);
}
/**
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 7766f55..7c55235 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/callback_forward.h"
+#include "content/public/browser/file_descriptor_info.h"
#include "content/public/common/content_client.h"
#include "content/public/common/window_container_type.h"
#include "net/cookies/canonical_cookie.h"
@@ -453,7 +454,7 @@ class CONTENT_EXPORT ContentBrowserClient {
// a child process.
virtual void GetAdditionalMappedFilesForChildProcess(
const CommandLine& command_line,
- base::GlobalDescriptors::Mapping* mappings) {}
+ std::vector<FileDescriptorInfo>* mappings) {}
#endif
#if defined(OS_WIN)
diff --git a/content/public/browser/file_descriptor_info.h b/content/public/browser/file_descriptor_info.h
new file mode 100644
index 0000000..2248eb6
--- /dev/null
+++ b/content/public/browser/file_descriptor_info.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 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.
+
+#ifndef CONTENT_PUBLIC_BROWSER_FILE_DESCRIPTOR_INFO_H_
+#define CONTENT_PUBLIC_BROWSER_FILE_DESCRIPTOR_INFO_H_
+
+#include "base/file_descriptor_posix.h"
+
+namespace content {
+
+// This struct is used when passing files that should be mapped in a process
+// that is been created and allows to associate that file with a specific ID.
+// It also provides a way to know if the actual file descriptor should be
+// closed with the FileDescriptor.auto_close field.
+
+struct FileDescriptorInfo {
+ FileDescriptorInfo(int id, const base::FileDescriptor& file_descriptor)
+ : id(id),
+ fd(file_descriptor) {
+ }
+
+ int id;
+ base::FileDescriptor fd;
+};
+
+}
+
+#endif // CONTENT_PUBLIC_BROWSER_FILE_DESCRIPTOR_INFO_H_
diff --git a/content/shell/shell_content_browser_client.cc b/content/shell/shell_content_browser_client.cc
index c2fd53c..e07287a 100644
--- a/content/shell/shell_content_browser_client.cc
+++ b/content/shell/shell_content_browser_client.cc
@@ -76,7 +76,7 @@ WebContentsViewDelegate* ShellContentBrowserClient::GetWebContentsViewDelegate(
#if defined(OS_ANDROID)
void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
const CommandLine& command_line,
- base::GlobalDescriptors::Mapping* mappings) {
+ std::vector<content::FileDescriptorInfo>* mappings) {
int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
FilePath pak_file;
DCHECK(PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file));
@@ -89,8 +89,9 @@ void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
NOTREACHED() << "Failed to open file when creating renderer process: "
<< "content_shell.pak";
}
- mappings->push_back(std::pair<base::GlobalDescriptors::Key, int>(
- kShellPakDescriptor, f));
+ mappings->push_back(
+ content::FileDescriptorInfo(kShellPakDescriptor,
+ base::FileDescriptor(f, true)));
}
#endif
diff --git a/content/shell/shell_content_browser_client.h b/content/shell/shell_content_browser_client.h
index 1cf3915..0a5ef05 100644
--- a/content/shell/shell_content_browser_client.h
+++ b/content/shell/shell_content_browser_client.h
@@ -38,7 +38,7 @@ class ShellContentBrowserClient : public ContentBrowserClient {
#if defined(OS_ANDROID)
virtual void GetAdditionalMappedFilesForChildProcess(
const CommandLine& command_line,
- base::GlobalDescriptors::Mapping* mappings) OVERRIDE;
+ std::vector<content::FileDescriptorInfo>* mappings) OVERRIDE;
#endif
ShellBrowserContext* browser_context();