Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / android / content_view_core_impl.cc
blob6e7643a9353ca4a36812f70ab9d6292e2f556c3c
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/content_view_core_impl.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "cc/layers/layer.h"
17 #include "cc/layers/solid_color_layer.h"
18 #include "cc/output/begin_frame_args.h"
19 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
20 #include "content/browser/android/gesture_event_type.h"
21 #include "content/browser/android/interstitial_page_delegate_android.h"
22 #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
23 #include "content/browser/android/load_url_params.h"
24 #include "content/browser/frame_host/interstitial_page_impl.h"
25 #include "content/browser/geolocation/geolocation_service_context.h"
26 #include "content/browser/media/media_web_contents_observer.h"
27 #include "content/browser/renderer_host/compositor_impl_android.h"
28 #include "content/browser/renderer_host/input/motion_event_android.h"
29 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
30 #include "content/browser/renderer_host/input/web_input_event_util.h"
31 #include "content/browser/renderer_host/render_view_host_impl.h"
32 #include "content/browser/renderer_host/render_widget_host_impl.h"
33 #include "content/browser/renderer_host/render_widget_host_view_android.h"
34 #include "content/browser/web_contents/web_contents_view_android.h"
35 #include "content/common/frame_messages.h"
36 #include "content/common/input/web_input_event_traits.h"
37 #include "content/common/input_messages.h"
38 #include "content/common/view_messages.h"
39 #include "content/public/browser/android/compositor.h"
40 #include "content/public/browser/browser_context.h"
41 #include "content/public/browser/browser_thread.h"
42 #include "content/public/browser/favicon_status.h"
43 #include "content/public/browser/render_frame_host.h"
44 #include "content/public/browser/screen_orientation_dispatcher_host.h"
45 #include "content/public/browser/ssl_host_state_delegate.h"
46 #include "content/public/browser/web_contents.h"
47 #include "content/public/common/content_client.h"
48 #include "content/public/common/content_switches.h"
49 #include "content/public/common/menu_item.h"
50 #include "content/public/common/user_agent.h"
51 #include "jni/ContentViewCore_jni.h"
52 #include "third_party/WebKit/public/web/WebInputEvent.h"
53 #include "ui/android/view_android.h"
54 #include "ui/android/window_android.h"
55 #include "ui/gfx/android/java_bitmap.h"
56 #include "ui/gfx/geometry/point_conversions.h"
57 #include "ui/gfx/geometry/size_conversions.h"
58 #include "ui/gfx/geometry/size_f.h"
60 using base::android::AttachCurrentThread;
61 using base::android::ConvertJavaStringToUTF16;
62 using base::android::ConvertJavaStringToUTF8;
63 using base::android::ConvertUTF16ToJavaString;
64 using base::android::ConvertUTF8ToJavaString;
65 using base::android::ScopedJavaLocalRef;
66 using blink::WebGestureEvent;
67 using blink::WebInputEvent;
69 // Describes the type and enabled state of a select popup item.
70 namespace {
72 // A Java counterpart will be generated for this enum.
73 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.input
74 enum PopupItemType {
75 // Popup item is of type group
76 POPUP_ITEM_TYPE_GROUP,
78 // Popup item is disabled
79 POPUP_ITEM_TYPE_DISABLED,
81 // Popup item is enabled
82 POPUP_ITEM_TYPE_ENABLED,
85 } //namespace
87 namespace content {
89 namespace {
91 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
93 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
94 DCHECK(host);
95 RenderProcessHost* render_process = host->GetProcess();
96 DCHECK(render_process);
97 if (render_process->HasConnection())
98 return render_process->GetHandle();
99 else
100 return 0;
103 ScopedJavaLocalRef<jobject> CreateJavaRect(
104 JNIEnv* env,
105 const gfx::Rect& rect) {
106 return ScopedJavaLocalRef<jobject>(
107 Java_ContentViewCore_createRect(env,
108 static_cast<int>(rect.x()),
109 static_cast<int>(rect.y()),
110 static_cast<int>(rect.right()),
111 static_cast<int>(rect.bottom())));
114 int ToGestureEventType(WebInputEvent::Type type) {
115 switch (type) {
116 case WebInputEvent::GestureScrollBegin:
117 return GESTURE_EVENT_TYPE_SCROLL_START;
118 case WebInputEvent::GestureScrollEnd:
119 return GESTURE_EVENT_TYPE_SCROLL_END;
120 case WebInputEvent::GestureScrollUpdate:
121 return GESTURE_EVENT_TYPE_SCROLL_BY;
122 case WebInputEvent::GestureFlingStart:
123 return GESTURE_EVENT_TYPE_FLING_START;
124 case WebInputEvent::GestureFlingCancel:
125 return GESTURE_EVENT_TYPE_FLING_CANCEL;
126 case WebInputEvent::GestureShowPress:
127 return GESTURE_EVENT_TYPE_SHOW_PRESS;
128 case WebInputEvent::GestureTap:
129 return GESTURE_EVENT_TYPE_SINGLE_TAP_CONFIRMED;
130 case WebInputEvent::GestureTapUnconfirmed:
131 return GESTURE_EVENT_TYPE_SINGLE_TAP_UNCONFIRMED;
132 case WebInputEvent::GestureTapDown:
133 return GESTURE_EVENT_TYPE_TAP_DOWN;
134 case WebInputEvent::GestureTapCancel:
135 return GESTURE_EVENT_TYPE_TAP_CANCEL;
136 case WebInputEvent::GestureDoubleTap:
137 return GESTURE_EVENT_TYPE_DOUBLE_TAP;
138 case WebInputEvent::GestureLongPress:
139 return GESTURE_EVENT_TYPE_LONG_PRESS;
140 case WebInputEvent::GestureLongTap:
141 return GESTURE_EVENT_TYPE_LONG_TAP;
142 case WebInputEvent::GesturePinchBegin:
143 return GESTURE_EVENT_TYPE_PINCH_BEGIN;
144 case WebInputEvent::GesturePinchEnd:
145 return GESTURE_EVENT_TYPE_PINCH_END;
146 case WebInputEvent::GesturePinchUpdate:
147 return GESTURE_EVENT_TYPE_PINCH_BY;
148 case WebInputEvent::GestureTwoFingerTap:
149 default:
150 NOTREACHED() << "Invalid source gesture type: "
151 << WebInputEventTraits::GetName(type);
152 return -1;
156 } // namespace
158 // Enables a callback when the underlying WebContents is destroyed, to enable
159 // nulling the back-pointer.
160 class ContentViewCoreImpl::ContentViewUserData
161 : public base::SupportsUserData::Data {
162 public:
163 explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
164 : content_view_core_(content_view_core) {
167 ~ContentViewUserData() override {
168 // TODO(joth): When chrome has finished removing the TabContents class (see
169 // crbug.com/107201) consider inverting relationship, so ContentViewCore
170 // would own WebContents. That effectively implies making the WebContents
171 // destructor private on Android.
172 delete content_view_core_;
175 ContentViewCoreImpl* get() const { return content_view_core_; }
177 private:
178 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
179 ContentViewCoreImpl* content_view_core_;
181 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
184 // static
185 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
186 content::WebContents* web_contents) {
187 ContentViewCoreImpl::ContentViewUserData* data =
188 static_cast<ContentViewCoreImpl::ContentViewUserData*>(
189 web_contents->GetUserData(kContentViewUserDataKey));
190 return data ? data->get() : NULL;
193 // static
194 ContentViewCore* ContentViewCore::FromWebContents(
195 content::WebContents* web_contents) {
196 return ContentViewCoreImpl::FromWebContents(web_contents);
199 // static
200 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
201 jobject obj) {
202 return reinterpret_cast<ContentViewCore*>(
203 Java_ContentViewCore_getNativeContentViewCore(env, obj));
206 ContentViewCoreImpl::ContentViewCoreImpl(
207 JNIEnv* env,
208 jobject obj,
209 WebContents* web_contents,
210 jobject view_android_delegate,
211 ui::WindowAndroid* window_android,
212 jobject java_bridge_retained_object_set)
213 : WebContentsObserver(web_contents),
214 java_ref_(env, obj),
215 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
216 root_layer_(cc::SolidColorLayer::Create(Compositor::LayerSettings())),
217 page_scale_(1),
218 view_android_(new ui::ViewAndroid(view_android_delegate, window_android)),
219 dpi_scale_(ui::GetScaleFactorForNativeView(view_android_.get())),
220 window_android_(window_android),
221 device_orientation_(0),
222 accessibility_enabled_(false) {
223 CHECK(web_contents) <<
224 "A ContentViewCoreImpl should be created with a valid WebContents.";
225 DCHECK(window_android_);
227 root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj));
228 gfx::Size physical_size(
229 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
230 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
231 root_layer_->SetBounds(physical_size);
232 root_layer_->SetIsDrawable(true);
234 // Currently, the only use case we have for overriding a user agent involves
235 // spoofing a desktop Linux user agent for "Request desktop site".
236 // Automatically set it for all WebContents so that it is available when a
237 // NavigationEntry requires the user agent to be overridden.
238 const char kLinuxInfoStr[] = "X11; Linux x86_64";
239 std::string product = content::GetContentClient()->GetProduct();
240 std::string spoofed_ua =
241 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
242 web_contents->SetUserAgentOverride(spoofed_ua);
244 java_bridge_dispatcher_host_ =
245 new GinJavaBridgeDispatcherHost(web_contents,
246 java_bridge_retained_object_set);
248 InitWebContents();
251 ContentViewCoreImpl::~ContentViewCoreImpl() {
252 root_layer_->RemoveFromParent();
254 JNIEnv* env = base::android::AttachCurrentThread();
255 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
256 java_ref_.reset();
257 if (!j_obj.is_null()) {
258 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
259 env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
263 base::android::ScopedJavaLocalRef<jobject>
264 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
265 return web_contents_->GetJavaWebContents();
268 base::android::ScopedJavaLocalRef<jobject>
269 ContentViewCoreImpl::GetJavaWindowAndroid(JNIEnv* env, jobject obj) {
270 if (!window_android_)
271 return ScopedJavaLocalRef<jobject>();
272 return window_android_->GetJavaObject();
275 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
276 jobject obj) {
277 DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
278 java_ref_.reset();
279 // Java peer has gone, ContentViewCore is not functional and waits to
280 // be destroyed with WebContents.
281 // We need to reset WebContentsViewAndroid's reference, otherwise, there
282 // could have call in when swapping the WebContents,
283 // see http://crbug.com/383939 .
284 DCHECK(web_contents_);
285 static_cast<WebContentsViewAndroid*>(
286 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
287 SetContentViewCore(NULL);
290 void ContentViewCoreImpl::InitWebContents() {
291 DCHECK(web_contents_);
292 static_cast<WebContentsViewAndroid*>(
293 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
294 SetContentViewCore(this);
295 DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
296 web_contents_->SetUserData(kContentViewUserDataKey,
297 new ContentViewUserData(this));
300 void ContentViewCoreImpl::RenderViewReady() {
301 JNIEnv* env = AttachCurrentThread();
302 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
303 if (!obj.is_null())
304 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
306 if (device_orientation_ != 0)
307 SendOrientationChangeEventInternal();
310 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host,
311 RenderViewHost* new_host) {
312 int old_pid = 0;
313 if (old_host) {
314 old_pid = GetRenderProcessIdFromRenderViewHost(old_host);
316 RenderWidgetHostViewAndroid* view =
317 static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView());
318 if (view)
319 view->SetContentViewCore(NULL);
321 view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView());
322 if (view)
323 view->SetContentViewCore(this);
325 int new_pid = GetRenderProcessIdFromRenderViewHost(
326 web_contents_->GetRenderViewHost());
327 if (new_pid != old_pid) {
328 // Notify the Java side that the renderer process changed.
329 JNIEnv* env = AttachCurrentThread();
330 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
331 if (!obj.is_null()) {
332 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
336 SetFocusInternal(HasFocus());
337 SetAccessibilityEnabledInternal(accessibility_enabled_);
340 RenderWidgetHostViewAndroid*
341 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() const {
342 RenderWidgetHostView* rwhv = NULL;
343 if (web_contents_) {
344 rwhv = web_contents_->GetRenderWidgetHostView();
345 if (web_contents_->ShowingInterstitialPage()) {
346 rwhv = web_contents_->GetInterstitialPage()
347 ->GetMainFrame()
348 ->GetRenderViewHost()
349 ->GetView();
352 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
355 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
356 JNIEnv* env = AttachCurrentThread();
357 return java_ref_.get(env);
360 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
361 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
362 if (!rwhva)
363 return SK_ColorWHITE;
364 return rwhva->GetCachedBackgroundColor();
367 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
368 if (should_pause)
369 web_contents_->GetGeolocationServiceContext()->PauseUpdates();
370 else
371 web_contents_->GetGeolocationServiceContext()->ResumeUpdates();
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 bool is_mobile_optimized_hint) {
386 JNIEnv* env = AttachCurrentThread();
387 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
388 if (obj.is_null())
389 return;
391 window_android_->set_content_offset(
392 gfx::ScaleVector2d(content_offset, dpi_scale_));
394 page_scale_ = page_scale_factor;
396 Java_ContentViewCore_updateFrameInfo(
397 env, obj.obj(),
398 scroll_offset.x(),
399 scroll_offset.y(),
400 page_scale_factor,
401 page_scale_factor_limits.x(),
402 page_scale_factor_limits.y(),
403 content_size.width(),
404 content_size.height(),
405 viewport_size.width(),
406 viewport_size.height(),
407 controls_offset.y(),
408 content_offset.y(),
409 is_mobile_optimized_hint);
412 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
413 JNIEnv* env = AttachCurrentThread();
414 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
415 if (obj.is_null())
416 return;
417 ScopedJavaLocalRef<jstring> jtitle =
418 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
419 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
422 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
423 root_layer_->SetBackgroundColor(color);
425 JNIEnv* env = AttachCurrentThread();
426 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
427 if (obj.is_null())
428 return;
429 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
432 void ContentViewCoreImpl::ShowSelectPopupMenu(
433 RenderFrameHost* frame,
434 const gfx::Rect& bounds,
435 const std::vector<MenuItem>& items,
436 int selected_item,
437 bool multiple) {
438 JNIEnv* env = AttachCurrentThread();
439 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
440 if (j_obj.is_null())
441 return;
443 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
445 // For multi-select list popups we find the list of previous selections by
446 // iterating through the items. But for single selection popups we take the
447 // given |selected_item| as is.
448 ScopedJavaLocalRef<jintArray> selected_array;
449 if (multiple) {
450 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
451 size_t selected_count = 0;
452 for (size_t i = 0; i < items.size(); ++i) {
453 if (items[i].checked)
454 native_selected_array[selected_count++] = i;
457 selected_array = ScopedJavaLocalRef<jintArray>(
458 env, env->NewIntArray(selected_count));
459 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
460 native_selected_array.get());
461 } else {
462 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
463 jint value = selected_item;
464 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
467 ScopedJavaLocalRef<jintArray> enabled_array(env,
468 env->NewIntArray(items.size()));
469 std::vector<base::string16> labels;
470 labels.reserve(items.size());
471 for (size_t i = 0; i < items.size(); ++i) {
472 labels.push_back(items[i].label);
473 jint enabled =
474 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
475 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
476 POPUP_ITEM_TYPE_DISABLED));
477 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
479 ScopedJavaLocalRef<jobjectArray> items_array(
480 base::android::ToJavaArrayOfStrings(env, labels));
481 Java_ContentViewCore_showSelectPopup(env,
482 j_obj.obj(),
483 reinterpret_cast<intptr_t>(frame),
484 bounds_rect.obj(),
485 items_array.obj(),
486 enabled_array.obj(),
487 multiple,
488 selected_array.obj());
491 void ContentViewCoreImpl::HideSelectPopupMenu() {
492 JNIEnv* env = AttachCurrentThread();
493 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
494 if (!j_obj.is_null())
495 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
498 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
499 InputEventAckState ack_result) {
500 JNIEnv* env = AttachCurrentThread();
501 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
502 if (j_obj.is_null())
503 return;
505 switch (event.type) {
506 case WebInputEvent::GestureFlingStart:
507 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
508 // The view expects the fling velocity in pixels/s.
509 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
510 event.data.flingStart.velocityX * dpi_scale(),
511 event.data.flingStart.velocityY * dpi_scale());
512 } else {
513 // If a scroll ends with a fling, a SCROLL_END event is never sent.
514 // However, if that fling went unconsumed, we still need to let the
515 // listeners know that scrolling has ended.
516 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
518 break;
519 case WebInputEvent::GestureFlingCancel:
520 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
521 break;
522 case WebInputEvent::GestureScrollBegin:
523 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
524 break;
525 case WebInputEvent::GestureScrollUpdate:
526 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
527 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
528 break;
529 case WebInputEvent::GestureScrollEnd:
530 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
531 break;
532 case WebInputEvent::GesturePinchBegin:
533 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
534 break;
535 case WebInputEvent::GesturePinchEnd:
536 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
537 break;
538 case WebInputEvent::GestureTap:
539 Java_ContentViewCore_onSingleTapEventAck(
540 env,
541 j_obj.obj(),
542 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
543 event.x * dpi_scale(),
544 event.y * dpi_scale());
545 break;
546 default:
547 break;
551 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
552 if (event.type != WebInputEvent::GestureTap &&
553 event.type != WebInputEvent::GestureDoubleTap &&
554 event.type != WebInputEvent::GestureLongTap &&
555 event.type != WebInputEvent::GestureLongPress)
556 return false;
558 JNIEnv* env = AttachCurrentThread();
559 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
560 if (j_obj.is_null())
561 return false;
563 const blink::WebGestureEvent& gesture =
564 static_cast<const blink::WebGestureEvent&>(event);
565 int gesture_type = ToGestureEventType(event.type);
566 return Java_ContentViewCore_filterTapOrPressEvent(env,
567 j_obj.obj(),
568 gesture_type,
569 gesture.x * dpi_scale(),
570 gesture.y * dpi_scale());
572 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
575 bool ContentViewCoreImpl::HasFocus() {
576 JNIEnv* env = AttachCurrentThread();
577 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
578 if (obj.is_null())
579 return false;
580 return Java_ContentViewCore_hasFocus(env, obj.obj());
583 void ContentViewCoreImpl::RequestDisallowInterceptTouchEvent() {
584 JNIEnv* env = AttachCurrentThread();
585 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
586 if (!obj.is_null())
587 Java_ContentViewCore_requestDisallowInterceptTouchEvent(env, obj.obj());
590 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
591 JNIEnv* env = AttachCurrentThread();
592 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
593 if (obj.is_null())
594 return;
595 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
596 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
599 void ContentViewCoreImpl::OnSelectionEvent(ui::SelectionEventType event,
600 const gfx::PointF& selection_anchor,
601 const gfx::RectF& selection_rect) {
602 JNIEnv* env = AttachCurrentThread();
603 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
604 if (j_obj.is_null())
605 return;
607 gfx::PointF selection_anchor_pix =
608 gfx::ScalePoint(selection_anchor, dpi_scale());
609 gfx::RectF selection_rect_pix = gfx::ScaleRect(selection_rect, dpi_scale());
610 Java_ContentViewCore_onSelectionEvent(
611 env, j_obj.obj(), event, selection_anchor_pix.x(),
612 selection_anchor_pix.y(), selection_rect_pix.x(), selection_rect_pix.y(),
613 selection_rect_pix.right(), selection_rect_pix.bottom());
616 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
617 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
618 if (!view)
619 return;
621 view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
623 JNIEnv* env = AttachCurrentThread();
624 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
625 if (obj.is_null())
626 return;
627 Java_ContentViewCore_showPastePopupWithFeedback(
628 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
629 static_cast<jint>(y_dip * dpi_scale()));
632 void ContentViewCoreImpl::GetScaledContentBitmap(
633 float scale,
634 SkColorType preferred_color_type,
635 const gfx::Rect& src_subrect,
636 ReadbackRequestCallback& result_callback) {
637 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
638 if (!view || preferred_color_type == kUnknown_SkColorType) {
639 result_callback.Run(SkBitmap(), READBACK_FAILED);
640 return;
643 view->GetScaledContentBitmap(scale, preferred_color_type, src_subrect,
644 result_callback);
647 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
648 JNIEnv* env = AttachCurrentThread();
649 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
650 if (j_obj.is_null())
651 return;
652 ScopedJavaLocalRef<jstring> jcontent_url =
653 ConvertUTF8ToJavaString(env, content_url.spec());
654 Java_ContentViewCore_startContentIntent(env,
655 j_obj.obj(),
656 jcontent_url.obj());
659 void ContentViewCoreImpl::ShowDisambiguationPopup(
660 const gfx::Rect& rect_pixels,
661 const SkBitmap& zoomed_bitmap) {
662 JNIEnv* env = AttachCurrentThread();
664 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
665 if (obj.is_null())
666 return;
668 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
670 ScopedJavaLocalRef<jobject> java_bitmap =
671 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
672 DCHECK(!java_bitmap.is_null());
674 Java_ContentViewCore_showDisambiguationPopup(env,
675 obj.obj(),
676 rect_object.obj(),
677 java_bitmap.obj());
680 ScopedJavaLocalRef<jobject>
681 ContentViewCoreImpl::CreateMotionEventSynthesizer() {
682 JNIEnv* env = AttachCurrentThread();
684 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
685 if (obj.is_null())
686 return ScopedJavaLocalRef<jobject>();
687 return Java_ContentViewCore_createMotionEventSynthesizer(env, obj.obj());
690 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
691 JNIEnv* env = AttachCurrentThread();
693 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
694 if (obj.is_null())
695 return true;
696 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
697 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
698 j_url.obj());
701 void ContentViewCoreImpl::DidStopFlinging() {
702 JNIEnv* env = AttachCurrentThread();
704 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
705 if (!obj.is_null())
706 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
709 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() const {
710 JNIEnv* env = AttachCurrentThread();
712 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
713 if (obj.is_null())
714 return ScopedJavaLocalRef<jobject>();
716 return Java_ContentViewCore_getContext(env, obj.obj());
719 gfx::Size ContentViewCoreImpl::GetViewSize() const {
720 gfx::Size size = GetViewportSizeDip();
721 if (DoTopControlsShrinkBlinkSize())
722 size.Enlarge(0, -GetTopControlsHeightDip());
723 return size;
726 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
727 JNIEnv* env = AttachCurrentThread();
728 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
729 if (j_obj.is_null())
730 return gfx::Size();
731 return gfx::Size(
732 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
733 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
736 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
737 JNIEnv* env = AttachCurrentThread();
738 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
739 if (j_obj.is_null())
740 return gfx::Size();
741 return gfx::Size(
742 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
743 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
746 int ContentViewCoreImpl::GetTopControlsHeightPix() const {
747 JNIEnv* env = AttachCurrentThread();
748 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
749 if (j_obj.is_null())
750 return 0;
751 return Java_ContentViewCore_getTopControlsHeightPix(env, j_obj.obj());
754 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
755 return gfx::ToCeiledSize(
756 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
759 bool ContentViewCoreImpl::DoTopControlsShrinkBlinkSize() const {
760 JNIEnv* env = AttachCurrentThread();
761 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
762 if (j_obj.is_null())
763 return false;
764 return Java_ContentViewCore_doTopControlsShrinkBlinkSize(env, j_obj.obj());
767 float ContentViewCoreImpl::GetTopControlsHeightDip() const {
768 return GetTopControlsHeightPix() / dpi_scale();
771 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
772 root_layer_->InsertChild(layer, 0);
773 root_layer_->SetIsDrawable(false);
776 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
777 layer->RemoveFromParent();
779 if (!root_layer_->children().size())
780 root_layer_->SetIsDrawable(true);
783 void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF& extent) {
784 if (!web_contents_)
785 return;
787 web_contents_->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
790 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& base,
791 const gfx::PointF& extent) {
792 if (!web_contents_)
793 return;
795 gfx::Point base_point = gfx::ToRoundedPoint(base);
796 gfx::Point extent_point = gfx::ToRoundedPoint(extent);
797 if (base_point == extent_point)
798 return;
800 web_contents_->SelectRange(base_point, extent_point);
803 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
804 return view_android_.get();
807 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
808 return window_android_;
811 const scoped_refptr<cc::Layer>& ContentViewCoreImpl::GetLayer() const {
812 return root_layer_;
815 // ----------------------------------------------------------------------------
816 // Methods called from Java via JNI
817 // ----------------------------------------------------------------------------
819 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
820 jobject obj,
821 jlong selectPopupSourceFrame,
822 jintArray indices) {
823 RenderFrameHostImpl* rfhi =
824 reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
825 DCHECK(rfhi);
826 if (indices == NULL) {
827 rfhi->DidCancelPopupMenu();
828 return;
831 int selected_count = env->GetArrayLength(indices);
832 std::vector<int> selected_indices;
833 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
834 for (int i = 0; i < selected_count; ++i)
835 selected_indices.push_back(indices_ptr[i]);
836 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
837 rfhi->DidSelectPopupMenuItems(selected_indices);
840 WebContents* ContentViewCoreImpl::GetWebContents() const {
841 return web_contents_;
844 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
845 SetFocusInternal(focused);
848 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
849 if (!GetRenderWidgetHostViewAndroid())
850 return;
852 if (focused)
853 GetRenderWidgetHostViewAndroid()->Focus();
854 else
855 GetRenderWidgetHostViewAndroid()->Blur();
858 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
859 jobject obj,
860 jint orientation) {
861 if (device_orientation_ != orientation) {
862 device_orientation_ = orientation;
863 SendOrientationChangeEventInternal();
867 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
868 jobject obj,
869 jobject motion_event,
870 jlong time_ms,
871 jint android_action,
872 jint pointer_count,
873 jint history_size,
874 jint action_index,
875 jfloat pos_x_0,
876 jfloat pos_y_0,
877 jfloat pos_x_1,
878 jfloat pos_y_1,
879 jint pointer_id_0,
880 jint pointer_id_1,
881 jfloat touch_major_0,
882 jfloat touch_major_1,
883 jfloat touch_minor_0,
884 jfloat touch_minor_1,
885 jfloat orientation_0,
886 jfloat orientation_1,
887 jfloat raw_pos_x,
888 jfloat raw_pos_y,
889 jint android_tool_type_0,
890 jint android_tool_type_1,
891 jint android_button_state,
892 jint android_meta_state,
893 jboolean is_touch_handle_event) {
894 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
895 // Avoid synthesizing a touch event if it cannot be forwarded.
896 if (!rwhv)
897 return false;
899 MotionEventAndroid::Pointer pointer0(pointer_id_0,
900 pos_x_0,
901 pos_y_0,
902 touch_major_0,
903 touch_minor_0,
904 orientation_0,
905 android_tool_type_0);
906 MotionEventAndroid::Pointer pointer1(pointer_id_1,
907 pos_x_1,
908 pos_y_1,
909 touch_major_1,
910 touch_minor_1,
911 orientation_1,
912 android_tool_type_1);
913 MotionEventAndroid event(1.f / dpi_scale(),
914 env,
915 motion_event,
916 time_ms,
917 android_action,
918 pointer_count,
919 history_size,
920 action_index,
921 android_button_state,
922 android_meta_state,
923 raw_pos_x - pos_x_0,
924 raw_pos_y - pos_y_0,
925 pointer0,
926 pointer1);
928 return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
929 : rwhv->OnTouchEvent(event);
932 float ContentViewCoreImpl::GetDpiScale() const {
933 return dpi_scale_;
936 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
937 jobject obj,
938 jlong time_ms,
939 jfloat x,
940 jfloat y) {
941 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
942 if (!rwhv)
943 return false;
945 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
946 WebInputEvent::MouseMove,
947 blink::WebMouseEvent::ButtonNone,
948 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
950 rwhv->SendMouseEvent(event);
951 return true;
954 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
955 jobject obj,
956 jlong time_ms,
957 jfloat x,
958 jfloat y,
959 jfloat ticks_x,
960 jfloat ticks_y,
961 jfloat pixels_per_tick) {
962 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
963 if (!rwhv)
964 return false;
966 if (!ticks_x && !ticks_y)
967 return false;
969 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
970 ticks_x, ticks_y, pixels_per_tick / dpi_scale(), time_ms / 1000.0,
971 x / dpi_scale(), y / dpi_scale());
973 rwhv->SendMouseWheelEvent(event);
974 return true;
977 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
978 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
979 return WebGestureEventBuilder::Build(
980 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
983 void ContentViewCoreImpl::SendGestureEvent(
984 const blink::WebGestureEvent& event) {
985 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
986 if (rwhv)
987 rwhv->SendGestureEvent(event);
990 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
991 jobject obj,
992 jlong time_ms,
993 jfloat x,
994 jfloat y,
995 jfloat hintx,
996 jfloat hinty,
997 jboolean target_viewport) {
998 WebGestureEvent event = MakeGestureEvent(
999 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1000 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1001 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1002 event.data.scrollBegin.targetViewport = target_viewport;
1004 SendGestureEvent(event);
1007 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1008 WebGestureEvent event = MakeGestureEvent(
1009 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1010 SendGestureEvent(event);
1013 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1014 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1015 WebGestureEvent event = MakeGestureEvent(
1016 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1017 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1018 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1020 SendGestureEvent(event);
1023 void ContentViewCoreImpl::FlingStart(JNIEnv* env,
1024 jobject obj,
1025 jlong time_ms,
1026 jfloat x,
1027 jfloat y,
1028 jfloat vx,
1029 jfloat vy,
1030 jboolean target_viewport) {
1031 WebGestureEvent event = MakeGestureEvent(
1032 WebInputEvent::GestureFlingStart, time_ms, x, y);
1033 event.data.flingStart.velocityX = vx / dpi_scale();
1034 event.data.flingStart.velocityY = vy / dpi_scale();
1035 event.data.flingStart.targetViewport = target_viewport;
1037 SendGestureEvent(event);
1040 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1041 WebGestureEvent event = MakeGestureEvent(
1042 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1043 event.data.flingCancel.preventBoosting = true;
1045 SendGestureEvent(event);
1048 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1049 jfloat x, jfloat y) {
1050 // Tap gestures should always be preceded by a TapDown, ensuring consistency
1051 // with the touch-based gesture detection pipeline.
1052 WebGestureEvent tap_down_event = MakeGestureEvent(
1053 WebInputEvent::GestureTapDown, time_ms, x, y);
1054 tap_down_event.data.tap.tapCount = 1;
1055 SendGestureEvent(tap_down_event);
1057 WebGestureEvent tap_event = MakeGestureEvent(
1058 WebInputEvent::GestureTap, time_ms, x, y);
1059 tap_event.data.tap.tapCount = 1;
1060 SendGestureEvent(tap_event);
1063 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1064 jfloat x, jfloat y) {
1065 WebGestureEvent event = MakeGestureEvent(
1066 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1067 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1068 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1069 event.data.tap.tapCount = 1;
1071 SendGestureEvent(event);
1074 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1075 jfloat x, jfloat y) {
1076 WebGestureEvent event = MakeGestureEvent(
1077 WebInputEvent::GestureLongPress, time_ms, x, y);
1079 SendGestureEvent(event);
1082 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1083 jfloat x, jfloat y) {
1084 WebGestureEvent event = MakeGestureEvent(
1085 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1086 SendGestureEvent(event);
1089 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1090 WebGestureEvent event = MakeGestureEvent(
1091 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1092 SendGestureEvent(event);
1095 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1096 jfloat anchor_x, jfloat anchor_y,
1097 jfloat delta) {
1098 WebGestureEvent event = MakeGestureEvent(
1099 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1100 event.data.pinchUpdate.scale = delta;
1102 SendGestureEvent(event);
1105 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1106 jfloat x1, jfloat y1,
1107 jfloat x2, jfloat y2) {
1108 SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
1109 gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
1112 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1113 jfloat x, jfloat y) {
1114 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1115 if (rwhv)
1116 rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
1119 void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
1120 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1121 if (rwhv)
1122 rwhv->DismissTextHandles();
1125 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
1126 jobject obj,
1127 jboolean hidden) {
1128 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1129 if (rwhv)
1130 rwhv->SetTextHandlesTemporarilyHidden(hidden);
1133 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1134 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1135 if (rwhv)
1136 rwhv->ResetGestureDetection();
1139 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1140 jobject obj,
1141 jboolean enabled) {
1142 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1143 if (rwhv)
1144 rwhv->SetDoubleTapSupportEnabled(enabled);
1147 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1148 jobject obj,
1149 jboolean enabled) {
1150 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1151 if (rwhv)
1152 rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1155 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1156 JNIEnv* env,
1157 jobject obj,
1158 jboolean allow) {
1159 java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
1162 void ContentViewCoreImpl::AddJavascriptInterface(
1163 JNIEnv* env,
1164 jobject /* obj */,
1165 jobject object,
1166 jstring name,
1167 jclass safe_annotation_clazz) {
1168 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1169 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1170 java_bridge_dispatcher_host_->AddNamedObject(
1171 ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
1174 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1175 jobject /* obj */,
1176 jstring name) {
1177 java_bridge_dispatcher_host_->RemoveNamedObject(
1178 ConvertJavaStringToUTF8(env, name));
1181 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1182 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1183 gfx::Size physical_size(
1184 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1185 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1186 root_layer_->SetBounds(physical_size);
1188 if (view) {
1189 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1190 view->GetRenderWidgetHost());
1191 host->SendScreenRects();
1192 view->WasResized();
1196 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1197 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1198 if (!rwhva)
1199 return 0;
1200 return rwhva->GetNativeImeAdapter();
1203 void ContentViewCoreImpl::ForceUpdateImeAdapter(long native_ime_adapter) {
1204 JNIEnv* env = AttachCurrentThread();
1205 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1206 if (obj.is_null())
1207 return;
1208 Java_ContentViewCore_forceUpdateImeAdapter(env, obj.obj(),
1209 native_ime_adapter);
1212 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1213 int text_input_type,
1214 int text_input_flags,
1215 const std::string& text,
1216 int selection_start,
1217 int selection_end,
1218 int composition_start,
1219 int composition_end,
1220 bool show_ime_if_needed,
1221 bool is_non_ime_change) {
1222 JNIEnv* env = AttachCurrentThread();
1223 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1224 if (obj.is_null())
1225 return;
1227 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1228 Java_ContentViewCore_updateImeAdapter(env,
1229 obj.obj(),
1230 native_ime_adapter,
1231 text_input_type,
1232 text_input_flags,
1233 jstring_text.obj(),
1234 selection_start,
1235 selection_end,
1236 composition_start,
1237 composition_end,
1238 show_ime_if_needed,
1239 is_non_ime_change);
1242 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1243 bool enabled) {
1244 SetAccessibilityEnabledInternal(enabled);
1247 void ContentViewCoreImpl::SetTextTrackSettings(JNIEnv* env,
1248 jobject obj,
1249 jboolean textTracksEnabled,
1250 jstring textTrackBackgroundColor,
1251 jstring textTrackFontFamily,
1252 jstring textTrackFontStyle,
1253 jstring textTrackFontVariant,
1254 jstring textTrackTextColor,
1255 jstring textTrackTextShadow,
1256 jstring textTrackTextSize) {
1257 FrameMsg_TextTrackSettings_Params params;
1258 params.text_tracks_enabled = textTracksEnabled;
1259 params.text_track_background_color = ConvertJavaStringToUTF8(
1260 env, textTrackBackgroundColor);
1261 params.text_track_font_family = ConvertJavaStringToUTF8(
1262 env, textTrackFontFamily);
1263 params.text_track_font_style = ConvertJavaStringToUTF8(
1264 env, textTrackFontStyle);
1265 params.text_track_font_variant = ConvertJavaStringToUTF8(
1266 env, textTrackFontVariant);
1267 params.text_track_text_color = ConvertJavaStringToUTF8(
1268 env, textTrackTextColor);
1269 params.text_track_text_shadow = ConvertJavaStringToUTF8(
1270 env, textTrackTextShadow);
1271 params.text_track_text_size = ConvertJavaStringToUTF8(
1272 env, textTrackTextSize);
1273 web_contents_->GetMainFrame()->SetTextTrackSettings(params);
1276 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1277 JNIEnv* env = AttachCurrentThread();
1278 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1279 if (obj.is_null())
1280 return true;
1281 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
1282 obj.obj());
1285 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1286 accessibility_enabled_ = enabled;
1287 BrowserAccessibilityStateImpl* accessibility_state =
1288 BrowserAccessibilityStateImpl::GetInstance();
1289 if (enabled) {
1290 // This enables accessibility globally unless it was explicitly disallowed
1291 // by a command-line flag.
1292 accessibility_state->OnScreenReaderDetected();
1293 // If it was actually enabled globally, enable it for this RenderWidget now.
1294 if (accessibility_state->IsAccessibleBrowser() && web_contents_)
1295 web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
1296 } else {
1297 accessibility_state->ResetAccessibilityMode();
1298 if (web_contents_) {
1299 web_contents_->SetAccessibilityMode(
1300 accessibility_state->accessibility_mode());
1305 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1306 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1307 if (rwhv)
1308 rwhv->UpdateScreenInfo(GetViewAndroid());
1310 static_cast<WebContentsImpl*>(web_contents())->
1311 screen_orientation_dispatcher_host()->OnOrientationChange();
1314 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1315 jobject obj,
1316 jint x,
1317 jint y,
1318 jint width,
1319 jint height) {
1320 gfx::Rect rect(
1321 static_cast<int>(x / dpi_scale()),
1322 static_cast<int>(y / dpi_scale()),
1323 static_cast<int>((width > 0 && width < dpi_scale()) ?
1324 1 : (int)(width / dpi_scale())),
1325 static_cast<int>((height > 0 && height < dpi_scale()) ?
1326 1 : (int)(height / dpi_scale())));
1327 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1328 GetWebContents()->GetRoutingID(), rect));
1331 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1332 return GetRenderProcessIdFromRenderViewHost(
1333 web_contents_->GetRenderViewHost());
1336 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1337 jboolean opaque) {
1338 if (GetRenderWidgetHostViewAndroid()) {
1339 if (opaque)
1340 GetRenderWidgetHostViewAndroid()->SetBackgroundColorToDefault();
1341 else
1342 GetRenderWidgetHostViewAndroid()->SetBackgroundColor(SK_ColorTRANSPARENT);
1346 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1347 int max_length,
1348 const base::Callback<
1349 void(const base::string16& content, int start_offset, int end_offset)>&
1350 callback) {
1351 DCHECK(!callback.is_null());
1352 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1353 if (!focused_frame)
1354 return;
1355 if (GetRenderWidgetHostViewAndroid()) {
1356 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1357 callback);
1358 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1359 focused_frame->GetRoutingID(), max_length));
1363 void ContentViewCoreImpl::OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip) {
1364 JNIEnv* env = AttachCurrentThread();
1365 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1366 if (obj.is_null())
1367 return;
1368 Java_ContentViewCore_onShowUnhandledTapUIIfNeeded(
1369 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
1370 static_cast<jint>(y_dip * dpi_scale()));
1373 float ContentViewCoreImpl::GetScaleFactor() const {
1374 return page_scale_ * dpi_scale_;
1377 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1378 const base::string16& text,
1379 const base::string16& html,
1380 const gfx::Rect& clip_rect) {
1381 JNIEnv* env = AttachCurrentThread();
1382 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1383 if (obj.is_null())
1384 return;
1385 ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
1386 ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
1387 ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
1388 Java_ContentViewCore_onSmartClipDataExtracted(
1389 env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
1392 void ContentViewCoreImpl::WebContentsDestroyed() {
1393 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1394 static_cast<WebContentsImpl*>(web_contents())->GetView());
1395 DCHECK(wcva);
1396 wcva->SetContentViewCore(NULL);
1399 bool ContentViewCoreImpl::PullStart() {
1400 JNIEnv* env = AttachCurrentThread();
1401 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1402 if (!obj.is_null())
1403 return Java_ContentViewCore_onOverscrollRefreshStart(env, obj.obj());
1404 return false;
1407 void ContentViewCoreImpl::PullUpdate(float delta) {
1408 JNIEnv* env = AttachCurrentThread();
1409 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1410 if (!obj.is_null())
1411 Java_ContentViewCore_onOverscrollRefreshUpdate(env, obj.obj(), delta);
1414 void ContentViewCoreImpl::PullRelease(bool allow_refresh) {
1415 JNIEnv* env = AttachCurrentThread();
1416 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1417 if (!obj.is_null()) {
1418 Java_ContentViewCore_onOverscrollRefreshRelease(env, obj.obj(),
1419 allow_refresh);
1423 void ContentViewCoreImpl::PullReset() {
1424 JNIEnv* env = AttachCurrentThread();
1425 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1426 if (!obj.is_null())
1427 Java_ContentViewCore_onOverscrollRefreshReset(env, obj.obj());
1430 // This is called for each ContentView.
1431 jlong Init(JNIEnv* env,
1432 const JavaParamRef<jobject>& obj,
1433 const JavaParamRef<jobject>& web_contents,
1434 const JavaParamRef<jobject>& view_android_delegate,
1435 jlong window_android,
1436 const JavaParamRef<jobject>& retained_objects_set) {
1437 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1438 env, obj, WebContents::FromJavaWebContents(web_contents),
1439 view_android_delegate,
1440 reinterpret_cast<ui::WindowAndroid*>(window_android),
1441 retained_objects_set);
1442 return reinterpret_cast<intptr_t>(view);
1445 static ScopedJavaLocalRef<jobject> FromWebContentsAndroid(
1446 JNIEnv* env,
1447 const JavaParamRef<jclass>& clazz,
1448 const JavaParamRef<jobject>& jweb_contents) {
1449 WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
1450 if (!web_contents)
1451 return ScopedJavaLocalRef<jobject>();
1453 ContentViewCore* view = ContentViewCore::FromWebContents(web_contents);
1454 if (!view)
1455 return ScopedJavaLocalRef<jobject>();
1457 return view->GetJavaObject();
1460 bool RegisterContentViewCore(JNIEnv* env) {
1461 return RegisterNativesImpl(env);
1464 } // namespace content