1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/child_process_launcher_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "content/browser/frame_host/render_frame_host_impl.h"
12 #include "content/browser/media/android/browser_media_player_manager.h"
13 #include "content/browser/media/media_web_contents_observer.h"
14 #include "content/browser/renderer_host/compositor_impl_android.h"
15 #include "content/browser/web_contents/web_contents_impl.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/common/content_switches.h"
19 #include "jni/ChildProcessLauncher_jni.h"
20 #include "media/base/android/media_player_android.h"
21 #include "ui/gl/android/surface_texture.h"
23 using base::android::AttachCurrentThread
;
24 using base::android::ToJavaArrayOfStrings
;
25 using base::android::ScopedJavaGlobalRef
;
26 using base::android::ScopedJavaLocalRef
;
27 using content::StartChildProcessCallback
;
33 // Pass a java surface object to the MediaPlayerAndroid object
34 // identified by render process handle, render frame ID and player ID.
35 static void SetSurfacePeer(
36 const base::android::JavaRef
<jobject
>& surface
,
37 base::ProcessHandle render_process_handle
,
40 int render_process_id
= 0;
41 RenderProcessHost::iterator it
= RenderProcessHost::AllHostsIterator();
42 while (!it
.IsAtEnd()) {
43 if (it
.GetCurrentValue()->GetHandle() == render_process_handle
) {
44 render_process_id
= it
.GetCurrentValue()->GetID();
49 if (!render_process_id
) {
50 DVLOG(1) << "Cannot find render process for render_process_handle "
51 << render_process_handle
;
55 RenderFrameHostImpl
* frame
=
56 RenderFrameHostImpl::FromID(render_process_id
, render_frame_id
);
58 DVLOG(1) << "Cannot find frame for render_frame_id " << render_frame_id
;
62 WebContentsImpl
* web_contents
=
63 static_cast<WebContentsImpl
*>(WebContents::FromRenderFrameHost(frame
));
64 BrowserMediaPlayerManager
* player_manager
=
65 web_contents
->media_web_contents_observer()->GetMediaPlayerManager(frame
);
66 if (!player_manager
) {
67 DVLOG(1) << "Cannot find the media player manager for frame " << frame
;
71 media::MediaPlayerAndroid
* player
= player_manager
->GetPlayer(player_id
);
73 DVLOG(1) << "Cannot find media player for player_id " << player_id
;
77 if (player
!= player_manager
->GetFullscreenPlayer()) {
78 gfx::ScopedJavaSurface
scoped_surface(surface
);
79 player
->SetVideoSurface(scoped_surface
.Pass());
83 } // anonymous namespace
85 // Called from ChildProcessLauncher.java when the ChildProcess was
87 // |client_context| is the pointer to StartChildProcessCallback which was
88 // passed in from StartChildProcess.
89 // |handle| is the processID of the child process as originated in Java, 0 if
90 // the ChildProcess could not be created.
91 static void OnChildProcessStarted(JNIEnv
*,
95 StartChildProcessCallback
* callback
=
96 reinterpret_cast<StartChildProcessCallback
*>(client_context
);
98 callback
->Run(static_cast<base::ProcessHandle
>(handle
));
102 void StartChildProcess(
103 const base::CommandLine::StringVector
& argv
,
104 int child_process_id
,
105 scoped_ptr
<content::FileDescriptorInfo
> files_to_register
,
106 const std::map
<int, base::MemoryMappedFile::Region
>& regions
,
107 const StartChildProcessCallback
& callback
) {
108 JNIEnv
* env
= AttachCurrentThread();
111 // Create the Command line String[]
112 ScopedJavaLocalRef
<jobjectArray
> j_argv
= ToJavaArrayOfStrings(env
, argv
);
114 size_t file_count
= files_to_register
->GetMappingSize();
115 DCHECK(file_count
> 0);
117 ScopedJavaLocalRef
<jclass
> j_file_info_class
= base::android::GetClass(
118 env
, "org/chromium/content/browser/FileDescriptorInfo");
119 ScopedJavaLocalRef
<jobjectArray
> j_file_infos(
120 env
, env
->NewObjectArray(file_count
, j_file_info_class
.obj(), NULL
));
121 base::android::CheckException(env
);
123 for (size_t i
= 0; i
< file_count
; ++i
) {
124 int fd
= files_to_register
->GetFDAt(i
);
126 int id
= files_to_register
->GetIDAt(i
);
127 bool auto_close
= files_to_register
->OwnsFD(fd
);
130 auto found_region_iter
= regions
.find(id
);
131 if (found_region_iter
!= regions
.end()) {
132 offset
= found_region_iter
->second
.offset
;
133 size
= found_region_iter
->second
.size
;
135 ScopedJavaLocalRef
<jobject
> j_file_info
=
136 Java_ChildProcessLauncher_makeFdInfo(env
, id
, fd
, auto_close
, offset
,
138 PCHECK(j_file_info
.obj());
139 env
->SetObjectArrayElement(j_file_infos
.obj(), i
, j_file_info
.obj());
141 ignore_result(files_to_register
->ReleaseFD(fd
).release());
145 Java_ChildProcessLauncher_start(
146 env
, base::android::GetApplicationContext(), j_argv
.obj(),
147 child_process_id
, j_file_infos
.obj(),
148 reinterpret_cast<intptr_t>(new StartChildProcessCallback(callback
)));
151 void StopChildProcess(base::ProcessHandle handle
) {
152 JNIEnv
* env
= AttachCurrentThread();
154 Java_ChildProcessLauncher_stop(env
, static_cast<jint
>(handle
));
157 bool IsChildProcessOomProtected(base::ProcessHandle handle
) {
158 JNIEnv
* env
= AttachCurrentThread();
160 return Java_ChildProcessLauncher_isOomProtected(env
,
161 static_cast<jint
>(handle
));
164 void SetChildProcessInForeground(base::ProcessHandle handle
,
165 bool in_foreground
) {
166 JNIEnv
* env
= AttachCurrentThread();
168 return Java_ChildProcessLauncher_setInForeground(env
,
169 static_cast<jint
>(handle
), static_cast<jboolean
>(in_foreground
));
172 void EstablishSurfacePeer(
173 JNIEnv
* env
, jclass clazz
,
174 jint pid
, jobject surface
, jint primary_id
, jint secondary_id
) {
175 ScopedJavaGlobalRef
<jobject
> jsurface
;
176 jsurface
.Reset(env
, surface
);
177 if (jsurface
.is_null())
180 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI
));
181 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, base::Bind(
182 &SetSurfacePeer
, jsurface
, pid
, primary_id
, secondary_id
));
185 void RegisterViewSurface(int surface_id
, jobject j_surface
) {
186 JNIEnv
* env
= AttachCurrentThread();
188 Java_ChildProcessLauncher_registerViewSurface(env
, surface_id
, j_surface
);
191 void UnregisterViewSurface(int surface_id
) {
192 JNIEnv
* env
= AttachCurrentThread();
194 Java_ChildProcessLauncher_unregisterViewSurface(env
, surface_id
);
197 void CreateSurfaceTextureSurface(int surface_texture_id
,
199 gfx::SurfaceTexture
* surface_texture
) {
200 JNIEnv
* env
= AttachCurrentThread();
202 Java_ChildProcessLauncher_createSurfaceTextureSurface(
206 surface_texture
->j_surface_texture().obj());
209 void DestroySurfaceTextureSurface(int surface_texture_id
, int client_id
) {
210 JNIEnv
* env
= AttachCurrentThread();
212 Java_ChildProcessLauncher_destroySurfaceTextureSurface(
213 env
, surface_texture_id
, client_id
);
216 gfx::ScopedJavaSurface
GetSurfaceTextureSurface(int surface_texture_id
,
218 JNIEnv
* env
= AttachCurrentThread();
220 return gfx::ScopedJavaSurface::AcquireExternalSurface(
221 Java_ChildProcessLauncher_getSurfaceTextureSurface(
222 env
, surface_texture_id
, client_id
).obj());
225 jboolean
IsSingleProcess(JNIEnv
* env
, jclass clazz
) {
226 return base::CommandLine::ForCurrentProcess()->HasSwitch(
227 switches::kSingleProcess
);
230 bool RegisterChildProcessLauncher(JNIEnv
* env
) {
231 return RegisterNativesImpl(env
);
234 } // namespace content