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 "chrome/browser/android/chrome_web_contents_delegate_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/command_line.h"
10 #include "chrome/browser/android/feature_utilities.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/file_select_helper.h"
13 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
14 #include "chrome/browser/media/media_stream_capture_indicator.h"
15 #include "chrome/browser/media/protected_media_identifier_permission_context.h"
16 #include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
17 #include "chrome/browser/prerender/prerender_manager.h"
18 #include "chrome/browser/prerender/prerender_manager_factory.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ssl/security_state_model.h"
21 #include "chrome/browser/ui/android/bluetooth_chooser_android.h"
22 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
23 #include "chrome/browser/ui/browser_navigator.h"
24 #include "chrome/browser/ui/find_bar/find_notification_details.h"
25 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
26 #include "chrome/browser/ui/tab_helpers.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "components/app_modal/javascript_dialog_manager.h"
29 #include "content/public/browser/notification_details.h"
30 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/notification_source.h"
32 #include "content/public/browser/render_process_host.h"
33 #include "content/public/browser/render_view_host.h"
34 #include "content/public/browser/web_contents.h"
35 #include "content/public/common/file_chooser_params.h"
36 #include "jni/ChromeWebContentsDelegateAndroid_jni.h"
37 #include "third_party/WebKit/public/web/WebWindowFeatures.h"
38 #include "ui/gfx/geometry/rect.h"
39 #include "ui/gfx/geometry/rect_f.h"
41 #if defined(ENABLE_PLUGINS)
42 #include "chrome/browser/pepper_broker_infobar_delegate.h"
45 using base::android::AttachCurrentThread
;
46 using base::android::ScopedJavaLocalRef
;
47 using content::BluetoothChooser
;
48 using content::FileChooserParams
;
49 using content::WebContents
;
53 ScopedJavaLocalRef
<jobject
> CreateJavaRectF(
55 const gfx::RectF
& rect
) {
56 return ScopedJavaLocalRef
<jobject
>(
57 Java_ChromeWebContentsDelegateAndroid_createRectF(env
,
64 ScopedJavaLocalRef
<jobject
> CreateJavaRect(
66 const gfx::Rect
& rect
) {
67 return ScopedJavaLocalRef
<jobject
>(
68 Java_ChromeWebContentsDelegateAndroid_createRect(
70 static_cast<int>(rect
.x()),
71 static_cast<int>(rect
.y()),
72 static_cast<int>(rect
.right()),
73 static_cast<int>(rect
.bottom())));
76 } // anonymous namespace
81 ChromeWebContentsDelegateAndroid::ChromeWebContentsDelegateAndroid(JNIEnv
* env
,
83 : WebContentsDelegateAndroid(env
, obj
) {
86 ChromeWebContentsDelegateAndroid::~ChromeWebContentsDelegateAndroid() {
87 notification_registrar_
.RemoveAll();
90 // Register native methods.
91 bool RegisterChromeWebContentsDelegateAndroid(JNIEnv
* env
) {
92 return RegisterNativesImpl(env
);
95 void ChromeWebContentsDelegateAndroid::LoadingStateChanged(
96 WebContents
* source
, bool to_different_document
) {
97 bool has_stopped
= source
== NULL
|| !source
->IsLoading();
98 WebContentsDelegateAndroid::LoadingStateChanged(
99 source
, to_different_document
);
100 LoadProgressChanged(source
, has_stopped
? 1 : 0);
103 void ChromeWebContentsDelegateAndroid::RunFileChooser(
104 WebContents
* web_contents
,
105 const FileChooserParams
& params
) {
106 FileSelectHelper::RunFileChooser(web_contents
, params
);
109 scoped_ptr
<BluetoothChooser
>
110 ChromeWebContentsDelegateAndroid::RunBluetoothChooser(
111 content::WebContents
* web_contents
,
112 const BluetoothChooser::EventHandler
& event_handler
,
113 const GURL
& origin
) {
114 return make_scoped_ptr(
115 new BluetoothChooserAndroid(web_contents
, event_handler
, origin
));
118 void ChromeWebContentsDelegateAndroid::VisibleSSLStateChanged(
119 content::WebContents
* web_contents
) {
120 DCHECK(web_contents
);
121 // Notify the model that the security state has changed, so that the
122 // URL bar updates with up-to-date data computed by the model.
123 SecurityStateModel
* model
= SecurityStateModel::FromWebContents(web_contents
);
125 model
->SecurityStateChanged();
126 WebContentsDelegateAndroid::VisibleSSLStateChanged(web_contents
);
129 void ChromeWebContentsDelegateAndroid::CloseContents(
130 WebContents
* web_contents
) {
131 // Prevent dangling registrations assigned to closed web contents.
132 if (notification_registrar_
.IsRegistered(this,
133 chrome::NOTIFICATION_FIND_RESULT_AVAILABLE
,
134 content::Source
<WebContents
>(web_contents
))) {
135 notification_registrar_
.Remove(this,
136 chrome::NOTIFICATION_FIND_RESULT_AVAILABLE
,
137 content::Source
<WebContents
>(web_contents
));
140 WebContentsDelegateAndroid::CloseContents(web_contents
);
143 void ChromeWebContentsDelegateAndroid::Observe(
145 const content::NotificationSource
& source
,
146 const content::NotificationDetails
& details
) {
148 case chrome::NOTIFICATION_FIND_RESULT_AVAILABLE
:
149 OnFindResultAvailable(
150 content::Source
<WebContents
>(source
).ptr(),
151 content::Details
<FindNotificationDetails
>(details
).ptr());
154 NOTREACHED() << "Unexpected notification: " << type
;
159 blink::WebDisplayMode
ChromeWebContentsDelegateAndroid::GetDisplayMode(
160 const WebContents
* web_contents
) const {
161 JNIEnv
* env
= base::android::AttachCurrentThread();
163 ScopedJavaLocalRef
<jobject
> obj
= GetJavaDelegate(env
);
165 return blink::WebDisplayModeUndefined
;
167 return static_cast<blink::WebDisplayMode
>(
168 Java_ChromeWebContentsDelegateAndroid_getDisplayMode(
173 void ChromeWebContentsDelegateAndroid::FindReply(
174 WebContents
* web_contents
,
176 int number_of_matches
,
177 const gfx::Rect
& selection_rect
,
178 int active_match_ordinal
,
180 if (!notification_registrar_
.IsRegistered(this,
181 chrome::NOTIFICATION_FIND_RESULT_AVAILABLE
,
182 content::Source
<WebContents
>(web_contents
))) {
183 notification_registrar_
.Add(this,
184 chrome::NOTIFICATION_FIND_RESULT_AVAILABLE
,
185 content::Source
<WebContents
>(web_contents
));
188 FindTabHelper
* find_tab_helper
= FindTabHelper::FromWebContents(web_contents
);
189 find_tab_helper
->HandleFindReply(request_id
,
192 active_match_ordinal
,
196 void ChromeWebContentsDelegateAndroid::OnFindResultAvailable(
197 WebContents
* web_contents
,
198 const FindNotificationDetails
* find_result
) {
199 JNIEnv
* env
= base::android::AttachCurrentThread();
200 ScopedJavaLocalRef
<jobject
> obj
= GetJavaDelegate(env
);
204 ScopedJavaLocalRef
<jobject
> selection_rect
= CreateJavaRect(
205 env
, find_result
->selection_rect());
207 // Create the details object.
208 ScopedJavaLocalRef
<jobject
> details_object
=
209 Java_ChromeWebContentsDelegateAndroid_createFindNotificationDetails(
211 find_result
->number_of_matches(),
212 selection_rect
.obj(),
213 find_result
->active_match_ordinal(),
214 find_result
->final_update());
216 Java_ChromeWebContentsDelegateAndroid_onFindResultAvailable(
219 details_object
.obj());
222 void ChromeWebContentsDelegateAndroid::FindMatchRectsReply(
223 WebContents
* web_contents
,
225 const std::vector
<gfx::RectF
>& rects
,
226 const gfx::RectF
& active_rect
) {
227 JNIEnv
* env
= base::android::AttachCurrentThread();
228 ScopedJavaLocalRef
<jobject
> obj
= GetJavaDelegate(env
);
232 // Create the details object.
233 ScopedJavaLocalRef
<jobject
> details_object
=
234 Java_ChromeWebContentsDelegateAndroid_createFindMatchRectsDetails(
238 CreateJavaRectF(env
, active_rect
).obj());
241 for (size_t i
= 0; i
< rects
.size(); ++i
) {
242 Java_ChromeWebContentsDelegateAndroid_setMatchRectByIndex(
244 details_object
.obj(),
246 CreateJavaRectF(env
, rects
[i
]).obj());
249 Java_ChromeWebContentsDelegateAndroid_onFindMatchRectsAvailable(
252 details_object
.obj());
255 content::JavaScriptDialogManager
*
256 ChromeWebContentsDelegateAndroid::GetJavaScriptDialogManager(
257 WebContents
* source
) {
258 return app_modal::JavaScriptDialogManager::GetInstance();
261 void ChromeWebContentsDelegateAndroid::RequestMediaAccessPermission(
262 content::WebContents
* web_contents
,
263 const content::MediaStreamRequest
& request
,
264 const content::MediaResponseCallback
& callback
) {
265 MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
266 web_contents
, request
, callback
, NULL
);
269 bool ChromeWebContentsDelegateAndroid::CheckMediaAccessPermission(
270 content::WebContents
* web_contents
,
271 const GURL
& security_origin
,
272 content::MediaStreamType type
) {
273 return MediaCaptureDevicesDispatcher::GetInstance()
274 ->CheckMediaAccessPermission(web_contents
, security_origin
, type
);
277 bool ChromeWebContentsDelegateAndroid::RequestPpapiBrokerPermission(
278 WebContents
* web_contents
,
280 const base::FilePath
& plugin_path
,
281 const base::Callback
<void(bool)>& callback
) {
282 #if defined(ENABLE_PLUGINS)
283 PepperBrokerInfoBarDelegate::Create(
284 web_contents
, url
, plugin_path
, callback
);
291 WebContents
* ChromeWebContentsDelegateAndroid::OpenURLFromTab(
293 const content::OpenURLParams
& params
) {
294 WindowOpenDisposition disposition
= params
.disposition
;
295 if (!source
|| (disposition
!= CURRENT_TAB
&&
296 disposition
!= NEW_FOREGROUND_TAB
&&
297 disposition
!= NEW_BACKGROUND_TAB
&&
298 disposition
!= OFF_THE_RECORD
&&
299 disposition
!= NEW_POPUP
&&
300 disposition
!= NEW_WINDOW
)) {
301 // We can't handle this here. Give the parent a chance.
302 return WebContentsDelegateAndroid::OpenURLFromTab(source
, params
);
305 Profile
* profile
= Profile::FromBrowserContext(source
->GetBrowserContext());
306 chrome::NavigateParams
nav_params(profile
,
309 FillNavigateParamsFromOpenURLParams(&nav_params
, params
);
310 nav_params
.source_contents
= source
;
311 nav_params
.window_action
= chrome::NavigateParams::SHOW_WINDOW
;
312 nav_params
.user_gesture
= params
.user_gesture
;
314 PopupBlockerTabHelper
* popup_blocker_helper
=
315 PopupBlockerTabHelper::FromWebContents(source
);
316 DCHECK(popup_blocker_helper
);
318 if ((params
.disposition
== NEW_POPUP
||
319 params
.disposition
== NEW_FOREGROUND_TAB
||
320 params
.disposition
== NEW_BACKGROUND_TAB
||
321 params
.disposition
== NEW_WINDOW
) &&
322 !params
.user_gesture
&&
323 !base::CommandLine::ForCurrentProcess()->HasSwitch(
324 switches::kDisablePopupBlocking
)) {
325 if (popup_blocker_helper
->MaybeBlockPopup(nav_params
,
326 blink::WebWindowFeatures())) {
331 if (disposition
== CURRENT_TAB
) {
332 // Only prerender for a current-tab navigation to avoid session storage
334 nav_params
.target_contents
= source
;
335 prerender::PrerenderManager
* prerender_manager
=
336 prerender::PrerenderManagerFactory::GetForProfile(profile
);
337 if (prerender_manager
&&
338 prerender_manager
->MaybeUsePrerenderedPage(params
.url
, &nav_params
)) {
339 return nav_params
.target_contents
;
343 return WebContentsDelegateAndroid::OpenURLFromTab(source
, params
);
346 bool ChromeWebContentsDelegateAndroid::ShouldResumeRequestsForCreatedWindow() {
347 JNIEnv
* env
= base::android::AttachCurrentThread();
348 ScopedJavaLocalRef
<jobject
> obj
= GetJavaDelegate(env
);
352 return Java_ChromeWebContentsDelegateAndroid_shouldResumeRequestsForCreatedWindow(
357 void ChromeWebContentsDelegateAndroid::AddNewContents(
359 WebContents
* new_contents
,
360 WindowOpenDisposition disposition
,
361 const gfx::Rect
& initial_rect
,
364 // No code for this yet.
365 DCHECK_NE(disposition
, SAVE_TO_DISK
);
366 // Can't create a new contents for the current tab - invalid case.
367 DCHECK_NE(disposition
, CURRENT_TAB
);
369 TabHelpers::AttachTabHelpers(new_contents
);
371 JNIEnv
* env
= AttachCurrentThread();
372 ScopedJavaLocalRef
<jobject
> obj
= GetJavaDelegate(env
);
373 bool handled
= false;
374 if (!obj
.is_null()) {
375 ScopedJavaLocalRef
<jobject
> jsource
;
377 jsource
= source
->GetJavaWebContents();
378 ScopedJavaLocalRef
<jobject
> jnew_contents
;
380 jnew_contents
= new_contents
->GetJavaWebContents();
382 handled
= Java_ChromeWebContentsDelegateAndroid_addNewContents(
387 static_cast<jint
>(disposition
),
393 *was_blocked
= !handled
;
398 } // namespace android
399 } // namespace chrome
401 jboolean
IsCapturingAudio(JNIEnv
* env
,
402 const JavaParamRef
<jclass
>& clazz
,
403 const JavaParamRef
<jobject
>& java_web_contents
) {
404 content::WebContents
* web_contents
=
405 content::WebContents::FromJavaWebContents(java_web_contents
);
406 scoped_refptr
<MediaStreamCaptureIndicator
> indicator
=
407 MediaCaptureDevicesDispatcher::GetInstance()->
408 GetMediaStreamCaptureIndicator();
409 return indicator
->IsCapturingAudio(web_contents
);
412 jboolean
IsCapturingVideo(JNIEnv
* env
,
413 const JavaParamRef
<jclass
>& clazz
,
414 const JavaParamRef
<jobject
>& java_web_contents
) {
415 content::WebContents
* web_contents
=
416 content::WebContents::FromJavaWebContents(java_web_contents
);
417 scoped_refptr
<MediaStreamCaptureIndicator
> indicator
=
418 MediaCaptureDevicesDispatcher::GetInstance()->
419 GetMediaStreamCaptureIndicator();
420 return indicator
->IsCapturingVideo(web_contents
);