ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / content / browser / android / content_view_core_impl.cc
blobd13d79600eae2e65f432ae7260f7ac7ab0368c9f
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/content_view_core_impl.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "cc/layers/layer.h"
17 #include "cc/layers/solid_color_layer.h"
18 #include "cc/output/begin_frame_args.h"
19 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
20 #include "content/browser/android/gesture_event_type.h"
21 #include "content/browser/android/interstitial_page_delegate_android.h"
22 #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
23 #include "content/browser/android/load_url_params.h"
24 #include "content/browser/android/popup_touch_handle_drawable.h"
25 #include "content/browser/frame_host/interstitial_page_impl.h"
26 #include "content/browser/geolocation/geolocation_service_context.h"
27 #include "content/browser/media/media_web_contents_observer.h"
28 #include "content/browser/renderer_host/compositor_impl_android.h"
29 #include "content/browser/renderer_host/input/motion_event_android.h"
30 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
31 #include "content/browser/renderer_host/input/web_input_event_util.h"
32 #include "content/browser/renderer_host/render_view_host_impl.h"
33 #include "content/browser/renderer_host/render_widget_host_impl.h"
34 #include "content/browser/renderer_host/render_widget_host_view_android.h"
35 #include "content/browser/transition_request_manager.h"
36 #include "content/browser/web_contents/web_contents_view_android.h"
37 #include "content/common/frame_messages.h"
38 #include "content/common/input/web_input_event_traits.h"
39 #include "content/common/input_messages.h"
40 #include "content/common/view_messages.h"
41 #include "content/public/browser/browser_context.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/favicon_status.h"
44 #include "content/public/browser/render_frame_host.h"
45 #include "content/public/browser/screen_orientation_dispatcher_host.h"
46 #include "content/public/browser/ssl_host_state_delegate.h"
47 #include "content/public/browser/web_contents.h"
48 #include "content/public/common/content_client.h"
49 #include "content/public/common/content_switches.h"
50 #include "content/public/common/menu_item.h"
51 #include "content/public/common/user_agent.h"
52 #include "jni/ContentViewCore_jni.h"
53 #include "third_party/WebKit/public/web/WebInputEvent.h"
54 #include "ui/android/view_android.h"
55 #include "ui/android/window_android.h"
56 #include "ui/gfx/android/java_bitmap.h"
57 #include "ui/gfx/geometry/size_conversions.h"
58 #include "ui/gfx/geometry/size_f.h"
59 #include "ui/gfx/screen.h"
61 using base::android::AttachCurrentThread;
62 using base::android::ConvertJavaStringToUTF16;
63 using base::android::ConvertJavaStringToUTF8;
64 using base::android::ConvertUTF16ToJavaString;
65 using base::android::ConvertUTF8ToJavaString;
66 using base::android::ScopedJavaLocalRef;
67 using blink::WebGestureEvent;
68 using blink::WebInputEvent;
70 // Describes the type and enabled state of a select popup item.
71 namespace {
73 // A Java counterpart will be generated for this enum.
74 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.input
75 enum PopupItemType {
76 // Popup item is of type group
77 POPUP_ITEM_TYPE_GROUP,
79 // Popup item is disabled
80 POPUP_ITEM_TYPE_DISABLED,
82 // Popup item is enabled
83 POPUP_ITEM_TYPE_ENABLED,
86 } //namespace
88 namespace content {
90 namespace {
92 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
94 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
95 DCHECK(host);
96 RenderProcessHost* render_process = host->GetProcess();
97 DCHECK(render_process);
98 if (render_process->HasConnection())
99 return render_process->GetHandle();
100 else
101 return 0;
104 ScopedJavaLocalRef<jobject> CreateJavaRect(
105 JNIEnv* env,
106 const gfx::Rect& rect) {
107 return ScopedJavaLocalRef<jobject>(
108 Java_ContentViewCore_createRect(env,
109 static_cast<int>(rect.x()),
110 static_cast<int>(rect.y()),
111 static_cast<int>(rect.right()),
112 static_cast<int>(rect.bottom())));
115 int ToGestureEventType(WebInputEvent::Type type) {
116 switch (type) {
117 case WebInputEvent::GestureScrollBegin:
118 return GESTURE_EVENT_TYPE_SCROLL_START;
119 case WebInputEvent::GestureScrollEnd:
120 return GESTURE_EVENT_TYPE_SCROLL_END;
121 case WebInputEvent::GestureScrollUpdate:
122 return GESTURE_EVENT_TYPE_SCROLL_BY;
123 case WebInputEvent::GestureFlingStart:
124 return GESTURE_EVENT_TYPE_FLING_START;
125 case WebInputEvent::GestureFlingCancel:
126 return GESTURE_EVENT_TYPE_FLING_CANCEL;
127 case WebInputEvent::GestureShowPress:
128 return GESTURE_EVENT_TYPE_SHOW_PRESS;
129 case WebInputEvent::GestureTap:
130 return GESTURE_EVENT_TYPE_SINGLE_TAP_CONFIRMED;
131 case WebInputEvent::GestureTapUnconfirmed:
132 return GESTURE_EVENT_TYPE_SINGLE_TAP_UNCONFIRMED;
133 case WebInputEvent::GestureTapDown:
134 return GESTURE_EVENT_TYPE_TAP_DOWN;
135 case WebInputEvent::GestureTapCancel:
136 return GESTURE_EVENT_TYPE_TAP_CANCEL;
137 case WebInputEvent::GestureDoubleTap:
138 return GESTURE_EVENT_TYPE_DOUBLE_TAP;
139 case WebInputEvent::GestureLongPress:
140 return GESTURE_EVENT_TYPE_LONG_PRESS;
141 case WebInputEvent::GestureLongTap:
142 return GESTURE_EVENT_TYPE_LONG_TAP;
143 case WebInputEvent::GesturePinchBegin:
144 return GESTURE_EVENT_TYPE_PINCH_BEGIN;
145 case WebInputEvent::GesturePinchEnd:
146 return GESTURE_EVENT_TYPE_PINCH_END;
147 case WebInputEvent::GesturePinchUpdate:
148 return GESTURE_EVENT_TYPE_PINCH_BY;
149 case WebInputEvent::GestureTwoFingerTap:
150 default:
151 NOTREACHED() << "Invalid source gesture type: "
152 << WebInputEventTraits::GetName(type);
153 return -1;
157 float GetPrimaryDisplayDeviceScaleFactor() {
158 const gfx::Display& display =
159 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
160 return display.device_scale_factor();
163 } // namespace
165 // Enables a callback when the underlying WebContents is destroyed, to enable
166 // nulling the back-pointer.
167 class ContentViewCoreImpl::ContentViewUserData
168 : public base::SupportsUserData::Data {
169 public:
170 explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
171 : content_view_core_(content_view_core) {
174 ~ContentViewUserData() override {
175 // TODO(joth): When chrome has finished removing the TabContents class (see
176 // crbug.com/107201) consider inverting relationship, so ContentViewCore
177 // would own WebContents. That effectively implies making the WebContents
178 // destructor private on Android.
179 delete content_view_core_;
182 ContentViewCoreImpl* get() const { return content_view_core_; }
184 private:
185 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
186 ContentViewCoreImpl* content_view_core_;
188 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
191 // static
192 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
193 content::WebContents* web_contents) {
194 ContentViewCoreImpl::ContentViewUserData* data =
195 static_cast<ContentViewCoreImpl::ContentViewUserData*>(
196 web_contents->GetUserData(kContentViewUserDataKey));
197 return data ? data->get() : NULL;
200 // static
201 ContentViewCore* ContentViewCore::FromWebContents(
202 content::WebContents* web_contents) {
203 return ContentViewCoreImpl::FromWebContents(web_contents);
206 // static
207 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
208 jobject obj) {
209 return reinterpret_cast<ContentViewCore*>(
210 Java_ContentViewCore_getNativeContentViewCore(env, obj));
213 ContentViewCoreImpl::ContentViewCoreImpl(
214 JNIEnv* env,
215 jobject obj,
216 WebContents* web_contents,
217 ui::ViewAndroid* view_android,
218 ui::WindowAndroid* window_android,
219 jobject java_bridge_retained_object_set)
220 : WebContentsObserver(web_contents),
221 java_ref_(env, obj),
222 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
223 root_layer_(cc::SolidColorLayer::Create()),
224 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
225 view_android_(view_android),
226 window_android_(window_android),
227 device_orientation_(0),
228 accessibility_enabled_(false) {
229 CHECK(web_contents) <<
230 "A ContentViewCoreImpl should be created with a valid WebContents.";
231 DCHECK(view_android_);
232 DCHECK(window_android_);
234 root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj));
235 gfx::Size physical_size(
236 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
237 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
238 root_layer_->SetBounds(physical_size);
239 root_layer_->SetIsDrawable(true);
241 // Currently, the only use case we have for overriding a user agent involves
242 // spoofing a desktop Linux user agent for "Request desktop site".
243 // Automatically set it for all WebContents so that it is available when a
244 // NavigationEntry requires the user agent to be overridden.
245 const char kLinuxInfoStr[] = "X11; Linux x86_64";
246 std::string product = content::GetContentClient()->GetProduct();
247 std::string spoofed_ua =
248 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
249 web_contents->SetUserAgentOverride(spoofed_ua);
251 java_bridge_dispatcher_host_ =
252 new GinJavaBridgeDispatcherHost(web_contents,
253 java_bridge_retained_object_set);
255 InitWebContents();
258 ContentViewCoreImpl::~ContentViewCoreImpl() {
259 root_layer_->RemoveFromParent();
261 JNIEnv* env = base::android::AttachCurrentThread();
262 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
263 java_ref_.reset();
264 if (!j_obj.is_null()) {
265 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
266 env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
270 base::android::ScopedJavaLocalRef<jobject>
271 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
272 return web_contents_->GetJavaWebContents();
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 Java_ContentViewCore_updateFrameInfo(
395 env, obj.obj(),
396 scroll_offset.x(),
397 scroll_offset.y(),
398 page_scale_factor,
399 page_scale_factor_limits.x(),
400 page_scale_factor_limits.y(),
401 content_size.width(),
402 content_size.height(),
403 viewport_size.width(),
404 viewport_size.height(),
405 controls_offset.y(),
406 content_offset.y(),
407 is_mobile_optimized_hint);
410 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
411 JNIEnv* env = AttachCurrentThread();
412 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
413 if (obj.is_null())
414 return;
415 ScopedJavaLocalRef<jstring> jtitle =
416 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
417 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
420 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
421 root_layer_->SetBackgroundColor(color);
423 JNIEnv* env = AttachCurrentThread();
424 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
425 if (obj.is_null())
426 return;
427 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
430 void ContentViewCoreImpl::ShowSelectPopupMenu(
431 RenderFrameHost* frame,
432 const gfx::Rect& bounds,
433 const std::vector<MenuItem>& items,
434 int selected_item,
435 bool multiple) {
436 JNIEnv* env = AttachCurrentThread();
437 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
438 if (j_obj.is_null())
439 return;
441 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
443 // For multi-select list popups we find the list of previous selections by
444 // iterating through the items. But for single selection popups we take the
445 // given |selected_item| as is.
446 ScopedJavaLocalRef<jintArray> selected_array;
447 if (multiple) {
448 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
449 size_t selected_count = 0;
450 for (size_t i = 0; i < items.size(); ++i) {
451 if (items[i].checked)
452 native_selected_array[selected_count++] = i;
455 selected_array = ScopedJavaLocalRef<jintArray>(
456 env, env->NewIntArray(selected_count));
457 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
458 native_selected_array.get());
459 } else {
460 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
461 jint value = selected_item;
462 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
465 ScopedJavaLocalRef<jintArray> enabled_array(env,
466 env->NewIntArray(items.size()));
467 std::vector<base::string16> labels;
468 labels.reserve(items.size());
469 for (size_t i = 0; i < items.size(); ++i) {
470 labels.push_back(items[i].label);
471 jint enabled =
472 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
473 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
474 POPUP_ITEM_TYPE_DISABLED));
475 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
477 ScopedJavaLocalRef<jobjectArray> items_array(
478 base::android::ToJavaArrayOfStrings(env, labels));
479 Java_ContentViewCore_showSelectPopup(env,
480 j_obj.obj(),
481 reinterpret_cast<intptr_t>(frame),
482 bounds_rect.obj(),
483 items_array.obj(),
484 enabled_array.obj(),
485 multiple,
486 selected_array.obj());
489 void ContentViewCoreImpl::HideSelectPopupMenu() {
490 JNIEnv* env = AttachCurrentThread();
491 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
492 if (!j_obj.is_null())
493 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
496 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
497 InputEventAckState ack_result) {
498 JNIEnv* env = AttachCurrentThread();
499 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
500 if (j_obj.is_null())
501 return;
503 switch (event.type) {
504 case WebInputEvent::GestureFlingStart:
505 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
506 // The view expects the fling velocity in pixels/s.
507 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
508 event.data.flingStart.velocityX * dpi_scale(),
509 event.data.flingStart.velocityY * dpi_scale());
510 } else {
511 // If a scroll ends with a fling, a SCROLL_END event is never sent.
512 // However, if that fling went unconsumed, we still need to let the
513 // listeners know that scrolling has ended.
514 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
517 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
518 // The view expects the fling velocity in pixels/s.
519 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
520 event.data.flingStart.velocityX * dpi_scale(),
521 event.data.flingStart.velocityY * dpi_scale());
523 break;
524 case WebInputEvent::GestureFlingCancel:
525 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
526 break;
527 case WebInputEvent::GestureScrollBegin:
528 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
529 break;
530 case WebInputEvent::GestureScrollUpdate:
531 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
532 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
533 break;
534 case WebInputEvent::GestureScrollEnd:
535 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
536 break;
537 case WebInputEvent::GesturePinchBegin:
538 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
539 break;
540 case WebInputEvent::GesturePinchEnd:
541 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
542 break;
543 case WebInputEvent::GestureTap:
544 Java_ContentViewCore_onSingleTapEventAck(
545 env,
546 j_obj.obj(),
547 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
548 event.x * dpi_scale(),
549 event.y * dpi_scale());
550 break;
551 default:
552 break;
556 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
557 if (event.type != WebInputEvent::GestureTap &&
558 event.type != WebInputEvent::GestureDoubleTap &&
559 event.type != WebInputEvent::GestureLongTap &&
560 event.type != WebInputEvent::GestureLongPress)
561 return false;
563 JNIEnv* env = AttachCurrentThread();
564 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
565 if (j_obj.is_null())
566 return false;
568 const blink::WebGestureEvent& gesture =
569 static_cast<const blink::WebGestureEvent&>(event);
570 int gesture_type = ToGestureEventType(event.type);
571 return Java_ContentViewCore_filterTapOrPressEvent(env,
572 j_obj.obj(),
573 gesture_type,
574 gesture.x * dpi_scale(),
575 gesture.y * dpi_scale());
577 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
580 bool ContentViewCoreImpl::HasFocus() {
581 JNIEnv* env = AttachCurrentThread();
582 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
583 if (obj.is_null())
584 return false;
585 return Java_ContentViewCore_hasFocus(env, obj.obj());
588 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
589 JNIEnv* env = AttachCurrentThread();
590 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
591 if (obj.is_null())
592 return;
593 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
594 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
597 void ContentViewCoreImpl::OnSelectionEvent(ui::SelectionEventType event,
598 const gfx::PointF& position) {
599 JNIEnv* env = AttachCurrentThread();
600 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
601 if (j_obj.is_null())
602 return;
603 Java_ContentViewCore_onSelectionEvent(env, j_obj.obj(), event,
604 position.x() * dpi_scale(),
605 position.y() * dpi_scale());
608 scoped_ptr<ui::TouchHandleDrawable>
609 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
610 JNIEnv* env = AttachCurrentThread();
611 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
612 if (obj.is_null()) {
613 NOTREACHED();
614 return scoped_ptr<ui::TouchHandleDrawable>();
616 return scoped_ptr<ui::TouchHandleDrawable>(new PopupTouchHandleDrawable(
617 Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()),
618 dpi_scale_));
621 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
622 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
623 if (!view)
624 return;
626 view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
628 JNIEnv* env = AttachCurrentThread();
629 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
630 if (obj.is_null())
631 return;
632 Java_ContentViewCore_showPastePopupWithFeedback(
633 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
634 static_cast<jint>(y_dip * dpi_scale()));
637 void ContentViewCoreImpl::GetScaledContentBitmap(
638 float scale,
639 SkColorType color_type,
640 gfx::Rect src_subrect,
641 ReadbackRequestCallback& result_callback) {
642 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
643 if (!view) {
644 result_callback.Run(SkBitmap(), READBACK_FAILED);
645 return;
648 view->GetScaledContentBitmap(scale, color_type, src_subrect,
649 result_callback);
652 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
653 JNIEnv* env = AttachCurrentThread();
654 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
655 if (j_obj.is_null())
656 return;
657 ScopedJavaLocalRef<jstring> jcontent_url =
658 ConvertUTF8ToJavaString(env, content_url.spec());
659 Java_ContentViewCore_startContentIntent(env,
660 j_obj.obj(),
661 jcontent_url.obj());
664 void ContentViewCoreImpl::ShowDisambiguationPopup(
665 const gfx::Rect& rect_pixels,
666 const SkBitmap& zoomed_bitmap) {
667 JNIEnv* env = AttachCurrentThread();
669 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
670 if (obj.is_null())
671 return;
673 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
675 ScopedJavaLocalRef<jobject> java_bitmap =
676 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
677 DCHECK(!java_bitmap.is_null());
679 Java_ContentViewCore_showDisambiguationPopup(env,
680 obj.obj(),
681 rect_object.obj(),
682 java_bitmap.obj());
685 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
686 JNIEnv* env = AttachCurrentThread();
688 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
689 if (obj.is_null())
690 return ScopedJavaLocalRef<jobject>();
691 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
694 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
695 JNIEnv* env = AttachCurrentThread();
697 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
698 if (obj.is_null())
699 return true;
700 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
701 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
702 j_url.obj());
705 void ContentViewCoreImpl::DidStopFlinging() {
706 JNIEnv* env = AttachCurrentThread();
708 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
709 if (!obj.is_null())
710 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
713 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() const {
714 JNIEnv* env = AttachCurrentThread();
716 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
717 if (obj.is_null())
718 return ScopedJavaLocalRef<jobject>();
720 return Java_ContentViewCore_getContext(env, obj.obj());
723 gfx::Size ContentViewCoreImpl::GetViewSize() const {
724 gfx::Size size = GetViewportSizeDip();
725 if (DoTopControlsShrinkBlinkSize())
726 size.Enlarge(0, -GetTopControlsHeightDip());
727 return size;
730 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
731 JNIEnv* env = AttachCurrentThread();
732 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
733 if (j_obj.is_null())
734 return gfx::Size();
735 return gfx::Size(
736 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
737 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
740 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
741 JNIEnv* env = AttachCurrentThread();
742 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
743 if (j_obj.is_null())
744 return gfx::Size();
745 return gfx::Size(
746 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
747 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
750 int ContentViewCoreImpl::GetTopControlsHeightPix() const {
751 JNIEnv* env = AttachCurrentThread();
752 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
753 if (j_obj.is_null())
754 return 0;
755 return Java_ContentViewCore_getTopControlsHeightPix(env, j_obj.obj());
758 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
759 return gfx::ToCeiledSize(
760 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
763 bool ContentViewCoreImpl::DoTopControlsShrinkBlinkSize() const {
764 JNIEnv* env = AttachCurrentThread();
765 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
766 if (j_obj.is_null())
767 return false;
768 return Java_ContentViewCore_doTopControlsShrinkBlinkSize(env, j_obj.obj());
771 float ContentViewCoreImpl::GetTopControlsHeightDip() const {
772 return GetTopControlsHeightPix() / dpi_scale();
775 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
776 root_layer_->InsertChild(layer, 0);
777 root_layer_->SetIsDrawable(false);
780 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
781 layer->RemoveFromParent();
783 if (!root_layer_->children().size())
784 root_layer_->SetIsDrawable(true);
787 void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF& extent) {
788 if (!web_contents_)
789 return;
791 web_contents_->MoveRangeSelectionExtent(gfx::Point(extent.x(), extent.y()));
794 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& base,
795 const gfx::PointF& extent) {
796 if (!web_contents_)
797 return;
799 gfx::Point base_point = gfx::Point(base.x(), base.y());
800 gfx::Point extent_point = gfx::Point(extent.x(), extent.y());
801 if (base_point == extent_point)
802 return;
804 web_contents_->SelectRange(base_point, extent_point);
807 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
808 return view_android_;
811 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
812 return window_android_;
815 const scoped_refptr<cc::Layer>& ContentViewCoreImpl::GetLayer() const {
816 return root_layer_;
819 // ----------------------------------------------------------------------------
820 // Methods called from Java via JNI
821 // ----------------------------------------------------------------------------
823 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
824 jobject obj,
825 jlong selectPopupSourceFrame,
826 jintArray indices) {
827 RenderFrameHostImpl* rfhi =
828 reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
829 DCHECK(rfhi);
830 if (indices == NULL) {
831 rfhi->DidCancelPopupMenu();
832 return;
835 int selected_count = env->GetArrayLength(indices);
836 std::vector<int> selected_indices;
837 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
838 for (int i = 0; i < selected_count; ++i)
839 selected_indices.push_back(indices_ptr[i]);
840 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
841 rfhi->DidSelectPopupMenuItems(selected_indices);
844 WebContents* ContentViewCoreImpl::GetWebContents() const {
845 return web_contents_;
848 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
849 SetFocusInternal(focused);
852 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
853 if (!GetRenderWidgetHostViewAndroid())
854 return;
856 if (focused)
857 GetRenderWidgetHostViewAndroid()->Focus();
858 else
859 GetRenderWidgetHostViewAndroid()->Blur();
862 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
863 jobject obj,
864 jint orientation) {
865 if (device_orientation_ != orientation) {
866 device_orientation_ = orientation;
867 SendOrientationChangeEventInternal();
871 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
872 jobject obj,
873 jobject motion_event,
874 jlong time_ms,
875 jint android_action,
876 jint pointer_count,
877 jint history_size,
878 jint action_index,
879 jfloat pos_x_0,
880 jfloat pos_y_0,
881 jfloat pos_x_1,
882 jfloat pos_y_1,
883 jint pointer_id_0,
884 jint pointer_id_1,
885 jfloat touch_major_0,
886 jfloat touch_major_1,
887 jfloat touch_minor_0,
888 jfloat touch_minor_1,
889 jfloat orientation_0,
890 jfloat orientation_1,
891 jfloat raw_pos_x,
892 jfloat raw_pos_y,
893 jint android_tool_type_0,
894 jint android_tool_type_1,
895 jint android_button_state,
896 jint android_meta_state,
897 jboolean is_touch_handle_event) {
898 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
899 // Avoid synthesizing a touch event if it cannot be forwarded.
900 if (!rwhv)
901 return false;
903 MotionEventAndroid::Pointer pointer0(pointer_id_0,
904 pos_x_0,
905 pos_y_0,
906 touch_major_0,
907 touch_minor_0,
908 orientation_0,
909 android_tool_type_0);
910 MotionEventAndroid::Pointer pointer1(pointer_id_1,
911 pos_x_1,
912 pos_y_1,
913 touch_major_1,
914 touch_minor_1,
915 orientation_1,
916 android_tool_type_1);
917 MotionEventAndroid event(1.f / dpi_scale(),
918 env,
919 motion_event,
920 time_ms,
921 android_action,
922 pointer_count,
923 history_size,
924 action_index,
925 android_button_state,
926 android_meta_state,
927 raw_pos_x - pos_x_0,
928 raw_pos_y - pos_y_0,
929 pointer0,
930 pointer1);
932 return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
933 : rwhv->OnTouchEvent(event);
936 float ContentViewCoreImpl::GetDpiScale() const {
937 return dpi_scale_;
940 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
941 jobject obj,
942 jlong time_ms,
943 jfloat x,
944 jfloat y) {
945 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
946 if (!rwhv)
947 return false;
949 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
950 WebInputEvent::MouseMove,
951 blink::WebMouseEvent::ButtonNone,
952 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
954 rwhv->SendMouseEvent(event);
955 return true;
958 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
959 jobject obj,
960 jlong time_ms,
961 jfloat x,
962 jfloat y,
963 jfloat vertical_axis,
964 jfloat horizontal_axis) {
965 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
966 if (!rwhv)
967 return false;
969 WebMouseWheelEventBuilder::Direction direction;
970 if (vertical_axis > 0) {
971 direction = WebMouseWheelEventBuilder::DIRECTION_UP;
972 } else if (vertical_axis < 0) {
973 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
974 } else if (horizontal_axis > 0) {
975 direction = WebMouseWheelEventBuilder::DIRECTION_RIGHT;
976 } else if (horizontal_axis < 0) {
977 direction = WebMouseWheelEventBuilder::DIRECTION_LEFT;
978 } else {
979 return false;
981 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
982 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
984 rwhv->SendMouseWheelEvent(event);
985 return true;
988 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
989 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
990 return WebGestureEventBuilder::Build(
991 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
994 void ContentViewCoreImpl::SendGestureEvent(
995 const blink::WebGestureEvent& event) {
996 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
997 if (rwhv)
998 rwhv->SendGestureEvent(event);
1001 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
1002 jobject obj,
1003 jlong time_ms,
1004 jfloat x,
1005 jfloat y,
1006 jfloat hintx,
1007 jfloat hinty) {
1008 WebGestureEvent event = MakeGestureEvent(
1009 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1010 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1011 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1013 SendGestureEvent(event);
1016 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1017 WebGestureEvent event = MakeGestureEvent(
1018 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1019 SendGestureEvent(event);
1022 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1023 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1024 WebGestureEvent event = MakeGestureEvent(
1025 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1026 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1027 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1029 SendGestureEvent(event);
1032 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1033 jfloat x, jfloat y, jfloat vx, jfloat vy) {
1034 WebGestureEvent event = MakeGestureEvent(
1035 WebInputEvent::GestureFlingStart, time_ms, x, y);
1036 event.data.flingStart.velocityX = vx / dpi_scale();
1037 event.data.flingStart.velocityY = vy / dpi_scale();
1039 SendGestureEvent(event);
1042 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1043 WebGestureEvent event = MakeGestureEvent(
1044 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1045 event.data.flingCancel.preventBoosting = true;
1047 SendGestureEvent(event);
1050 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1051 jfloat x, jfloat y) {
1052 // Tap gestures should always be preceded by a TapDown, ensuring consistency
1053 // with the touch-based gesture detection pipeline.
1054 WebGestureEvent tap_down_event = MakeGestureEvent(
1055 WebInputEvent::GestureTapDown, time_ms, x, y);
1056 tap_down_event.data.tap.tapCount = 1;
1057 SendGestureEvent(tap_down_event);
1059 WebGestureEvent tap_event = MakeGestureEvent(
1060 WebInputEvent::GestureTap, time_ms, x, y);
1061 tap_event.data.tap.tapCount = 1;
1062 SendGestureEvent(tap_event);
1065 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1066 jfloat x, jfloat y) {
1067 WebGestureEvent event = MakeGestureEvent(
1068 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1069 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1070 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1071 event.data.tap.tapCount = 1;
1073 SendGestureEvent(event);
1076 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1077 jfloat x, jfloat y) {
1078 WebGestureEvent event = MakeGestureEvent(
1079 WebInputEvent::GestureLongPress, time_ms, x, y);
1081 SendGestureEvent(event);
1084 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1085 jfloat x, jfloat y) {
1086 WebGestureEvent event = MakeGestureEvent(
1087 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1088 SendGestureEvent(event);
1091 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1092 WebGestureEvent event = MakeGestureEvent(
1093 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1094 SendGestureEvent(event);
1097 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1098 jfloat anchor_x, jfloat anchor_y,
1099 jfloat delta) {
1100 WebGestureEvent event = MakeGestureEvent(
1101 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1102 event.data.pinchUpdate.scale = delta;
1104 SendGestureEvent(event);
1107 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1108 jfloat x1, jfloat y1,
1109 jfloat x2, jfloat y2) {
1110 SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
1111 gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
1114 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1115 jfloat x, jfloat y) {
1116 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1117 if (rwhv)
1118 rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
1121 void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
1122 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1123 if (rwhv)
1124 rwhv->DismissTextHandles();
1127 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
1128 jobject obj,
1129 jboolean hidden) {
1130 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1131 if (rwhv)
1132 rwhv->SetTextHandlesTemporarilyHidden(hidden);
1135 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1136 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1137 if (rwhv)
1138 rwhv->ResetGestureDetection();
1141 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1142 jobject obj,
1143 jboolean enabled) {
1144 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1145 if (rwhv)
1146 rwhv->SetDoubleTapSupportEnabled(enabled);
1149 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1150 jobject obj,
1151 jboolean enabled) {
1152 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1153 if (rwhv)
1154 rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1157 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1158 JNIEnv* env,
1159 jobject obj,
1160 jboolean allow) {
1161 java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
1164 void ContentViewCoreImpl::AddJavascriptInterface(
1165 JNIEnv* env,
1166 jobject /* obj */,
1167 jobject object,
1168 jstring name,
1169 jclass safe_annotation_clazz) {
1170 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1171 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1172 java_bridge_dispatcher_host_->AddNamedObject(
1173 ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
1176 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1177 jobject /* obj */,
1178 jstring name) {
1179 java_bridge_dispatcher_host_->RemoveNamedObject(
1180 ConvertJavaStringToUTF8(env, name));
1183 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1184 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1185 gfx::Size physical_size(
1186 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1187 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1188 root_layer_->SetBounds(physical_size);
1190 if (view) {
1191 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1192 view->GetRenderWidgetHost());
1193 host->SendScreenRects();
1194 view->WasResized();
1198 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1199 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1200 if (!rwhva)
1201 return 0;
1202 return rwhva->GetNativeImeAdapter();
1205 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1206 int text_input_type,
1207 int text_input_flags,
1208 const std::string& text,
1209 int selection_start,
1210 int selection_end,
1211 int composition_start,
1212 int composition_end,
1213 bool show_ime_if_needed,
1214 bool is_non_ime_change) {
1215 JNIEnv* env = AttachCurrentThread();
1216 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1217 if (obj.is_null())
1218 return;
1220 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1221 Java_ContentViewCore_updateImeAdapter(env,
1222 obj.obj(),
1223 native_ime_adapter,
1224 text_input_type,
1225 text_input_flags,
1226 jstring_text.obj(),
1227 selection_start,
1228 selection_end,
1229 composition_start,
1230 composition_end,
1231 show_ime_if_needed,
1232 is_non_ime_change);
1235 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1236 bool enabled) {
1237 SetAccessibilityEnabledInternal(enabled);
1240 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1241 JNIEnv* env = AttachCurrentThread();
1242 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1243 if (obj.is_null())
1244 return true;
1245 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
1246 obj.obj());
1249 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1250 accessibility_enabled_ = enabled;
1251 BrowserAccessibilityStateImpl* accessibility_state =
1252 BrowserAccessibilityStateImpl::GetInstance();
1253 if (enabled) {
1254 // This enables accessibility globally unless it was explicitly disallowed
1255 // by a command-line flag.
1256 accessibility_state->OnScreenReaderDetected();
1257 // If it was actually enabled globally, enable it for this RenderWidget now.
1258 if (accessibility_state->IsAccessibleBrowser() && web_contents_)
1259 web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
1260 } else {
1261 accessibility_state->ResetAccessibilityMode();
1262 if (web_contents_) {
1263 web_contents_->SetAccessibilityMode(
1264 accessibility_state->accessibility_mode());
1269 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1270 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1271 if (rwhv)
1272 rwhv->UpdateScreenInfo(GetViewAndroid());
1274 static_cast<WebContentsImpl*>(web_contents())->
1275 screen_orientation_dispatcher_host()->OnOrientationChange();
1278 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1279 jobject obj,
1280 jint x,
1281 jint y,
1282 jint width,
1283 jint height) {
1284 gfx::Rect rect(
1285 static_cast<int>(x / dpi_scale()),
1286 static_cast<int>(y / dpi_scale()),
1287 static_cast<int>((width > 0 && width < dpi_scale()) ?
1288 1 : (int)(width / dpi_scale())),
1289 static_cast<int>((height > 0 && height < dpi_scale()) ?
1290 1 : (int)(height / dpi_scale())));
1291 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1292 GetWebContents()->GetRoutingID(), rect));
1295 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1296 return GetRenderProcessIdFromRenderViewHost(
1297 web_contents_->GetRenderViewHost());
1300 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1301 jboolean opaque) {
1302 if (GetRenderWidgetHostViewAndroid()) {
1303 if (opaque)
1304 GetRenderWidgetHostViewAndroid()->SetBackgroundColorToDefault();
1305 else
1306 GetRenderWidgetHostViewAndroid()->SetBackgroundColor(SK_ColorTRANSPARENT);
1310 void ContentViewCoreImpl::SetDrawsContent(JNIEnv* env,
1311 jobject jobj,
1312 jboolean draws) {
1313 GetLayer()->SetHideLayerAndSubtree(!draws);
1316 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1317 int max_length,
1318 const base::Callback<
1319 void(const base::string16& content, int start_offset, int end_offset)>&
1320 callback) {
1321 DCHECK(!callback.is_null());
1322 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1323 if (!focused_frame)
1324 return;
1325 if (GetRenderWidgetHostViewAndroid()) {
1326 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1327 callback);
1328 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1329 focused_frame->GetRoutingID(), max_length));
1333 void ContentViewCoreImpl::OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip) {
1334 JNIEnv* env = AttachCurrentThread();
1335 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1336 if (obj.is_null())
1337 return;
1338 Java_ContentViewCore_onShowUnhandledTapUIIfNeeded(
1339 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
1340 static_cast<jint>(y_dip * dpi_scale()));
1343 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1344 const base::string16& text,
1345 const base::string16& html,
1346 const gfx::Rect& clip_rect) {
1347 JNIEnv* env = AttachCurrentThread();
1348 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1349 if (obj.is_null())
1350 return;
1351 ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
1352 ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
1353 ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
1354 Java_ContentViewCore_onSmartClipDataExtracted(
1355 env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
1358 void ContentViewCoreImpl::WebContentsDestroyed() {
1359 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1360 static_cast<WebContentsImpl*>(web_contents())->GetView());
1361 DCHECK(wcva);
1362 wcva->SetContentViewCore(NULL);
1365 // This is called for each ContentView.
1366 jlong Init(JNIEnv* env,
1367 jobject obj,
1368 jobject web_contents,
1369 jlong view_android,
1370 jlong window_android,
1371 jobject retained_objects_set) {
1372 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1373 env, obj,
1374 WebContents::FromJavaWebContents(web_contents),
1375 reinterpret_cast<ui::ViewAndroid*>(view_android),
1376 reinterpret_cast<ui::WindowAndroid*>(window_android),
1377 retained_objects_set);
1378 return reinterpret_cast<intptr_t>(view);
1381 static jobject FromWebContentsAndroid(
1382 JNIEnv* env,
1383 jclass clazz,
1384 jobject jweb_contents) {
1385 WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
1386 if (!web_contents)
1387 return NULL;
1389 ContentViewCore* view = ContentViewCore::FromWebContents(web_contents);
1390 if (!view)
1391 return NULL;
1393 return view->GetJavaObject().Release();
1396 bool RegisterContentViewCore(JNIEnv* env) {
1397 return RegisterNativesImpl(env);
1400 } // namespace content