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/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "cc/layers/layer.h"
17 #include "cc/layers/solid_color_layer.h"
18 #include "cc/output/begin_frame_args.h"
19 #include "content/browser/accessibility/browser_accessibility_state_impl.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/android/popup_touch_handle_drawable.h"
25 #include "content/browser/frame_host/interstitial_page_impl.h"
26 #include "content/browser/geolocation/geolocation_service_context.h"
27 #include "content/browser/media/media_web_contents_observer.h"
28 #include "content/browser/renderer_host/compositor_impl_android.h"
29 #include "content/browser/renderer_host/input/motion_event_android.h"
30 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
31 #include "content/browser/renderer_host/input/web_input_event_util.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/transition_request_manager.h"
36 #include "content/browser/web_contents/web_contents_view_android.h"
37 #include "content/common/frame_messages.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_context.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/favicon_status.h"
44 #include "content/public/browser/render_frame_host.h"
45 #include "content/public/browser/screen_orientation_dispatcher_host.h"
46 #include "content/public/browser/ssl_host_state_delegate.h"
47 #include "content/public/browser/web_contents.h"
48 #include "content/public/common/content_client.h"
49 #include "content/public/common/content_switches.h"
50 #include "content/public/common/menu_item.h"
51 #include "content/public/common/user_agent.h"
52 #include "jni/ContentViewCore_jni.h"
53 #include "third_party/WebKit/public/web/WebInputEvent.h"
54 #include "ui/base/android/view_android.h"
55 #include "ui/base/android/window_android.h"
56 #include "ui/gfx/android/java_bitmap.h"
57 #include "ui/gfx/screen.h"
58 #include "ui/gfx/size_conversions.h"
59 #include "ui/gfx/size_f.h"
61 using base::android::AttachCurrentThread
;
62 using base::android::ConvertJavaStringToUTF16
;
63 using base::android::ConvertJavaStringToUTF8
;
64 using base::android::ConvertUTF16ToJavaString
;
65 using base::android::ConvertUTF8ToJavaString
;
66 using base::android::ScopedJavaLocalRef
;
67 using blink::WebGestureEvent
;
68 using blink::WebInputEvent
;
70 // Describes the type and enabled state of a select popup item.
73 // A Java counterpart will be generated for this enum.
74 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.input
76 // Popup item is of type group
77 POPUP_ITEM_TYPE_GROUP
,
79 // Popup item is disabled
80 POPUP_ITEM_TYPE_DISABLED
,
82 // Popup item is enabled
83 POPUP_ITEM_TYPE_ENABLED
,
92 const void* kContentViewUserDataKey
= &kContentViewUserDataKey
;
94 int GetRenderProcessIdFromRenderViewHost(RenderViewHost
* host
) {
96 RenderProcessHost
* render_process
= host
->GetProcess();
97 DCHECK(render_process
);
98 if (render_process
->HasConnection())
99 return render_process
->GetHandle();
104 ScopedJavaLocalRef
<jobject
> CreateJavaRect(
106 const gfx::Rect
& rect
) {
107 return ScopedJavaLocalRef
<jobject
>(
108 Java_ContentViewCore_createRect(env
,
109 static_cast<int>(rect
.x()),
110 static_cast<int>(rect
.y()),
111 static_cast<int>(rect
.right()),
112 static_cast<int>(rect
.bottom())));
115 int ToGestureEventType(WebInputEvent::Type type
) {
117 case WebInputEvent::GestureScrollBegin
:
118 return GESTURE_EVENT_TYPE_SCROLL_START
;
119 case WebInputEvent::GestureScrollEnd
:
120 return GESTURE_EVENT_TYPE_SCROLL_END
;
121 case WebInputEvent::GestureScrollUpdate
:
122 return GESTURE_EVENT_TYPE_SCROLL_BY
;
123 case WebInputEvent::GestureFlingStart
:
124 return GESTURE_EVENT_TYPE_FLING_START
;
125 case WebInputEvent::GestureFlingCancel
:
126 return GESTURE_EVENT_TYPE_FLING_CANCEL
;
127 case WebInputEvent::GestureShowPress
:
128 return GESTURE_EVENT_TYPE_SHOW_PRESS
;
129 case WebInputEvent::GestureTap
:
130 return GESTURE_EVENT_TYPE_SINGLE_TAP_CONFIRMED
;
131 case WebInputEvent::GestureTapUnconfirmed
:
132 return GESTURE_EVENT_TYPE_SINGLE_TAP_UNCONFIRMED
;
133 case WebInputEvent::GestureTapDown
:
134 return GESTURE_EVENT_TYPE_TAP_DOWN
;
135 case WebInputEvent::GestureTapCancel
:
136 return GESTURE_EVENT_TYPE_TAP_CANCEL
;
137 case WebInputEvent::GestureDoubleTap
:
138 return GESTURE_EVENT_TYPE_DOUBLE_TAP
;
139 case WebInputEvent::GestureLongPress
:
140 return GESTURE_EVENT_TYPE_LONG_PRESS
;
141 case WebInputEvent::GestureLongTap
:
142 return GESTURE_EVENT_TYPE_LONG_TAP
;
143 case WebInputEvent::GesturePinchBegin
:
144 return GESTURE_EVENT_TYPE_PINCH_BEGIN
;
145 case WebInputEvent::GesturePinchEnd
:
146 return GESTURE_EVENT_TYPE_PINCH_END
;
147 case WebInputEvent::GesturePinchUpdate
:
148 return GESTURE_EVENT_TYPE_PINCH_BY
;
149 case WebInputEvent::GestureTwoFingerTap
:
150 case WebInputEvent::GestureScrollUpdateWithoutPropagation
:
152 NOTREACHED() << "Invalid source gesture type: "
153 << WebInputEventTraits::GetName(type
);
158 float GetPrimaryDisplayDeviceScaleFactor() {
159 const gfx::Display
& display
=
160 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
161 return display
.device_scale_factor();
166 // Enables a callback when the underlying WebContents is destroyed, to enable
167 // nulling the back-pointer.
168 class ContentViewCoreImpl::ContentViewUserData
169 : public base::SupportsUserData::Data
{
171 explicit ContentViewUserData(ContentViewCoreImpl
* content_view_core
)
172 : content_view_core_(content_view_core
) {
175 virtual ~ContentViewUserData() {
176 // TODO(joth): When chrome has finished removing the TabContents class (see
177 // crbug.com/107201) consider inverting relationship, so ContentViewCore
178 // would own WebContents. That effectively implies making the WebContents
179 // destructor private on Android.
180 delete content_view_core_
;
183 ContentViewCoreImpl
* get() const { return content_view_core_
; }
186 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
187 ContentViewCoreImpl
* content_view_core_
;
189 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData
);
193 ContentViewCoreImpl
* ContentViewCoreImpl::FromWebContents(
194 content::WebContents
* web_contents
) {
195 ContentViewCoreImpl::ContentViewUserData
* data
=
196 static_cast<ContentViewCoreImpl::ContentViewUserData
*>(
197 web_contents
->GetUserData(kContentViewUserDataKey
));
198 return data
? data
->get() : NULL
;
202 ContentViewCore
* ContentViewCore::FromWebContents(
203 content::WebContents
* web_contents
) {
204 return ContentViewCoreImpl::FromWebContents(web_contents
);
208 ContentViewCore
* ContentViewCore::GetNativeContentViewCore(JNIEnv
* env
,
210 return reinterpret_cast<ContentViewCore
*>(
211 Java_ContentViewCore_getNativeContentViewCore(env
, obj
));
214 ContentViewCoreImpl::ContentViewCoreImpl(
217 WebContents
* web_contents
,
218 ui::ViewAndroid
* view_android
,
219 ui::WindowAndroid
* window_android
,
220 jobject java_bridge_retained_object_set
)
221 : WebContentsObserver(web_contents
),
223 web_contents_(static_cast<WebContentsImpl
*>(web_contents
)),
224 root_layer_(cc::SolidColorLayer::Create()),
225 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
226 view_android_(view_android
),
227 window_android_(window_android
),
228 device_orientation_(0),
229 accessibility_enabled_(false) {
230 CHECK(web_contents
) <<
231 "A ContentViewCoreImpl should be created with a valid WebContents.";
232 DCHECK(view_android_
);
233 DCHECK(window_android_
);
235 root_layer_
->SetBackgroundColor(GetBackgroundColor(env
, obj
));
236 gfx::Size
physical_size(
237 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, obj
),
238 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, obj
));
239 root_layer_
->SetBounds(physical_size
);
240 root_layer_
->SetIsDrawable(true);
242 // Currently, the only use case we have for overriding a user agent involves
243 // spoofing a desktop Linux user agent for "Request desktop site".
244 // Automatically set it for all WebContents so that it is available when a
245 // NavigationEntry requires the user agent to be overridden.
246 const char kLinuxInfoStr
[] = "X11; Linux x86_64";
247 std::string product
= content::GetContentClient()->GetProduct();
248 std::string spoofed_ua
=
249 BuildUserAgentFromOSAndProduct(kLinuxInfoStr
, product
);
250 web_contents
->SetUserAgentOverride(spoofed_ua
);
252 java_bridge_dispatcher_host_
.reset(
253 new GinJavaBridgeDispatcherHost(web_contents
,
254 java_bridge_retained_object_set
));
259 ContentViewCoreImpl::~ContentViewCoreImpl() {
260 JNIEnv
* env
= base::android::AttachCurrentThread();
261 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
263 if (!j_obj
.is_null()) {
264 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
265 env
, j_obj
.obj(), reinterpret_cast<intptr_t>(this));
269 base::android::ScopedJavaLocalRef
<jobject
>
270 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv
* env
, jobject obj
) {
271 return web_contents_
->GetJavaWebContents();
274 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv
* env
,
276 DCHECK(env
->IsSameObject(java_ref_
.get(env
).obj(), obj
));
278 // Java peer has gone, ContentViewCore is not functional and waits to
279 // be destroyed with WebContents.
280 // We need to reset WebContentsViewAndroid's reference, otherwise, there
281 // could have call in when swapping the WebContents,
282 // see http://crbug.com/383939 .
283 DCHECK(web_contents_
);
284 static_cast<WebContentsViewAndroid
*>(
285 static_cast<WebContentsImpl
*>(web_contents_
)->GetView())->
286 SetContentViewCore(NULL
);
289 void ContentViewCoreImpl::InitWebContents() {
290 DCHECK(web_contents_
);
291 static_cast<WebContentsViewAndroid
*>(
292 static_cast<WebContentsImpl
*>(web_contents_
)->GetView())->
293 SetContentViewCore(this);
294 DCHECK(!web_contents_
->GetUserData(kContentViewUserDataKey
));
295 web_contents_
->SetUserData(kContentViewUserDataKey
,
296 new ContentViewUserData(this));
299 void ContentViewCoreImpl::RenderViewReady() {
300 JNIEnv
* env
= AttachCurrentThread();
301 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
303 Java_ContentViewCore_onRenderProcessChange(env
, obj
.obj());
305 if (device_orientation_
!= 0)
306 SendOrientationChangeEventInternal();
309 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost
* old_host
,
310 RenderViewHost
* new_host
) {
313 old_pid
= GetRenderProcessIdFromRenderViewHost(old_host
);
315 RenderWidgetHostViewAndroid
* view
=
316 static_cast<RenderWidgetHostViewAndroid
*>(old_host
->GetView());
318 view
->SetContentViewCore(NULL
);
320 view
= static_cast<RenderWidgetHostViewAndroid
*>(new_host
->GetView());
322 view
->SetContentViewCore(this);
324 int new_pid
= GetRenderProcessIdFromRenderViewHost(
325 web_contents_
->GetRenderViewHost());
326 if (new_pid
!= old_pid
) {
327 // Notify the Java side that the renderer process changed.
328 JNIEnv
* env
= AttachCurrentThread();
329 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
330 if (!obj
.is_null()) {
331 Java_ContentViewCore_onRenderProcessChange(env
, obj
.obj());
335 SetFocusInternal(HasFocus());
336 SetAccessibilityEnabledInternal(accessibility_enabled_
);
339 RenderWidgetHostViewAndroid
*
340 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() const {
341 RenderWidgetHostView
* rwhv
= NULL
;
343 rwhv
= web_contents_
->GetRenderWidgetHostView();
344 if (web_contents_
->ShowingInterstitialPage()) {
345 rwhv
= static_cast<InterstitialPageImpl
*>(
346 web_contents_
->GetInterstitialPage())->
347 GetRenderViewHost()->GetView();
350 return static_cast<RenderWidgetHostViewAndroid
*>(rwhv
);
353 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetJavaObject() {
354 JNIEnv
* env
= AttachCurrentThread();
355 return java_ref_
.get(env
);
358 jint
ContentViewCoreImpl::GetBackgroundColor(JNIEnv
* env
, jobject obj
) {
359 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
361 return SK_ColorWHITE
;
362 return rwhva
->GetCachedBackgroundColor();
365 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause
) {
367 web_contents_
->GetGeolocationServiceContext()->PauseUpdates();
369 web_contents_
->GetGeolocationServiceContext()->ResumeUpdates();
372 // All positions and sizes are in CSS pixels.
373 // Note that viewport_width/height is a best effort based.
374 // ContentViewCore has the actual information about the physical viewport size.
375 void ContentViewCoreImpl::UpdateFrameInfo(
376 const gfx::Vector2dF
& scroll_offset
,
377 float page_scale_factor
,
378 const gfx::Vector2dF
& page_scale_factor_limits
,
379 const gfx::SizeF
& content_size
,
380 const gfx::SizeF
& viewport_size
,
381 const gfx::Vector2dF
& controls_offset
,
382 const gfx::Vector2dF
& content_offset
) {
383 JNIEnv
* env
= AttachCurrentThread();
384 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
388 window_android_
->set_content_offset(
389 gfx::ScaleVector2d(content_offset
, dpi_scale_
));
391 Java_ContentViewCore_updateFrameInfo(
396 page_scale_factor_limits
.x(),
397 page_scale_factor_limits
.y(),
398 content_size
.width(),
399 content_size
.height(),
400 viewport_size
.width(),
401 viewport_size
.height(),
406 void ContentViewCoreImpl::SetTitle(const base::string16
& title
) {
407 JNIEnv
* env
= AttachCurrentThread();
408 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
411 ScopedJavaLocalRef
<jstring
> jtitle
=
412 ConvertUTF8ToJavaString(env
, base::UTF16ToUTF8(title
));
413 Java_ContentViewCore_setTitle(env
, obj
.obj(), jtitle
.obj());
416 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color
) {
417 root_layer_
->SetBackgroundColor(color
);
419 JNIEnv
* env
= AttachCurrentThread();
420 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
423 Java_ContentViewCore_onBackgroundColorChanged(env
, obj
.obj(), color
);
426 void ContentViewCoreImpl::ShowSelectPopupMenu(
427 RenderFrameHost
* frame
,
428 const gfx::Rect
& bounds
,
429 const std::vector
<MenuItem
>& items
,
432 JNIEnv
* env
= AttachCurrentThread();
433 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
437 ScopedJavaLocalRef
<jobject
> bounds_rect(CreateJavaRect(env
, bounds
));
439 // For multi-select list popups we find the list of previous selections by
440 // iterating through the items. But for single selection popups we take the
441 // given |selected_item| as is.
442 ScopedJavaLocalRef
<jintArray
> selected_array
;
444 scoped_ptr
<jint
[]> native_selected_array(new jint
[items
.size()]);
445 size_t selected_count
= 0;
446 for (size_t i
= 0; i
< items
.size(); ++i
) {
447 if (items
[i
].checked
)
448 native_selected_array
[selected_count
++] = i
;
451 selected_array
= ScopedJavaLocalRef
<jintArray
>(
452 env
, env
->NewIntArray(selected_count
));
453 env
->SetIntArrayRegion(selected_array
.obj(), 0, selected_count
,
454 native_selected_array
.get());
456 selected_array
= ScopedJavaLocalRef
<jintArray
>(env
, env
->NewIntArray(1));
457 jint value
= selected_item
;
458 env
->SetIntArrayRegion(selected_array
.obj(), 0, 1, &value
);
461 ScopedJavaLocalRef
<jintArray
> enabled_array(env
,
462 env
->NewIntArray(items
.size()));
463 std::vector
<base::string16
> labels
;
464 labels
.reserve(items
.size());
465 for (size_t i
= 0; i
< items
.size(); ++i
) {
466 labels
.push_back(items
[i
].label
);
468 (items
[i
].type
== MenuItem::GROUP
? POPUP_ITEM_TYPE_GROUP
:
469 (items
[i
].enabled
? POPUP_ITEM_TYPE_ENABLED
:
470 POPUP_ITEM_TYPE_DISABLED
));
471 env
->SetIntArrayRegion(enabled_array
.obj(), i
, 1, &enabled
);
473 ScopedJavaLocalRef
<jobjectArray
> items_array(
474 base::android::ToJavaArrayOfStrings(env
, labels
));
475 Java_ContentViewCore_showSelectPopup(env
,
477 reinterpret_cast<intptr_t>(frame
),
482 selected_array
.obj());
485 void ContentViewCoreImpl::HideSelectPopupMenu() {
486 JNIEnv
* env
= AttachCurrentThread();
487 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
488 if (!j_obj
.is_null())
489 Java_ContentViewCore_hideSelectPopup(env
, j_obj
.obj());
492 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent
& event
,
493 InputEventAckState ack_result
) {
494 JNIEnv
* env
= AttachCurrentThread();
495 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
499 switch (event
.type
) {
500 case WebInputEvent::GestureFlingStart
:
501 if (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
) {
502 // The view expects the fling velocity in pixels/s.
503 Java_ContentViewCore_onFlingStartEventConsumed(env
, j_obj
.obj(),
504 event
.data
.flingStart
.velocityX
* dpi_scale(),
505 event
.data
.flingStart
.velocityY
* dpi_scale());
507 // If a scroll ends with a fling, a SCROLL_END event is never sent.
508 // However, if that fling went unconsumed, we still need to let the
509 // listeners know that scrolling has ended.
510 Java_ContentViewCore_onScrollEndEventAck(env
, j_obj
.obj());
513 if (ack_result
== INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
) {
514 // The view expects the fling velocity in pixels/s.
515 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env
, j_obj
.obj(),
516 event
.data
.flingStart
.velocityX
* dpi_scale(),
517 event
.data
.flingStart
.velocityY
* dpi_scale());
520 case WebInputEvent::GestureFlingCancel
:
521 Java_ContentViewCore_onFlingCancelEventAck(env
, j_obj
.obj());
523 case WebInputEvent::GestureScrollBegin
:
524 Java_ContentViewCore_onScrollBeginEventAck(env
, j_obj
.obj());
526 case WebInputEvent::GestureScrollUpdate
:
527 if (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
)
528 Java_ContentViewCore_onScrollUpdateGestureConsumed(env
, j_obj
.obj());
530 case WebInputEvent::GestureScrollEnd
:
531 Java_ContentViewCore_onScrollEndEventAck(env
, j_obj
.obj());
533 case WebInputEvent::GesturePinchBegin
:
534 Java_ContentViewCore_onPinchBeginEventAck(env
, j_obj
.obj());
536 case WebInputEvent::GesturePinchEnd
:
537 Java_ContentViewCore_onPinchEndEventAck(env
, j_obj
.obj());
539 case WebInputEvent::GestureTap
:
540 Java_ContentViewCore_onSingleTapEventAck(
543 ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
,
544 event
.x
* dpi_scale(),
545 event
.y
* dpi_scale());
552 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent
& event
) {
553 if (event
.type
!= WebInputEvent::GestureTap
&&
554 event
.type
!= WebInputEvent::GestureDoubleTap
&&
555 event
.type
!= WebInputEvent::GestureLongTap
&&
556 event
.type
!= WebInputEvent::GestureLongPress
)
559 JNIEnv
* env
= AttachCurrentThread();
560 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
564 const blink::WebGestureEvent
& gesture
=
565 static_cast<const blink::WebGestureEvent
&>(event
);
566 int gesture_type
= ToGestureEventType(event
.type
);
567 return Java_ContentViewCore_filterTapOrPressEvent(env
,
570 gesture
.x
* dpi_scale(),
571 gesture
.y
* dpi_scale());
573 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
576 bool ContentViewCoreImpl::HasFocus() {
577 JNIEnv
* env
= AttachCurrentThread();
578 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
581 return Java_ContentViewCore_hasFocus(env
, obj
.obj());
584 void ContentViewCoreImpl::OnSelectionChanged(const std::string
& text
) {
585 JNIEnv
* env
= AttachCurrentThread();
586 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
589 ScopedJavaLocalRef
<jstring
> jtext
= ConvertUTF8ToJavaString(env
, text
);
590 Java_ContentViewCore_onSelectionChanged(env
, obj
.obj(), jtext
.obj());
593 void ContentViewCoreImpl::OnSelectionEvent(SelectionEventType event
,
594 const gfx::PointF
& position
) {
595 JNIEnv
* env
= AttachCurrentThread();
596 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
599 Java_ContentViewCore_onSelectionEvent(
600 env
, j_obj
.obj(), event
, position
.x(), position
.y());
603 scoped_ptr
<TouchHandleDrawable
>
604 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
605 JNIEnv
* env
= AttachCurrentThread();
606 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
609 return scoped_ptr
<TouchHandleDrawable
>();
611 return scoped_ptr
<TouchHandleDrawable
>(new PopupTouchHandleDrawable(
612 Java_ContentViewCore_createPopupTouchHandleDrawable(env
, obj
.obj()),
616 void ContentViewCoreImpl::ShowPastePopup(int x_dip
, int y_dip
) {
617 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
621 view
->OnShowingPastePopup(gfx::PointF(x_dip
, y_dip
));
623 JNIEnv
* env
= AttachCurrentThread();
624 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
627 Java_ContentViewCore_showPastePopupWithFeedback(env
, obj
.obj(),
628 static_cast<jint
>(x_dip
),
629 static_cast<jint
>(y_dip
));
632 void ContentViewCoreImpl::GetScaledContentBitmap(
634 SkColorType color_type
,
635 gfx::Rect src_subrect
,
636 ReadbackRequestCallback
& result_callback
) {
637 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
639 result_callback
.Run(SkBitmap(), READBACK_FAILED
);
643 view
->GetScaledContentBitmap(scale
, color_type
, src_subrect
,
647 void ContentViewCoreImpl::StartContentIntent(const GURL
& content_url
) {
648 JNIEnv
* env
= AttachCurrentThread();
649 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
652 ScopedJavaLocalRef
<jstring
> jcontent_url
=
653 ConvertUTF8ToJavaString(env
, content_url
.spec());
654 Java_ContentViewCore_startContentIntent(env
,
659 void ContentViewCoreImpl::ShowDisambiguationPopup(
660 const gfx::Rect
& rect_pixels
,
661 const SkBitmap
& zoomed_bitmap
) {
662 JNIEnv
* env
= AttachCurrentThread();
664 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
668 ScopedJavaLocalRef
<jobject
> rect_object(CreateJavaRect(env
, rect_pixels
));
670 ScopedJavaLocalRef
<jobject
> java_bitmap
=
671 gfx::ConvertToJavaBitmap(&zoomed_bitmap
);
672 DCHECK(!java_bitmap
.is_null());
674 Java_ContentViewCore_showDisambiguationPopup(env
,
680 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
681 JNIEnv
* env
= AttachCurrentThread();
683 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
685 return ScopedJavaLocalRef
<jobject
>();
686 return Java_ContentViewCore_createTouchEventSynthesizer(env
, obj
.obj());
689 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL
& url
) {
690 JNIEnv
* env
= AttachCurrentThread();
692 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
695 ScopedJavaLocalRef
<jstring
> j_url
= ConvertUTF8ToJavaString(env
, url
.spec());
696 return Java_ContentViewCore_shouldBlockMediaRequest(env
, obj
.obj(),
700 void ContentViewCoreImpl::DidStopFlinging() {
701 JNIEnv
* env
= AttachCurrentThread();
703 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
705 Java_ContentViewCore_onNativeFlingStopped(env
, obj
.obj());
708 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetContext() const {
709 JNIEnv
* env
= AttachCurrentThread();
711 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
713 return ScopedJavaLocalRef
<jobject
>();
715 return Java_ContentViewCore_getContext(env
, obj
.obj());
718 gfx::Size
ContentViewCoreImpl::GetViewSize() const {
719 gfx::Size size
= GetViewportSizeDip();
720 size
.Enlarge(0, -GetTopControlsLayoutHeightDip());
724 gfx::Size
ContentViewCoreImpl::GetPhysicalBackingSize() const {
725 JNIEnv
* env
= AttachCurrentThread();
726 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
730 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, j_obj
.obj()),
731 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, j_obj
.obj()));
734 gfx::Size
ContentViewCoreImpl::GetViewportSizePix() const {
735 JNIEnv
* env
= AttachCurrentThread();
736 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
740 Java_ContentViewCore_getViewportWidthPix(env
, j_obj
.obj()),
741 Java_ContentViewCore_getViewportHeightPix(env
, j_obj
.obj()));
744 int ContentViewCoreImpl::GetTopControlsLayoutHeightPix() const {
745 JNIEnv
* env
= AttachCurrentThread();
746 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
749 return Java_ContentViewCore_getTopControlsLayoutHeightPix(env
, j_obj
.obj());
752 gfx::Size
ContentViewCoreImpl::GetViewportSizeDip() const {
753 return gfx::ToCeiledSize(
754 gfx::ScaleSize(GetViewportSizePix(), 1.0f
/ dpi_scale()));
757 float ContentViewCoreImpl::GetTopControlsLayoutHeightDip() const {
758 return GetTopControlsLayoutHeightPix() / dpi_scale();
761 void ContentViewCoreImpl::AttachLayer(scoped_refptr
<cc::Layer
> layer
) {
762 root_layer_
->InsertChild(layer
, 0);
763 root_layer_
->SetIsDrawable(false);
766 void ContentViewCoreImpl::RemoveLayer(scoped_refptr
<cc::Layer
> layer
) {
767 layer
->RemoveFromParent();
769 if (!root_layer_
->children().size())
770 root_layer_
->SetIsDrawable(true);
773 void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF
& extent
) {
777 web_contents_
->MoveRangeSelectionExtent(gfx::Point(extent
.x(), extent
.y()));
780 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF
& base
,
781 const gfx::PointF
& extent
) {
785 gfx::Point base_point
= gfx::Point(base
.x(), base
.y());
786 gfx::Point extent_point
= gfx::Point(extent
.x(), extent
.y());
787 if (base_point
== extent_point
)
790 web_contents_
->SelectRange(base_point
, extent_point
);
793 ui::ViewAndroid
* ContentViewCoreImpl::GetViewAndroid() const {
794 return view_android_
;
797 ui::WindowAndroid
* ContentViewCoreImpl::GetWindowAndroid() const {
798 return window_android_
;
801 const scoped_refptr
<cc::Layer
>& ContentViewCoreImpl::GetLayer() const {
805 // ----------------------------------------------------------------------------
806 // Methods called from Java via JNI
807 // ----------------------------------------------------------------------------
809 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv
* env
,
811 jlong selectPopupSourceFrame
,
813 RenderFrameHostImpl
* rfhi
=
814 reinterpret_cast<RenderFrameHostImpl
*>(selectPopupSourceFrame
);
816 if (indices
== NULL
) {
817 rfhi
->DidCancelPopupMenu();
821 int selected_count
= env
->GetArrayLength(indices
);
822 std::vector
<int> selected_indices
;
823 jint
* indices_ptr
= env
->GetIntArrayElements(indices
, NULL
);
824 for (int i
= 0; i
< selected_count
; ++i
)
825 selected_indices
.push_back(indices_ptr
[i
]);
826 env
->ReleaseIntArrayElements(indices
, indices_ptr
, JNI_ABORT
);
827 rfhi
->DidSelectPopupMenuItems(selected_indices
);
830 WebContents
* ContentViewCoreImpl::GetWebContents() const {
831 return web_contents_
;
834 void ContentViewCoreImpl::SetFocus(JNIEnv
* env
, jobject obj
, jboolean focused
) {
835 SetFocusInternal(focused
);
838 void ContentViewCoreImpl::SetFocusInternal(bool focused
) {
839 if (!GetRenderWidgetHostViewAndroid())
843 GetRenderWidgetHostViewAndroid()->Focus();
845 GetRenderWidgetHostViewAndroid()->Blur();
848 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv
* env
,
851 if (device_orientation_
!= orientation
) {
852 device_orientation_
= orientation
;
853 SendOrientationChangeEventInternal();
857 jboolean
ContentViewCoreImpl::OnTouchEvent(JNIEnv
* env
,
859 jobject motion_event
,
871 jfloat touch_major_0
,
872 jfloat touch_major_1
,
873 jfloat touch_minor_0
,
874 jfloat touch_minor_1
,
875 jfloat orientation_0
,
876 jfloat orientation_1
,
879 jint android_tool_type_0
,
880 jint android_tool_type_1
,
881 jint android_button_state
,
882 jint android_meta_state
,
883 jboolean is_touch_handle_event
) {
884 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
885 // Avoid synthesizing a touch event if it cannot be forwarded.
889 MotionEventAndroid::Pointer
pointer0(pointer_id_0
,
895 android_tool_type_0
);
896 MotionEventAndroid::Pointer
pointer1(pointer_id_1
,
902 android_tool_type_1
);
903 MotionEventAndroid
event(1.f
/ dpi_scale(),
911 android_button_state
,
918 return is_touch_handle_event
? rwhv
->OnTouchHandleEvent(event
)
919 : rwhv
->OnTouchEvent(event
);
922 float ContentViewCoreImpl::GetDpiScale() const {
926 jboolean
ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv
* env
,
931 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
935 blink::WebMouseEvent event
= WebMouseEventBuilder::Build(
936 WebInputEvent::MouseMove
,
937 blink::WebMouseEvent::ButtonNone
,
938 time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale(), 0, 1);
940 rwhv
->SendMouseEvent(event
);
944 jboolean
ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv
* env
,
949 jfloat vertical_axis
) {
950 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
954 WebMouseWheelEventBuilder::Direction direction
;
955 if (vertical_axis
> 0) {
956 direction
= WebMouseWheelEventBuilder::DIRECTION_UP
;
957 } else if (vertical_axis
< 0) {
958 direction
= WebMouseWheelEventBuilder::DIRECTION_DOWN
;
962 blink::WebMouseWheelEvent event
= WebMouseWheelEventBuilder::Build(
963 direction
, time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale());
965 rwhv
->SendMouseWheelEvent(event
);
969 WebGestureEvent
ContentViewCoreImpl::MakeGestureEvent(
970 WebInputEvent::Type type
, int64 time_ms
, float x
, float y
) const {
971 return WebGestureEventBuilder::Build(
972 type
, time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale());
975 void ContentViewCoreImpl::SendGestureEvent(
976 const blink::WebGestureEvent
& event
) {
977 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
979 rwhv
->SendGestureEvent(event
);
982 void ContentViewCoreImpl::ScrollBegin(JNIEnv
* env
,
989 WebGestureEvent event
= MakeGestureEvent(
990 WebInputEvent::GestureScrollBegin
, time_ms
, x
, y
);
991 event
.data
.scrollBegin
.deltaXHint
= hintx
/ dpi_scale();
992 event
.data
.scrollBegin
.deltaYHint
= hinty
/ dpi_scale();
994 SendGestureEvent(event
);
997 void ContentViewCoreImpl::ScrollEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
998 WebGestureEvent event
= MakeGestureEvent(
999 WebInputEvent::GestureScrollEnd
, time_ms
, 0, 0);
1000 SendGestureEvent(event
);
1003 void ContentViewCoreImpl::ScrollBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1004 jfloat x
, jfloat y
, jfloat dx
, jfloat dy
) {
1005 WebGestureEvent event
= MakeGestureEvent(
1006 WebInputEvent::GestureScrollUpdate
, time_ms
, x
, y
);
1007 event
.data
.scrollUpdate
.deltaX
= -dx
/ dpi_scale();
1008 event
.data
.scrollUpdate
.deltaY
= -dy
/ dpi_scale();
1010 SendGestureEvent(event
);
1013 void ContentViewCoreImpl::FlingStart(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1014 jfloat x
, jfloat y
, jfloat vx
, jfloat vy
) {
1015 WebGestureEvent event
= MakeGestureEvent(
1016 WebInputEvent::GestureFlingStart
, time_ms
, x
, y
);
1017 event
.data
.flingStart
.velocityX
= vx
/ dpi_scale();
1018 event
.data
.flingStart
.velocityY
= vy
/ dpi_scale();
1020 SendGestureEvent(event
);
1023 void ContentViewCoreImpl::FlingCancel(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1024 WebGestureEvent event
= MakeGestureEvent(
1025 WebInputEvent::GestureFlingCancel
, time_ms
, 0, 0);
1026 SendGestureEvent(event
);
1029 void ContentViewCoreImpl::SingleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1030 jfloat x
, jfloat y
) {
1031 // Tap gestures should always be preceded by a TapDown, ensuring consistency
1032 // with the touch-based gesture detection pipeline.
1033 WebGestureEvent tap_down_event
= MakeGestureEvent(
1034 WebInputEvent::GestureTapDown
, time_ms
, x
, y
);
1035 tap_down_event
.data
.tap
.tapCount
= 1;
1036 SendGestureEvent(tap_down_event
);
1038 WebGestureEvent tap_event
= MakeGestureEvent(
1039 WebInputEvent::GestureTap
, time_ms
, x
, y
);
1040 tap_event
.data
.tap
.tapCount
= 1;
1041 SendGestureEvent(tap_event
);
1044 void ContentViewCoreImpl::DoubleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1045 jfloat x
, jfloat y
) {
1046 WebGestureEvent event
= MakeGestureEvent(
1047 WebInputEvent::GestureDoubleTap
, time_ms
, x
, y
);
1048 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1049 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1050 event
.data
.tap
.tapCount
= 1;
1052 SendGestureEvent(event
);
1055 void ContentViewCoreImpl::LongPress(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1056 jfloat x
, jfloat y
) {
1057 WebGestureEvent event
= MakeGestureEvent(
1058 WebInputEvent::GestureLongPress
, time_ms
, x
, y
);
1060 SendGestureEvent(event
);
1063 void ContentViewCoreImpl::PinchBegin(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1064 jfloat x
, jfloat y
) {
1065 WebGestureEvent event
= MakeGestureEvent(
1066 WebInputEvent::GesturePinchBegin
, time_ms
, x
, y
);
1067 SendGestureEvent(event
);
1070 void ContentViewCoreImpl::PinchEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1071 WebGestureEvent event
= MakeGestureEvent(
1072 WebInputEvent::GesturePinchEnd
, time_ms
, 0, 0);
1073 SendGestureEvent(event
);
1076 void ContentViewCoreImpl::PinchBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1077 jfloat anchor_x
, jfloat anchor_y
,
1079 WebGestureEvent event
= MakeGestureEvent(
1080 WebInputEvent::GesturePinchUpdate
, time_ms
, anchor_x
, anchor_y
);
1081 event
.data
.pinchUpdate
.scale
= delta
;
1083 SendGestureEvent(event
);
1086 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv
* env
, jobject obj
,
1087 jfloat x1
, jfloat y1
,
1088 jfloat x2
, jfloat y2
) {
1089 SelectBetweenCoordinates(gfx::PointF(x1
/ dpi_scale(), y1
/ dpi_scale()),
1090 gfx::PointF(x2
/ dpi_scale(), y2
/ dpi_scale()));
1093 void ContentViewCoreImpl::MoveCaret(JNIEnv
* env
, jobject obj
,
1094 jfloat x
, jfloat y
) {
1095 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1097 rwhv
->MoveCaret(gfx::Point(x
/ dpi_scale_
, y
/ dpi_scale_
));
1100 void ContentViewCoreImpl::DismissTextHandles(JNIEnv
* env
, jobject obj
) {
1101 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1103 rwhv
->DismissTextHandles();
1106 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv
* env
,
1109 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1111 rwhv
->SetTextHandlesTemporarilyHidden(hidden
);
1114 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv
* env
, jobject obj
) {
1115 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1117 rwhv
->ResetGestureDetection();
1120 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv
* env
,
1123 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1125 rwhv
->SetDoubleTapSupportEnabled(enabled
);
1128 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv
* env
,
1131 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1133 rwhv
->SetMultiTouchZoomSupportEnabled(enabled
);
1136 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1140 java_bridge_dispatcher_host_
->SetAllowObjectContentsInspection(allow
);
1143 void ContentViewCoreImpl::AddJavascriptInterface(
1148 jclass safe_annotation_clazz
) {
1149 ScopedJavaLocalRef
<jobject
> scoped_object(env
, object
);
1150 ScopedJavaLocalRef
<jclass
> scoped_clazz(env
, safe_annotation_clazz
);
1151 java_bridge_dispatcher_host_
->AddNamedObject(
1152 ConvertJavaStringToUTF8(env
, name
), scoped_object
, scoped_clazz
);
1155 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv
* env
,
1158 java_bridge_dispatcher_host_
->RemoveNamedObject(
1159 ConvertJavaStringToUTF8(env
, name
));
1162 void ContentViewCoreImpl::WasResized(JNIEnv
* env
, jobject obj
) {
1163 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1164 gfx::Size
physical_size(
1165 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, obj
),
1166 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, obj
));
1167 root_layer_
->SetBounds(physical_size
);
1170 RenderWidgetHostImpl
* host
= RenderWidgetHostImpl::From(
1171 view
->GetRenderWidgetHost());
1172 host
->SendScreenRects();
1177 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv
* env
, jobject obj
) {
1178 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
1181 return rwhva
->GetNativeImeAdapter();
1184 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter
,
1185 int text_input_type
,
1186 int text_input_flags
,
1187 const std::string
& text
,
1188 int selection_start
,
1190 int composition_start
,
1191 int composition_end
,
1192 bool show_ime_if_needed
,
1193 bool is_non_ime_change
) {
1194 JNIEnv
* env
= AttachCurrentThread();
1195 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1199 ScopedJavaLocalRef
<jstring
> jstring_text
= ConvertUTF8ToJavaString(env
, text
);
1200 Java_ContentViewCore_updateImeAdapter(env
,
1214 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv
* env
, jobject obj
,
1216 SetAccessibilityEnabledInternal(enabled
);
1219 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1220 JNIEnv
* env
= AttachCurrentThread();
1221 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1224 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env
,
1228 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled
) {
1229 accessibility_enabled_
= enabled
;
1230 BrowserAccessibilityStateImpl
* accessibility_state
=
1231 BrowserAccessibilityStateImpl::GetInstance();
1233 // This enables accessibility globally unless it was explicitly disallowed
1234 // by a command-line flag.
1235 accessibility_state
->OnScreenReaderDetected();
1236 // If it was actually enabled globally, enable it for this RenderWidget now.
1237 if (accessibility_state
->IsAccessibleBrowser() && web_contents_
)
1238 web_contents_
->AddAccessibilityMode(AccessibilityModeComplete
);
1240 accessibility_state
->ResetAccessibilityMode();
1241 if (web_contents_
) {
1242 web_contents_
->SetAccessibilityMode(
1243 accessibility_state
->accessibility_mode());
1248 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1249 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1251 rwhv
->UpdateScreenInfo(GetViewAndroid());
1253 static_cast<WebContentsImpl
*>(web_contents())->
1254 screen_orientation_dispatcher_host()->OnOrientationChange();
1257 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv
* env
,
1264 static_cast<int>(x
/ dpi_scale()),
1265 static_cast<int>(y
/ dpi_scale()),
1266 static_cast<int>((width
> 0 && width
< dpi_scale()) ?
1267 1 : (int)(width
/ dpi_scale())),
1268 static_cast<int>((height
> 0 && height
< dpi_scale()) ?
1269 1 : (int)(height
/ dpi_scale())));
1270 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1271 GetWebContents()->GetRoutingID(), rect
));
1274 jint
ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv
* env
, jobject obj
) {
1275 return GetRenderProcessIdFromRenderViewHost(
1276 web_contents_
->GetRenderViewHost());
1279 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv
* env
, jobject jobj
,
1281 if (GetRenderWidgetHostViewAndroid()) {
1283 GetRenderWidgetHostViewAndroid()->SetBackgroundColorToDefault();
1285 GetRenderWidgetHostViewAndroid()->SetBackgroundColor(SK_ColorTRANSPARENT
);
1289 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1291 const base::Callback
<
1292 void(const base::string16
& content
, int start_offset
, int end_offset
)>&
1294 DCHECK(!callback
.is_null());
1295 RenderFrameHost
* focused_frame
= web_contents_
->GetFocusedFrame();
1298 if (GetRenderWidgetHostViewAndroid()) {
1299 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1301 focused_frame
->Send(new FrameMsg_TextSurroundingSelectionRequest(
1302 focused_frame
->GetRoutingID(), max_length
));
1306 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1307 const base::string16
& text
,
1308 const base::string16
& html
,
1309 const gfx::Rect
& clip_rect
) {
1310 JNIEnv
* env
= AttachCurrentThread();
1311 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1314 ScopedJavaLocalRef
<jstring
> jtext
= ConvertUTF16ToJavaString(env
, text
);
1315 ScopedJavaLocalRef
<jstring
> jhtml
= ConvertUTF16ToJavaString(env
, html
);
1316 ScopedJavaLocalRef
<jobject
> clip_rect_object(CreateJavaRect(env
, clip_rect
));
1317 Java_ContentViewCore_onSmartClipDataExtracted(
1318 env
, obj
.obj(), jtext
.obj(), jhtml
.obj(), clip_rect_object
.obj());
1321 void ContentViewCoreImpl::WebContentsDestroyed() {
1322 WebContentsViewAndroid
* wcva
= static_cast<WebContentsViewAndroid
*>(
1323 static_cast<WebContentsImpl
*>(web_contents())->GetView());
1325 wcva
->SetContentViewCore(NULL
);
1328 // This is called for each ContentView.
1329 jlong
Init(JNIEnv
* env
,
1331 jlong native_web_contents
,
1333 jlong window_android
,
1334 jobject retained_objects_set
) {
1335 ContentViewCoreImpl
* view
= new ContentViewCoreImpl(
1337 reinterpret_cast<WebContents
*>(native_web_contents
),
1338 reinterpret_cast<ui::ViewAndroid
*>(view_android
),
1339 reinterpret_cast<ui::WindowAndroid
*>(window_android
),
1340 retained_objects_set
);
1341 return reinterpret_cast<intptr_t>(view
);
1344 bool RegisterContentViewCore(JNIEnv
* env
) {
1345 return RegisterNativesImpl(env
);
1348 } // namespace content