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/accessibility/browser_accessibility_state_impl.h"
21 #include "content/browser/android/gesture_event_type.h"
22 #include "content/browser/android/interstitial_page_delegate_android.h"
23 #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
24 #include "content/browser/android/load_url_params.h"
25 #include "content/browser/android/popup_touch_handle_drawable.h"
26 #include "content/browser/frame_host/interstitial_page_impl.h"
27 #include "content/browser/frame_host/navigation_controller_impl.h"
28 #include "content/browser/frame_host/navigation_entry_impl.h"
29 #include "content/browser/geolocation/geolocation_dispatcher_host.h"
30 #include "content/browser/media/media_web_contents_observer.h"
31 #include "content/browser/renderer_host/compositor_impl_android.h"
32 #include "content/browser/renderer_host/input/motion_event_android.h"
33 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
34 #include "content/browser/renderer_host/input/web_input_event_util.h"
35 #include "content/browser/renderer_host/render_view_host_impl.h"
36 #include "content/browser/renderer_host/render_widget_host_impl.h"
37 #include "content/browser/renderer_host/render_widget_host_view_android.h"
38 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
39 #include "content/browser/ssl/ssl_host_state.h"
40 #include "content/browser/transition_request_manager.h"
41 #include "content/browser/web_contents/web_contents_view_android.h"
42 #include "content/common/frame_messages.h"
43 #include "content/common/input/web_input_event_traits.h"
44 #include "content/common/input_messages.h"
45 #include "content/common/view_messages.h"
46 #include "content/public/browser/browser_context.h"
47 #include "content/public/browser/browser_thread.h"
48 #include "content/public/browser/favicon_status.h"
49 #include "content/public/browser/render_frame_host.h"
50 #include "content/public/browser/web_contents.h"
51 #include "content/public/common/content_client.h"
52 #include "content/public/common/content_switches.h"
53 #include "content/public/common/menu_item.h"
54 #include "content/public/common/page_transition_types.h"
55 #include "content/public/common/user_agent.h"
56 #include "jni/ContentViewCore_jni.h"
57 #include "third_party/WebKit/public/web/WebInputEvent.h"
58 #include "ui/base/android/view_android.h"
59 #include "ui/base/android/window_android.h"
60 #include "ui/gfx/android/java_bitmap.h"
61 #include "ui/gfx/screen.h"
62 #include "ui/gfx/size_conversions.h"
63 #include "ui/gfx/size_f.h"
65 using base::android::AttachCurrentThread
;
66 using base::android::ConvertJavaStringToUTF16
;
67 using base::android::ConvertJavaStringToUTF8
;
68 using base::android::ConvertUTF16ToJavaString
;
69 using base::android::ConvertUTF8ToJavaString
;
70 using base::android::ScopedJavaGlobalRef
;
71 using base::android::ScopedJavaLocalRef
;
72 using blink::WebGestureEvent
;
73 using blink::WebInputEvent
;
75 // Describes the type and enabled state of a select popup item.
79 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
80 #include "content/browser/android/popup_item_type_list.h"
81 #undef DEFINE_POPUP_ITEM_TYPE
90 const void* kContentViewUserDataKey
= &kContentViewUserDataKey
;
92 int GetRenderProcessIdFromRenderViewHost(RenderViewHost
* host
) {
94 RenderProcessHost
* render_process
= host
->GetProcess();
95 DCHECK(render_process
);
96 if (render_process
->HasConnection())
97 return render_process
->GetHandle();
102 ScopedJavaLocalRef
<jobject
> CreateJavaRect(
104 const gfx::Rect
& rect
) {
105 return ScopedJavaLocalRef
<jobject
>(
106 Java_ContentViewCore_createRect(env
,
107 static_cast<int>(rect
.x()),
108 static_cast<int>(rect
.y()),
109 static_cast<int>(rect
.right()),
110 static_cast<int>(rect
.bottom())));
113 int ToGestureEventType(WebInputEvent::Type type
) {
115 case WebInputEvent::GestureScrollBegin
:
117 case WebInputEvent::GestureScrollEnd
:
119 case WebInputEvent::GestureScrollUpdate
:
121 case WebInputEvent::GestureFlingStart
:
123 case WebInputEvent::GestureFlingCancel
:
125 case WebInputEvent::GestureShowPress
:
127 case WebInputEvent::GestureTap
:
128 return SINGLE_TAP_CONFIRMED
;
129 case WebInputEvent::GestureTapUnconfirmed
:
130 return SINGLE_TAP_UNCONFIRMED
;
131 case WebInputEvent::GestureTapDown
:
133 case WebInputEvent::GestureTapCancel
:
135 case WebInputEvent::GestureDoubleTap
:
137 case WebInputEvent::GestureLongPress
:
139 case WebInputEvent::GestureLongTap
:
141 case WebInputEvent::GesturePinchBegin
:
143 case WebInputEvent::GesturePinchEnd
:
145 case WebInputEvent::GesturePinchUpdate
:
147 case WebInputEvent::GestureTwoFingerTap
:
148 case WebInputEvent::GestureScrollUpdateWithoutPropagation
:
150 NOTREACHED() << "Invalid source gesture type: "
151 << WebInputEventTraits::GetName(type
);
156 float GetPrimaryDisplayDeviceScaleFactor() {
157 const gfx::Display
& display
=
158 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
159 return display
.device_scale_factor();
164 // Enables a callback when the underlying WebContents is destroyed, to enable
165 // nulling the back-pointer.
166 class ContentViewCoreImpl::ContentViewUserData
167 : public base::SupportsUserData::Data
{
169 explicit ContentViewUserData(ContentViewCoreImpl
* content_view_core
)
170 : content_view_core_(content_view_core
) {
173 virtual ~ContentViewUserData() {
174 // TODO(joth): When chrome has finished removing the TabContents class (see
175 // crbug.com/107201) consider inverting relationship, so ContentViewCore
176 // would own WebContents. That effectively implies making the WebContents
177 // destructor private on Android.
178 delete content_view_core_
;
181 ContentViewCoreImpl
* get() const { return content_view_core_
; }
184 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
185 ContentViewCoreImpl
* content_view_core_
;
187 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData
);
191 ContentViewCoreImpl
* ContentViewCoreImpl::FromWebContents(
192 content::WebContents
* web_contents
) {
193 ContentViewCoreImpl::ContentViewUserData
* data
=
194 reinterpret_cast<ContentViewCoreImpl::ContentViewUserData
*>(
195 web_contents
->GetUserData(kContentViewUserDataKey
));
196 return data
? data
->get() : NULL
;
200 ContentViewCore
* ContentViewCore::FromWebContents(
201 content::WebContents
* web_contents
) {
202 return ContentViewCoreImpl::FromWebContents(web_contents
);
206 ContentViewCore
* ContentViewCore::GetNativeContentViewCore(JNIEnv
* env
,
208 return reinterpret_cast<ContentViewCore
*>(
209 Java_ContentViewCore_getNativeContentViewCore(env
, obj
));
212 ContentViewCoreImpl::ContentViewCoreImpl(
215 WebContents
* web_contents
,
216 ui::ViewAndroid
* view_android
,
217 ui::WindowAndroid
* window_android
,
218 jobject java_bridge_retained_object_set
)
219 : WebContentsObserver(web_contents
),
221 web_contents_(static_cast<WebContentsImpl
*>(web_contents
)),
222 root_layer_(cc::SolidColorLayer::Create()),
223 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
224 view_android_(view_android
),
225 window_android_(window_android
),
226 device_orientation_(0),
227 accessibility_enabled_(false) {
228 CHECK(web_contents
) <<
229 "A ContentViewCoreImpl should be created with a valid WebContents.";
230 DCHECK(view_android_
);
231 DCHECK(window_android_
);
233 root_layer_
->SetBackgroundColor(GetBackgroundColor(env
, obj
));
234 gfx::Size
physical_size(
235 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, obj
),
236 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, obj
));
237 root_layer_
->SetBounds(physical_size
);
238 root_layer_
->SetIsDrawable(true);
240 // Currently, the only use case we have for overriding a user agent involves
241 // spoofing a desktop Linux user agent for "Request desktop site".
242 // Automatically set it for all WebContents so that it is available when a
243 // NavigationEntry requires the user agent to be overridden.
244 const char kLinuxInfoStr
[] = "X11; Linux x86_64";
245 std::string product
= content::GetContentClient()->GetProduct();
246 std::string spoofed_ua
=
247 BuildUserAgentFromOSAndProduct(kLinuxInfoStr
, product
);
248 web_contents
->SetUserAgentOverride(spoofed_ua
);
250 java_bridge_dispatcher_host_
.reset(
251 new GinJavaBridgeDispatcherHost(web_contents
,
252 java_bridge_retained_object_set
));
257 ContentViewCoreImpl::~ContentViewCoreImpl() {
258 JNIEnv
* env
= base::android::AttachCurrentThread();
259 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
261 if (!j_obj
.is_null()) {
262 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
263 env
, j_obj
.obj(), reinterpret_cast<intptr_t>(this));
267 base::android::ScopedJavaLocalRef
<jobject
>
268 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv
* env
, jobject obj
) {
269 return web_contents_
->GetJavaWebContents();
272 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv
* env
,
274 DCHECK(env
->IsSameObject(java_ref_
.get(env
).obj(), obj
));
276 // Java peer has gone, ContentViewCore is not functional and waits to
277 // be destroyed with WebContents.
278 // We need to reset WebContentsViewAndroid's reference, otherwise, there
279 // could have call in when swapping the WebContents,
280 // see http://crbug.com/383939 .
281 DCHECK(web_contents_
);
282 static_cast<WebContentsViewAndroid
*>(
283 static_cast<WebContentsImpl
*>(web_contents_
)->GetView())->
284 SetContentViewCore(NULL
);
287 void ContentViewCoreImpl::InitWebContents() {
288 DCHECK(web_contents_
);
289 static_cast<WebContentsViewAndroid
*>(
290 static_cast<WebContentsImpl
*>(web_contents_
)->GetView())->
291 SetContentViewCore(this);
292 DCHECK(!web_contents_
->GetUserData(kContentViewUserDataKey
));
293 web_contents_
->SetUserData(kContentViewUserDataKey
,
294 new ContentViewUserData(this));
297 void ContentViewCoreImpl::RenderViewReady() {
298 JNIEnv
* env
= AttachCurrentThread();
299 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
301 Java_ContentViewCore_onRenderProcessChange(env
, obj
.obj());
303 if (device_orientation_
!= 0)
304 SendOrientationChangeEventInternal();
307 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost
* old_host
,
308 RenderViewHost
* new_host
) {
311 old_pid
= GetRenderProcessIdFromRenderViewHost(old_host
);
313 RenderWidgetHostViewAndroid
* view
=
314 static_cast<RenderWidgetHostViewAndroid
*>(old_host
->GetView());
316 view
->SetContentViewCore(NULL
);
318 view
= static_cast<RenderWidgetHostViewAndroid
*>(new_host
->GetView());
320 view
->SetContentViewCore(this);
322 int new_pid
= GetRenderProcessIdFromRenderViewHost(
323 web_contents_
->GetRenderViewHost());
324 if (new_pid
!= old_pid
) {
325 // Notify the Java side that the renderer process changed.
326 JNIEnv
* env
= AttachCurrentThread();
327 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
328 if (!obj
.is_null()) {
329 Java_ContentViewCore_onRenderProcessChange(env
, obj
.obj());
333 SetFocusInternal(HasFocus());
334 SetAccessibilityEnabledInternal(accessibility_enabled_
);
337 RenderWidgetHostViewAndroid
*
338 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
339 RenderWidgetHostView
* rwhv
= NULL
;
341 rwhv
= web_contents_
->GetRenderWidgetHostView();
342 if (web_contents_
->ShowingInterstitialPage()) {
343 rwhv
= static_cast<InterstitialPageImpl
*>(
344 web_contents_
->GetInterstitialPage())->
345 GetRenderViewHost()->GetView();
348 return static_cast<RenderWidgetHostViewAndroid
*>(rwhv
);
351 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetJavaObject() {
352 JNIEnv
* env
= AttachCurrentThread();
353 return java_ref_
.get(env
);
356 jint
ContentViewCoreImpl::GetBackgroundColor(JNIEnv
* env
, jobject obj
) {
357 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
359 return SK_ColorWHITE
;
360 return rwhva
->GetCachedBackgroundColor();
363 void ContentViewCoreImpl::PauseVideo() {
364 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
365 web_contents_
->GetRenderViewHost());
367 rvhi
->media_web_contents_observer()->PauseVideo();
370 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause
) {
371 web_contents_
->geolocation_dispatcher_host()->PauseOrResume(should_pause
);
374 // All positions and sizes are in CSS pixels.
375 // Note that viewport_width/height is a best effort based.
376 // ContentViewCore has the actual information about the physical viewport size.
377 void ContentViewCoreImpl::UpdateFrameInfo(
378 const gfx::Vector2dF
& scroll_offset
,
379 float page_scale_factor
,
380 const gfx::Vector2dF
& page_scale_factor_limits
,
381 const gfx::SizeF
& content_size
,
382 const gfx::SizeF
& viewport_size
,
383 const gfx::Vector2dF
& controls_offset
,
384 const gfx::Vector2dF
& content_offset
,
385 float overdraw_bottom_height
) {
386 JNIEnv
* env
= AttachCurrentThread();
387 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
391 window_android_
->set_content_offset(
392 gfx::ScaleVector2d(content_offset
, dpi_scale_
));
394 Java_ContentViewCore_updateFrameInfo(
399 page_scale_factor_limits
.x(),
400 page_scale_factor_limits
.y(),
401 content_size
.width(),
402 content_size
.height(),
403 viewport_size
.width(),
404 viewport_size
.height(),
407 overdraw_bottom_height
);
410 void ContentViewCoreImpl::SetTitle(const base::string16
& title
) {
411 JNIEnv
* env
= AttachCurrentThread();
412 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
415 ScopedJavaLocalRef
<jstring
> jtitle
=
416 ConvertUTF8ToJavaString(env
, base::UTF16ToUTF8(title
));
417 Java_ContentViewCore_setTitle(env
, obj
.obj(), jtitle
.obj());
420 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color
) {
421 root_layer_
->SetBackgroundColor(color
);
423 JNIEnv
* env
= AttachCurrentThread();
424 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
427 Java_ContentViewCore_onBackgroundColorChanged(env
, obj
.obj(), color
);
430 void ContentViewCoreImpl::ShowSelectPopupMenu(const gfx::Rect
& bounds
,
431 const std::vector
<MenuItem
>& items
, int selected_item
, bool multiple
) {
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
, j_obj
.obj(),
480 selected_array
.obj());
483 void ContentViewCoreImpl::HideSelectPopupMenu() {
484 JNIEnv
* env
= AttachCurrentThread();
485 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
486 if (!j_obj
.is_null())
487 Java_ContentViewCore_hideSelectPopup(env
, j_obj
.obj());
490 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent
& event
,
491 InputEventAckState ack_result
) {
492 JNIEnv
* env
= AttachCurrentThread();
493 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
497 switch (event
.type
) {
498 case WebInputEvent::GestureFlingStart
:
499 if (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
) {
500 // The view expects the fling velocity in pixels/s.
501 Java_ContentViewCore_onFlingStartEventConsumed(env
, j_obj
.obj(),
502 event
.data
.flingStart
.velocityX
* dpi_scale(),
503 event
.data
.flingStart
.velocityY
* dpi_scale());
505 // If a scroll ends with a fling, a SCROLL_END event is never sent.
506 // However, if that fling went unconsumed, we still need to let the
507 // listeners know that scrolling has ended.
508 Java_ContentViewCore_onScrollEndEventAck(env
, j_obj
.obj());
511 if (ack_result
== INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
) {
512 // The view expects the fling velocity in pixels/s.
513 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env
, j_obj
.obj(),
514 event
.data
.flingStart
.velocityX
* dpi_scale(),
515 event
.data
.flingStart
.velocityY
* dpi_scale());
518 case WebInputEvent::GestureFlingCancel
:
519 Java_ContentViewCore_onFlingCancelEventAck(env
, j_obj
.obj());
521 case WebInputEvent::GestureScrollBegin
:
522 Java_ContentViewCore_onScrollBeginEventAck(env
, j_obj
.obj());
524 case WebInputEvent::GestureScrollUpdate
:
525 if (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
)
526 Java_ContentViewCore_onScrollUpdateGestureConsumed(env
, j_obj
.obj());
528 case WebInputEvent::GestureScrollEnd
:
529 Java_ContentViewCore_onScrollEndEventAck(env
, j_obj
.obj());
531 case WebInputEvent::GesturePinchBegin
:
532 Java_ContentViewCore_onPinchBeginEventAck(env
, j_obj
.obj());
534 case WebInputEvent::GesturePinchEnd
:
535 Java_ContentViewCore_onPinchEndEventAck(env
, j_obj
.obj());
537 case WebInputEvent::GestureTap
:
538 Java_ContentViewCore_onSingleTapEventAck(
541 ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
,
542 event
.x
* dpi_scale(),
543 event
.y
* dpi_scale());
550 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent
& event
) {
551 if (event
.type
!= WebInputEvent::GestureTap
&&
552 event
.type
!= WebInputEvent::GestureDoubleTap
&&
553 event
.type
!= WebInputEvent::GestureLongTap
&&
554 event
.type
!= WebInputEvent::GestureLongPress
)
557 JNIEnv
* env
= AttachCurrentThread();
558 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
562 const blink::WebGestureEvent
& gesture
=
563 static_cast<const blink::WebGestureEvent
&>(event
);
564 int gesture_type
= ToGestureEventType(event
.type
);
565 return Java_ContentViewCore_filterTapOrPressEvent(env
,
568 gesture
.x
* dpi_scale(),
569 gesture
.y
* dpi_scale());
571 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
574 bool ContentViewCoreImpl::HasFocus() {
575 JNIEnv
* env
= AttachCurrentThread();
576 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
579 return Java_ContentViewCore_hasFocus(env
, obj
.obj());
582 void ContentViewCoreImpl::OnSelectionChanged(const std::string
& text
) {
583 JNIEnv
* env
= AttachCurrentThread();
584 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
587 ScopedJavaLocalRef
<jstring
> jtext
= ConvertUTF8ToJavaString(env
, text
);
588 Java_ContentViewCore_onSelectionChanged(env
, obj
.obj(), jtext
.obj());
591 void ContentViewCoreImpl::OnSelectionEvent(SelectionEventType event
,
592 const gfx::PointF
& position
) {
593 JNIEnv
* env
= AttachCurrentThread();
594 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
597 Java_ContentViewCore_onSelectionEvent(
598 env
, j_obj
.obj(), event
, position
.x(), position
.y());
601 scoped_ptr
<TouchHandleDrawable
>
602 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
603 JNIEnv
* env
= AttachCurrentThread();
604 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
607 return scoped_ptr
<TouchHandleDrawable
>();
609 return scoped_ptr
<TouchHandleDrawable
>(new PopupTouchHandleDrawable(
610 Java_ContentViewCore_createPopupTouchHandleDrawable(env
, obj
.obj()),
614 void ContentViewCoreImpl::ShowPastePopup(int x_dip
, int y_dip
) {
615 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
619 view
->OnShowingPastePopup(gfx::PointF(x_dip
, y_dip
));
621 JNIEnv
* env
= AttachCurrentThread();
622 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
625 Java_ContentViewCore_showPastePopup(env
, obj
.obj(),
626 static_cast<jint
>(x_dip
),
627 static_cast<jint
>(y_dip
));
630 void ContentViewCoreImpl::GetScaledContentBitmap(
632 SkColorType color_type
,
633 gfx::Rect src_subrect
,
634 const base::Callback
<void(bool, const SkBitmap
&)>& result_callback
) {
635 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
637 result_callback
.Run(false, SkBitmap());
641 view
->GetScaledContentBitmap(scale
, color_type
, src_subrect
,
645 void ContentViewCoreImpl::StartContentIntent(const GURL
& content_url
) {
646 JNIEnv
* env
= AttachCurrentThread();
647 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
650 ScopedJavaLocalRef
<jstring
> jcontent_url
=
651 ConvertUTF8ToJavaString(env
, content_url
.spec());
652 Java_ContentViewCore_startContentIntent(env
,
657 void ContentViewCoreImpl::ShowDisambiguationPopup(
658 const gfx::Rect
& target_rect
,
659 const SkBitmap
& zoomed_bitmap
) {
660 JNIEnv
* env
= AttachCurrentThread();
662 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
666 ScopedJavaLocalRef
<jobject
> rect_object(CreateJavaRect(env
, target_rect
));
668 ScopedJavaLocalRef
<jobject
> java_bitmap
=
669 gfx::ConvertToJavaBitmap(&zoomed_bitmap
);
670 DCHECK(!java_bitmap
.is_null());
672 Java_ContentViewCore_showDisambiguationPopup(env
,
678 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
679 JNIEnv
* env
= AttachCurrentThread();
681 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
683 return ScopedJavaLocalRef
<jobject
>();
684 return Java_ContentViewCore_createTouchEventSynthesizer(env
, obj
.obj());
687 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetContentVideoViewClient() {
688 JNIEnv
* env
= AttachCurrentThread();
690 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
692 return ScopedJavaLocalRef
<jobject
>();
694 return Java_ContentViewCore_getContentVideoViewClient(env
, obj
.obj());
697 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetContext() {
698 JNIEnv
* env
= AttachCurrentThread();
700 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
702 return ScopedJavaLocalRef
<jobject
>();
704 return Java_ContentViewCore_getContext(env
, obj
.obj());
707 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL
& url
) {
708 JNIEnv
* env
= AttachCurrentThread();
710 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
713 ScopedJavaLocalRef
<jstring
> j_url
= ConvertUTF8ToJavaString(env
, url
.spec());
714 return Java_ContentViewCore_shouldBlockMediaRequest(env
, obj
.obj(),
718 void ContentViewCoreImpl::DidStopFlinging() {
719 JNIEnv
* env
= AttachCurrentThread();
721 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
723 Java_ContentViewCore_onNativeFlingStopped(env
, obj
.obj());
726 gfx::Size
ContentViewCoreImpl::GetViewSize() const {
727 gfx::Size size
= GetViewportSizeDip();
728 gfx::Size offset
= GetViewportSizeOffsetDip();
729 size
.Enlarge(-offset
.width(), -offset
.height());
733 gfx::Size
ContentViewCoreImpl::GetPhysicalBackingSize() const {
734 JNIEnv
* env
= AttachCurrentThread();
735 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
739 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, j_obj
.obj()),
740 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, j_obj
.obj()));
743 gfx::Size
ContentViewCoreImpl::GetViewportSizePix() const {
744 JNIEnv
* env
= AttachCurrentThread();
745 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
749 Java_ContentViewCore_getViewportWidthPix(env
, j_obj
.obj()),
750 Java_ContentViewCore_getViewportHeightPix(env
, j_obj
.obj()));
753 gfx::Size
ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
754 JNIEnv
* env
= AttachCurrentThread();
755 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
759 Java_ContentViewCore_getViewportSizeOffsetWidthPix(env
, j_obj
.obj()),
760 Java_ContentViewCore_getViewportSizeOffsetHeightPix(env
, j_obj
.obj()));
763 gfx::Size
ContentViewCoreImpl::GetViewportSizeDip() const {
764 return gfx::ToCeiledSize(
765 gfx::ScaleSize(GetViewportSizePix(), 1.0f
/ dpi_scale()));
768 gfx::Size
ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
769 return gfx::ToCeiledSize(
770 gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f
/ dpi_scale()));
773 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
774 JNIEnv
* env
= AttachCurrentThread();
775 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
778 return Java_ContentViewCore_getOverdrawBottomHeightPix(env
, j_obj
.obj())
782 void ContentViewCoreImpl::AttachLayer(scoped_refptr
<cc::Layer
> layer
) {
783 root_layer_
->InsertChild(layer
, 0);
784 root_layer_
->SetIsDrawable(false);
787 void ContentViewCoreImpl::RemoveLayer(scoped_refptr
<cc::Layer
> layer
) {
788 layer
->RemoveFromParent();
790 if (!root_layer_
->children().size())
791 root_layer_
->SetIsDrawable(true);
794 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF
& start
,
795 const gfx::PointF
& end
) {
799 gfx::Point start_point
= gfx::Point(start
.x(), start
.y());
800 gfx::Point end_point
= gfx::Point(end
.x(), end
.y());
801 if (start_point
== end_point
)
804 web_contents_
->SelectRange(start_point
, end_point
);
807 void ContentViewCoreImpl::LoadUrl(
808 NavigationController::LoadURLParams
& params
) {
809 GetWebContents()->GetController().LoadURLWithParams(params
);
812 ui::ViewAndroid
* ContentViewCoreImpl::GetViewAndroid() const {
813 return view_android_
;
816 ui::WindowAndroid
* ContentViewCoreImpl::GetWindowAndroid() const {
817 return window_android_
;
820 scoped_refptr
<cc::Layer
> ContentViewCoreImpl::GetLayer() const {
821 return root_layer_
.get();
824 // ----------------------------------------------------------------------------
825 // Methods called from Java via JNI
826 // ----------------------------------------------------------------------------
828 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv
* env
, jobject obj
,
830 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
831 web_contents_
->GetRenderViewHost());
833 if (indices
== NULL
) {
834 rvhi
->DidCancelPopupMenu();
838 int selected_count
= env
->GetArrayLength(indices
);
839 std::vector
<int> selected_indices
;
840 jint
* indices_ptr
= env
->GetIntArrayElements(indices
, NULL
);
841 for (int i
= 0; i
< selected_count
; ++i
)
842 selected_indices
.push_back(indices_ptr
[i
]);
843 env
->ReleaseIntArrayElements(indices
, indices_ptr
, JNI_ABORT
);
844 rvhi
->DidSelectPopupMenuItems(selected_indices
);
847 void ContentViewCoreImpl::LoadUrl(
848 JNIEnv
* env
, jobject obj
,
851 jint transition_type
,
852 jstring j_referrer_url
,
853 jint referrer_policy
,
854 jint ua_override_option
,
855 jstring extra_headers
,
856 jbyteArray post_data
,
857 jstring base_url_for_data_url
,
858 jstring virtual_url_for_data_url
,
859 jboolean can_load_local_resources
,
860 jboolean is_renderer_initiated
) {
862 NavigationController::LoadURLParams
params(
863 GURL(ConvertJavaStringToUTF8(env
, url
)));
865 params
.load_type
= static_cast<NavigationController::LoadURLType
>(
867 params
.transition_type
= PageTransitionFromInt(transition_type
);
868 params
.override_user_agent
=
869 static_cast<NavigationController::UserAgentOverrideOption
>(
873 params
.extra_headers
= ConvertJavaStringToUTF8(env
, extra_headers
);
876 std::vector
<uint8
> http_body_vector
;
877 base::android::JavaByteArrayToByteVector(env
, post_data
, &http_body_vector
);
878 params
.browser_initiated_post_data
=
879 base::RefCountedBytes::TakeVector(&http_body_vector
);
882 if (base_url_for_data_url
) {
883 params
.base_url_for_data_url
=
884 GURL(ConvertJavaStringToUTF8(env
, base_url_for_data_url
));
887 if (virtual_url_for_data_url
) {
888 params
.virtual_url_for_data_url
=
889 GURL(ConvertJavaStringToUTF8(env
, virtual_url_for_data_url
));
892 params
.can_load_local_resources
= can_load_local_resources
;
893 if (j_referrer_url
) {
894 params
.referrer
= content::Referrer(
895 GURL(ConvertJavaStringToUTF8(env
, j_referrer_url
)),
896 static_cast<blink::WebReferrerPolicy
>(referrer_policy
));
899 params
.is_renderer_initiated
= is_renderer_initiated
;
904 ScopedJavaLocalRef
<jstring
> ContentViewCoreImpl::GetURL(
905 JNIEnv
* env
, jobject
) const {
906 return ConvertUTF8ToJavaString(env
, GetWebContents()->GetURL().spec());
909 jboolean
ContentViewCoreImpl::IsIncognito(JNIEnv
* env
, jobject obj
) {
910 return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
913 WebContents
* ContentViewCoreImpl::GetWebContents() const {
914 return web_contents_
;
917 void ContentViewCoreImpl::SetFocus(JNIEnv
* env
, jobject obj
, jboolean focused
) {
918 SetFocusInternal(focused
);
921 void ContentViewCoreImpl::SetFocusInternal(bool focused
) {
922 if (!GetRenderWidgetHostViewAndroid())
926 GetRenderWidgetHostViewAndroid()->Focus();
928 GetRenderWidgetHostViewAndroid()->Blur();
931 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv
* env
,
934 if (device_orientation_
!= orientation
) {
935 device_orientation_
= orientation
;
936 SendOrientationChangeEventInternal();
940 jboolean
ContentViewCoreImpl::OnTouchEvent(JNIEnv
* env
,
942 jobject motion_event
,
954 jfloat touch_major_0
,
955 jfloat touch_major_1
,
958 jint android_tool_type_0
,
959 jint android_tool_type_1
,
960 jint android_button_state
,
961 jboolean is_touch_handle_event
) {
962 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
963 // Avoid synthesizing a touch event if it cannot be forwarded.
967 MotionEventAndroid
event(1.f
/ dpi_scale(),
987 android_button_state
);
989 return is_touch_handle_event
? rwhv
->OnTouchHandleEvent(event
)
990 : rwhv
->OnTouchEvent(event
);
993 float ContentViewCoreImpl::GetDpiScale() const {
997 jboolean
ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv
* env
,
1002 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1006 blink::WebMouseEvent event
= WebMouseEventBuilder::Build(
1007 WebInputEvent::MouseMove
,
1008 blink::WebMouseEvent::ButtonNone
,
1009 time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale(), 0, 1);
1011 rwhv
->SendMouseEvent(event
);
1015 jboolean
ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv
* env
,
1020 jfloat vertical_axis
) {
1021 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1025 WebMouseWheelEventBuilder::Direction direction
;
1026 if (vertical_axis
> 0) {
1027 direction
= WebMouseWheelEventBuilder::DIRECTION_UP
;
1028 } else if (vertical_axis
< 0) {
1029 direction
= WebMouseWheelEventBuilder::DIRECTION_DOWN
;
1033 blink::WebMouseWheelEvent event
= WebMouseWheelEventBuilder::Build(
1034 direction
, time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale());
1036 rwhv
->SendMouseWheelEvent(event
);
1040 WebGestureEvent
ContentViewCoreImpl::MakeGestureEvent(
1041 WebInputEvent::Type type
, int64 time_ms
, float x
, float y
) const {
1042 return WebGestureEventBuilder::Build(
1043 type
, time_ms
/ 1000.0, x
/ dpi_scale(), y
/ dpi_scale());
1046 void ContentViewCoreImpl::SendGestureEvent(
1047 const blink::WebGestureEvent
& event
) {
1048 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1050 rwhv
->SendGestureEvent(event
);
1053 void ContentViewCoreImpl::ScrollBegin(JNIEnv
* env
,
1060 WebGestureEvent event
= MakeGestureEvent(
1061 WebInputEvent::GestureScrollBegin
, time_ms
, x
, y
);
1062 event
.data
.scrollBegin
.deltaXHint
= hintx
/ dpi_scale();
1063 event
.data
.scrollBegin
.deltaYHint
= hinty
/ dpi_scale();
1065 SendGestureEvent(event
);
1068 void ContentViewCoreImpl::ScrollEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1069 WebGestureEvent event
= MakeGestureEvent(
1070 WebInputEvent::GestureScrollEnd
, time_ms
, 0, 0);
1071 SendGestureEvent(event
);
1074 void ContentViewCoreImpl::ScrollBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1075 jfloat x
, jfloat y
, jfloat dx
, jfloat dy
) {
1076 WebGestureEvent event
= MakeGestureEvent(
1077 WebInputEvent::GestureScrollUpdate
, time_ms
, x
, y
);
1078 event
.data
.scrollUpdate
.deltaX
= -dx
/ dpi_scale();
1079 event
.data
.scrollUpdate
.deltaY
= -dy
/ dpi_scale();
1081 SendGestureEvent(event
);
1084 void ContentViewCoreImpl::FlingStart(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1085 jfloat x
, jfloat y
, jfloat vx
, jfloat vy
) {
1086 WebGestureEvent event
= MakeGestureEvent(
1087 WebInputEvent::GestureFlingStart
, time_ms
, x
, y
);
1088 event
.data
.flingStart
.velocityX
= vx
/ dpi_scale();
1089 event
.data
.flingStart
.velocityY
= vy
/ dpi_scale();
1091 SendGestureEvent(event
);
1094 void ContentViewCoreImpl::FlingCancel(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1095 WebGestureEvent event
= MakeGestureEvent(
1096 WebInputEvent::GestureFlingCancel
, time_ms
, 0, 0);
1097 SendGestureEvent(event
);
1100 void ContentViewCoreImpl::SingleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1101 jfloat x
, jfloat y
) {
1102 WebGestureEvent event
= MakeGestureEvent(
1103 WebInputEvent::GestureTap
, time_ms
, x
, y
);
1104 event
.data
.tap
.tapCount
= 1;
1106 SendGestureEvent(event
);
1109 void ContentViewCoreImpl::DoubleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1110 jfloat x
, jfloat y
) {
1111 WebGestureEvent event
= MakeGestureEvent(
1112 WebInputEvent::GestureDoubleTap
, time_ms
, x
, y
);
1113 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1114 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1115 event
.data
.tap
.tapCount
= 1;
1117 SendGestureEvent(event
);
1120 void ContentViewCoreImpl::LongPress(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1121 jfloat x
, jfloat y
) {
1122 WebGestureEvent event
= MakeGestureEvent(
1123 WebInputEvent::GestureLongPress
, time_ms
, x
, y
);
1125 SendGestureEvent(event
);
1128 void ContentViewCoreImpl::PinchBegin(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1129 jfloat x
, jfloat y
) {
1130 WebGestureEvent event
= MakeGestureEvent(
1131 WebInputEvent::GesturePinchBegin
, time_ms
, x
, y
);
1132 SendGestureEvent(event
);
1135 void ContentViewCoreImpl::PinchEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1136 WebGestureEvent event
= MakeGestureEvent(
1137 WebInputEvent::GesturePinchEnd
, time_ms
, 0, 0);
1138 SendGestureEvent(event
);
1141 void ContentViewCoreImpl::PinchBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1142 jfloat anchor_x
, jfloat anchor_y
,
1144 WebGestureEvent event
= MakeGestureEvent(
1145 WebInputEvent::GesturePinchUpdate
, time_ms
, anchor_x
, anchor_y
);
1146 event
.data
.pinchUpdate
.scale
= delta
;
1148 SendGestureEvent(event
);
1151 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv
* env
, jobject obj
,
1152 jfloat x1
, jfloat y1
,
1153 jfloat x2
, jfloat y2
) {
1154 SelectBetweenCoordinates(gfx::PointF(x1
/ dpi_scale(), y1
/ dpi_scale()),
1155 gfx::PointF(x2
/ dpi_scale(), y2
/ dpi_scale()));
1158 void ContentViewCoreImpl::MoveCaret(JNIEnv
* env
, jobject obj
,
1159 jfloat x
, jfloat y
) {
1160 if (GetRenderWidgetHostViewAndroid()) {
1161 GetRenderWidgetHostViewAndroid()->MoveCaret(
1162 gfx::Point(x
/ dpi_scale_
, y
/ dpi_scale_
));
1166 void ContentViewCoreImpl::HideTextHandles(JNIEnv
* env
, jobject obj
) {
1167 if (GetRenderWidgetHostViewAndroid())
1168 GetRenderWidgetHostViewAndroid()->HideTextHandles();
1171 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv
* env
, jobject obj
) {
1172 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1174 rwhv
->ResetGestureDetection();
1177 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv
* env
,
1180 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1182 rwhv
->SetDoubleTapSupportEnabled(enabled
);
1185 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv
* env
,
1188 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1190 rwhv
->SetMultiTouchZoomSupportEnabled(enabled
);
1193 void ContentViewCoreImpl::ClearHistory(JNIEnv
* env
, jobject obj
) {
1194 // TODO(creis): Do callers of this need to know if it fails?
1195 if (web_contents_
->GetController().CanPruneAllButLastCommitted())
1196 web_contents_
->GetController().PruneAllButLastCommitted();
1199 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1203 java_bridge_dispatcher_host_
->SetAllowObjectContentsInspection(allow
);
1206 void ContentViewCoreImpl::AddJavascriptInterface(
1211 jclass safe_annotation_clazz
) {
1212 ScopedJavaLocalRef
<jobject
> scoped_object(env
, object
);
1213 ScopedJavaLocalRef
<jclass
> scoped_clazz(env
, safe_annotation_clazz
);
1214 java_bridge_dispatcher_host_
->AddNamedObject(
1215 ConvertJavaStringToUTF8(env
, name
), scoped_object
, scoped_clazz
);
1218 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv
* env
,
1221 java_bridge_dispatcher_host_
->RemoveNamedObject(
1222 ConvertJavaStringToUTF8(env
, name
));
1225 void ContentViewCoreImpl::WasResized(JNIEnv
* env
, jobject obj
) {
1226 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1227 gfx::Size
physical_size(
1228 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, obj
),
1229 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, obj
));
1230 root_layer_
->SetBounds(physical_size
);
1233 RenderWidgetHostImpl
* host
= RenderWidgetHostImpl::From(
1234 view
->GetRenderWidgetHost());
1235 host
->SendScreenRects();
1242 static void AddNavigationEntryToHistory(JNIEnv
* env
, jobject obj
,
1244 NavigationEntry
* entry
,
1246 // Get the details of the current entry
1247 ScopedJavaLocalRef
<jstring
> j_url(
1248 ConvertUTF8ToJavaString(env
, entry
->GetURL().spec()));
1249 ScopedJavaLocalRef
<jstring
> j_virtual_url(
1250 ConvertUTF8ToJavaString(env
, entry
->GetVirtualURL().spec()));
1251 ScopedJavaLocalRef
<jstring
> j_original_url(
1252 ConvertUTF8ToJavaString(env
, entry
->GetOriginalRequestURL().spec()));
1253 ScopedJavaLocalRef
<jstring
> j_title(
1254 ConvertUTF16ToJavaString(env
, entry
->GetTitle()));
1255 ScopedJavaLocalRef
<jobject
> j_bitmap
;
1256 const FaviconStatus
& status
= entry
->GetFavicon();
1257 if (status
.valid
&& status
.image
.ToSkBitmap()->getSize() > 0)
1258 j_bitmap
= gfx::ConvertToJavaBitmap(status
.image
.ToSkBitmap());
1260 // Add the item to the list
1261 Java_ContentViewCore_addToNavigationHistory(
1262 env
, obj
, history
, index
, j_url
.obj(), j_virtual_url
.obj(),
1263 j_original_url
.obj(), j_title
.obj(), j_bitmap
.obj());
1268 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv
* env
,
1271 // Iterate through navigation entries to populate the list
1272 const NavigationController
& controller
= web_contents_
->GetController();
1273 int count
= controller
.GetEntryCount();
1274 for (int i
= 0; i
< count
; ++i
) {
1275 AddNavigationEntryToHistory(
1276 env
, obj
, history
, controller
.GetEntryAtIndex(i
), i
);
1279 return controller
.GetCurrentEntryIndex();
1282 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv
* env
,
1285 jboolean is_forward
,
1287 // Iterate through navigation entries to populate the list
1288 const NavigationController
& controller
= web_contents_
->GetController();
1289 int count
= controller
.GetEntryCount();
1291 int increment_value
= is_forward
? 1 : -1;
1292 for (int i
= controller
.GetCurrentEntryIndex() + increment_value
;
1293 i
>= 0 && i
< count
;
1294 i
+= increment_value
) {
1295 if (num_added
>= max_entries
)
1298 AddNavigationEntryToHistory(
1299 env
, obj
, history
, controller
.GetEntryAtIndex(i
), i
);
1304 ScopedJavaLocalRef
<jstring
>
1305 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv
* env
,
1307 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1309 return ScopedJavaLocalRef
<jstring
>(env
, NULL
);
1310 return ConvertUTF8ToJavaString(env
, entry
->GetOriginalRequestURL().spec());
1313 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv
* env
, jobject obj
) {
1314 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
1317 return rwhva
->GetNativeImeAdapter();
1321 void JavaScriptResultCallback(const ScopedJavaGlobalRef
<jobject
>& callback
,
1322 const base::Value
* result
) {
1323 JNIEnv
* env
= base::android::AttachCurrentThread();
1325 base::JSONWriter::Write(result
, &json
);
1326 ScopedJavaLocalRef
<jstring
> j_json
= ConvertUTF8ToJavaString(env
, json
);
1327 Java_ContentViewCore_onEvaluateJavaScriptResult(env
,
1333 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv
* env
,
1337 jboolean start_renderer
) {
1338 RenderViewHost
* rvh
= web_contents_
->GetRenderViewHost();
1341 if (start_renderer
&& !rvh
->IsRenderViewLive()) {
1342 if (!web_contents_
->CreateRenderViewForInitialEmptyDocument()) {
1343 LOG(ERROR
) << "Failed to create RenderView in EvaluateJavaScript";
1349 // No callback requested.
1350 web_contents_
->GetMainFrame()->ExecuteJavaScript(
1351 ConvertJavaStringToUTF16(env
, script
));
1355 // Secure the Java callback in a scoped object and give ownership of it to the
1357 ScopedJavaGlobalRef
<jobject
> j_callback
;
1358 j_callback
.Reset(env
, callback
);
1359 content::RenderFrameHost::JavaScriptResultCallback c_callback
=
1360 base::Bind(&JavaScriptResultCallback
, j_callback
);
1362 web_contents_
->GetMainFrame()->ExecuteJavaScript(
1363 ConvertJavaStringToUTF16(env
, script
),
1367 // TODO(sgurun) add support for posting a frame whose name is known (only
1368 // main frame is supported at this time, see crbug.com/389721)
1369 // TODO(sgurun) add support for passing message ports
1370 void ContentViewCoreImpl::PostMessageToFrame(JNIEnv
* env
, jobject obj
,
1371 jstring frame_name
, jstring message
, jstring source_origin
,
1372 jstring target_origin
) {
1374 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1377 ViewMsg_PostMessage_Params params
;
1378 params
.source_origin
= ConvertJavaStringToUTF16(env
, source_origin
);
1379 params
.target_origin
= ConvertJavaStringToUTF16(env
, target_origin
);
1380 params
.data
= ConvertJavaStringToUTF16(env
, message
);
1381 params
.is_data_raw_string
= true;
1382 params
.source_routing_id
= MSG_ROUTING_NONE
;
1383 host
->Send(new ViewMsg_PostMessageEvent(host
->GetRoutingID(), params
));
1387 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
1388 JNIEnv
* env
, jobject obj
) {
1389 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1390 return entry
&& entry
->GetIsOverridingUserAgent();
1393 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter
,
1394 int text_input_type
,
1395 const std::string
& text
,
1396 int selection_start
,
1398 int composition_start
,
1399 int composition_end
,
1400 bool show_ime_if_needed
,
1401 bool is_non_ime_change
) {
1402 JNIEnv
* env
= AttachCurrentThread();
1403 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1407 ScopedJavaLocalRef
<jstring
> jstring_text
= ConvertUTF8ToJavaString(env
, text
);
1408 Java_ContentViewCore_updateImeAdapter(env
, obj
.obj(),
1409 native_ime_adapter
, text_input_type
,
1411 selection_start
, selection_end
,
1412 composition_start
, composition_end
,
1413 show_ime_if_needed
, is_non_ime_change
);
1416 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv
* env
, jobject obj
) {
1417 SSLHostState
* state
= SSLHostState::GetFor(
1418 web_contents_
->GetController().GetBrowserContext());
1422 void ContentViewCoreImpl::SetUseDesktopUserAgent(
1426 jboolean reload_on_state_change
) {
1427 if (GetUseDesktopUserAgent(env
, obj
) == enabled
)
1430 // Make sure the navigation entry actually exists.
1431 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1435 // Set the flag in the NavigationEntry.
1436 entry
->SetIsOverridingUserAgent(enabled
);
1438 // Send the override to the renderer.
1439 if (reload_on_state_change
) {
1440 // Reloading the page will send the override down as part of the
1441 // navigation IPC message.
1442 NavigationControllerImpl
& controller
=
1443 static_cast<NavigationControllerImpl
&>(web_contents_
->GetController());
1444 controller
.ReloadOriginalRequestURL(false);
1448 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv
* env
, jobject obj
,
1450 SetAccessibilityEnabledInternal(enabled
);
1453 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1454 JNIEnv
* env
= AttachCurrentThread();
1455 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1458 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env
,
1462 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled
) {
1463 accessibility_enabled_
= enabled
;
1464 BrowserAccessibilityStateImpl
* accessibility_state
=
1465 BrowserAccessibilityStateImpl::GetInstance();
1467 // This enables accessibility globally unless it was explicitly disallowed
1468 // by a command-line flag.
1469 accessibility_state
->OnScreenReaderDetected();
1470 // If it was actually enabled globally, enable it for this RenderWidget now.
1471 if (accessibility_state
->IsAccessibleBrowser() && web_contents_
)
1472 web_contents_
->AddAccessibilityMode(AccessibilityModeComplete
);
1474 accessibility_state
->ResetAccessibilityMode();
1475 if (web_contents_
) {
1476 web_contents_
->SetAccessibilityMode(
1477 accessibility_state
->accessibility_mode());
1482 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1483 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1485 rwhv
->UpdateScreenInfo(GetViewAndroid());
1487 static_cast<WebContentsImpl
*>(web_contents())->
1488 screen_orientation_dispatcher_host()->OnOrientationChange();
1491 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv
* env
,
1498 static_cast<int>(x
/ dpi_scale()),
1499 static_cast<int>(y
/ dpi_scale()),
1500 static_cast<int>((width
> 0 && width
< dpi_scale()) ?
1501 1 : (int)(width
/ dpi_scale())),
1502 static_cast<int>((height
> 0 && height
< dpi_scale()) ?
1503 1 : (int)(height
/ dpi_scale())));
1504 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1505 GetWebContents()->GetRoutingID(), rect
));
1508 void ContentViewCoreImpl::ResumeResponseDeferredAtStart(JNIEnv
* env
,
1510 static_cast<WebContentsImpl
*>(GetWebContents())->
1511 ResumeResponseDeferredAtStart();
1514 void ContentViewCoreImpl::SetHasPendingNavigationTransitionForTesting(
1517 RenderFrameHost
* frame
= static_cast<WebContentsImpl
*>(GetWebContents())->
1519 BrowserThread::PostTask(
1523 &TransitionRequestManager::SetHasPendingTransitionRequest
,
1524 base::Unretained(TransitionRequestManager::GetInstance()),
1525 frame
->GetProcess()->GetID(),
1526 frame
->GetRoutingID(),
1530 jint
ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv
* env
, jobject obj
) {
1531 return GetRenderProcessIdFromRenderViewHost(
1532 web_contents_
->GetRenderViewHost());
1535 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv
* env
, jobject jobj
,
1537 if (GetRenderWidgetHostViewAndroid())
1538 GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque
);
1541 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1543 const base::Callback
<
1544 void(const base::string16
& content
, int start_offset
, int end_offset
)>&
1546 DCHECK(!callback
.is_null());
1547 RenderFrameHost
* focused_frame
= web_contents_
->GetFocusedFrame();
1550 if (GetRenderWidgetHostViewAndroid()) {
1551 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1553 focused_frame
->Send(new FrameMsg_TextSurroundingSelectionRequest(
1554 focused_frame
->GetRoutingID(), max_length
));
1558 void ContentViewCoreImpl::DidDeferAfterResponseStarted(
1559 const scoped_refptr
<net::HttpResponseHeaders
>& headers
,
1561 JNIEnv
* env
= AttachCurrentThread();
1562 ScopedJavaLocalRef
<jobject
> obj(java_ref_
.get(env
));
1566 std::vector
<GURL
> entering_stylesheets
;
1567 std::string transition_color
;
1569 TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
1570 headers
, entering_stylesheets
, url
);
1572 headers
->EnumerateHeader(
1573 NULL
, "X-Transition-Entering-Color", &transition_color
);
1576 ScopedJavaLocalRef
<jstring
> jstring_transition_color(ConvertUTF8ToJavaString(
1577 env
, transition_color
));
1579 Java_ContentViewCore_didDeferAfterResponseStarted(
1580 env
, obj
.obj(), jstring_transition_color
.obj());
1582 std::vector
<GURL
>::const_iterator iter
= entering_stylesheets
.begin();
1583 for (; iter
!= entering_stylesheets
.end(); ++iter
) {
1584 ScopedJavaLocalRef
<jstring
> jstring_url(ConvertUTF8ToJavaString(
1585 env
, iter
->spec()));
1586 Java_ContentViewCore_addEnteringStylesheetToTransition(
1587 env
, obj
.obj(), jstring_url
.obj());
1591 bool ContentViewCoreImpl::WillHandleDeferAfterResponseStarted() {
1592 JNIEnv
* env
= AttachCurrentThread();
1593 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1597 return Java_ContentViewCore_willHandleDeferAfterResponseStarted(env
,
1601 void ContentViewCoreImpl::DidStartNavigationTransitionForFrame(int64 frame_id
) {
1602 JNIEnv
* env
= AttachCurrentThread();
1603 ScopedJavaLocalRef
<jobject
> obj(java_ref_
.get(env
));
1606 Java_ContentViewCore_didStartNavigationTransitionForFrame(
1607 env
, obj
.obj(), frame_id
);
1610 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1611 const base::string16
& text
,
1612 const base::string16
& html
,
1613 const gfx::Rect
& clip_rect
) {
1614 JNIEnv
* env
= AttachCurrentThread();
1615 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1618 ScopedJavaLocalRef
<jstring
> jtext
= ConvertUTF16ToJavaString(env
, text
);
1619 ScopedJavaLocalRef
<jstring
> jhtml
= ConvertUTF16ToJavaString(env
, html
);
1620 ScopedJavaLocalRef
<jobject
> clip_rect_object(CreateJavaRect(env
, clip_rect
));
1621 Java_ContentViewCore_onSmartClipDataExtracted(
1622 env
, obj
.obj(), jtext
.obj(), jhtml
.obj(), clip_rect_object
.obj());
1625 void ContentViewCoreImpl::WebContentsDestroyed() {
1626 WebContentsViewAndroid
* wcva
= static_cast<WebContentsViewAndroid
*>(
1627 static_cast<WebContentsImpl
*>(web_contents())->GetView());
1629 wcva
->SetContentViewCore(NULL
);
1632 // This is called for each ContentView.
1633 jlong
Init(JNIEnv
* env
,
1635 jlong native_web_contents
,
1637 jlong window_android
,
1638 jobject retained_objects_set
) {
1639 ContentViewCoreImpl
* view
= new ContentViewCoreImpl(
1641 reinterpret_cast<WebContents
*>(native_web_contents
),
1642 reinterpret_cast<ui::ViewAndroid
*>(view_android
),
1643 reinterpret_cast<ui::WindowAndroid
*>(window_android
),
1644 retained_objects_set
);
1645 return reinterpret_cast<intptr_t>(view
);
1648 bool RegisterContentViewCore(JNIEnv
* env
) {
1649 return RegisterNativesImpl(env
);
1652 } // namespace content