1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/content_view_core_impl.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/command_line.h"
12 #include "base/json/json_writer.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/values.h"
17 #include "cc/layers/layer.h"
18 #include "cc/layers/solid_color_layer.h"
19 #include "cc/output/begin_frame_args.h"
20 #include "content/browser/android/gesture_event_type.h"
21 #include "content/browser/android/interstitial_page_delegate_android.h"
22 #include "content/browser/android/load_url_params.h"
23 #include "content/browser/frame_host/interstitial_page_impl.h"
24 #include "content/browser/frame_host/navigation_controller_impl.h"
25 #include "content/browser/frame_host/navigation_entry_impl.h"
26 #include "content/browser/geolocation/geolocation_dispatcher_host.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/java/java_bound_object.h"
33 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
34 #include "content/browser/renderer_host/render_view_host_impl.h"
35 #include "content/browser/renderer_host/render_widget_host_impl.h"
36 #include "content/browser/renderer_host/render_widget_host_view_android.h"
37 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
38 #include "content/browser/ssl/ssl_host_state.h"
39 #include "content/browser/web_contents/web_contents_view_android.h"
40 #include "content/common/frame_messages.h"
41 #include "content/common/input/web_input_event_traits.h"
42 #include "content/common/input_messages.h"
43 #include "content/common/view_messages.h"
44 #include "content/public/browser/browser_accessibility_state.h"
45 #include "content/public/browser/browser_context.h"
46 #include "content/public/browser/favicon_status.h"
47 #include "content/public/browser/render_frame_host.h"
48 #include "content/public/browser/web_contents.h"
49 #include "content/public/common/content_client.h"
50 #include "content/public/common/content_switches.h"
51 #include "content/public/common/menu_item.h"
52 #include "content/public/common/page_transition_types.h"
53 #include "content/public/common/user_agent.h"
54 #include "jni/ContentViewCore_jni.h"
55 #include "third_party/WebKit/public/web/WebBindings.h"
56 #include "third_party/WebKit/public/web/WebInputEvent.h"
57 #include "ui/base/android/view_android.h"
58 #include "ui/base/android/window_android.h"
59 #include "ui/gfx/android/java_bitmap.h"
60 #include "ui/gfx/screen.h"
61 #include "ui/gfx/size_conversions.h"
62 #include "ui/gfx/size_f.h"
64 using base::android::AttachCurrentThread;
65 using base::android::ConvertJavaStringToUTF16;
66 using base::android::ConvertJavaStringToUTF8;
67 using base::android::ConvertUTF16ToJavaString;
68 using base::android::ConvertUTF8ToJavaString;
69 using base::android::ScopedJavaGlobalRef;
70 using base::android::ScopedJavaLocalRef;
71 using blink::WebGestureEvent;
72 using blink::WebInputEvent;
74 // Describes the type and enabled state of a select popup item.
78 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
79 #include "content/browser/android/popup_item_type_list.h"
80 #undef DEFINE_POPUP_ITEM_TYPE
89 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
91 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
93 RenderProcessHost* render_process = host->GetProcess();
94 DCHECK(render_process);
95 if (render_process->HasConnection())
96 return render_process->GetHandle();
101 ScopedJavaLocalRef<jobject> CreateJavaRect(
103 const gfx::Rect& rect) {
104 return ScopedJavaLocalRef<jobject>(
105 Java_ContentViewCore_createRect(env,
106 static_cast<int>(rect.x()),
107 static_cast<int>(rect.y()),
108 static_cast<int>(rect.right()),
109 static_cast<int>(rect.bottom())));
112 int ToGestureEventType(WebInputEvent::Type type) {
114 case WebInputEvent::GestureScrollBegin:
116 case WebInputEvent::GestureScrollEnd:
118 case WebInputEvent::GestureScrollUpdate:
120 case WebInputEvent::GestureFlingStart:
122 case WebInputEvent::GestureFlingCancel:
124 case WebInputEvent::GestureShowPress:
126 case WebInputEvent::GestureTap:
127 return SINGLE_TAP_CONFIRMED;
128 case WebInputEvent::GestureTapUnconfirmed:
129 return SINGLE_TAP_UNCONFIRMED;
130 case WebInputEvent::GestureTapDown:
132 case WebInputEvent::GestureTapCancel:
134 case WebInputEvent::GestureDoubleTap:
136 case WebInputEvent::GestureLongPress:
138 case WebInputEvent::GestureLongTap:
140 case WebInputEvent::GesturePinchBegin:
142 case WebInputEvent::GesturePinchEnd:
144 case WebInputEvent::GesturePinchUpdate:
146 case WebInputEvent::GestureTwoFingerTap:
147 case WebInputEvent::GestureScrollUpdateWithoutPropagation:
149 NOTREACHED() << "Invalid source gesture type: "
150 << WebInputEventTraits::GetName(type);
155 float GetPrimaryDisplayDeviceScaleFactor() {
156 const gfx::Display& display =
157 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
158 return display.device_scale_factor();
163 // Enables a callback when the underlying WebContents is destroyed, to enable
164 // nulling the back-pointer.
165 class ContentViewCoreImpl::ContentViewUserData
166 : public base::SupportsUserData::Data {
168 explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
169 : content_view_core_(content_view_core) {
172 virtual ~ContentViewUserData() {
173 // TODO(joth): When chrome has finished removing the TabContents class (see
174 // crbug.com/107201) consider inverting relationship, so ContentViewCore
175 // would own WebContents. That effectively implies making the WebContents
176 // destructor private on Android.
177 delete content_view_core_;
180 ContentViewCoreImpl* get() const { return content_view_core_; }
183 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
184 ContentViewCoreImpl* content_view_core_;
186 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
190 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
191 content::WebContents* web_contents) {
192 ContentViewCoreImpl::ContentViewUserData* data =
193 reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
194 web_contents->GetUserData(kContentViewUserDataKey));
195 return data ? data->get() : NULL;
199 ContentViewCore* ContentViewCore::FromWebContents(
200 content::WebContents* web_contents) {
201 return ContentViewCoreImpl::FromWebContents(web_contents);
205 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
207 return reinterpret_cast<ContentViewCore*>(
208 Java_ContentViewCore_getNativeContentViewCore(env, obj));
211 ContentViewCoreImpl::ContentViewCoreImpl(
214 WebContents* web_contents,
215 ui::ViewAndroid* view_android,
216 ui::WindowAndroid* window_android,
217 jobject java_bridge_retained_object_set)
218 : WebContentsObserver(web_contents),
220 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
221 root_layer_(cc::SolidColorLayer::Create()),
222 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
223 view_android_(view_android),
224 window_android_(window_android),
225 device_orientation_(0),
226 accessibility_enabled_(false) {
227 CHECK(web_contents) <<
228 "A ContentViewCoreImpl should be created with a valid WebContents.";
230 root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj));
231 gfx::Size physical_size(
232 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
233 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
234 root_layer_->SetBounds(physical_size);
235 root_layer_->SetIsDrawable(true);
237 // Currently, the only use case we have for overriding a user agent involves
238 // spoofing a desktop Linux user agent for "Request desktop site".
239 // Automatically set it for all WebContents so that it is available when a
240 // NavigationEntry requires the user agent to be overridden.
241 const char kLinuxInfoStr[] = "X11; Linux x86_64";
242 std::string product = content::GetContentClient()->GetProduct();
243 std::string spoofed_ua =
244 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
245 web_contents->SetUserAgentOverride(spoofed_ua);
247 java_bridge_dispatcher_host_manager_.reset(
248 new JavaBridgeDispatcherHostManager(web_contents,
249 java_bridge_retained_object_set));
254 ContentViewCoreImpl::~ContentViewCoreImpl() {
255 JNIEnv* env = base::android::AttachCurrentThread();
256 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
258 if (!j_obj.is_null()) {
259 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
260 env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
264 base::android::ScopedJavaLocalRef<jobject>
265 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
266 return web_contents_->GetJavaWebContents();
269 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
271 DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
275 void ContentViewCoreImpl::InitWebContents() {
276 DCHECK(web_contents_);
277 static_cast<WebContentsViewAndroid*>(
278 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
279 SetContentViewCore(this);
280 DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
281 web_contents_->SetUserData(kContentViewUserDataKey,
282 new ContentViewUserData(this));
285 void ContentViewCoreImpl::RenderViewReady() {
286 JNIEnv* env = AttachCurrentThread();
287 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
289 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
291 if (device_orientation_ != 0)
292 SendOrientationChangeEventInternal();
295 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host,
296 RenderViewHost* new_host) {
299 old_pid = GetRenderProcessIdFromRenderViewHost(old_host);
301 RenderWidgetHostViewAndroid* view =
302 static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView());
304 view->SetContentViewCore(NULL);
306 view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView());
308 view->SetContentViewCore(this);
310 int new_pid = GetRenderProcessIdFromRenderViewHost(
311 web_contents_->GetRenderViewHost());
312 if (new_pid != old_pid) {
313 // Notify the Java side that the renderer process changed.
314 JNIEnv* env = AttachCurrentThread();
315 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
316 if (!obj.is_null()) {
317 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
321 SetFocusInternal(HasFocus());
322 SetAccessibilityEnabledInternal(accessibility_enabled_);
325 RenderWidgetHostViewAndroid*
326 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
327 RenderWidgetHostView* rwhv = NULL;
329 rwhv = web_contents_->GetRenderWidgetHostView();
330 if (web_contents_->ShowingInterstitialPage()) {
331 rwhv = static_cast<InterstitialPageImpl*>(
332 web_contents_->GetInterstitialPage())->
333 GetRenderViewHost()->GetView();
336 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
339 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
340 JNIEnv* env = AttachCurrentThread();
341 return java_ref_.get(env);
344 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
345 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
347 return SK_ColorWHITE;
348 return rwhva->GetCachedBackgroundColor();
351 void ContentViewCoreImpl::OnHide(JNIEnv* env, jobject obj) {
355 void ContentViewCoreImpl::OnShow(JNIEnv* env, jobject obj) {
359 void ContentViewCoreImpl::Show() {
360 GetWebContents()->WasShown();
363 void ContentViewCoreImpl::Hide() {
364 GetWebContents()->WasHidden();
368 void ContentViewCoreImpl::PauseVideo() {
369 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
370 web_contents_->GetRenderViewHost());
372 rvhi->media_web_contents_observer()->PauseVideo();
375 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
376 web_contents_->geolocation_dispatcher_host()->PauseOrResume(should_pause);
379 // All positions and sizes are in CSS pixels.
380 // Note that viewport_width/height is a best effort based.
381 // ContentViewCore has the actual information about the physical viewport size.
382 void ContentViewCoreImpl::UpdateFrameInfo(
383 const gfx::Vector2dF& scroll_offset,
384 float page_scale_factor,
385 const gfx::Vector2dF& page_scale_factor_limits,
386 const gfx::SizeF& content_size,
387 const gfx::SizeF& viewport_size,
388 const gfx::Vector2dF& controls_offset,
389 const gfx::Vector2dF& content_offset,
390 float overdraw_bottom_height) {
391 JNIEnv* env = AttachCurrentThread();
392 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
396 if (window_android_) {
397 window_android_->set_content_offset(
398 gfx::ScaleVector2d(content_offset, dpi_scale_));
401 Java_ContentViewCore_updateFrameInfo(
406 page_scale_factor_limits.x(),
407 page_scale_factor_limits.y(),
408 content_size.width(),
409 content_size.height(),
410 viewport_size.width(),
411 viewport_size.height(),
414 overdraw_bottom_height);
417 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
418 JNIEnv* env = AttachCurrentThread();
419 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
422 ScopedJavaLocalRef<jstring> jtitle =
423 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
424 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
427 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
428 root_layer_->SetBackgroundColor(color);
430 JNIEnv* env = AttachCurrentThread();
431 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
434 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
437 void ContentViewCoreImpl::ShowSelectPopupMenu(const gfx::Rect& bounds,
438 const std::vector<MenuItem>& items, int selected_item, bool multiple) {
439 JNIEnv* env = AttachCurrentThread();
440 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
444 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
446 // For multi-select list popups we find the list of previous selections by
447 // iterating through the items. But for single selection popups we take the
448 // given |selected_item| as is.
449 ScopedJavaLocalRef<jintArray> selected_array;
451 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
452 size_t selected_count = 0;
453 for (size_t i = 0; i < items.size(); ++i) {
454 if (items[i].checked)
455 native_selected_array[selected_count++] = i;
458 selected_array = ScopedJavaLocalRef<jintArray>(
459 env, env->NewIntArray(selected_count));
460 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
461 native_selected_array.get());
463 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
464 jint value = selected_item;
465 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
468 ScopedJavaLocalRef<jintArray> enabled_array(env,
469 env->NewIntArray(items.size()));
470 std::vector<base::string16> labels;
471 labels.reserve(items.size());
472 for (size_t i = 0; i < items.size(); ++i) {
473 labels.push_back(items[i].label);
475 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
476 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
477 POPUP_ITEM_TYPE_DISABLED));
478 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
480 ScopedJavaLocalRef<jobjectArray> items_array(
481 base::android::ToJavaArrayOfStrings(env, labels));
482 Java_ContentViewCore_showSelectPopup(env, j_obj.obj(),
487 selected_array.obj());
490 void ContentViewCoreImpl::HideSelectPopupMenu() {
491 JNIEnv* env = AttachCurrentThread();
492 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
493 if (!j_obj.is_null())
494 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
497 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
498 InputEventAckState ack_result) {
499 JNIEnv* env = AttachCurrentThread();
500 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
504 switch (event.type) {
505 case WebInputEvent::GestureFlingStart:
506 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
507 // The view expects the fling velocity in pixels/s.
508 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
509 event.data.flingStart.velocityX * dpi_scale(),
510 event.data.flingStart.velocityY * dpi_scale());
512 // If a scroll ends with a fling, a SCROLL_END event is never sent.
513 // However, if that fling went unconsumed, we still need to let the
514 // listeners know that scrolling has ended.
515 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
518 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
519 // The view expects the fling velocity in pixels/s.
520 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
521 event.data.flingStart.velocityX * dpi_scale(),
522 event.data.flingStart.velocityY * dpi_scale());
525 case WebInputEvent::GestureFlingCancel:
526 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
528 case WebInputEvent::GestureScrollBegin:
529 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
531 case WebInputEvent::GestureScrollUpdate:
532 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
533 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
535 case WebInputEvent::GestureScrollEnd:
536 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
538 case WebInputEvent::GesturePinchBegin:
539 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
541 case WebInputEvent::GesturePinchEnd:
542 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
544 case WebInputEvent::GestureTap:
545 Java_ContentViewCore_onSingleTapEventAck(
548 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
549 event.x * dpi_scale(),
550 event.y * dpi_scale());
552 case WebInputEvent::GestureDoubleTap:
553 Java_ContentViewCore_onDoubleTapEventAck(env, j_obj.obj());
560 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
561 if (event.type != WebInputEvent::GestureTap &&
562 event.type != WebInputEvent::GestureDoubleTap &&
563 event.type != WebInputEvent::GestureLongTap &&
564 event.type != WebInputEvent::GestureLongPress)
567 JNIEnv* env = AttachCurrentThread();
568 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
572 const blink::WebGestureEvent& gesture =
573 static_cast<const blink::WebGestureEvent&>(event);
574 int gesture_type = ToGestureEventType(event.type);
575 return Java_ContentViewCore_filterTapOrPressEvent(env,
578 gesture.x * dpi_scale(),
579 gesture.y * dpi_scale());
581 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
584 bool ContentViewCoreImpl::HasFocus() {
585 JNIEnv* env = AttachCurrentThread();
586 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
589 return Java_ContentViewCore_hasFocus(env, obj.obj());
592 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
593 JNIEnv* env = AttachCurrentThread();
594 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
597 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
598 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
601 void ContentViewCoreImpl::OnSelectionBoundsChanged(
602 const ViewHostMsg_SelectionBounds_Params& params) {
603 JNIEnv* env = AttachCurrentThread();
604 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
607 ScopedJavaLocalRef<jobject> anchor_rect_dip(
608 CreateJavaRect(env, params.anchor_rect));
609 ScopedJavaLocalRef<jobject> focus_rect_dip(
610 CreateJavaRect(env, params.focus_rect));
611 Java_ContentViewCore_onSelectionBoundsChanged(env, obj.obj(),
612 anchor_rect_dip.obj(),
614 focus_rect_dip.obj(),
616 params.is_anchor_first);
619 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
620 JNIEnv* env = AttachCurrentThread();
621 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
624 Java_ContentViewCore_showPastePopup(env, obj.obj(),
625 static_cast<jint>(x_dip),
626 static_cast<jint>(y_dip));
629 void ContentViewCoreImpl::GetScaledContentBitmap(
631 jobject jbitmap_config,
632 gfx::Rect src_subrect,
633 const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
634 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
636 result_callback.Run(false, SkBitmap());
639 SkBitmap::Config skbitmap_format = gfx::ConvertToSkiaConfig(jbitmap_config);
640 view->GetScaledContentBitmap(scale, skbitmap_format, src_subrect,
644 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
645 JNIEnv* env = AttachCurrentThread();
646 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
649 ScopedJavaLocalRef<jstring> jcontent_url =
650 ConvertUTF8ToJavaString(env, content_url.spec());
651 Java_ContentViewCore_startContentIntent(env,
656 void ContentViewCoreImpl::ShowDisambiguationPopup(
657 const gfx::Rect& target_rect,
658 const SkBitmap& zoomed_bitmap) {
659 JNIEnv* env = AttachCurrentThread();
661 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
665 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, target_rect));
667 ScopedJavaLocalRef<jobject> java_bitmap =
668 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
669 DCHECK(!java_bitmap.is_null());
671 Java_ContentViewCore_showDisambiguationPopup(env,
677 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
678 JNIEnv* env = AttachCurrentThread();
680 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
682 return ScopedJavaLocalRef<jobject>();
683 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
686 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
687 JNIEnv* env = AttachCurrentThread();
689 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
691 return ScopedJavaLocalRef<jobject>();
693 return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
696 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
697 JNIEnv* env = AttachCurrentThread();
699 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
701 return ScopedJavaLocalRef<jobject>();
703 return Java_ContentViewCore_getContext(env, obj.obj());
706 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
707 JNIEnv* env = AttachCurrentThread();
709 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
712 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
713 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
717 void ContentViewCoreImpl::DidStopFlinging() {
718 JNIEnv* env = AttachCurrentThread();
720 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
722 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
725 gfx::Size ContentViewCoreImpl::GetViewSize() const {
726 gfx::Size size = GetViewportSizeDip();
727 gfx::Size offset = GetViewportSizeOffsetDip();
728 size.Enlarge(-offset.width(), -offset.height());
732 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
733 JNIEnv* env = AttachCurrentThread();
734 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
738 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
739 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
742 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
743 JNIEnv* env = AttachCurrentThread();
744 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
748 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
749 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
752 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
753 JNIEnv* env = AttachCurrentThread();
754 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
758 Java_ContentViewCore_getViewportSizeOffsetWidthPix(env, j_obj.obj()),
759 Java_ContentViewCore_getViewportSizeOffsetHeightPix(env, j_obj.obj()));
762 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
763 return gfx::ToCeiledSize(
764 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
767 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
768 return gfx::ToCeiledSize(
769 gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f / dpi_scale()));
772 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
773 JNIEnv* env = AttachCurrentThread();
774 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
777 return Java_ContentViewCore_getOverdrawBottomHeightPix(env, j_obj.obj())
781 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
782 root_layer_->AddChild(layer);
783 root_layer_->SetIsDrawable(false);
786 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
787 layer->RemoveFromParent();
789 if (!root_layer_->children().size())
790 root_layer_->SetIsDrawable(true);
793 void ContentViewCoreImpl::LoadUrl(
794 NavigationController::LoadURLParams& params) {
795 GetWebContents()->GetController().LoadURLWithParams(params);
798 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
799 // view_android_ should never be null for Chrome.
800 DCHECK(view_android_);
801 return view_android_;
804 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
805 // This should never be NULL for Chrome, but will be NULL for WebView.
806 DCHECK(window_android_);
807 return window_android_;
810 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
811 return root_layer_.get();
814 // ----------------------------------------------------------------------------
815 // Methods called from Java via JNI
816 // ----------------------------------------------------------------------------
818 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env, jobject obj,
820 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
821 web_contents_->GetRenderViewHost());
823 if (indices == NULL) {
824 rvhi->DidCancelPopupMenu();
828 int selected_count = env->GetArrayLength(indices);
829 std::vector<int> selected_indices;
830 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
831 for (int i = 0; i < selected_count; ++i)
832 selected_indices.push_back(indices_ptr[i]);
833 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
834 rvhi->DidSelectPopupMenuItems(selected_indices);
837 void ContentViewCoreImpl::LoadUrl(
838 JNIEnv* env, jobject obj,
841 jint transition_type,
842 jstring j_referrer_url,
843 jint referrer_policy,
844 jint ua_override_option,
845 jstring extra_headers,
846 jbyteArray post_data,
847 jstring base_url_for_data_url,
848 jstring virtual_url_for_data_url,
849 jboolean can_load_local_resources,
850 jboolean is_renderer_initiated) {
852 NavigationController::LoadURLParams params(
853 GURL(ConvertJavaStringToUTF8(env, url)));
855 params.load_type = static_cast<NavigationController::LoadURLType>(
857 params.transition_type = PageTransitionFromInt(transition_type);
858 params.override_user_agent =
859 static_cast<NavigationController::UserAgentOverrideOption>(
863 params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
866 std::vector<uint8> http_body_vector;
867 base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
868 params.browser_initiated_post_data =
869 base::RefCountedBytes::TakeVector(&http_body_vector);
872 if (base_url_for_data_url) {
873 params.base_url_for_data_url =
874 GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
877 if (virtual_url_for_data_url) {
878 params.virtual_url_for_data_url =
879 GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
882 params.can_load_local_resources = can_load_local_resources;
883 if (j_referrer_url) {
884 params.referrer = content::Referrer(
885 GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
886 static_cast<blink::WebReferrerPolicy>(referrer_policy));
889 params.is_renderer_initiated = is_renderer_initiated;
894 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetURL(
895 JNIEnv* env, jobject) const {
896 return ConvertUTF8ToJavaString(env, GetWebContents()->GetURL().spec());
899 jboolean ContentViewCoreImpl::IsIncognito(JNIEnv* env, jobject obj) {
900 return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
903 WebContents* ContentViewCoreImpl::GetWebContents() const {
904 return web_contents_;
907 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
908 SetFocusInternal(focused);
911 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
912 if (!GetRenderWidgetHostViewAndroid())
916 GetRenderWidgetHostViewAndroid()->Focus();
918 GetRenderWidgetHostViewAndroid()->Blur();
921 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
924 if (device_orientation_ != orientation) {
925 device_orientation_ = orientation;
926 SendOrientationChangeEventInternal();
930 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
932 jobject motion_event,
944 jfloat touch_major_0,
945 jfloat touch_major_1,
948 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
949 // Avoid synthesizing a touch event if it cannot be forwarded.
953 MotionEventAndroid event(1.f / dpi_scale(),
972 return rwhv->OnTouchEvent(event);
975 float ContentViewCoreImpl::GetDpiScale() const {
979 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
984 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
988 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
989 WebInputEvent::MouseMove,
990 blink::WebMouseEvent::ButtonNone,
991 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
993 rwhv->SendMouseEvent(event);
997 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
1002 jfloat vertical_axis) {
1003 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1007 WebMouseWheelEventBuilder::Direction direction;
1008 if (vertical_axis > 0) {
1009 direction = WebMouseWheelEventBuilder::DIRECTION_UP;
1010 } else if (vertical_axis < 0) {
1011 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
1015 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
1016 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1018 rwhv->SendMouseWheelEvent(event);
1022 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
1023 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
1024 return WebGestureEventBuilder::Build(
1025 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1028 void ContentViewCoreImpl::SendGestureEvent(
1029 const blink::WebGestureEvent& event) {
1030 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1032 rwhv->SendGestureEvent(event);
1035 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
1042 WebGestureEvent event = MakeGestureEvent(
1043 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1044 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1045 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1047 SendGestureEvent(event);
1050 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1051 WebGestureEvent event = MakeGestureEvent(
1052 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1053 SendGestureEvent(event);
1056 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1057 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1058 WebGestureEvent event = MakeGestureEvent(
1059 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1060 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1061 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1063 SendGestureEvent(event);
1066 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1067 jfloat x, jfloat y, jfloat vx, jfloat vy) {
1068 WebGestureEvent event = MakeGestureEvent(
1069 WebInputEvent::GestureFlingStart, time_ms, x, y);
1070 event.data.flingStart.velocityX = vx / dpi_scale();
1071 event.data.flingStart.velocityY = vy / dpi_scale();
1073 SendGestureEvent(event);
1076 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1077 WebGestureEvent event = MakeGestureEvent(
1078 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1079 SendGestureEvent(event);
1082 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1083 jfloat x, jfloat y) {
1084 WebGestureEvent event = MakeGestureEvent(
1085 WebInputEvent::GestureTap, time_ms, x, y);
1086 event.data.tap.tapCount = 1;
1088 SendGestureEvent(event);
1091 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1092 jfloat x, jfloat y) {
1093 WebGestureEvent event = MakeGestureEvent(
1094 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1095 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1096 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1097 event.data.tap.tapCount = 1;
1099 SendGestureEvent(event);
1102 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1103 jfloat x, jfloat y) {
1104 WebGestureEvent event = MakeGestureEvent(
1105 WebInputEvent::GestureLongPress, time_ms, x, y);
1107 SendGestureEvent(event);
1110 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1111 jfloat x, jfloat y) {
1112 WebGestureEvent event = MakeGestureEvent(
1113 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1114 SendGestureEvent(event);
1117 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1118 WebGestureEvent event = MakeGestureEvent(
1119 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1120 SendGestureEvent(event);
1123 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1124 jfloat anchor_x, jfloat anchor_y,
1126 WebGestureEvent event = MakeGestureEvent(
1127 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1128 event.data.pinchUpdate.scale = delta;
1130 SendGestureEvent(event);
1133 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1134 jfloat x1, jfloat y1,
1135 jfloat x2, jfloat y2) {
1139 web_contents_->SelectRange(
1140 gfx::Point(x1 / dpi_scale(), y1 / dpi_scale()),
1141 gfx::Point(x2 / dpi_scale(), y2 / dpi_scale()));
1144 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1145 jfloat x, jfloat y) {
1146 if (GetRenderWidgetHostViewAndroid()) {
1147 GetRenderWidgetHostViewAndroid()->MoveCaret(
1148 gfx::Point(x / dpi_scale(), y / dpi_scale()));
1152 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1153 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1155 rwhv->ResetGestureDetection();
1158 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1161 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1163 rwhv->SetDoubleTapSupportEnabled(enabled);
1166 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1169 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1171 rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1174 void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) {
1175 web_contents_->GetController().LoadIfNecessary();
1178 void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv* env, jobject obj) {
1179 web_contents_->GetController().SetNeedsReload();
1182 void ContentViewCoreImpl::Reload(JNIEnv* env,
1184 jboolean check_for_repost) {
1185 if (web_contents_->GetController().NeedsReload())
1186 web_contents_->GetController().LoadIfNecessary();
1188 web_contents_->GetController().Reload(check_for_repost);
1191 void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv* env,
1193 jboolean check_for_repost) {
1194 web_contents_->GetController().ReloadIgnoringCache(check_for_repost);
1197 void ContentViewCoreImpl::CancelPendingReload(JNIEnv* env, jobject obj) {
1198 web_contents_->GetController().CancelPendingReload();
1201 void ContentViewCoreImpl::ContinuePendingReload(JNIEnv* env, jobject obj) {
1202 web_contents_->GetController().ContinuePendingReload();
1205 void ContentViewCoreImpl::ClearHistory(JNIEnv* env, jobject obj) {
1206 // TODO(creis): Do callers of this need to know if it fails?
1207 if (web_contents_->GetController().CanPruneAllButLastCommitted())
1208 web_contents_->GetController().PruneAllButLastCommitted();
1211 void ContentViewCoreImpl::AddStyleSheetByURL(
1212 JNIEnv* env, jobject obj, jstring url) {
1216 web_contents_->GetMainFrame()->Send(new FrameMsg_AddStyleSheetByURL(
1217 web_contents_->GetMainFrame()->GetRoutingID(),
1218 ConvertJavaStringToUTF8(env, url)));
1221 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1225 java_bridge_dispatcher_host_manager_->SetAllowObjectContentsInspection(allow);
1228 void ContentViewCoreImpl::AddJavascriptInterface(
1233 jclass safe_annotation_clazz) {
1234 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1235 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1237 // JavaBoundObject creates the NPObject with a ref count of 1, and
1238 // JavaBridgeDispatcherHostManager takes its own ref.
1239 NPObject* bound_object = JavaBoundObject::Create(
1242 java_bridge_dispatcher_host_manager_->AsWeakPtr(),
1243 java_bridge_dispatcher_host_manager_->GetAllowObjectContentsInspection());
1244 java_bridge_dispatcher_host_manager_->AddNamedObject(
1245 ConvertJavaStringToUTF16(env, name), bound_object);
1246 blink::WebBindings::releaseObject(bound_object);
1249 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1252 java_bridge_dispatcher_host_manager_->RemoveNamedObject(
1253 ConvertJavaStringToUTF16(env, name));
1256 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1257 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1258 gfx::Size physical_size(
1259 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1260 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1261 root_layer_->SetBounds(physical_size);
1264 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1265 view->GetRenderWidgetHost());
1266 host->SendScreenRects();
1271 void ContentViewCoreImpl::ShowInterstitialPage(
1272 JNIEnv* env, jobject obj, jstring jurl, jlong delegate_ptr) {
1273 GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
1274 InterstitialPageDelegateAndroid* delegate =
1275 reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
1276 InterstitialPage* interstitial = InterstitialPage::Create(
1277 web_contents_, false, url, delegate);
1278 delegate->set_interstitial_page(interstitial);
1279 interstitial->Show();
1282 jboolean ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv* env,
1284 return web_contents_->ShowingInterstitialPage();
1287 jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
1289 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1290 return view && view->HasValidFrame();
1293 void ContentViewCoreImpl::ExitFullscreen(JNIEnv* env, jobject obj) {
1294 RenderViewHost* host = web_contents_->GetRenderViewHost();
1297 host->ExitFullscreen();
1300 void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv* env,
1303 bool enable_showing,
1305 RenderViewHost* host = web_contents_->GetRenderViewHost();
1308 host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
1314 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
1315 RenderViewHost* host = web_contents_->GetRenderViewHost();
1316 host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
1319 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv* env,
1321 RenderViewHost* host = web_contents_->GetRenderViewHost();
1322 host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
1323 host->GetRoutingID(), gfx::Rect()));
1326 void ContentViewCoreImpl::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
1327 RenderViewHost* host = web_contents_->GetRenderViewHost();
1330 host->SelectWordAroundCaret();
1335 static void AddNavigationEntryToHistory(JNIEnv* env, jobject obj,
1337 NavigationEntry* entry,
1339 // Get the details of the current entry
1340 ScopedJavaLocalRef<jstring> j_url(
1341 ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
1342 ScopedJavaLocalRef<jstring> j_virtual_url(
1343 ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
1344 ScopedJavaLocalRef<jstring> j_original_url(
1345 ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
1346 ScopedJavaLocalRef<jstring> j_title(
1347 ConvertUTF16ToJavaString(env, entry->GetTitle()));
1348 ScopedJavaLocalRef<jobject> j_bitmap;
1349 const FaviconStatus& status = entry->GetFavicon();
1350 if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
1351 j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
1353 // Add the item to the list
1354 Java_ContentViewCore_addToNavigationHistory(
1355 env, obj, history, index, j_url.obj(), j_virtual_url.obj(),
1356 j_original_url.obj(), j_title.obj(), j_bitmap.obj());
1361 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env,
1364 // Iterate through navigation entries to populate the list
1365 const NavigationController& controller = web_contents_->GetController();
1366 int count = controller.GetEntryCount();
1367 for (int i = 0; i < count; ++i) {
1368 AddNavigationEntryToHistory(
1369 env, obj, history, controller.GetEntryAtIndex(i), i);
1372 return controller.GetCurrentEntryIndex();
1375 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv* env,
1378 jboolean is_forward,
1380 // Iterate through navigation entries to populate the list
1381 const NavigationController& controller = web_contents_->GetController();
1382 int count = controller.GetEntryCount();
1384 int increment_value = is_forward ? 1 : -1;
1385 for (int i = controller.GetCurrentEntryIndex() + increment_value;
1386 i >= 0 && i < count;
1387 i += increment_value) {
1388 if (num_added >= max_entries)
1391 AddNavigationEntryToHistory(
1392 env, obj, history, controller.GetEntryAtIndex(i), i);
1397 ScopedJavaLocalRef<jstring>
1398 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv* env,
1400 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1402 return ScopedJavaLocalRef<jstring>(env, NULL);
1403 return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
1406 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1407 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1410 return rwhva->GetNativeImeAdapter();
1414 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
1415 const base::Value* result) {
1416 JNIEnv* env = base::android::AttachCurrentThread();
1418 base::JSONWriter::Write(result, &json);
1419 ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
1420 Java_ContentViewCore_onEvaluateJavaScriptResult(env,
1426 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env,
1430 jboolean start_renderer) {
1431 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
1434 if (start_renderer && !rvh->IsRenderViewLive()) {
1435 if (!web_contents_->CreateRenderViewForInitialEmptyDocument()) {
1436 LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
1442 // No callback requested.
1443 web_contents_->GetMainFrame()->ExecuteJavaScript(
1444 ConvertJavaStringToUTF16(env, script));
1448 // Secure the Java callback in a scoped object and give ownership of it to the
1450 ScopedJavaGlobalRef<jobject> j_callback;
1451 j_callback.Reset(env, callback);
1452 content::RenderFrameHost::JavaScriptResultCallback c_callback =
1453 base::Bind(&JavaScriptResultCallback, j_callback);
1455 web_contents_->GetMainFrame()->ExecuteJavaScript(
1456 ConvertJavaStringToUTF16(env, script),
1460 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
1461 JNIEnv* env, jobject obj) {
1462 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1463 return entry && entry->GetIsOverridingUserAgent();
1466 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1467 int text_input_type,
1468 const std::string& text,
1469 int selection_start,
1471 int composition_start,
1472 int composition_end,
1473 bool show_ime_if_needed,
1474 bool is_non_ime_change) {
1475 JNIEnv* env = AttachCurrentThread();
1476 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1480 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1481 Java_ContentViewCore_updateImeAdapter(env, obj.obj(),
1482 native_ime_adapter, text_input_type,
1484 selection_start, selection_end,
1485 composition_start, composition_end,
1486 show_ime_if_needed, is_non_ime_change);
1489 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv* env, jobject obj) {
1490 SSLHostState* state = SSLHostState::GetFor(
1491 web_contents_->GetController().GetBrowserContext());
1495 void ContentViewCoreImpl::SetUseDesktopUserAgent(
1499 jboolean reload_on_state_change) {
1500 if (GetUseDesktopUserAgent(env, obj) == enabled)
1503 // Make sure the navigation entry actually exists.
1504 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1508 // Set the flag in the NavigationEntry.
1509 entry->SetIsOverridingUserAgent(enabled);
1511 // Send the override to the renderer.
1512 if (reload_on_state_change) {
1513 // Reloading the page will send the override down as part of the
1514 // navigation IPC message.
1515 NavigationControllerImpl& controller =
1516 static_cast<NavigationControllerImpl&>(web_contents_->GetController());
1517 controller.ReloadOriginalRequestURL(false);
1521 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1523 SetAccessibilityEnabledInternal(enabled);
1526 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1527 accessibility_enabled_ = enabled;
1528 RenderWidgetHostViewAndroid* host_view = GetRenderWidgetHostViewAndroid();
1531 RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(
1532 host_view->GetRenderWidgetHost());
1533 BrowserAccessibilityState* accessibility_state =
1534 BrowserAccessibilityState::GetInstance();
1536 // This enables accessibility globally unless it was explicitly disallowed
1537 // by a command-line flag.
1538 accessibility_state->OnScreenReaderDetected();
1539 // If it was actually enabled globally, enable it for this RenderWidget now.
1540 if (accessibility_state->IsAccessibleBrowser() && host_impl)
1541 host_impl->AddAccessibilityMode(AccessibilityModeComplete);
1543 accessibility_state->ResetAccessibilityMode();
1545 host_impl->ResetAccessibilityMode();
1549 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1550 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1552 rwhv->UpdateScreenInfo(GetViewAndroid());
1555 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1562 static_cast<int>(x / dpi_scale()),
1563 static_cast<int>(y / dpi_scale()),
1564 static_cast<int>((width > 0 && width < dpi_scale()) ?
1565 1 : (int)(width / dpi_scale())),
1566 static_cast<int>((height > 0 && height < dpi_scale()) ?
1567 1 : (int)(height / dpi_scale())));
1568 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1569 GetWebContents()->GetRoutingID(), rect));
1572 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1573 return GetRenderProcessIdFromRenderViewHost(
1574 web_contents_->GetRenderViewHost());
1577 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1579 if (GetRenderWidgetHostViewAndroid())
1580 GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque);
1583 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1585 const base::Callback<
1586 void(const base::string16& content, int start_offset, int end_offset)>&
1588 DCHECK(!callback.is_null());
1589 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1592 if (GetRenderWidgetHostViewAndroid()) {
1593 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1595 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1596 focused_frame->GetRoutingID(), max_length));
1600 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1601 const base::string16& result) {
1602 JNIEnv* env = AttachCurrentThread();
1603 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1606 ScopedJavaLocalRef<jstring> jresult = ConvertUTF16ToJavaString(env, result);
1607 Java_ContentViewCore_onSmartClipDataExtracted(
1608 env, obj.obj(), jresult.obj());
1611 void ContentViewCoreImpl::WebContentsDestroyed() {
1612 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1613 static_cast<WebContentsImpl*>(web_contents())->GetView());
1615 wcva->SetContentViewCore(NULL);
1618 // This is called for each ContentView.
1619 jlong Init(JNIEnv* env,
1621 jlong native_web_contents,
1623 jlong window_android,
1624 jobject retained_objects_set) {
1625 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1627 reinterpret_cast<WebContents*>(native_web_contents),
1628 reinterpret_cast<ui::ViewAndroid*>(view_android),
1629 reinterpret_cast<ui::WindowAndroid*>(window_android),
1630 retained_objects_set);
1631 return reinterpret_cast<intptr_t>(view);
1634 bool RegisterContentViewCore(JNIEnv* env) {
1635 return RegisterNativesImpl(env);
1638 } // namespace content