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/layers/solid_color_layer.h"
19 #include "cc/output/begin_frame_args.h"
20 #include "content/browser/android/gesture_event_type.h"
21 #include "content/browser/android/interstitial_page_delegate_android.h"
22 #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
23 #include "content/browser/android/load_url_params.h"
24 #include "content/browser/frame_host/interstitial_page_impl.h"
25 #include "content/browser/frame_host/navigation_controller_impl.h"
26 #include "content/browser/frame_host/navigation_entry_impl.h"
27 #include "content/browser/geolocation/geolocation_dispatcher_host.h"
28 #include "content/browser/media/media_web_contents_observer.h"
29 #include "content/browser/renderer_host/compositor_impl_android.h"
30 #include "content/browser/renderer_host/input/motion_event_android.h"
31 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
32 #include "content/browser/renderer_host/input/web_input_event_util.h"
33 #include "content/browser/renderer_host/render_view_host_impl.h"
34 #include "content/browser/renderer_host/render_widget_host_impl.h"
35 #include "content/browser/renderer_host/render_widget_host_view_android.h"
36 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
37 #include "content/browser/ssl/ssl_host_state.h"
38 #include "content/browser/transition_request_manager.h"
39 #include "content/browser/web_contents/web_contents_view_android.h"
40 #include "content/common/frame_messages.h"
41 #include "content/common/input/web_input_event_traits.h"
42 #include "content/common/input_messages.h"
43 #include "content/common/view_messages.h"
44 #include "content/public/browser/browser_accessibility_state.h"
45 #include "content/public/browser/browser_context.h"
46 #include "content/public/browser/browser_thread.h"
47 #include "content/public/browser/favicon_status.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/WebInputEvent.h"
57 #include "ui/base/android/view_android.h"
58 #include "ui/base/android/window_android.h"
59 #include "ui/gfx/android/java_bitmap.h"
60 #include "ui/gfx/screen.h"
61 #include "ui/gfx/size_conversions.h"
62 #include "ui/gfx/size_f.h"
64 using base::android::AttachCurrentThread
;
65 using base::android::ConvertJavaStringToUTF16
;
66 using base::android::ConvertJavaStringToUTF8
;
67 using base::android::ConvertUTF16ToJavaString
;
68 using base::android::ConvertUTF8ToJavaString
;
69 using base::android::ScopedJavaGlobalRef
;
70 using base::android::ScopedJavaLocalRef
;
71 using blink::WebGestureEvent
;
72 using blink::WebInputEvent
;
74 // Describes the type and enabled state of a select popup item.
78 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
79 #include "content/browser/android/popup_item_type_list.h"
80 #undef DEFINE_POPUP_ITEM_TYPE
89 const void* kContentViewUserDataKey
= &kContentViewUserDataKey
;
91 int GetRenderProcessIdFromRenderViewHost(RenderViewHost
* host
) {
93 RenderProcessHost
* render_process
= host
->GetProcess();
94 DCHECK(render_process
);
95 if (render_process
->HasConnection())
96 return render_process
->GetHandle();
101 ScopedJavaLocalRef
<jobject
> CreateJavaRect(
103 const gfx::Rect
& rect
) {
104 return ScopedJavaLocalRef
<jobject
>(
105 Java_ContentViewCore_createRect(env
,
106 static_cast<int>(rect
.x()),
107 static_cast<int>(rect
.y()),
108 static_cast<int>(rect
.right()),
109 static_cast<int>(rect
.bottom())));
112 int ToGestureEventType(WebInputEvent::Type type
) {
114 case WebInputEvent::GestureScrollBegin
:
116 case WebInputEvent::GestureScrollEnd
:
118 case WebInputEvent::GestureScrollUpdate
:
120 case WebInputEvent::GestureFlingStart
:
122 case WebInputEvent::GestureFlingCancel
:
124 case WebInputEvent::GestureShowPress
:
126 case WebInputEvent::GestureTap
:
127 return SINGLE_TAP_CONFIRMED
;
128 case WebInputEvent::GestureTapUnconfirmed
:
129 return SINGLE_TAP_UNCONFIRMED
;
130 case WebInputEvent::GestureTapDown
:
132 case WebInputEvent::GestureTapCancel
:
134 case WebInputEvent::GestureDoubleTap
:
136 case WebInputEvent::GestureLongPress
:
138 case WebInputEvent::GestureLongTap
:
140 case WebInputEvent::GesturePinchBegin
:
142 case WebInputEvent::GesturePinchEnd
:
144 case WebInputEvent::GesturePinchUpdate
:
146 case WebInputEvent::GestureTwoFingerTap
:
147 case WebInputEvent::GestureScrollUpdateWithoutPropagation
:
149 NOTREACHED() << "Invalid source gesture type: "
150 << WebInputEventTraits::GetName(type
);
155 float GetPrimaryDisplayDeviceScaleFactor() {
156 const gfx::Display
& display
=
157 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
158 return display
.device_scale_factor();
163 // Enables a callback when the underlying WebContents is destroyed, to enable
164 // nulling the back-pointer.
165 class ContentViewCoreImpl::ContentViewUserData
166 : public base::SupportsUserData::Data
{
168 explicit ContentViewUserData(ContentViewCoreImpl
* content_view_core
)
169 : content_view_core_(content_view_core
) {
172 virtual ~ContentViewUserData() {
173 // TODO(joth): When chrome has finished removing the TabContents class (see
174 // crbug.com/107201) consider inverting relationship, so ContentViewCore
175 // would own WebContents. That effectively implies making the WebContents
176 // destructor private on Android.
177 delete content_view_core_
;
180 ContentViewCoreImpl
* get() const { return content_view_core_
; }
183 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
184 ContentViewCoreImpl
* content_view_core_
;
186 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData
);
190 ContentViewCoreImpl
* ContentViewCoreImpl::FromWebContents(
191 content::WebContents
* web_contents
) {
192 ContentViewCoreImpl::ContentViewUserData
* data
=
193 reinterpret_cast<ContentViewCoreImpl::ContentViewUserData
*>(
194 web_contents
->GetUserData(kContentViewUserDataKey
));
195 return data
? data
->get() : NULL
;
199 ContentViewCore
* ContentViewCore::FromWebContents(
200 content::WebContents
* web_contents
) {
201 return ContentViewCoreImpl::FromWebContents(web_contents
);
205 ContentViewCore
* ContentViewCore::GetNativeContentViewCore(JNIEnv
* env
,
207 return reinterpret_cast<ContentViewCore
*>(
208 Java_ContentViewCore_getNativeContentViewCore(env
, obj
));
211 ContentViewCoreImpl::ContentViewCoreImpl(
214 WebContents
* web_contents
,
215 ui::ViewAndroid
* view_android
,
216 ui::WindowAndroid
* window_android
,
217 jobject java_bridge_retained_object_set
)
218 : WebContentsObserver(web_contents
),
220 web_contents_(static_cast<WebContentsImpl
*>(web_contents
)),
221 root_layer_(cc::SolidColorLayer::Create()),
222 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
223 view_android_(view_android
),
224 window_android_(window_android
),
225 device_orientation_(0),
226 accessibility_enabled_(false) {
227 CHECK(web_contents
) <<
228 "A ContentViewCoreImpl should be created with a valid WebContents.";
229 DCHECK(view_android_
);
230 DCHECK(window_android_
);
232 root_layer_
->SetBackgroundColor(GetBackgroundColor(env
, obj
));
233 gfx::Size
physical_size(
234 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, obj
),
235 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, obj
));
236 root_layer_
->SetBounds(physical_size
);
237 root_layer_
->SetIsDrawable(true);
239 // Currently, the only use case we have for overriding a user agent involves
240 // spoofing a desktop Linux user agent for "Request desktop site".
241 // Automatically set it for all WebContents so that it is available when a
242 // NavigationEntry requires the user agent to be overridden.
243 const char kLinuxInfoStr
[] = "X11; Linux x86_64";
244 std::string product
= content::GetContentClient()->GetProduct();
245 std::string spoofed_ua
=
246 BuildUserAgentFromOSAndProduct(kLinuxInfoStr
, product
);
247 web_contents
->SetUserAgentOverride(spoofed_ua
);
249 java_bridge_dispatcher_host_
.reset(
250 new GinJavaBridgeDispatcherHost(web_contents
,
251 java_bridge_retained_object_set
));
256 ContentViewCoreImpl::~ContentViewCoreImpl() {
257 JNIEnv
* env
= base::android::AttachCurrentThread();
258 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
260 if (!j_obj
.is_null()) {
261 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
262 env
, j_obj
.obj(), reinterpret_cast<intptr_t>(this));
266 base::android::ScopedJavaLocalRef
<jobject
>
267 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv
* env
, jobject obj
) {
268 return web_contents_
->GetJavaWebContents();
271 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv
* env
,
273 DCHECK(env
->IsSameObject(java_ref_
.get(env
).obj(), obj
));
275 // Java peer has gone, ContentViewCore is not functional and waits to
276 // be destroyed with WebContents.
277 // We need to reset WebContentsViewAndroid's reference, otherwise, there
278 // could have call in when swapping the WebContents,
279 // see http://crbug.com/383939 .
280 DCHECK(web_contents_
);
281 static_cast<WebContentsViewAndroid
*>(
282 static_cast<WebContentsImpl
*>(web_contents_
)->GetView())->
283 SetContentViewCore(NULL
);
286 void ContentViewCoreImpl::InitWebContents() {
287 DCHECK(web_contents_
);
288 static_cast<WebContentsViewAndroid
*>(
289 static_cast<WebContentsImpl
*>(web_contents_
)->GetView())->
290 SetContentViewCore(this);
291 DCHECK(!web_contents_
->GetUserData(kContentViewUserDataKey
));
292 web_contents_
->SetUserData(kContentViewUserDataKey
,
293 new ContentViewUserData(this));
296 void ContentViewCoreImpl::RenderViewReady() {
297 JNIEnv
* env
= AttachCurrentThread();
298 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
300 Java_ContentViewCore_onRenderProcessChange(env
, obj
.obj());
302 if (device_orientation_
!= 0)
303 SendOrientationChangeEventInternal();
306 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost
* old_host
,
307 RenderViewHost
* new_host
) {
310 old_pid
= GetRenderProcessIdFromRenderViewHost(old_host
);
312 RenderWidgetHostViewAndroid
* view
=
313 static_cast<RenderWidgetHostViewAndroid
*>(old_host
->GetView());
315 view
->SetContentViewCore(NULL
);
317 view
= static_cast<RenderWidgetHostViewAndroid
*>(new_host
->GetView());
319 view
->SetContentViewCore(this);
321 int new_pid
= GetRenderProcessIdFromRenderViewHost(
322 web_contents_
->GetRenderViewHost());
323 if (new_pid
!= old_pid
) {
324 // Notify the Java side that the renderer process changed.
325 JNIEnv
* env
= AttachCurrentThread();
326 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
327 if (!obj
.is_null()) {
328 Java_ContentViewCore_onRenderProcessChange(env
, obj
.obj());
332 SetFocusInternal(HasFocus());
333 SetAccessibilityEnabledInternal(accessibility_enabled_
);
336 RenderWidgetHostViewAndroid
*
337 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
338 RenderWidgetHostView
* rwhv
= NULL
;
340 rwhv
= web_contents_
->GetRenderWidgetHostView();
341 if (web_contents_
->ShowingInterstitialPage()) {
342 rwhv
= static_cast<InterstitialPageImpl
*>(
343 web_contents_
->GetInterstitialPage())->
344 GetRenderViewHost()->GetView();
347 return static_cast<RenderWidgetHostViewAndroid
*>(rwhv
);
350 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetJavaObject() {
351 JNIEnv
* env
= AttachCurrentThread();
352 return java_ref_
.get(env
);
355 jint
ContentViewCoreImpl::GetBackgroundColor(JNIEnv
* env
, jobject obj
) {
356 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
358 return SK_ColorWHITE
;
359 return rwhva
->GetCachedBackgroundColor();
362 void ContentViewCoreImpl::OnHide(JNIEnv
* env
, jobject obj
) {
366 void ContentViewCoreImpl::OnShow(JNIEnv
* env
, jobject obj
) {
370 void ContentViewCoreImpl::Show() {
371 GetWebContents()->WasShown();
374 void ContentViewCoreImpl::Hide() {
375 GetWebContents()->WasHidden();
379 void ContentViewCoreImpl::PauseVideo() {
380 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
381 web_contents_
->GetRenderViewHost());
383 rvhi
->media_web_contents_observer()->PauseVideo();
386 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause
) {
387 web_contents_
->geolocation_dispatcher_host()->PauseOrResume(should_pause
);
390 // All positions and sizes are in CSS pixels.
391 // Note that viewport_width/height is a best effort based.
392 // ContentViewCore has the actual information about the physical viewport size.
393 void ContentViewCoreImpl::UpdateFrameInfo(
394 const gfx::Vector2dF
& scroll_offset
,
395 float page_scale_factor
,
396 const gfx::Vector2dF
& page_scale_factor_limits
,
397 const gfx::SizeF
& content_size
,
398 const gfx::SizeF
& viewport_size
,
399 const gfx::Vector2dF
& controls_offset
,
400 const gfx::Vector2dF
& content_offset
,
401 float overdraw_bottom_height
) {
402 JNIEnv
* env
= AttachCurrentThread();
403 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
407 window_android_
->set_content_offset(
408 gfx::ScaleVector2d(content_offset
, dpi_scale_
));
410 Java_ContentViewCore_updateFrameInfo(
415 page_scale_factor_limits
.x(),
416 page_scale_factor_limits
.y(),
417 content_size
.width(),
418 content_size
.height(),
419 viewport_size
.width(),
420 viewport_size
.height(),
423 overdraw_bottom_height
);
426 void ContentViewCoreImpl::SetTitle(const base::string16
& title
) {
427 JNIEnv
* env
= AttachCurrentThread();
428 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
431 ScopedJavaLocalRef
<jstring
> jtitle
=
432 ConvertUTF8ToJavaString(env
, base::UTF16ToUTF8(title
));
433 Java_ContentViewCore_setTitle(env
, obj
.obj(), jtitle
.obj());
436 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color
) {
437 root_layer_
->SetBackgroundColor(color
);
439 JNIEnv
* env
= AttachCurrentThread();
440 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
443 Java_ContentViewCore_onBackgroundColorChanged(env
, obj
.obj(), color
);
446 void ContentViewCoreImpl::ShowSelectPopupMenu(const gfx::Rect
& bounds
,
447 const std::vector
<MenuItem
>& items
, int selected_item
, bool multiple
) {
448 JNIEnv
* env
= AttachCurrentThread();
449 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
453 ScopedJavaLocalRef
<jobject
> bounds_rect(CreateJavaRect(env
, bounds
));
455 // For multi-select list popups we find the list of previous selections by
456 // iterating through the items. But for single selection popups we take the
457 // given |selected_item| as is.
458 ScopedJavaLocalRef
<jintArray
> selected_array
;
460 scoped_ptr
<jint
[]> native_selected_array(new jint
[items
.size()]);
461 size_t selected_count
= 0;
462 for (size_t i
= 0; i
< items
.size(); ++i
) {
463 if (items
[i
].checked
)
464 native_selected_array
[selected_count
++] = i
;
467 selected_array
= ScopedJavaLocalRef
<jintArray
>(
468 env
, env
->NewIntArray(selected_count
));
469 env
->SetIntArrayRegion(selected_array
.obj(), 0, selected_count
,
470 native_selected_array
.get());
472 selected_array
= ScopedJavaLocalRef
<jintArray
>(env
, env
->NewIntArray(1));
473 jint value
= selected_item
;
474 env
->SetIntArrayRegion(selected_array
.obj(), 0, 1, &value
);
477 ScopedJavaLocalRef
<jintArray
> enabled_array(env
,
478 env
->NewIntArray(items
.size()));
479 std::vector
<base::string16
> labels
;
480 labels
.reserve(items
.size());
481 for (size_t i
= 0; i
< items
.size(); ++i
) {
482 labels
.push_back(items
[i
].label
);
484 (items
[i
].type
== MenuItem::GROUP
? POPUP_ITEM_TYPE_GROUP
:
485 (items
[i
].enabled
? POPUP_ITEM_TYPE_ENABLED
:
486 POPUP_ITEM_TYPE_DISABLED
));
487 env
->SetIntArrayRegion(enabled_array
.obj(), i
, 1, &enabled
);
489 ScopedJavaLocalRef
<jobjectArray
> items_array(
490 base::android::ToJavaArrayOfStrings(env
, labels
));
491 Java_ContentViewCore_showSelectPopup(env
, j_obj
.obj(),
496 selected_array
.obj());
499 void ContentViewCoreImpl::HideSelectPopupMenu() {
500 JNIEnv
* env
= AttachCurrentThread();
501 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
502 if (!j_obj
.is_null())
503 Java_ContentViewCore_hideSelectPopup(env
, j_obj
.obj());
506 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent
& event
,
507 InputEventAckState ack_result
) {
508 JNIEnv
* env
= AttachCurrentThread();
509 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
513 switch (event
.type
) {
514 case WebInputEvent::GestureFlingStart
:
515 if (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
) {
516 // The view expects the fling velocity in pixels/s.
517 Java_ContentViewCore_onFlingStartEventConsumed(env
, j_obj
.obj(),
518 event
.data
.flingStart
.velocityX
* dpi_scale(),
519 event
.data
.flingStart
.velocityY
* dpi_scale());
521 // If a scroll ends with a fling, a SCROLL_END event is never sent.
522 // However, if that fling went unconsumed, we still need to let the
523 // listeners know that scrolling has ended.
524 Java_ContentViewCore_onScrollEndEventAck(env
, j_obj
.obj());
527 if (ack_result
== INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
) {
528 // The view expects the fling velocity in pixels/s.
529 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env
, j_obj
.obj(),
530 event
.data
.flingStart
.velocityX
* dpi_scale(),
531 event
.data
.flingStart
.velocityY
* dpi_scale());
534 case WebInputEvent::GestureFlingCancel
:
535 Java_ContentViewCore_onFlingCancelEventAck(env
, j_obj
.obj());
537 case WebInputEvent::GestureScrollBegin
:
538 Java_ContentViewCore_onScrollBeginEventAck(env
, j_obj
.obj());
540 case WebInputEvent::GestureScrollUpdate
:
541 if (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
)
542 Java_ContentViewCore_onScrollUpdateGestureConsumed(env
, j_obj
.obj());
544 case WebInputEvent::GestureScrollEnd
:
545 Java_ContentViewCore_onScrollEndEventAck(env
, j_obj
.obj());
547 case WebInputEvent::GesturePinchBegin
:
548 Java_ContentViewCore_onPinchBeginEventAck(env
, j_obj
.obj());
550 case WebInputEvent::GesturePinchEnd
:
551 Java_ContentViewCore_onPinchEndEventAck(env
, j_obj
.obj());
553 case WebInputEvent::GestureTap
:
554 Java_ContentViewCore_onSingleTapEventAck(
557 ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
,
558 event
.x
* dpi_scale(),
559 event
.y
* dpi_scale());
561 case WebInputEvent::GestureDoubleTap
:
562 Java_ContentViewCore_onDoubleTapEventAck(env
, j_obj
.obj());
569 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent
& event
) {
570 if (event
.type
!= WebInputEvent::GestureTap
&&
571 event
.type
!= WebInputEvent::GestureDoubleTap
&&
572 event
.type
!= WebInputEvent::GestureLongTap
&&
573 event
.type
!= WebInputEvent::GestureLongPress
)
576 JNIEnv
* env
= AttachCurrentThread();
577 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
581 const blink::WebGestureEvent
& gesture
=
582 static_cast<const blink::WebGestureEvent
&>(event
);
583 int gesture_type
= ToGestureEventType(event
.type
);
584 return Java_ContentViewCore_filterTapOrPressEvent(env
,
587 gesture
.x
* dpi_scale(),
588 gesture
.y
* dpi_scale());
590 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
593 bool ContentViewCoreImpl::HasFocus() {
594 JNIEnv
* env
= AttachCurrentThread();
595 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
598 return Java_ContentViewCore_hasFocus(env
, obj
.obj());
601 void ContentViewCoreImpl::OnSelectionChanged(const std::string
& text
) {
602 JNIEnv
* env
= AttachCurrentThread();
603 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
606 ScopedJavaLocalRef
<jstring
> jtext
= ConvertUTF8ToJavaString(env
, text
);
607 Java_ContentViewCore_onSelectionChanged(env
, obj
.obj(), jtext
.obj());
610 void ContentViewCoreImpl::OnSelectionBoundsChanged(
611 const ViewHostMsg_SelectionBounds_Params
& params
) {
612 JNIEnv
* env
= AttachCurrentThread();
613 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
616 ScopedJavaLocalRef
<jobject
> anchor_rect_dip(
617 CreateJavaRect(env
, params
.anchor_rect
));
618 ScopedJavaLocalRef
<jobject
> focus_rect_dip(
619 CreateJavaRect(env
, params
.focus_rect
));
620 Java_ContentViewCore_onSelectionBoundsChanged(env
, obj
.obj(),
621 anchor_rect_dip
.obj(),
623 focus_rect_dip
.obj(),
625 params
.is_anchor_first
);
628 void ContentViewCoreImpl::ShowPastePopup(int x_dip
, int y_dip
) {
629 JNIEnv
* env
= AttachCurrentThread();
630 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
633 Java_ContentViewCore_showPastePopup(env
, obj
.obj(),
634 static_cast<jint
>(x_dip
),
635 static_cast<jint
>(y_dip
));
638 void ContentViewCoreImpl::GetScaledContentBitmap(
640 jobject jbitmap_config
,
641 gfx::Rect src_subrect
,
642 const base::Callback
<void(bool, const SkBitmap
&)>& result_callback
) {
643 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
645 result_callback
.Run(false, SkBitmap());
648 SkColorType color_type
= gfx::ConvertToSkiaColorType(jbitmap_config
);
649 view
->GetScaledContentBitmap(scale
, color_type
, src_subrect
,
653 void ContentViewCoreImpl::StartContentIntent(const GURL
& content_url
) {
654 JNIEnv
* env
= AttachCurrentThread();
655 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
658 ScopedJavaLocalRef
<jstring
> jcontent_url
=
659 ConvertUTF8ToJavaString(env
, content_url
.spec());
660 Java_ContentViewCore_startContentIntent(env
,
665 void ContentViewCoreImpl::ShowDisambiguationPopup(
666 const gfx::Rect
& target_rect
,
667 const SkBitmap
& zoomed_bitmap
) {
668 JNIEnv
* env
= AttachCurrentThread();
670 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
674 ScopedJavaLocalRef
<jobject
> rect_object(CreateJavaRect(env
, target_rect
));
676 ScopedJavaLocalRef
<jobject
> java_bitmap
=
677 gfx::ConvertToJavaBitmap(&zoomed_bitmap
);
678 DCHECK(!java_bitmap
.is_null());
680 Java_ContentViewCore_showDisambiguationPopup(env
,
686 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
687 JNIEnv
* env
= AttachCurrentThread();
689 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
691 return ScopedJavaLocalRef
<jobject
>();
692 return Java_ContentViewCore_createTouchEventSynthesizer(env
, obj
.obj());
695 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetContentVideoViewClient() {
696 JNIEnv
* env
= AttachCurrentThread();
698 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
700 return ScopedJavaLocalRef
<jobject
>();
702 return Java_ContentViewCore_getContentVideoViewClient(env
, obj
.obj());
705 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetContext() {
706 JNIEnv
* env
= AttachCurrentThread();
708 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
710 return ScopedJavaLocalRef
<jobject
>();
712 return Java_ContentViewCore_getContext(env
, obj
.obj());
715 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL
& url
) {
716 JNIEnv
* env
= AttachCurrentThread();
718 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
721 ScopedJavaLocalRef
<jstring
> j_url
= ConvertUTF8ToJavaString(env
, url
.spec());
722 return Java_ContentViewCore_shouldBlockMediaRequest(env
, obj
.obj(),
726 void ContentViewCoreImpl::DidStopFlinging() {
727 JNIEnv
* env
= AttachCurrentThread();
729 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
731 Java_ContentViewCore_onNativeFlingStopped(env
, obj
.obj());
734 gfx::Size
ContentViewCoreImpl::GetViewSize() const {
735 gfx::Size size
= GetViewportSizeDip();
736 gfx::Size offset
= GetViewportSizeOffsetDip();
737 size
.Enlarge(-offset
.width(), -offset
.height());
741 gfx::Size
ContentViewCoreImpl::GetPhysicalBackingSize() const {
742 JNIEnv
* env
= AttachCurrentThread();
743 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
747 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, j_obj
.obj()),
748 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, j_obj
.obj()));
751 gfx::Size
ContentViewCoreImpl::GetViewportSizePix() const {
752 JNIEnv
* env
= AttachCurrentThread();
753 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
757 Java_ContentViewCore_getViewportWidthPix(env
, j_obj
.obj()),
758 Java_ContentViewCore_getViewportHeightPix(env
, j_obj
.obj()));
761 gfx::Size
ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
762 JNIEnv
* env
= AttachCurrentThread();
763 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
767 Java_ContentViewCore_getViewportSizeOffsetWidthPix(env
, j_obj
.obj()),
768 Java_ContentViewCore_getViewportSizeOffsetHeightPix(env
, j_obj
.obj()));
771 gfx::Size
ContentViewCoreImpl::GetViewportSizeDip() const {
772 return gfx::ToCeiledSize(
773 gfx::ScaleSize(GetViewportSizePix(), 1.0f
/ dpi_scale()));
776 gfx::Size
ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
777 return gfx::ToCeiledSize(
778 gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f
/ dpi_scale()));
781 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
782 JNIEnv
* env
= AttachCurrentThread();
783 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
786 return Java_ContentViewCore_getOverdrawBottomHeightPix(env
, j_obj
.obj())
790 void ContentViewCoreImpl::AttachLayer(scoped_refptr
<cc::Layer
> layer
) {
791 root_layer_
->AddChild(layer
);
792 root_layer_
->SetIsDrawable(false);
795 void ContentViewCoreImpl::RemoveLayer(scoped_refptr
<cc::Layer
> layer
) {
796 layer
->RemoveFromParent();
798 if (!root_layer_
->children().size())
799 root_layer_
->SetIsDrawable(true);
802 void ContentViewCoreImpl::LoadUrl(
803 NavigationController::LoadURLParams
& params
) {
804 GetWebContents()->GetController().LoadURLWithParams(params
);
807 ui::ViewAndroid
* ContentViewCoreImpl::GetViewAndroid() const {
808 return view_android_
;
811 ui::WindowAndroid
* ContentViewCoreImpl::GetWindowAndroid() const {
812 return window_android_
;
815 scoped_refptr
<cc::Layer
> ContentViewCoreImpl::GetLayer() const {
816 return root_layer_
.get();
819 // ----------------------------------------------------------------------------
820 // Methods called from Java via JNI
821 // ----------------------------------------------------------------------------
823 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv
* env
, jobject obj
,
825 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
826 web_contents_
->GetRenderViewHost());
828 if (indices
== NULL
) {
829 rvhi
->DidCancelPopupMenu();
833 int selected_count
= env
->GetArrayLength(indices
);
834 std::vector
<int> selected_indices
;
835 jint
* indices_ptr
= env
->GetIntArrayElements(indices
, NULL
);
836 for (int i
= 0; i
< selected_count
; ++i
)
837 selected_indices
.push_back(indices_ptr
[i
]);
838 env
->ReleaseIntArrayElements(indices
, indices_ptr
, JNI_ABORT
);
839 rvhi
->DidSelectPopupMenuItems(selected_indices
);
842 void ContentViewCoreImpl::LoadUrl(
843 JNIEnv
* env
, jobject obj
,
846 jint transition_type
,
847 jstring j_referrer_url
,
848 jint referrer_policy
,
849 jint ua_override_option
,
850 jstring extra_headers
,
851 jbyteArray post_data
,
852 jstring base_url_for_data_url
,
853 jstring virtual_url_for_data_url
,
854 jboolean can_load_local_resources
,
855 jboolean is_renderer_initiated
) {
857 NavigationController::LoadURLParams
params(
858 GURL(ConvertJavaStringToUTF8(env
, url
)));
860 params
.load_type
= static_cast<NavigationController::LoadURLType
>(
862 params
.transition_type
= PageTransitionFromInt(transition_type
);
863 params
.override_user_agent
=
864 static_cast<NavigationController::UserAgentOverrideOption
>(
868 params
.extra_headers
= ConvertJavaStringToUTF8(env
, extra_headers
);
871 std::vector
<uint8
> http_body_vector
;
872 base::android::JavaByteArrayToByteVector(env
, post_data
, &http_body_vector
);
873 params
.browser_initiated_post_data
=
874 base::RefCountedBytes::TakeVector(&http_body_vector
);
877 if (base_url_for_data_url
) {
878 params
.base_url_for_data_url
=
879 GURL(ConvertJavaStringToUTF8(env
, base_url_for_data_url
));
882 if (virtual_url_for_data_url
) {
883 params
.virtual_url_for_data_url
=
884 GURL(ConvertJavaStringToUTF8(env
, virtual_url_for_data_url
));
887 params
.can_load_local_resources
= can_load_local_resources
;
888 if (j_referrer_url
) {
889 params
.referrer
= content::Referrer(
890 GURL(ConvertJavaStringToUTF8(env
, j_referrer_url
)),
891 static_cast<blink::WebReferrerPolicy
>(referrer_policy
));
894 params
.is_renderer_initiated
= is_renderer_initiated
;
899 ScopedJavaLocalRef
<jstring
> ContentViewCoreImpl::GetURL(
900 JNIEnv
* env
, jobject
) const {
901 return ConvertUTF8ToJavaString(env
, GetWebContents()->GetURL().spec());
904 jboolean
ContentViewCoreImpl::IsIncognito(JNIEnv
* env
, jobject obj
) {
905 return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
908 WebContents
* ContentViewCoreImpl::GetWebContents() const {
909 return web_contents_
;
912 void ContentViewCoreImpl::SetFocus(JNIEnv
* env
, jobject obj
, jboolean focused
) {
913 SetFocusInternal(focused
);
916 void ContentViewCoreImpl::SetFocusInternal(bool focused
) {
917 if (!GetRenderWidgetHostViewAndroid())
921 GetRenderWidgetHostViewAndroid()->Focus();
923 GetRenderWidgetHostViewAndroid()->Blur();
926 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv
* env
,
929 if (device_orientation_
!= orientation
) {
930 device_orientation_
= orientation
;
931 SendOrientationChangeEventInternal();
935 jboolean
ContentViewCoreImpl::OnTouchEvent(JNIEnv
* env
,
937 jobject motion_event
,
949 jfloat touch_major_0
,
950 jfloat touch_major_1
,
953 jint android_tool_type_0
,
954 jint android_tool_type_1
,
955 jint android_button_state
) {
956 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
957 // Avoid synthesizing a touch event if it cannot be forwarded.
961 MotionEventAndroid
event(1.f
/ dpi_scale(),
981 android_button_state
);
983 return rwhv
->OnTouchEvent(event
);
986 float ContentViewCoreImpl::GetDpiScale() const {
990 jboolean
ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv
* env
,
995 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
999 blink::WebMouseEvent event
= WebMouseEventBuilder::Build(
1000 WebInputEvent::MouseMove
,
1001 blink::WebMouseEvent::ButtonNone
,
1002 time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale(), 0, 1);
1004 rwhv
->SendMouseEvent(event
);
1008 jboolean
ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv
* env
,
1013 jfloat vertical_axis
) {
1014 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1018 WebMouseWheelEventBuilder::Direction direction
;
1019 if (vertical_axis
> 0) {
1020 direction
= WebMouseWheelEventBuilder::DIRECTION_UP
;
1021 } else if (vertical_axis
< 0) {
1022 direction
= WebMouseWheelEventBuilder::DIRECTION_DOWN
;
1026 blink::WebMouseWheelEvent event
= WebMouseWheelEventBuilder::Build(
1027 direction
, time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale());
1029 rwhv
->SendMouseWheelEvent(event
);
1033 WebGestureEvent
ContentViewCoreImpl::MakeGestureEvent(
1034 WebInputEvent::Type type
, int64 time_ms
, float x
, float y
) const {
1035 return WebGestureEventBuilder::Build(
1036 type
, time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale());
1039 void ContentViewCoreImpl::SendGestureEvent(
1040 const blink::WebGestureEvent
& event
) {
1041 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1043 rwhv
->SendGestureEvent(event
);
1046 void ContentViewCoreImpl::ScrollBegin(JNIEnv
* env
,
1053 WebGestureEvent event
= MakeGestureEvent(
1054 WebInputEvent::GestureScrollBegin
, time_ms
, x
, y
);
1055 event
.data
.scrollBegin
.deltaXHint
= hintx
/ dpi_scale();
1056 event
.data
.scrollBegin
.deltaYHint
= hinty
/ dpi_scale();
1058 SendGestureEvent(event
);
1061 void ContentViewCoreImpl::ScrollEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1062 WebGestureEvent event
= MakeGestureEvent(
1063 WebInputEvent::GestureScrollEnd
, time_ms
, 0, 0);
1064 SendGestureEvent(event
);
1067 void ContentViewCoreImpl::ScrollBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1068 jfloat x
, jfloat y
, jfloat dx
, jfloat dy
) {
1069 WebGestureEvent event
= MakeGestureEvent(
1070 WebInputEvent::GestureScrollUpdate
, time_ms
, x
, y
);
1071 event
.data
.scrollUpdate
.deltaX
= -dx
/ dpi_scale();
1072 event
.data
.scrollUpdate
.deltaY
= -dy
/ dpi_scale();
1074 SendGestureEvent(event
);
1077 void ContentViewCoreImpl::FlingStart(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1078 jfloat x
, jfloat y
, jfloat vx
, jfloat vy
) {
1079 WebGestureEvent event
= MakeGestureEvent(
1080 WebInputEvent::GestureFlingStart
, time_ms
, x
, y
);
1081 event
.data
.flingStart
.velocityX
= vx
/ dpi_scale();
1082 event
.data
.flingStart
.velocityY
= vy
/ dpi_scale();
1084 SendGestureEvent(event
);
1087 void ContentViewCoreImpl::FlingCancel(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1088 WebGestureEvent event
= MakeGestureEvent(
1089 WebInputEvent::GestureFlingCancel
, time_ms
, 0, 0);
1090 SendGestureEvent(event
);
1093 void ContentViewCoreImpl::SingleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1094 jfloat x
, jfloat y
) {
1095 WebGestureEvent event
= MakeGestureEvent(
1096 WebInputEvent::GestureTap
, time_ms
, x
, y
);
1097 event
.data
.tap
.tapCount
= 1;
1099 SendGestureEvent(event
);
1102 void ContentViewCoreImpl::DoubleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1103 jfloat x
, jfloat y
) {
1104 WebGestureEvent event
= MakeGestureEvent(
1105 WebInputEvent::GestureDoubleTap
, time_ms
, x
, y
);
1106 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1107 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1108 event
.data
.tap
.tapCount
= 1;
1110 SendGestureEvent(event
);
1113 void ContentViewCoreImpl::LongPress(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1114 jfloat x
, jfloat y
) {
1115 WebGestureEvent event
= MakeGestureEvent(
1116 WebInputEvent::GestureLongPress
, time_ms
, x
, y
);
1118 SendGestureEvent(event
);
1121 void ContentViewCoreImpl::PinchBegin(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1122 jfloat x
, jfloat y
) {
1123 WebGestureEvent event
= MakeGestureEvent(
1124 WebInputEvent::GesturePinchBegin
, time_ms
, x
, y
);
1125 SendGestureEvent(event
);
1128 void ContentViewCoreImpl::PinchEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1129 WebGestureEvent event
= MakeGestureEvent(
1130 WebInputEvent::GesturePinchEnd
, time_ms
, 0, 0);
1131 SendGestureEvent(event
);
1134 void ContentViewCoreImpl::PinchBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1135 jfloat anchor_x
, jfloat anchor_y
,
1137 WebGestureEvent event
= MakeGestureEvent(
1138 WebInputEvent::GesturePinchUpdate
, time_ms
, anchor_x
, anchor_y
);
1139 event
.data
.pinchUpdate
.scale
= delta
;
1141 SendGestureEvent(event
);
1144 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv
* env
, jobject obj
,
1145 jfloat x1
, jfloat y1
,
1146 jfloat x2
, jfloat y2
) {
1150 web_contents_
->SelectRange(
1151 gfx::Point(x1
/ dpi_scale(), y1
/ dpi_scale()),
1152 gfx::Point(x2
/ dpi_scale(), y2
/ dpi_scale()));
1155 void ContentViewCoreImpl::MoveCaret(JNIEnv
* env
, jobject obj
,
1156 jfloat x
, jfloat y
) {
1157 if (GetRenderWidgetHostViewAndroid()) {
1158 GetRenderWidgetHostViewAndroid()->MoveCaret(
1159 gfx::Point(x
/ dpi_scale(), y
/ dpi_scale()));
1163 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv
* env
, jobject obj
) {
1164 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1166 rwhv
->ResetGestureDetection();
1169 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv
* env
,
1172 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1174 rwhv
->SetDoubleTapSupportEnabled(enabled
);
1177 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv
* env
,
1180 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1182 rwhv
->SetMultiTouchZoomSupportEnabled(enabled
);
1185 void ContentViewCoreImpl::ClearHistory(JNIEnv
* env
, jobject obj
) {
1186 // TODO(creis): Do callers of this need to know if it fails?
1187 if (web_contents_
->GetController().CanPruneAllButLastCommitted())
1188 web_contents_
->GetController().PruneAllButLastCommitted();
1191 void ContentViewCoreImpl::AddStyleSheetByURL(
1192 JNIEnv
* env
, jobject obj
, jstring url
) {
1196 web_contents_
->GetMainFrame()->Send(new FrameMsg_AddStyleSheetByURL(
1197 web_contents_
->GetMainFrame()->GetRoutingID(),
1198 ConvertJavaStringToUTF8(env
, url
)));
1201 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1205 java_bridge_dispatcher_host_
->SetAllowObjectContentsInspection(allow
);
1208 void ContentViewCoreImpl::AddJavascriptInterface(
1213 jclass safe_annotation_clazz
) {
1214 ScopedJavaLocalRef
<jobject
> scoped_object(env
, object
);
1215 ScopedJavaLocalRef
<jclass
> scoped_clazz(env
, safe_annotation_clazz
);
1216 java_bridge_dispatcher_host_
->AddNamedObject(
1217 ConvertJavaStringToUTF8(env
, name
), scoped_object
, scoped_clazz
);
1220 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv
* env
,
1223 java_bridge_dispatcher_host_
->RemoveNamedObject(
1224 ConvertJavaStringToUTF8(env
, name
));
1227 void ContentViewCoreImpl::WasResized(JNIEnv
* env
, jobject obj
) {
1228 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1229 gfx::Size
physical_size(
1230 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, obj
),
1231 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, obj
));
1232 root_layer_
->SetBounds(physical_size
);
1235 RenderWidgetHostImpl
* host
= RenderWidgetHostImpl::From(
1236 view
->GetRenderWidgetHost());
1237 host
->SendScreenRects();
1242 void ContentViewCoreImpl::ShowInterstitialPage(
1243 JNIEnv
* env
, jobject obj
, jstring jurl
, jlong delegate_ptr
) {
1244 GURL
url(base::android::ConvertJavaStringToUTF8(env
, jurl
));
1245 InterstitialPageDelegateAndroid
* delegate
=
1246 reinterpret_cast<InterstitialPageDelegateAndroid
*>(delegate_ptr
);
1247 InterstitialPage
* interstitial
= InterstitialPage::Create(
1248 web_contents_
, false, url
, delegate
);
1249 delegate
->set_interstitial_page(interstitial
);
1250 interstitial
->Show();
1253 jboolean
ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv
* env
,
1255 return web_contents_
->ShowingInterstitialPage();
1258 jboolean
ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv
* env
,
1260 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1261 return view
&& view
->HasValidFrame();
1264 void ContentViewCoreImpl::ExitFullscreen(JNIEnv
* env
, jobject obj
) {
1265 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1268 host
->ExitFullscreen();
1271 void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv
* env
,
1274 bool enable_showing
,
1276 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1279 host
->Send(new ViewMsg_UpdateTopControlsState(host
->GetRoutingID(),
1285 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv
* env
, jobject obj
) {
1286 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1287 host
->Send(new ViewMsg_ShowImeIfNeeded(host
->GetRoutingID()));
1290 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv
* env
,
1292 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1293 host
->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
1294 host
->GetRoutingID(), gfx::Rect()));
1297 void ContentViewCoreImpl::SelectWordAroundCaret(JNIEnv
* env
, jobject obj
) {
1298 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1301 host
->SelectWordAroundCaret();
1306 static void AddNavigationEntryToHistory(JNIEnv
* env
, jobject obj
,
1308 NavigationEntry
* entry
,
1310 // Get the details of the current entry
1311 ScopedJavaLocalRef
<jstring
> j_url(
1312 ConvertUTF8ToJavaString(env
, entry
->GetURL().spec()));
1313 ScopedJavaLocalRef
<jstring
> j_virtual_url(
1314 ConvertUTF8ToJavaString(env
, entry
->GetVirtualURL().spec()));
1315 ScopedJavaLocalRef
<jstring
> j_original_url(
1316 ConvertUTF8ToJavaString(env
, entry
->GetOriginalRequestURL().spec()));
1317 ScopedJavaLocalRef
<jstring
> j_title(
1318 ConvertUTF16ToJavaString(env
, entry
->GetTitle()));
1319 ScopedJavaLocalRef
<jobject
> j_bitmap
;
1320 const FaviconStatus
& status
= entry
->GetFavicon();
1321 if (status
.valid
&& status
.image
.ToSkBitmap()->getSize() > 0)
1322 j_bitmap
= gfx::ConvertToJavaBitmap(status
.image
.ToSkBitmap());
1324 // Add the item to the list
1325 Java_ContentViewCore_addToNavigationHistory(
1326 env
, obj
, history
, index
, j_url
.obj(), j_virtual_url
.obj(),
1327 j_original_url
.obj(), j_title
.obj(), j_bitmap
.obj());
1332 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv
* env
,
1335 // Iterate through navigation entries to populate the list
1336 const NavigationController
& controller
= web_contents_
->GetController();
1337 int count
= controller
.GetEntryCount();
1338 for (int i
= 0; i
< count
; ++i
) {
1339 AddNavigationEntryToHistory(
1340 env
, obj
, history
, controller
.GetEntryAtIndex(i
), i
);
1343 return controller
.GetCurrentEntryIndex();
1346 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv
* env
,
1349 jboolean is_forward
,
1351 // Iterate through navigation entries to populate the list
1352 const NavigationController
& controller
= web_contents_
->GetController();
1353 int count
= controller
.GetEntryCount();
1355 int increment_value
= is_forward
? 1 : -1;
1356 for (int i
= controller
.GetCurrentEntryIndex() + increment_value
;
1357 i
>= 0 && i
< count
;
1358 i
+= increment_value
) {
1359 if (num_added
>= max_entries
)
1362 AddNavigationEntryToHistory(
1363 env
, obj
, history
, controller
.GetEntryAtIndex(i
), i
);
1368 ScopedJavaLocalRef
<jstring
>
1369 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv
* env
,
1371 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1373 return ScopedJavaLocalRef
<jstring
>(env
, NULL
);
1374 return ConvertUTF8ToJavaString(env
, entry
->GetOriginalRequestURL().spec());
1377 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv
* env
, jobject obj
) {
1378 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
1381 return rwhva
->GetNativeImeAdapter();
1385 void JavaScriptResultCallback(const ScopedJavaGlobalRef
<jobject
>& callback
,
1386 const base::Value
* result
) {
1387 JNIEnv
* env
= base::android::AttachCurrentThread();
1389 base::JSONWriter::Write(result
, &json
);
1390 ScopedJavaLocalRef
<jstring
> j_json
= ConvertUTF8ToJavaString(env
, json
);
1391 Java_ContentViewCore_onEvaluateJavaScriptResult(env
,
1397 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv
* env
,
1401 jboolean start_renderer
) {
1402 RenderViewHost
* rvh
= web_contents_
->GetRenderViewHost();
1405 if (start_renderer
&& !rvh
->IsRenderViewLive()) {
1406 if (!web_contents_
->CreateRenderViewForInitialEmptyDocument()) {
1407 LOG(ERROR
) << "Failed to create RenderView in EvaluateJavaScript";
1413 // No callback requested.
1414 web_contents_
->GetMainFrame()->ExecuteJavaScript(
1415 ConvertJavaStringToUTF16(env
, script
));
1419 // Secure the Java callback in a scoped object and give ownership of it to the
1421 ScopedJavaGlobalRef
<jobject
> j_callback
;
1422 j_callback
.Reset(env
, callback
);
1423 content::RenderFrameHost::JavaScriptResultCallback c_callback
=
1424 base::Bind(&JavaScriptResultCallback
, j_callback
);
1426 web_contents_
->GetMainFrame()->ExecuteJavaScript(
1427 ConvertJavaStringToUTF16(env
, script
),
1431 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
1432 JNIEnv
* env
, jobject obj
) {
1433 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1434 return entry
&& entry
->GetIsOverridingUserAgent();
1437 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter
,
1438 int text_input_type
,
1439 const std::string
& text
,
1440 int selection_start
,
1442 int composition_start
,
1443 int composition_end
,
1444 bool show_ime_if_needed
,
1445 bool is_non_ime_change
) {
1446 JNIEnv
* env
= AttachCurrentThread();
1447 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1451 ScopedJavaLocalRef
<jstring
> jstring_text
= ConvertUTF8ToJavaString(env
, text
);
1452 Java_ContentViewCore_updateImeAdapter(env
, obj
.obj(),
1453 native_ime_adapter
, text_input_type
,
1455 selection_start
, selection_end
,
1456 composition_start
, composition_end
,
1457 show_ime_if_needed
, is_non_ime_change
);
1460 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv
* env
, jobject obj
) {
1461 SSLHostState
* state
= SSLHostState::GetFor(
1462 web_contents_
->GetController().GetBrowserContext());
1466 void ContentViewCoreImpl::SetUseDesktopUserAgent(
1470 jboolean reload_on_state_change
) {
1471 if (GetUseDesktopUserAgent(env
, obj
) == enabled
)
1474 // Make sure the navigation entry actually exists.
1475 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1479 // Set the flag in the NavigationEntry.
1480 entry
->SetIsOverridingUserAgent(enabled
);
1482 // Send the override to the renderer.
1483 if (reload_on_state_change
) {
1484 // Reloading the page will send the override down as part of the
1485 // navigation IPC message.
1486 NavigationControllerImpl
& controller
=
1487 static_cast<NavigationControllerImpl
&>(web_contents_
->GetController());
1488 controller
.ReloadOriginalRequestURL(false);
1492 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv
* env
, jobject obj
,
1494 SetAccessibilityEnabledInternal(enabled
);
1497 void ContentViewCoreImpl::ShowSelectionHandlesAutomatically() const {
1498 JNIEnv
* env
= AttachCurrentThread();
1499 ScopedJavaLocalRef
<jobject
> obj(java_ref_
.get(env
));
1502 Java_ContentViewCore_showSelectionHandlesAutomatically(env
, obj
.obj());
1505 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1506 JNIEnv
* env
= AttachCurrentThread();
1507 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1510 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env
,
1514 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled
) {
1515 accessibility_enabled_
= enabled
;
1516 RenderWidgetHostViewAndroid
* host_view
= GetRenderWidgetHostViewAndroid();
1519 RenderWidgetHostImpl
* host_impl
= RenderWidgetHostImpl::From(
1520 host_view
->GetRenderWidgetHost());
1521 BrowserAccessibilityState
* accessibility_state
=
1522 BrowserAccessibilityState::GetInstance();
1524 // This enables accessibility globally unless it was explicitly disallowed
1525 // by a command-line flag.
1526 accessibility_state
->OnScreenReaderDetected();
1527 // If it was actually enabled globally, enable it for this RenderWidget now.
1528 if (accessibility_state
->IsAccessibleBrowser() && host_impl
)
1529 host_impl
->AddAccessibilityMode(AccessibilityModeComplete
);
1531 accessibility_state
->ResetAccessibilityMode();
1533 host_impl
->ResetAccessibilityMode();
1537 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1538 static_cast<WebContentsImpl
*>(web_contents())->
1539 screen_orientation_dispatcher_host()->OnOrientationChange();
1541 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1543 rwhv
->UpdateScreenInfo(GetViewAndroid());
1546 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv
* env
,
1553 static_cast<int>(x
/ dpi_scale()),
1554 static_cast<int>(y
/ dpi_scale()),
1555 static_cast<int>((width
> 0 && width
< dpi_scale()) ?
1556 1 : (int)(width
/ dpi_scale())),
1557 static_cast<int>((height
> 0 && height
< dpi_scale()) ?
1558 1 : (int)(height
/ dpi_scale())));
1559 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1560 GetWebContents()->GetRoutingID(), rect
));
1563 void ContentViewCoreImpl::ResumeResponseDeferredAtStart(JNIEnv
* env
,
1565 static_cast<WebContentsImpl
*>(GetWebContents())->
1566 ResumeResponseDeferredAtStart();
1569 void ContentViewCoreImpl::SetHasPendingNavigationTransitionForTesting(
1572 RenderFrameHost
* frame
= static_cast<WebContentsImpl
*>(GetWebContents())->
1574 BrowserThread::PostTask(
1578 &TransitionRequestManager::SetHasPendingTransitionRequest
,
1579 base::Unretained(TransitionRequestManager::GetInstance()),
1580 frame
->GetProcess()->GetID(),
1581 frame
->GetRoutingID(),
1585 jint
ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv
* env
, jobject obj
) {
1586 return GetRenderProcessIdFromRenderViewHost(
1587 web_contents_
->GetRenderViewHost());
1590 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv
* env
, jobject jobj
,
1592 if (GetRenderWidgetHostViewAndroid())
1593 GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque
);
1596 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1598 const base::Callback
<
1599 void(const base::string16
& content
, int start_offset
, int end_offset
)>&
1601 DCHECK(!callback
.is_null());
1602 RenderFrameHost
* focused_frame
= web_contents_
->GetFocusedFrame();
1605 if (GetRenderWidgetHostViewAndroid()) {
1606 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1608 focused_frame
->Send(new FrameMsg_TextSurroundingSelectionRequest(
1609 focused_frame
->GetRoutingID(), max_length
));
1613 void ContentViewCoreImpl::DidDeferAfterResponseStarted() {
1614 JNIEnv
* env
= AttachCurrentThread();
1615 ScopedJavaLocalRef
<jobject
> obj(java_ref_
.get(env
));
1618 Java_ContentViewCore_didDeferAfterResponseStarted(env
, obj
.obj());
1621 bool ContentViewCoreImpl::WillHandleDeferAfterResponseStarted() {
1622 JNIEnv
* env
= AttachCurrentThread();
1623 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1627 return Java_ContentViewCore_willHandleDeferAfterResponseStarted(env
,
1631 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1632 const base::string16
& text
,
1633 const base::string16
& html
,
1634 const gfx::Rect
& clip_rect
) {
1635 JNIEnv
* env
= AttachCurrentThread();
1636 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1639 ScopedJavaLocalRef
<jstring
> jtext
= ConvertUTF16ToJavaString(env
, text
);
1640 ScopedJavaLocalRef
<jstring
> jhtml
= ConvertUTF16ToJavaString(env
, html
);
1641 ScopedJavaLocalRef
<jobject
> clip_rect_object(CreateJavaRect(env
, clip_rect
));
1642 Java_ContentViewCore_onSmartClipDataExtracted(
1643 env
, obj
.obj(), jtext
.obj(), jhtml
.obj(), clip_rect_object
.obj());
1646 void ContentViewCoreImpl::WebContentsDestroyed() {
1647 WebContentsViewAndroid
* wcva
= static_cast<WebContentsViewAndroid
*>(
1648 static_cast<WebContentsImpl
*>(web_contents())->GetView());
1650 wcva
->SetContentViewCore(NULL
);
1653 // This is called for each ContentView.
1654 jlong
Init(JNIEnv
* env
,
1656 jlong native_web_contents
,
1658 jlong window_android
,
1659 jobject retained_objects_set
) {
1660 ContentViewCoreImpl
* view
= new ContentViewCoreImpl(
1662 reinterpret_cast<WebContents
*>(native_web_contents
),
1663 reinterpret_cast<ui::ViewAndroid
*>(view_android
),
1664 reinterpret_cast<ui::WindowAndroid
*>(window_android
),
1665 retained_objects_set
);
1666 return reinterpret_cast<intptr_t>(view
);
1669 bool RegisterContentViewCore(JNIEnv
* env
) {
1670 return RegisterNativesImpl(env
);
1673 } // namespace content