1 // Copyright 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/content_view_core_impl.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/command_line.h"
12 #include "base/json/json_writer.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/values.h"
17 #include "cc/layers/layer.h"
18 #include "cc/output/begin_frame_args.h"
19 #include "content/browser/android/gesture_event_type.h"
20 #include "content/browser/android/interstitial_page_delegate_android.h"
21 #include "content/browser/android/load_url_params.h"
22 #include "content/browser/frame_host/interstitial_page_impl.h"
23 #include "content/browser/frame_host/navigation_controller_impl.h"
24 #include "content/browser/frame_host/navigation_entry_impl.h"
25 #include "content/browser/media/android/browser_media_player_manager.h"
26 #include "content/browser/renderer_host/compositor_impl_android.h"
27 #include "content/browser/renderer_host/input/motion_event_android.h"
28 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
29 #include "content/browser/renderer_host/input/web_input_event_util.h"
30 #include "content/browser/renderer_host/java/java_bound_object.h"
31 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
32 #include "content/browser/renderer_host/render_view_host_impl.h"
33 #include "content/browser/renderer_host/render_widget_host_impl.h"
34 #include "content/browser/renderer_host/render_widget_host_view_android.h"
35 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
36 #include "content/browser/ssl/ssl_host_state.h"
37 #include "content/browser/web_contents/web_contents_view_android.h"
38 #include "content/common/input/web_input_event_traits.h"
39 #include "content/common/input_messages.h"
40 #include "content/common/view_messages.h"
41 #include "content/public/browser/browser_accessibility_state.h"
42 #include "content/public/browser/browser_context.h"
43 #include "content/public/browser/favicon_status.h"
44 #include "content/public/browser/notification_details.h"
45 #include "content/public/browser/notification_service.h"
46 #include "content/public/browser/notification_source.h"
47 #include "content/public/browser/notification_types.h"
48 #include "content/public/browser/render_frame_host.h"
49 #include "content/public/browser/web_contents.h"
50 #include "content/public/common/content_client.h"
51 #include "content/public/common/content_switches.h"
52 #include "content/public/common/menu_item.h"
53 #include "content/public/common/page_transition_types.h"
54 #include "content/public/common/user_agent.h"
55 #include "jni/ContentViewCore_jni.h"
56 #include "third_party/WebKit/public/web/WebBindings.h"
57 #include "third_party/WebKit/public/web/WebInputEvent.h"
58 #include "ui/base/android/view_android.h"
59 #include "ui/base/android/window_android.h"
60 #include "ui/gfx/android/java_bitmap.h"
61 #include "ui/gfx/screen.h"
62 #include "ui/gfx/size_conversions.h"
63 #include "ui/gfx/size_f.h"
65 using base::android::AttachCurrentThread
;
66 using base::android::ConvertJavaStringToUTF16
;
67 using base::android::ConvertJavaStringToUTF8
;
68 using base::android::ConvertUTF16ToJavaString
;
69 using base::android::ConvertUTF8ToJavaString
;
70 using base::android::ScopedJavaGlobalRef
;
71 using base::android::ScopedJavaLocalRef
;
72 using blink::WebGestureEvent
;
73 using blink::WebInputEvent
;
75 // Describes the type and enabled state of a select popup item.
79 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
80 #include "content/browser/android/popup_item_type_list.h"
81 #undef DEFINE_POPUP_ITEM_TYPE
90 const void* kContentViewUserDataKey
= &kContentViewUserDataKey
;
92 int GetRenderProcessIdFromRenderViewHost(RenderViewHost
* host
) {
94 RenderProcessHost
* render_process
= host
->GetProcess();
95 DCHECK(render_process
);
96 if (render_process
->HasConnection())
97 return render_process
->GetHandle();
102 ScopedJavaLocalRef
<jobject
> CreateJavaRect(
104 const gfx::Rect
& rect
) {
105 return ScopedJavaLocalRef
<jobject
>(
106 Java_ContentViewCore_createRect(env
,
107 static_cast<int>(rect
.x()),
108 static_cast<int>(rect
.y()),
109 static_cast<int>(rect
.right()),
110 static_cast<int>(rect
.bottom())));
113 int ToGestureEventType(WebInputEvent::Type type
) {
115 case WebInputEvent::GestureScrollBegin
:
117 case WebInputEvent::GestureScrollEnd
:
119 case WebInputEvent::GestureScrollUpdate
:
121 case WebInputEvent::GestureFlingStart
:
123 case WebInputEvent::GestureFlingCancel
:
125 case WebInputEvent::GestureShowPress
:
127 case WebInputEvent::GestureTap
:
128 return SINGLE_TAP_CONFIRMED
;
129 case WebInputEvent::GestureTapUnconfirmed
:
130 return SINGLE_TAP_UNCONFIRMED
;
131 case WebInputEvent::GestureTapDown
:
133 case WebInputEvent::GestureTapCancel
:
135 case WebInputEvent::GestureDoubleTap
:
137 case WebInputEvent::GestureLongPress
:
139 case WebInputEvent::GestureLongTap
:
141 case WebInputEvent::GesturePinchBegin
:
143 case WebInputEvent::GesturePinchEnd
:
145 case WebInputEvent::GesturePinchUpdate
:
147 case WebInputEvent::GestureTwoFingerTap
:
148 case WebInputEvent::GestureScrollUpdateWithoutPropagation
:
150 NOTREACHED() << "Invalid source gesture type: "
151 << WebInputEventTraits::GetName(type
);
156 float GetPrimaryDisplayDeviceScaleFactor() {
157 const gfx::Display
& display
=
158 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
159 return display
.device_scale_factor();
164 // Enables a callback when the underlying WebContents is destroyed, to enable
165 // nulling the back-pointer.
166 class ContentViewCoreImpl::ContentViewUserData
167 : public base::SupportsUserData::Data
{
169 explicit ContentViewUserData(ContentViewCoreImpl
* content_view_core
)
170 : content_view_core_(content_view_core
) {
173 virtual ~ContentViewUserData() {
174 // TODO(joth): When chrome has finished removing the TabContents class (see
175 // crbug.com/107201) consider inverting relationship, so ContentViewCore
176 // would own WebContents. That effectively implies making the WebContents
177 // destructor private on Android.
178 delete content_view_core_
;
181 ContentViewCoreImpl
* get() const { return content_view_core_
; }
184 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
185 ContentViewCoreImpl
* content_view_core_
;
187 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData
);
191 ContentViewCoreImpl
* ContentViewCoreImpl::FromWebContents(
192 content::WebContents
* web_contents
) {
193 ContentViewCoreImpl::ContentViewUserData
* data
=
194 reinterpret_cast<ContentViewCoreImpl::ContentViewUserData
*>(
195 web_contents
->GetUserData(kContentViewUserDataKey
));
196 return data
? data
->get() : NULL
;
200 ContentViewCore
* ContentViewCore::FromWebContents(
201 content::WebContents
* web_contents
) {
202 return ContentViewCoreImpl::FromWebContents(web_contents
);
206 ContentViewCore
* ContentViewCore::GetNativeContentViewCore(JNIEnv
* env
,
208 return reinterpret_cast<ContentViewCore
*>(
209 Java_ContentViewCore_getNativeContentViewCore(env
, obj
));
212 ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv
* env
,
214 WebContents
* web_contents
,
215 ui::ViewAndroid
* view_android
,
216 ui::WindowAndroid
* window_android
)
217 : WebContentsObserver(web_contents
),
219 web_contents_(static_cast<WebContentsImpl
*>(web_contents
)),
220 root_layer_(cc::Layer::Create()),
221 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
222 view_android_(view_android
),
223 window_android_(window_android
),
224 device_orientation_(0),
225 geolocation_needs_pause_(false) {
226 CHECK(web_contents
) <<
227 "A ContentViewCoreImpl should be created with a valid WebContents.";
229 // Currently, the only use case we have for overriding a user agent involves
230 // spoofing a desktop Linux user agent for "Request desktop site".
231 // Automatically set it for all WebContents so that it is available when a
232 // NavigationEntry requires the user agent to be overridden.
233 const char kLinuxInfoStr
[] = "X11; Linux x86_64";
234 std::string product
= content::GetContentClient()->GetProduct();
235 std::string spoofed_ua
=
236 BuildUserAgentFromOSAndProduct(kLinuxInfoStr
, product
);
237 web_contents
->SetUserAgentOverride(spoofed_ua
);
242 ContentViewCoreImpl::~ContentViewCoreImpl() {
243 JNIEnv
* env
= base::android::AttachCurrentThread();
244 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
246 if (!j_obj
.is_null()) {
247 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
248 env
, j_obj
.obj(), reinterpret_cast<intptr_t>(this));
250 // Make sure nobody calls back into this object while we are tearing things
252 notification_registrar_
.RemoveAll();
255 base::android::ScopedJavaLocalRef
<jobject
>
256 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv
* env
, jobject obj
) {
257 return web_contents_
->GetJavaWebContents();
260 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv
* env
,
262 DCHECK(env
->IsSameObject(java_ref_
.get(env
).obj(), obj
));
266 void ContentViewCoreImpl::InitWebContents() {
267 DCHECK(web_contents_
);
268 notification_registrar_
.Add(
269 this, NOTIFICATION_RENDER_VIEW_HOST_CHANGED
,
270 Source
<WebContents
>(web_contents_
));
271 notification_registrar_
.Add(
272 this, NOTIFICATION_RENDERER_PROCESS_CREATED
,
273 content::NotificationService::AllBrowserContextsAndSources());
274 notification_registrar_
.Add(
275 this, NOTIFICATION_WEB_CONTENTS_CONNECTED
,
276 Source
<WebContents
>(web_contents_
));
278 static_cast<WebContentsViewAndroid
*>(
279 static_cast<WebContentsImpl
*>(web_contents_
)->GetView())->
280 SetContentViewCore(this);
281 DCHECK(!web_contents_
->GetUserData(kContentViewUserDataKey
));
282 web_contents_
->SetUserData(kContentViewUserDataKey
,
283 new ContentViewUserData(this));
286 void ContentViewCoreImpl::Observe(int type
,
287 const NotificationSource
& source
,
288 const NotificationDetails
& details
) {
290 case NOTIFICATION_RENDER_VIEW_HOST_CHANGED
: {
291 std::pair
<RenderViewHost
*, RenderViewHost
*>* switched_details
=
292 Details
<std::pair
<RenderViewHost
*, RenderViewHost
*> >(details
).ptr();
294 if (switched_details
->first
) {
295 old_pid
= GetRenderProcessIdFromRenderViewHost(
296 switched_details
->first
);
298 RenderWidgetHostViewAndroid
* view
=
299 static_cast<RenderWidgetHostViewAndroid
*>(
300 switched_details
->first
->GetView());
302 view
->SetContentViewCore(NULL
);
304 view
= static_cast<RenderWidgetHostViewAndroid
*>(
305 switched_details
->second
->GetView());
308 view
->SetContentViewCore(this);
310 int new_pid
= GetRenderProcessIdFromRenderViewHost(
311 web_contents_
->GetRenderViewHost());
312 if (new_pid
!= old_pid
) {
313 // Notify the Java side of the change of the current renderer process.
314 JNIEnv
* env
= AttachCurrentThread();
315 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
316 if (!obj
.is_null()) {
317 Java_ContentViewCore_onRenderProcessSwap(env
, obj
.obj());
320 SetFocusInternal(HasFocus());
321 if (geolocation_needs_pause_
)
322 PauseOrResumeGeolocation(true);
325 case NOTIFICATION_RENDERER_PROCESS_CREATED
: {
326 // Notify the Java side of the current renderer process.
327 RenderProcessHost
* source_process_host
=
328 Source
<RenderProcessHost
>(source
).ptr();
329 RenderProcessHost
* current_process_host
=
330 web_contents_
->GetRenderViewHost()->GetProcess();
332 if (source_process_host
== current_process_host
) {
333 JNIEnv
* env
= AttachCurrentThread();
334 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
335 if (!obj
.is_null()) {
336 Java_ContentViewCore_onRenderProcessSwap(env
, obj
.obj());
341 case NOTIFICATION_WEB_CONTENTS_CONNECTED
: {
342 JNIEnv
* env
= AttachCurrentThread();
343 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
344 if (!obj
.is_null()) {
345 Java_ContentViewCore_onWebContentsConnected(env
, obj
.obj());
352 void ContentViewCoreImpl::RenderViewReady() {
353 if (device_orientation_
!= 0)
354 SendOrientationChangeEventInternal();
357 RenderWidgetHostViewAndroid
*
358 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
359 RenderWidgetHostView
* rwhv
= NULL
;
361 rwhv
= web_contents_
->GetRenderWidgetHostView();
362 if (web_contents_
->ShowingInterstitialPage()) {
363 rwhv
= static_cast<InterstitialPageImpl
*>(
364 web_contents_
->GetInterstitialPage())->
365 GetRenderViewHost()->GetView();
368 return static_cast<RenderWidgetHostViewAndroid
*>(rwhv
);
371 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetJavaObject() {
372 JNIEnv
* env
= AttachCurrentThread();
373 return java_ref_
.get(env
);
376 jint
ContentViewCoreImpl::GetBackgroundColor(JNIEnv
* env
, jobject obj
) {
377 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
379 return SK_ColorWHITE
;
380 return rwhva
->GetCachedBackgroundColor();
383 void ContentViewCoreImpl::OnHide(JNIEnv
* env
, jobject obj
) {
387 void ContentViewCoreImpl::OnShow(JNIEnv
* env
, jobject obj
) {
391 void ContentViewCoreImpl::Show() {
392 GetWebContents()->WasShown();
395 void ContentViewCoreImpl::Hide() {
396 GetWebContents()->WasHidden();
400 void ContentViewCoreImpl::PauseVideo() {
401 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
403 host
->Send(new ViewMsg_PauseVideo(host
->GetRoutingID()));
406 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause
) {
407 geolocation_needs_pause_
= should_pause
;
408 RenderViewHostImpl
* rvh
=
409 static_cast<RenderViewHostImpl
*>(web_contents_
->GetRenderViewHost());
411 scoped_refptr
<GeolocationDispatcherHost
> geolocation_dispatcher
=
412 static_cast<RenderProcessHostImpl
*>(
413 web_contents_
->GetRenderProcessHost())->
414 geolocation_dispatcher_host();
415 if (geolocation_dispatcher
.get()) {
416 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
417 base::Bind(&GeolocationDispatcherHost::PauseOrResume
,
418 geolocation_dispatcher
,
421 geolocation_needs_pause_
= false;
426 // All positions and sizes are in CSS pixels.
427 // Note that viewport_width/height is a best effort based.
428 // ContentViewCore has the actual information about the physical viewport size.
429 void ContentViewCoreImpl::UpdateFrameInfo(
430 const gfx::Vector2dF
& scroll_offset
,
431 float page_scale_factor
,
432 const gfx::Vector2dF
& page_scale_factor_limits
,
433 const gfx::SizeF
& content_size
,
434 const gfx::SizeF
& viewport_size
,
435 const gfx::Vector2dF
& controls_offset
,
436 const gfx::Vector2dF
& content_offset
,
437 float overdraw_bottom_height
) {
438 JNIEnv
* env
= AttachCurrentThread();
439 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
443 if (window_android_
) {
444 gfx::Vector2dF
window_offset(
445 Java_ContentViewCore_getLocationInWindowX(env
, obj
.obj()),
446 Java_ContentViewCore_getLocationInWindowY(env
, obj
.obj()));
447 window_android_
->set_content_offset(
448 gfx::ScaleVector2d(content_offset
, dpi_scale_
) + window_offset
);
451 Java_ContentViewCore_updateFrameInfo(
456 page_scale_factor_limits
.x(),
457 page_scale_factor_limits
.y(),
458 content_size
.width(),
459 content_size
.height(),
460 viewport_size
.width(),
461 viewport_size
.height(),
464 overdraw_bottom_height
);
467 void ContentViewCoreImpl::SetTitle(const base::string16
& title
) {
468 JNIEnv
* env
= AttachCurrentThread();
469 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
472 ScopedJavaLocalRef
<jstring
> jtitle
=
473 ConvertUTF8ToJavaString(env
, base::UTF16ToUTF8(title
));
474 Java_ContentViewCore_setTitle(env
, obj
.obj(), jtitle
.obj());
477 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color
) {
478 JNIEnv
* env
= AttachCurrentThread();
479 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
482 Java_ContentViewCore_onBackgroundColorChanged(env
, obj
.obj(), color
);
485 void ContentViewCoreImpl::ShowSelectPopupMenu(const gfx::Rect
& bounds
,
486 const std::vector
<MenuItem
>& items
, int selected_item
, bool multiple
) {
487 JNIEnv
* env
= AttachCurrentThread();
488 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
492 ScopedJavaLocalRef
<jobject
> bounds_rect(CreateJavaRect(env
, bounds
));
494 // For multi-select list popups we find the list of previous selections by
495 // iterating through the items. But for single selection popups we take the
496 // given |selected_item| as is.
497 ScopedJavaLocalRef
<jintArray
> selected_array
;
499 scoped_ptr
<jint
[]> native_selected_array(new jint
[items
.size()]);
500 size_t selected_count
= 0;
501 for (size_t i
= 0; i
< items
.size(); ++i
) {
502 if (items
[i
].checked
)
503 native_selected_array
[selected_count
++] = i
;
506 selected_array
= ScopedJavaLocalRef
<jintArray
>(
507 env
, env
->NewIntArray(selected_count
));
508 env
->SetIntArrayRegion(selected_array
.obj(), 0, selected_count
,
509 native_selected_array
.get());
511 selected_array
= ScopedJavaLocalRef
<jintArray
>(env
, env
->NewIntArray(1));
512 jint value
= selected_item
;
513 env
->SetIntArrayRegion(selected_array
.obj(), 0, 1, &value
);
516 ScopedJavaLocalRef
<jintArray
> enabled_array(env
,
517 env
->NewIntArray(items
.size()));
518 std::vector
<base::string16
> labels
;
519 labels
.reserve(items
.size());
520 for (size_t i
= 0; i
< items
.size(); ++i
) {
521 labels
.push_back(items
[i
].label
);
523 (items
[i
].type
== MenuItem::GROUP
? POPUP_ITEM_TYPE_GROUP
:
524 (items
[i
].enabled
? POPUP_ITEM_TYPE_ENABLED
:
525 POPUP_ITEM_TYPE_DISABLED
));
526 env
->SetIntArrayRegion(enabled_array
.obj(), i
, 1, &enabled
);
528 ScopedJavaLocalRef
<jobjectArray
> items_array(
529 base::android::ToJavaArrayOfStrings(env
, labels
));
530 Java_ContentViewCore_showSelectPopup(env
, j_obj
.obj(),
535 selected_array
.obj());
538 void ContentViewCoreImpl::HideSelectPopupMenu() {
539 JNIEnv
* env
= AttachCurrentThread();
540 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
541 if (!j_obj
.is_null())
542 Java_ContentViewCore_hideSelectPopup(env
, j_obj
.obj());
545 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent
& event
,
546 InputEventAckState ack_result
) {
547 JNIEnv
* env
= AttachCurrentThread();
548 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
552 switch (event
.type
) {
553 case WebInputEvent::GestureFlingStart
:
554 if (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
) {
555 // The view expects the fling velocity in pixels/s.
556 Java_ContentViewCore_onFlingStartEventConsumed(env
, j_obj
.obj(),
557 event
.data
.flingStart
.velocityX
* dpi_scale(),
558 event
.data
.flingStart
.velocityY
* dpi_scale());
560 // If a scroll ends with a fling, a SCROLL_END event is never sent.
561 // However, if that fling went unconsumed, we still need to let the
562 // listeners know that scrolling has ended.
563 Java_ContentViewCore_onScrollEndEventAck(env
, j_obj
.obj());
566 if (ack_result
== INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
) {
567 // The view expects the fling velocity in pixels/s.
568 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env
, j_obj
.obj(),
569 event
.data
.flingStart
.velocityX
* dpi_scale(),
570 event
.data
.flingStart
.velocityY
* dpi_scale());
573 case WebInputEvent::GestureFlingCancel
:
574 Java_ContentViewCore_onFlingCancelEventAck(env
, j_obj
.obj());
576 case WebInputEvent::GestureScrollBegin
:
577 Java_ContentViewCore_onScrollBeginEventAck(env
, j_obj
.obj());
579 case WebInputEvent::GestureScrollUpdate
:
580 if (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
)
581 Java_ContentViewCore_onScrollUpdateGestureConsumed(env
, j_obj
.obj());
583 case WebInputEvent::GestureScrollEnd
:
584 Java_ContentViewCore_onScrollEndEventAck(env
, j_obj
.obj());
586 case WebInputEvent::GesturePinchBegin
:
587 Java_ContentViewCore_onPinchBeginEventAck(env
, j_obj
.obj());
589 case WebInputEvent::GesturePinchEnd
:
590 Java_ContentViewCore_onPinchEndEventAck(env
, j_obj
.obj());
592 case WebInputEvent::GestureTap
:
593 if (ack_result
!= INPUT_EVENT_ACK_STATE_CONSUMED
) {
594 Java_ContentViewCore_onTapEventNotConsumed(
595 env
, j_obj
.obj(), event
.x
* dpi_scale(), event
.y
* dpi_scale());
598 case WebInputEvent::GestureDoubleTap
:
599 Java_ContentViewCore_onDoubleTapEventAck(env
, j_obj
.obj());
606 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent
& event
) {
607 if (event
.type
!= WebInputEvent::GestureTap
&&
608 event
.type
!= WebInputEvent::GestureDoubleTap
&&
609 event
.type
!= WebInputEvent::GestureLongTap
&&
610 event
.type
!= WebInputEvent::GestureLongPress
)
613 JNIEnv
* env
= AttachCurrentThread();
614 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
618 const blink::WebGestureEvent
& gesture
=
619 static_cast<const blink::WebGestureEvent
&>(event
);
620 int gesture_type
= ToGestureEventType(event
.type
);
621 return Java_ContentViewCore_filterTapOrPressEvent(env
,
624 gesture
.x
* dpi_scale(),
625 gesture
.y
* dpi_scale());
627 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
630 bool ContentViewCoreImpl::HasFocus() {
631 JNIEnv
* env
= AttachCurrentThread();
632 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
635 return Java_ContentViewCore_hasFocus(env
, obj
.obj());
638 void ContentViewCoreImpl::OnSelectionChanged(const std::string
& text
) {
639 JNIEnv
* env
= AttachCurrentThread();
640 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
643 ScopedJavaLocalRef
<jstring
> jtext
= ConvertUTF8ToJavaString(env
, text
);
644 Java_ContentViewCore_onSelectionChanged(env
, obj
.obj(), jtext
.obj());
647 void ContentViewCoreImpl::OnSelectionBoundsChanged(
648 const ViewHostMsg_SelectionBounds_Params
& params
) {
649 JNIEnv
* env
= AttachCurrentThread();
650 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
653 ScopedJavaLocalRef
<jobject
> anchor_rect_dip(
654 CreateJavaRect(env
, params
.anchor_rect
));
655 ScopedJavaLocalRef
<jobject
> focus_rect_dip(
656 CreateJavaRect(env
, params
.focus_rect
));
657 Java_ContentViewCore_onSelectionBoundsChanged(env
, obj
.obj(),
658 anchor_rect_dip
.obj(),
660 focus_rect_dip
.obj(),
662 params
.is_anchor_first
);
665 void ContentViewCoreImpl::OnSelectionRootBoundsChanged(
666 const gfx::Rect
& bounds
) {
667 JNIEnv
* env
= AttachCurrentThread();
669 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
673 ScopedJavaLocalRef
<jobject
> rect_object(CreateJavaRect(env
, bounds
));
674 Java_ContentViewCore_setSelectionRootBounds(env
,
679 void ContentViewCoreImpl::ShowPastePopup(int x_dip
, int y_dip
) {
680 JNIEnv
* env
= AttachCurrentThread();
681 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
684 Java_ContentViewCore_showPastePopup(env
, obj
.obj(),
685 static_cast<jint
>(x_dip
),
686 static_cast<jint
>(y_dip
));
689 void ContentViewCoreImpl::GetScaledContentBitmap(
691 jobject jbitmap_config
,
692 gfx::Rect src_subrect
,
693 const base::Callback
<void(bool, const SkBitmap
&)>& result_callback
) {
694 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
696 result_callback
.Run(false, SkBitmap());
699 SkBitmap::Config skbitmap_format
= gfx::ConvertToSkiaConfig(jbitmap_config
);
700 view
->GetScaledContentBitmap(scale
, skbitmap_format
, src_subrect
,
704 void ContentViewCoreImpl::StartContentIntent(const GURL
& content_url
) {
705 JNIEnv
* env
= AttachCurrentThread();
706 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
709 ScopedJavaLocalRef
<jstring
> jcontent_url
=
710 ConvertUTF8ToJavaString(env
, content_url
.spec());
711 Java_ContentViewCore_startContentIntent(env
,
716 void ContentViewCoreImpl::ShowDisambiguationPopup(
717 const gfx::Rect
& target_rect
,
718 const SkBitmap
& zoomed_bitmap
) {
719 JNIEnv
* env
= AttachCurrentThread();
721 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
725 ScopedJavaLocalRef
<jobject
> rect_object(CreateJavaRect(env
, target_rect
));
727 ScopedJavaLocalRef
<jobject
> java_bitmap
=
728 gfx::ConvertToJavaBitmap(&zoomed_bitmap
);
729 DCHECK(!java_bitmap
.is_null());
731 Java_ContentViewCore_showDisambiguationPopup(env
,
737 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
738 JNIEnv
* env
= AttachCurrentThread();
740 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
742 return ScopedJavaLocalRef
<jobject
>();
743 return Java_ContentViewCore_createTouchEventSynthesizer(env
, obj
.obj());
746 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetContentVideoViewClient() {
747 JNIEnv
* env
= AttachCurrentThread();
749 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
751 return ScopedJavaLocalRef
<jobject
>();
753 return Java_ContentViewCore_getContentVideoViewClient(env
, obj
.obj());
756 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetContext() {
757 JNIEnv
* env
= AttachCurrentThread();
759 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
761 return ScopedJavaLocalRef
<jobject
>();
763 return Java_ContentViewCore_getContext(env
, obj
.obj());
766 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL
& url
) {
767 JNIEnv
* env
= AttachCurrentThread();
769 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
772 ScopedJavaLocalRef
<jstring
> j_url
= ConvertUTF8ToJavaString(env
, url
.spec());
773 return Java_ContentViewCore_shouldBlockMediaRequest(env
, obj
.obj(),
777 void ContentViewCoreImpl::DidStopFlinging() {
778 JNIEnv
* env
= AttachCurrentThread();
780 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
782 Java_ContentViewCore_onNativeFlingStopped(env
, obj
.obj());
785 gfx::Size
ContentViewCoreImpl::GetViewSize() const {
786 gfx::Size size
= GetViewportSizeDip();
787 gfx::Size offset
= GetViewportSizeOffsetDip();
788 size
.Enlarge(-offset
.width(), -offset
.height());
792 gfx::Size
ContentViewCoreImpl::GetPhysicalBackingSize() const {
793 JNIEnv
* env
= AttachCurrentThread();
794 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
798 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, j_obj
.obj()),
799 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, j_obj
.obj()));
802 gfx::Size
ContentViewCoreImpl::GetViewportSizePix() const {
803 JNIEnv
* env
= AttachCurrentThread();
804 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
808 Java_ContentViewCore_getViewportWidthPix(env
, j_obj
.obj()),
809 Java_ContentViewCore_getViewportHeightPix(env
, j_obj
.obj()));
812 gfx::Size
ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
813 JNIEnv
* env
= AttachCurrentThread();
814 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
818 Java_ContentViewCore_getViewportSizeOffsetWidthPix(env
, j_obj
.obj()),
819 Java_ContentViewCore_getViewportSizeOffsetHeightPix(env
, j_obj
.obj()));
822 gfx::Size
ContentViewCoreImpl::GetViewportSizeDip() const {
823 return gfx::ToCeiledSize(
824 gfx::ScaleSize(GetViewportSizePix(), 1.0f
/ dpi_scale()));
827 gfx::Size
ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
828 return gfx::ToCeiledSize(
829 gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f
/ dpi_scale()));
832 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
833 JNIEnv
* env
= AttachCurrentThread();
834 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
837 return Java_ContentViewCore_getOverdrawBottomHeightPix(env
, j_obj
.obj())
841 void ContentViewCoreImpl::AttachLayer(scoped_refptr
<cc::Layer
> layer
) {
842 root_layer_
->AddChild(layer
);
845 void ContentViewCoreImpl::RemoveLayer(scoped_refptr
<cc::Layer
> layer
) {
846 layer
->RemoveFromParent();
849 void ContentViewCoreImpl::LoadUrl(
850 NavigationController::LoadURLParams
& params
) {
851 GetWebContents()->GetController().LoadURLWithParams(params
);
854 ui::ViewAndroid
* ContentViewCoreImpl::GetViewAndroid() const {
855 // view_android_ should never be null for Chrome.
856 DCHECK(view_android_
);
857 return view_android_
;
860 ui::WindowAndroid
* ContentViewCoreImpl::GetWindowAndroid() const {
861 // This should never be NULL for Chrome, but will be NULL for WebView.
862 DCHECK(window_android_
);
863 return window_android_
;
866 scoped_refptr
<cc::Layer
> ContentViewCoreImpl::GetLayer() const {
867 return root_layer_
.get();
870 // ----------------------------------------------------------------------------
871 // Methods called from Java via JNI
872 // ----------------------------------------------------------------------------
874 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv
* env
, jobject obj
,
876 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
877 web_contents_
->GetRenderViewHost());
879 if (indices
== NULL
) {
880 rvhi
->DidCancelPopupMenu();
884 int selected_count
= env
->GetArrayLength(indices
);
885 std::vector
<int> selected_indices
;
886 jint
* indices_ptr
= env
->GetIntArrayElements(indices
, NULL
);
887 for (int i
= 0; i
< selected_count
; ++i
)
888 selected_indices
.push_back(indices_ptr
[i
]);
889 env
->ReleaseIntArrayElements(indices
, indices_ptr
, JNI_ABORT
);
890 rvhi
->DidSelectPopupMenuItems(selected_indices
);
893 void ContentViewCoreImpl::LoadUrl(
894 JNIEnv
* env
, jobject obj
,
897 jint transition_type
,
898 jstring j_referrer_url
,
899 jint referrer_policy
,
900 jint ua_override_option
,
901 jstring extra_headers
,
902 jbyteArray post_data
,
903 jstring base_url_for_data_url
,
904 jstring virtual_url_for_data_url
,
905 jboolean can_load_local_resources
) {
907 NavigationController::LoadURLParams
params(
908 GURL(ConvertJavaStringToUTF8(env
, url
)));
910 params
.load_type
= static_cast<NavigationController::LoadURLType
>(
912 params
.transition_type
= PageTransitionFromInt(transition_type
);
913 params
.override_user_agent
=
914 static_cast<NavigationController::UserAgentOverrideOption
>(
918 params
.extra_headers
= ConvertJavaStringToUTF8(env
, extra_headers
);
921 std::vector
<uint8
> http_body_vector
;
922 base::android::JavaByteArrayToByteVector(env
, post_data
, &http_body_vector
);
923 params
.browser_initiated_post_data
=
924 base::RefCountedBytes::TakeVector(&http_body_vector
);
927 if (base_url_for_data_url
) {
928 params
.base_url_for_data_url
=
929 GURL(ConvertJavaStringToUTF8(env
, base_url_for_data_url
));
932 if (virtual_url_for_data_url
) {
933 params
.virtual_url_for_data_url
=
934 GURL(ConvertJavaStringToUTF8(env
, virtual_url_for_data_url
));
937 params
.can_load_local_resources
= can_load_local_resources
;
938 if (j_referrer_url
) {
939 params
.referrer
= content::Referrer(
940 GURL(ConvertJavaStringToUTF8(env
, j_referrer_url
)),
941 static_cast<blink::WebReferrerPolicy
>(referrer_policy
));
947 ScopedJavaLocalRef
<jstring
> ContentViewCoreImpl::GetURL(
948 JNIEnv
* env
, jobject
) const {
949 return ConvertUTF8ToJavaString(env
, GetWebContents()->GetURL().spec());
952 jboolean
ContentViewCoreImpl::IsIncognito(JNIEnv
* env
, jobject obj
) {
953 return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
956 WebContents
* ContentViewCoreImpl::GetWebContents() const {
957 return web_contents_
;
960 void ContentViewCoreImpl::SetFocus(JNIEnv
* env
, jobject obj
, jboolean focused
) {
961 SetFocusInternal(focused
);
964 void ContentViewCoreImpl::SetFocusInternal(bool focused
) {
965 if (!GetRenderWidgetHostViewAndroid())
969 GetRenderWidgetHostViewAndroid()->Focus();
971 GetRenderWidgetHostViewAndroid()->Blur();
974 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv
* env
,
977 if (device_orientation_
!= orientation
) {
978 device_orientation_
= orientation
;
979 SendOrientationChangeEventInternal();
983 jboolean
ContentViewCoreImpl::OnTouchEvent(JNIEnv
* env
,
985 jobject motion_event
,
997 jfloat touch_major_0
,
998 jfloat touch_major_1
) {
999 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1000 // Avoid synthesizing a touch event if it cannot be forwarded.
1004 MotionEventAndroid
event(1.f
/ dpi_scale(),
1021 return rwhv
->OnTouchEvent(event
);
1024 float ContentViewCoreImpl::GetDpiScale() const {
1028 jboolean
ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv
* env
,
1033 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1037 blink::WebMouseEvent event
= WebMouseEventBuilder::Build(
1038 WebInputEvent::MouseMove
,
1039 blink::WebMouseEvent::ButtonNone
,
1040 time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale(), 0, 1);
1042 rwhv
->SendMouseEvent(event
);
1046 jboolean
ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv
* env
,
1051 jfloat vertical_axis
) {
1052 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1056 WebMouseWheelEventBuilder::Direction direction
;
1057 if (vertical_axis
> 0) {
1058 direction
= WebMouseWheelEventBuilder::DIRECTION_UP
;
1059 } else if (vertical_axis
< 0) {
1060 direction
= WebMouseWheelEventBuilder::DIRECTION_DOWN
;
1064 blink::WebMouseWheelEvent event
= WebMouseWheelEventBuilder::Build(
1065 direction
, time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale());
1067 rwhv
->SendMouseWheelEvent(event
);
1071 WebGestureEvent
ContentViewCoreImpl::MakeGestureEvent(
1072 WebInputEvent::Type type
, int64 time_ms
, float x
, float y
) const {
1073 return WebGestureEventBuilder::Build(
1074 type
, time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale());
1077 void ContentViewCoreImpl::SendGestureEvent(
1078 const blink::WebGestureEvent
& event
) {
1079 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1081 rwhv
->SendGestureEvent(event
);
1084 void ContentViewCoreImpl::ScrollBegin(JNIEnv
* env
,
1091 WebGestureEvent event
= MakeGestureEvent(
1092 WebInputEvent::GestureScrollBegin
, time_ms
, x
, y
);
1093 event
.data
.scrollBegin
.deltaXHint
= hintx
/ dpi_scale();
1094 event
.data
.scrollBegin
.deltaYHint
= hinty
/ dpi_scale();
1096 SendGestureEvent(event
);
1099 void ContentViewCoreImpl::ScrollEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1100 WebGestureEvent event
= MakeGestureEvent(
1101 WebInputEvent::GestureScrollEnd
, time_ms
, 0, 0);
1102 SendGestureEvent(event
);
1105 void ContentViewCoreImpl::ScrollBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1106 jfloat x
, jfloat y
, jfloat dx
, jfloat dy
) {
1107 WebGestureEvent event
= MakeGestureEvent(
1108 WebInputEvent::GestureScrollUpdate
, time_ms
, x
, y
);
1109 event
.data
.scrollUpdate
.deltaX
= -dx
/ dpi_scale();
1110 event
.data
.scrollUpdate
.deltaY
= -dy
/ dpi_scale();
1112 SendGestureEvent(event
);
1115 void ContentViewCoreImpl::FlingStart(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1116 jfloat x
, jfloat y
, jfloat vx
, jfloat vy
) {
1117 WebGestureEvent event
= MakeGestureEvent(
1118 WebInputEvent::GestureFlingStart
, time_ms
, x
, y
);
1119 event
.data
.flingStart
.velocityX
= vx
/ dpi_scale();
1120 event
.data
.flingStart
.velocityY
= vy
/ dpi_scale();
1122 SendGestureEvent(event
);
1125 void ContentViewCoreImpl::FlingCancel(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1126 WebGestureEvent event
= MakeGestureEvent(
1127 WebInputEvent::GestureFlingCancel
, time_ms
, 0, 0);
1128 SendGestureEvent(event
);
1131 void ContentViewCoreImpl::SingleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1132 jfloat x
, jfloat y
) {
1133 WebGestureEvent event
= MakeGestureEvent(
1134 WebInputEvent::GestureTap
, time_ms
, x
, y
);
1135 event
.data
.tap
.tapCount
= 1;
1137 SendGestureEvent(event
);
1140 void ContentViewCoreImpl::DoubleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1141 jfloat x
, jfloat y
) {
1142 WebGestureEvent event
= MakeGestureEvent(
1143 WebInputEvent::GestureDoubleTap
, time_ms
, x
, y
);
1144 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1145 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1146 event
.data
.tap
.tapCount
= 1;
1148 SendGestureEvent(event
);
1151 void ContentViewCoreImpl::LongPress(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1152 jfloat x
, jfloat y
) {
1153 WebGestureEvent event
= MakeGestureEvent(
1154 WebInputEvent::GestureLongPress
, time_ms
, x
, y
);
1156 SendGestureEvent(event
);
1159 void ContentViewCoreImpl::PinchBegin(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1160 jfloat x
, jfloat y
) {
1161 WebGestureEvent event
= MakeGestureEvent(
1162 WebInputEvent::GesturePinchBegin
, time_ms
, x
, y
);
1163 SendGestureEvent(event
);
1166 void ContentViewCoreImpl::PinchEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1167 WebGestureEvent event
= MakeGestureEvent(
1168 WebInputEvent::GesturePinchEnd
, time_ms
, 0, 0);
1169 SendGestureEvent(event
);
1172 void ContentViewCoreImpl::PinchBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1173 jfloat anchor_x
, jfloat anchor_y
,
1175 WebGestureEvent event
= MakeGestureEvent(
1176 WebInputEvent::GesturePinchUpdate
, time_ms
, anchor_x
, anchor_y
);
1177 event
.data
.pinchUpdate
.scale
= delta
;
1179 SendGestureEvent(event
);
1182 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv
* env
, jobject obj
,
1183 jfloat x1
, jfloat y1
,
1184 jfloat x2
, jfloat y2
) {
1188 web_contents_
->SelectRange(
1189 gfx::Point(x1
/ dpi_scale(), y1
/ dpi_scale()),
1190 gfx::Point(x2
/ dpi_scale(), y2
/ dpi_scale()));
1193 void ContentViewCoreImpl::MoveCaret(JNIEnv
* env
, jobject obj
,
1194 jfloat x
, jfloat y
) {
1195 if (GetRenderWidgetHostViewAndroid()) {
1196 GetRenderWidgetHostViewAndroid()->MoveCaret(
1197 gfx::Point(x
/ dpi_scale(), y
/ dpi_scale()));
1201 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv
* env
, jobject obj
) {
1202 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1204 rwhv
->ResetGestureDetection();
1207 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv
* env
,
1210 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1212 rwhv
->SetDoubleTapSupportEnabled(enabled
);
1215 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv
* env
,
1218 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1220 rwhv
->SetMultiTouchZoomSupportEnabled(enabled
);
1223 void ContentViewCoreImpl::LoadIfNecessary(JNIEnv
* env
, jobject obj
) {
1224 web_contents_
->GetController().LoadIfNecessary();
1227 void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv
* env
, jobject obj
) {
1228 web_contents_
->GetController().SetNeedsReload();
1231 void ContentViewCoreImpl::Reload(JNIEnv
* env
,
1233 jboolean check_for_repost
) {
1234 if (web_contents_
->GetController().NeedsReload())
1235 web_contents_
->GetController().LoadIfNecessary();
1237 web_contents_
->GetController().Reload(check_for_repost
);
1240 void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv
* env
,
1242 jboolean check_for_repost
) {
1243 web_contents_
->GetController().ReloadIgnoringCache(check_for_repost
);
1246 void ContentViewCoreImpl::CancelPendingReload(JNIEnv
* env
, jobject obj
) {
1247 web_contents_
->GetController().CancelPendingReload();
1250 void ContentViewCoreImpl::ContinuePendingReload(JNIEnv
* env
, jobject obj
) {
1251 web_contents_
->GetController().ContinuePendingReload();
1254 void ContentViewCoreImpl::ClearHistory(JNIEnv
* env
, jobject obj
) {
1255 // TODO(creis): Do callers of this need to know if it fails?
1256 if (web_contents_
->GetController().CanPruneAllButLastCommitted())
1257 web_contents_
->GetController().PruneAllButLastCommitted();
1260 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1264 web_contents_
->java_bridge_dispatcher_host_manager()
1265 ->SetAllowObjectContentsInspection(allow
);
1268 void ContentViewCoreImpl::AddJavascriptInterface(
1273 jclass safe_annotation_clazz
,
1274 jobject retained_object_set
) {
1275 ScopedJavaLocalRef
<jobject
> scoped_object(env
, object
);
1276 ScopedJavaLocalRef
<jclass
> scoped_clazz(env
, safe_annotation_clazz
);
1277 JavaObjectWeakGlobalRef
weak_retained_object_set(env
, retained_object_set
);
1279 // JavaBoundObject creates the NPObject with a ref count of 1, and
1280 // JavaBridgeDispatcherHostManager takes its own ref.
1281 JavaBridgeDispatcherHostManager
* java_bridge
=
1282 web_contents_
->java_bridge_dispatcher_host_manager();
1283 java_bridge
->SetRetainedObjectSet(weak_retained_object_set
);
1284 NPObject
* bound_object
=
1285 JavaBoundObject::Create(scoped_object
,
1287 java_bridge
->AsWeakPtr(),
1288 java_bridge
->GetAllowObjectContentsInspection());
1289 java_bridge
->AddNamedObject(ConvertJavaStringToUTF16(env
, name
),
1291 blink::WebBindings::releaseObject(bound_object
);
1294 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv
* env
,
1297 web_contents_
->java_bridge_dispatcher_host_manager()->RemoveNamedObject(
1298 ConvertJavaStringToUTF16(env
, name
));
1301 void ContentViewCoreImpl::WasResized(JNIEnv
* env
, jobject obj
) {
1302 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1304 RenderWidgetHostImpl
* host
= RenderWidgetHostImpl::From(
1305 view
->GetRenderWidgetHost());
1306 host
->SendScreenRects();
1311 void ContentViewCoreImpl::ShowInterstitialPage(
1312 JNIEnv
* env
, jobject obj
, jstring jurl
, jlong delegate_ptr
) {
1313 GURL
url(base::android::ConvertJavaStringToUTF8(env
, jurl
));
1314 InterstitialPageDelegateAndroid
* delegate
=
1315 reinterpret_cast<InterstitialPageDelegateAndroid
*>(delegate_ptr
);
1316 InterstitialPage
* interstitial
= InterstitialPage::Create(
1317 web_contents_
, false, url
, delegate
);
1318 delegate
->set_interstitial_page(interstitial
);
1319 interstitial
->Show();
1322 jboolean
ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv
* env
,
1324 return web_contents_
->ShowingInterstitialPage();
1327 jboolean
ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv
* env
,
1329 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1330 return view
&& view
->HasValidFrame();
1333 void ContentViewCoreImpl::ExitFullscreen(JNIEnv
* env
, jobject obj
) {
1334 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1337 host
->ExitFullscreen();
1340 void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv
* env
,
1343 bool enable_showing
,
1345 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1348 host
->Send(new ViewMsg_UpdateTopControlsState(host
->GetRoutingID(),
1354 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv
* env
, jobject obj
) {
1355 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1356 host
->Send(new ViewMsg_ShowImeIfNeeded(host
->GetRoutingID()));
1359 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv
* env
,
1361 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1362 host
->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
1363 host
->GetRoutingID(), gfx::Rect()));
1368 static void AddNavigationEntryToHistory(JNIEnv
* env
, jobject obj
,
1370 NavigationEntry
* entry
,
1372 // Get the details of the current entry
1373 ScopedJavaLocalRef
<jstring
> j_url(
1374 ConvertUTF8ToJavaString(env
, entry
->GetURL().spec()));
1375 ScopedJavaLocalRef
<jstring
> j_virtual_url(
1376 ConvertUTF8ToJavaString(env
, entry
->GetVirtualURL().spec()));
1377 ScopedJavaLocalRef
<jstring
> j_original_url(
1378 ConvertUTF8ToJavaString(env
, entry
->GetOriginalRequestURL().spec()));
1379 ScopedJavaLocalRef
<jstring
> j_title(
1380 ConvertUTF16ToJavaString(env
, entry
->GetTitle()));
1381 ScopedJavaLocalRef
<jobject
> j_bitmap
;
1382 const FaviconStatus
& status
= entry
->GetFavicon();
1383 if (status
.valid
&& status
.image
.ToSkBitmap()->getSize() > 0)
1384 j_bitmap
= gfx::ConvertToJavaBitmap(status
.image
.ToSkBitmap());
1386 // Add the item to the list
1387 Java_ContentViewCore_addToNavigationHistory(
1388 env
, obj
, history
, index
, j_url
.obj(), j_virtual_url
.obj(),
1389 j_original_url
.obj(), j_title
.obj(), j_bitmap
.obj());
1394 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv
* env
,
1397 // Iterate through navigation entries to populate the list
1398 const NavigationController
& controller
= web_contents_
->GetController();
1399 int count
= controller
.GetEntryCount();
1400 for (int i
= 0; i
< count
; ++i
) {
1401 AddNavigationEntryToHistory(
1402 env
, obj
, history
, controller
.GetEntryAtIndex(i
), i
);
1405 return controller
.GetCurrentEntryIndex();
1408 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv
* env
,
1411 jboolean is_forward
,
1413 // Iterate through navigation entries to populate the list
1414 const NavigationController
& controller
= web_contents_
->GetController();
1415 int count
= controller
.GetEntryCount();
1417 int increment_value
= is_forward
? 1 : -1;
1418 for (int i
= controller
.GetCurrentEntryIndex() + increment_value
;
1419 i
>= 0 && i
< count
;
1420 i
+= increment_value
) {
1421 if (num_added
>= max_entries
)
1424 AddNavigationEntryToHistory(
1425 env
, obj
, history
, controller
.GetEntryAtIndex(i
), i
);
1430 ScopedJavaLocalRef
<jstring
>
1431 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv
* env
,
1433 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1435 return ScopedJavaLocalRef
<jstring
>(env
, NULL
);
1436 return ConvertUTF8ToJavaString(env
, entry
->GetOriginalRequestURL().spec());
1439 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv
* env
, jobject obj
) {
1440 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
1443 return rwhva
->GetNativeImeAdapter();
1447 void JavaScriptResultCallback(const ScopedJavaGlobalRef
<jobject
>& callback
,
1448 const base::Value
* result
) {
1449 JNIEnv
* env
= base::android::AttachCurrentThread();
1451 base::JSONWriter::Write(result
, &json
);
1452 ScopedJavaLocalRef
<jstring
> j_json
= ConvertUTF8ToJavaString(env
, json
);
1453 Java_ContentViewCore_onEvaluateJavaScriptResult(env
,
1459 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv
* env
,
1463 jboolean start_renderer
) {
1464 RenderViewHost
* rvh
= web_contents_
->GetRenderViewHost();
1467 if (start_renderer
&& !rvh
->IsRenderViewLive()) {
1468 if (!web_contents_
->CreateRenderViewForInitialEmptyDocument()) {
1469 LOG(ERROR
) << "Failed to create RenderView in EvaluateJavaScript";
1475 // No callback requested.
1476 web_contents_
->GetMainFrame()->ExecuteJavaScript(
1477 ConvertJavaStringToUTF16(env
, script
));
1481 // Secure the Java callback in a scoped object and give ownership of it to the
1483 ScopedJavaGlobalRef
<jobject
> j_callback
;
1484 j_callback
.Reset(env
, callback
);
1485 content::RenderFrameHost::JavaScriptResultCallback c_callback
=
1486 base::Bind(&JavaScriptResultCallback
, j_callback
);
1488 web_contents_
->GetMainFrame()->ExecuteJavaScript(
1489 ConvertJavaStringToUTF16(env
, script
),
1493 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
1494 JNIEnv
* env
, jobject obj
) {
1495 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1496 return entry
&& entry
->GetIsOverridingUserAgent();
1499 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter
,
1500 int text_input_type
,
1501 const std::string
& text
,
1502 int selection_start
,
1504 int composition_start
,
1505 int composition_end
,
1506 bool show_ime_if_needed
,
1507 bool is_non_ime_change
) {
1508 JNIEnv
* env
= AttachCurrentThread();
1509 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1513 ScopedJavaLocalRef
<jstring
> jstring_text
= ConvertUTF8ToJavaString(env
, text
);
1514 Java_ContentViewCore_updateImeAdapter(env
, obj
.obj(),
1515 native_ime_adapter
, text_input_type
,
1517 selection_start
, selection_end
,
1518 composition_start
, composition_end
,
1519 show_ime_if_needed
, is_non_ime_change
);
1522 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv
* env
, jobject obj
) {
1523 SSLHostState
* state
= SSLHostState::GetFor(
1524 web_contents_
->GetController().GetBrowserContext());
1528 void ContentViewCoreImpl::SetUseDesktopUserAgent(
1532 jboolean reload_on_state_change
) {
1533 if (GetUseDesktopUserAgent(env
, obj
) == enabled
)
1536 // Make sure the navigation entry actually exists.
1537 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1541 // Set the flag in the NavigationEntry.
1542 entry
->SetIsOverridingUserAgent(enabled
);
1544 // Send the override to the renderer.
1545 if (reload_on_state_change
) {
1546 // Reloading the page will send the override down as part of the
1547 // navigation IPC message.
1548 NavigationControllerImpl
& controller
=
1549 static_cast<NavigationControllerImpl
&>(web_contents_
->GetController());
1550 controller
.ReloadOriginalRequestURL(false);
1554 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv
* env
, jobject obj
,
1556 RenderWidgetHostViewAndroid
* host_view
= GetRenderWidgetHostViewAndroid();
1559 RenderWidgetHostImpl
* host_impl
= RenderWidgetHostImpl::From(
1560 host_view
->GetRenderWidgetHost());
1561 BrowserAccessibilityState
* accessibility_state
=
1562 BrowserAccessibilityState::GetInstance();
1564 // This enables accessibility globally unless it was explicitly disallowed
1565 // by a command-line flag.
1566 accessibility_state
->OnScreenReaderDetected();
1567 // If it was actually enabled globally, enable it for this RenderWidget now.
1568 if (accessibility_state
->IsAccessibleBrowser() && host_impl
)
1569 host_impl
->AddAccessibilityMode(AccessibilityModeComplete
);
1571 accessibility_state
->ResetAccessibilityMode();
1573 host_impl
->ResetAccessibilityMode();
1577 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1578 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1580 rwhv
->UpdateScreenInfo(GetViewAndroid());
1582 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
1583 web_contents_
->GetRenderViewHost());
1584 rvhi
->SendOrientationChangeEvent(device_orientation_
);
1586 // TODO(mlamouri): temporary plumbing for Screen Orientation, this will change
1587 // in the future. It might leave ContentViewCoreImpl or simply replace the
1588 // SendOrientationChangeEvent call above.
1589 blink::WebScreenOrientationType orientation
=
1590 blink::WebScreenOrientationPortraitPrimary
;
1592 switch (device_orientation_
) {
1594 orientation
= blink::WebScreenOrientationPortraitPrimary
;
1597 orientation
= blink::WebScreenOrientationLandscapePrimary
;
1600 orientation
= blink::WebScreenOrientationLandscapeSecondary
;
1603 orientation
= blink::WebScreenOrientationPortraitSecondary
;
1609 ScreenOrientationDispatcherHost
* sodh
=
1610 static_cast<RenderProcessHostImpl
*>(web_contents_
->
1611 GetRenderProcessHost())->screen_orientation_dispatcher_host();
1613 // sodh can be null if the RenderProcessHost is in the process of being
1614 // destroyed or not yet initialized.
1616 sodh
->OnOrientationChange(orientation
);
1619 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv
* env
,
1626 static_cast<int>(x
/ dpi_scale()),
1627 static_cast<int>(y
/ dpi_scale()),
1628 static_cast<int>((width
> 0 && width
< dpi_scale()) ?
1629 1 : (int)(width
/ dpi_scale())),
1630 static_cast<int>((height
> 0 && height
< dpi_scale()) ?
1631 1 : (int)(height
/ dpi_scale())));
1632 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1633 GetWebContents()->GetRoutingID(), rect
));
1636 jint
ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv
* env
, jobject obj
) {
1637 return GetRenderProcessIdFromRenderViewHost(
1638 web_contents_
->GetRenderViewHost());
1641 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1642 const base::string16
& result
) {
1643 JNIEnv
* env
= AttachCurrentThread();
1644 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1647 ScopedJavaLocalRef
<jstring
> jresult
= ConvertUTF16ToJavaString(env
, result
);
1648 Java_ContentViewCore_onSmartClipDataExtracted(
1649 env
, obj
.obj(), jresult
.obj());
1652 void ContentViewCoreImpl::WebContentsDestroyed(WebContents
* web_contents
) {
1653 WebContentsViewAndroid
* wcva
= static_cast<WebContentsViewAndroid
*>(
1654 static_cast<WebContentsImpl
*>(web_contents
)->GetView());
1656 wcva
->SetContentViewCore(NULL
);
1659 // This is called for each ContentView.
1660 jlong
Init(JNIEnv
* env
,
1662 jlong native_web_contents
,
1664 jlong window_android
) {
1665 ContentViewCoreImpl
* view
= new ContentViewCoreImpl(
1667 reinterpret_cast<WebContents
*>(native_web_contents
),
1668 reinterpret_cast<ui::ViewAndroid
*>(view_android
),
1669 reinterpret_cast<ui::WindowAndroid
*>(window_android
));
1670 return reinterpret_cast<intptr_t>(view
);
1673 bool RegisterContentViewCore(JNIEnv
* env
) {
1674 return RegisterNativesImpl(env
);
1677 } // namespace content