Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / android / content_view_core_impl.cc
blobcd11919c08046bdcd954a25d846a028fa2a2f4d2
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/content_view_core_impl.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "cc/layers/layer.h"
17 #include "cc/layers/solid_color_layer.h"
18 #include "cc/output/begin_frame_args.h"
19 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
20 #include "content/browser/android/gesture_event_type.h"
21 #include "content/browser/android/interstitial_page_delegate_android.h"
22 #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
23 #include "content/browser/android/load_url_params.h"
24 #include "content/browser/android/popup_touch_handle_drawable.h"
25 #include "content/browser/frame_host/interstitial_page_impl.h"
26 #include "content/browser/geolocation/geolocation_service_context.h"
27 #include "content/browser/media/media_web_contents_observer.h"
28 #include "content/browser/renderer_host/compositor_impl_android.h"
29 #include "content/browser/renderer_host/input/motion_event_android.h"
30 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
31 #include "content/browser/renderer_host/input/web_input_event_util.h"
32 #include "content/browser/renderer_host/render_view_host_impl.h"
33 #include "content/browser/renderer_host/render_widget_host_impl.h"
34 #include "content/browser/renderer_host/render_widget_host_view_android.h"
35 #include "content/browser/transition_request_manager.h"
36 #include "content/browser/web_contents/web_contents_view_android.h"
37 #include "content/common/frame_messages.h"
38 #include "content/common/input/web_input_event_traits.h"
39 #include "content/common/input_messages.h"
40 #include "content/common/view_messages.h"
41 #include "content/public/browser/browser_context.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/favicon_status.h"
44 #include "content/public/browser/render_frame_host.h"
45 #include "content/public/browser/screen_orientation_dispatcher_host.h"
46 #include "content/public/browser/ssl_host_state_delegate.h"
47 #include "content/public/browser/web_contents.h"
48 #include "content/public/common/content_client.h"
49 #include "content/public/common/content_switches.h"
50 #include "content/public/common/menu_item.h"
51 #include "content/public/common/user_agent.h"
52 #include "jni/ContentViewCore_jni.h"
53 #include "third_party/WebKit/public/web/WebInputEvent.h"
54 #include "ui/base/android/view_android.h"
55 #include "ui/base/android/window_android.h"
56 #include "ui/gfx/android/java_bitmap.h"
57 #include "ui/gfx/screen.h"
58 #include "ui/gfx/size_conversions.h"
59 #include "ui/gfx/size_f.h"
61 using base::android::AttachCurrentThread;
62 using base::android::ConvertJavaStringToUTF16;
63 using base::android::ConvertJavaStringToUTF8;
64 using base::android::ConvertUTF16ToJavaString;
65 using base::android::ConvertUTF8ToJavaString;
66 using base::android::ScopedJavaLocalRef;
67 using blink::WebGestureEvent;
68 using blink::WebInputEvent;
70 // Describes the type and enabled state of a select popup item.
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 case WebInputEvent::GestureScrollUpdateWithoutPropagation:
151 default:
152 NOTREACHED() << "Invalid source gesture type: "
153 << WebInputEventTraits::GetName(type);
154 return -1;
158 float GetPrimaryDisplayDeviceScaleFactor() {
159 const gfx::Display& display =
160 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
161 return display.device_scale_factor();
164 } // namespace
166 // Enables a callback when the underlying WebContents is destroyed, to enable
167 // nulling the back-pointer.
168 class ContentViewCoreImpl::ContentViewUserData
169 : public base::SupportsUserData::Data {
170 public:
171 explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
172 : content_view_core_(content_view_core) {
175 virtual ~ContentViewUserData() {
176 // TODO(joth): When chrome has finished removing the TabContents class (see
177 // crbug.com/107201) consider inverting relationship, so ContentViewCore
178 // would own WebContents. That effectively implies making the WebContents
179 // destructor private on Android.
180 delete content_view_core_;
183 ContentViewCoreImpl* get() const { return content_view_core_; }
185 private:
186 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
187 ContentViewCoreImpl* content_view_core_;
189 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
192 // static
193 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
194 content::WebContents* web_contents) {
195 ContentViewCoreImpl::ContentViewUserData* data =
196 static_cast<ContentViewCoreImpl::ContentViewUserData*>(
197 web_contents->GetUserData(kContentViewUserDataKey));
198 return data ? data->get() : NULL;
201 // static
202 ContentViewCore* ContentViewCore::FromWebContents(
203 content::WebContents* web_contents) {
204 return ContentViewCoreImpl::FromWebContents(web_contents);
207 // static
208 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
209 jobject obj) {
210 return reinterpret_cast<ContentViewCore*>(
211 Java_ContentViewCore_getNativeContentViewCore(env, obj));
214 ContentViewCoreImpl::ContentViewCoreImpl(
215 JNIEnv* env,
216 jobject obj,
217 WebContents* web_contents,
218 ui::ViewAndroid* view_android,
219 ui::WindowAndroid* window_android,
220 jobject java_bridge_retained_object_set)
221 : WebContentsObserver(web_contents),
222 java_ref_(env, obj),
223 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
224 root_layer_(cc::SolidColorLayer::Create()),
225 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
226 view_android_(view_android),
227 window_android_(window_android),
228 device_orientation_(0),
229 accessibility_enabled_(false) {
230 CHECK(web_contents) <<
231 "A ContentViewCoreImpl should be created with a valid WebContents.";
232 DCHECK(view_android_);
233 DCHECK(window_android_);
235 root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj));
236 gfx::Size physical_size(
237 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
238 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
239 root_layer_->SetBounds(physical_size);
240 root_layer_->SetIsDrawable(true);
242 // Currently, the only use case we have for overriding a user agent involves
243 // spoofing a desktop Linux user agent for "Request desktop site".
244 // Automatically set it for all WebContents so that it is available when a
245 // NavigationEntry requires the user agent to be overridden.
246 const char kLinuxInfoStr[] = "X11; Linux x86_64";
247 std::string product = content::GetContentClient()->GetProduct();
248 std::string spoofed_ua =
249 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
250 web_contents->SetUserAgentOverride(spoofed_ua);
252 java_bridge_dispatcher_host_.reset(
253 new GinJavaBridgeDispatcherHost(web_contents,
254 java_bridge_retained_object_set));
256 InitWebContents();
259 ContentViewCoreImpl::~ContentViewCoreImpl() {
260 JNIEnv* env = base::android::AttachCurrentThread();
261 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
262 java_ref_.reset();
263 if (!j_obj.is_null()) {
264 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
265 env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
269 base::android::ScopedJavaLocalRef<jobject>
270 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
271 return web_contents_->GetJavaWebContents();
274 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
275 jobject obj) {
276 DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
277 java_ref_.reset();
278 // Java peer has gone, ContentViewCore is not functional and waits to
279 // be destroyed with WebContents.
280 // We need to reset WebContentsViewAndroid's reference, otherwise, there
281 // could have call in when swapping the WebContents,
282 // see http://crbug.com/383939 .
283 DCHECK(web_contents_);
284 static_cast<WebContentsViewAndroid*>(
285 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
286 SetContentViewCore(NULL);
289 void ContentViewCoreImpl::InitWebContents() {
290 DCHECK(web_contents_);
291 static_cast<WebContentsViewAndroid*>(
292 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
293 SetContentViewCore(this);
294 DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
295 web_contents_->SetUserData(kContentViewUserDataKey,
296 new ContentViewUserData(this));
299 void ContentViewCoreImpl::RenderViewReady() {
300 JNIEnv* env = AttachCurrentThread();
301 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
302 if (!obj.is_null())
303 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
305 if (device_orientation_ != 0)
306 SendOrientationChangeEventInternal();
309 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host,
310 RenderViewHost* new_host) {
311 int old_pid = 0;
312 if (old_host) {
313 old_pid = GetRenderProcessIdFromRenderViewHost(old_host);
315 RenderWidgetHostViewAndroid* view =
316 static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView());
317 if (view)
318 view->SetContentViewCore(NULL);
320 view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView());
321 if (view)
322 view->SetContentViewCore(this);
324 int new_pid = GetRenderProcessIdFromRenderViewHost(
325 web_contents_->GetRenderViewHost());
326 if (new_pid != old_pid) {
327 // Notify the Java side that the renderer process changed.
328 JNIEnv* env = AttachCurrentThread();
329 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
330 if (!obj.is_null()) {
331 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
335 SetFocusInternal(HasFocus());
336 SetAccessibilityEnabledInternal(accessibility_enabled_);
339 RenderWidgetHostViewAndroid*
340 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() const {
341 RenderWidgetHostView* rwhv = NULL;
342 if (web_contents_) {
343 rwhv = web_contents_->GetRenderWidgetHostView();
344 if (web_contents_->ShowingInterstitialPage()) {
345 rwhv = static_cast<InterstitialPageImpl*>(
346 web_contents_->GetInterstitialPage())->
347 GetRenderViewHost()->GetView();
350 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
353 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
354 JNIEnv* env = AttachCurrentThread();
355 return java_ref_.get(env);
358 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
359 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
360 if (!rwhva)
361 return SK_ColorWHITE;
362 return rwhva->GetCachedBackgroundColor();
365 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
366 if (should_pause)
367 web_contents_->GetGeolocationServiceContext()->PauseUpdates();
368 else
369 web_contents_->GetGeolocationServiceContext()->ResumeUpdates();
372 // All positions and sizes are in CSS pixels.
373 // Note that viewport_width/height is a best effort based.
374 // ContentViewCore has the actual information about the physical viewport size.
375 void ContentViewCoreImpl::UpdateFrameInfo(
376 const gfx::Vector2dF& scroll_offset,
377 float page_scale_factor,
378 const gfx::Vector2dF& page_scale_factor_limits,
379 const gfx::SizeF& content_size,
380 const gfx::SizeF& viewport_size,
381 const gfx::Vector2dF& controls_offset,
382 const gfx::Vector2dF& content_offset) {
383 JNIEnv* env = AttachCurrentThread();
384 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
385 if (obj.is_null())
386 return;
388 window_android_->set_content_offset(
389 gfx::ScaleVector2d(content_offset, dpi_scale_));
391 Java_ContentViewCore_updateFrameInfo(
392 env, obj.obj(),
393 scroll_offset.x(),
394 scroll_offset.y(),
395 page_scale_factor,
396 page_scale_factor_limits.x(),
397 page_scale_factor_limits.y(),
398 content_size.width(),
399 content_size.height(),
400 viewport_size.width(),
401 viewport_size.height(),
402 controls_offset.y(),
403 content_offset.y());
406 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
407 JNIEnv* env = AttachCurrentThread();
408 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
409 if (obj.is_null())
410 return;
411 ScopedJavaLocalRef<jstring> jtitle =
412 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
413 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
416 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
417 root_layer_->SetBackgroundColor(color);
419 JNIEnv* env = AttachCurrentThread();
420 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
421 if (obj.is_null())
422 return;
423 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
426 void ContentViewCoreImpl::ShowSelectPopupMenu(
427 RenderFrameHost* frame,
428 const gfx::Rect& bounds,
429 const std::vector<MenuItem>& items,
430 int selected_item,
431 bool multiple) {
432 JNIEnv* env = AttachCurrentThread();
433 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
434 if (j_obj.is_null())
435 return;
437 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
439 // For multi-select list popups we find the list of previous selections by
440 // iterating through the items. But for single selection popups we take the
441 // given |selected_item| as is.
442 ScopedJavaLocalRef<jintArray> selected_array;
443 if (multiple) {
444 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
445 size_t selected_count = 0;
446 for (size_t i = 0; i < items.size(); ++i) {
447 if (items[i].checked)
448 native_selected_array[selected_count++] = i;
451 selected_array = ScopedJavaLocalRef<jintArray>(
452 env, env->NewIntArray(selected_count));
453 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
454 native_selected_array.get());
455 } else {
456 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
457 jint value = selected_item;
458 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
461 ScopedJavaLocalRef<jintArray> enabled_array(env,
462 env->NewIntArray(items.size()));
463 std::vector<base::string16> labels;
464 labels.reserve(items.size());
465 for (size_t i = 0; i < items.size(); ++i) {
466 labels.push_back(items[i].label);
467 jint enabled =
468 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
469 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
470 POPUP_ITEM_TYPE_DISABLED));
471 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
473 ScopedJavaLocalRef<jobjectArray> items_array(
474 base::android::ToJavaArrayOfStrings(env, labels));
475 Java_ContentViewCore_showSelectPopup(env,
476 j_obj.obj(),
477 reinterpret_cast<intptr_t>(frame),
478 bounds_rect.obj(),
479 items_array.obj(),
480 enabled_array.obj(),
481 multiple,
482 selected_array.obj());
485 void ContentViewCoreImpl::HideSelectPopupMenu() {
486 JNIEnv* env = AttachCurrentThread();
487 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
488 if (!j_obj.is_null())
489 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
492 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
493 InputEventAckState ack_result) {
494 JNIEnv* env = AttachCurrentThread();
495 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
496 if (j_obj.is_null())
497 return;
499 switch (event.type) {
500 case WebInputEvent::GestureFlingStart:
501 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
502 // The view expects the fling velocity in pixels/s.
503 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
504 event.data.flingStart.velocityX * dpi_scale(),
505 event.data.flingStart.velocityY * dpi_scale());
506 } else {
507 // If a scroll ends with a fling, a SCROLL_END event is never sent.
508 // However, if that fling went unconsumed, we still need to let the
509 // listeners know that scrolling has ended.
510 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
513 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
514 // The view expects the fling velocity in pixels/s.
515 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
516 event.data.flingStart.velocityX * dpi_scale(),
517 event.data.flingStart.velocityY * dpi_scale());
519 break;
520 case WebInputEvent::GestureFlingCancel:
521 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
522 break;
523 case WebInputEvent::GestureScrollBegin:
524 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
525 break;
526 case WebInputEvent::GestureScrollUpdate:
527 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
528 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
529 break;
530 case WebInputEvent::GestureScrollEnd:
531 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
532 break;
533 case WebInputEvent::GesturePinchBegin:
534 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
535 break;
536 case WebInputEvent::GesturePinchEnd:
537 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
538 break;
539 case WebInputEvent::GestureTap:
540 Java_ContentViewCore_onSingleTapEventAck(
541 env,
542 j_obj.obj(),
543 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
544 event.x * dpi_scale(),
545 event.y * dpi_scale());
546 break;
547 default:
548 break;
552 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
553 if (event.type != WebInputEvent::GestureTap &&
554 event.type != WebInputEvent::GestureDoubleTap &&
555 event.type != WebInputEvent::GestureLongTap &&
556 event.type != WebInputEvent::GestureLongPress)
557 return false;
559 JNIEnv* env = AttachCurrentThread();
560 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
561 if (j_obj.is_null())
562 return false;
564 const blink::WebGestureEvent& gesture =
565 static_cast<const blink::WebGestureEvent&>(event);
566 int gesture_type = ToGestureEventType(event.type);
567 return Java_ContentViewCore_filterTapOrPressEvent(env,
568 j_obj.obj(),
569 gesture_type,
570 gesture.x * dpi_scale(),
571 gesture.y * dpi_scale());
573 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
576 bool ContentViewCoreImpl::HasFocus() {
577 JNIEnv* env = AttachCurrentThread();
578 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
579 if (obj.is_null())
580 return false;
581 return Java_ContentViewCore_hasFocus(env, obj.obj());
584 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
585 JNIEnv* env = AttachCurrentThread();
586 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
587 if (obj.is_null())
588 return;
589 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
590 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
593 void ContentViewCoreImpl::OnSelectionEvent(SelectionEventType event,
594 const gfx::PointF& position) {
595 JNIEnv* env = AttachCurrentThread();
596 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
597 if (j_obj.is_null())
598 return;
599 Java_ContentViewCore_onSelectionEvent(
600 env, j_obj.obj(), event, position.x(), position.y());
603 scoped_ptr<TouchHandleDrawable>
604 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
605 JNIEnv* env = AttachCurrentThread();
606 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
607 if (obj.is_null()) {
608 NOTREACHED();
609 return scoped_ptr<TouchHandleDrawable>();
611 return scoped_ptr<TouchHandleDrawable>(new PopupTouchHandleDrawable(
612 Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()),
613 dpi_scale_));
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(env, obj.obj(),
628 static_cast<jint>(x_dip),
629 static_cast<jint>(y_dip));
632 void ContentViewCoreImpl::GetScaledContentBitmap(
633 float scale,
634 SkColorType color_type,
635 gfx::Rect src_subrect,
636 ReadbackRequestCallback& result_callback) {
637 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
638 if (!view) {
639 result_callback.Run(SkBitmap(), READBACK_FAILED);
640 return;
643 view->GetScaledContentBitmap(scale, 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> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
681 JNIEnv* env = AttachCurrentThread();
683 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
684 if (obj.is_null())
685 return ScopedJavaLocalRef<jobject>();
686 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
689 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
690 JNIEnv* env = AttachCurrentThread();
692 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
693 if (obj.is_null())
694 return true;
695 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
696 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
697 j_url.obj());
700 void ContentViewCoreImpl::DidStopFlinging() {
701 JNIEnv* env = AttachCurrentThread();
703 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
704 if (!obj.is_null())
705 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
708 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() const {
709 JNIEnv* env = AttachCurrentThread();
711 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
712 if (obj.is_null())
713 return ScopedJavaLocalRef<jobject>();
715 return Java_ContentViewCore_getContext(env, obj.obj());
718 gfx::Size ContentViewCoreImpl::GetViewSize() const {
719 gfx::Size size = GetViewportSizeDip();
720 size.Enlarge(0, -GetTopControlsLayoutHeightDip());
721 return size;
724 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
725 JNIEnv* env = AttachCurrentThread();
726 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
727 if (j_obj.is_null())
728 return gfx::Size();
729 return gfx::Size(
730 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
731 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
734 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
735 JNIEnv* env = AttachCurrentThread();
736 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
737 if (j_obj.is_null())
738 return gfx::Size();
739 return gfx::Size(
740 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
741 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
744 int ContentViewCoreImpl::GetTopControlsLayoutHeightPix() const {
745 JNIEnv* env = AttachCurrentThread();
746 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
747 if (j_obj.is_null())
748 return 0;
749 return Java_ContentViewCore_getTopControlsLayoutHeightPix(env, j_obj.obj());
752 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
753 return gfx::ToCeiledSize(
754 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
757 float ContentViewCoreImpl::GetTopControlsLayoutHeightDip() const {
758 return GetTopControlsLayoutHeightPix() / dpi_scale();
761 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
762 root_layer_->InsertChild(layer, 0);
763 root_layer_->SetIsDrawable(false);
766 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
767 layer->RemoveFromParent();
769 if (!root_layer_->children().size())
770 root_layer_->SetIsDrawable(true);
773 void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF& extent) {
774 if (!web_contents_)
775 return;
777 web_contents_->MoveRangeSelectionExtent(gfx::Point(extent.x(), extent.y()));
780 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& base,
781 const gfx::PointF& extent) {
782 if (!web_contents_)
783 return;
785 gfx::Point base_point = gfx::Point(base.x(), base.y());
786 gfx::Point extent_point = gfx::Point(extent.x(), extent.y());
787 if (base_point == extent_point)
788 return;
790 web_contents_->SelectRange(base_point, extent_point);
793 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
794 return view_android_;
797 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
798 return window_android_;
801 const scoped_refptr<cc::Layer>& ContentViewCoreImpl::GetLayer() const {
802 return root_layer_;
805 // ----------------------------------------------------------------------------
806 // Methods called from Java via JNI
807 // ----------------------------------------------------------------------------
809 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
810 jobject obj,
811 jlong selectPopupSourceFrame,
812 jintArray indices) {
813 RenderFrameHostImpl* rfhi =
814 reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
815 DCHECK(rfhi);
816 if (indices == NULL) {
817 rfhi->DidCancelPopupMenu();
818 return;
821 int selected_count = env->GetArrayLength(indices);
822 std::vector<int> selected_indices;
823 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
824 for (int i = 0; i < selected_count; ++i)
825 selected_indices.push_back(indices_ptr[i]);
826 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
827 rfhi->DidSelectPopupMenuItems(selected_indices);
830 WebContents* ContentViewCoreImpl::GetWebContents() const {
831 return web_contents_;
834 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
835 SetFocusInternal(focused);
838 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
839 if (!GetRenderWidgetHostViewAndroid())
840 return;
842 if (focused)
843 GetRenderWidgetHostViewAndroid()->Focus();
844 else
845 GetRenderWidgetHostViewAndroid()->Blur();
848 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
849 jobject obj,
850 jint orientation) {
851 if (device_orientation_ != orientation) {
852 device_orientation_ = orientation;
853 SendOrientationChangeEventInternal();
857 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
858 jobject obj,
859 jobject motion_event,
860 jlong time_ms,
861 jint android_action,
862 jint pointer_count,
863 jint history_size,
864 jint action_index,
865 jfloat pos_x_0,
866 jfloat pos_y_0,
867 jfloat pos_x_1,
868 jfloat pos_y_1,
869 jint pointer_id_0,
870 jint pointer_id_1,
871 jfloat touch_major_0,
872 jfloat touch_major_1,
873 jfloat touch_minor_0,
874 jfloat touch_minor_1,
875 jfloat orientation_0,
876 jfloat orientation_1,
877 jfloat raw_pos_x,
878 jfloat raw_pos_y,
879 jint android_tool_type_0,
880 jint android_tool_type_1,
881 jint android_button_state,
882 jint android_meta_state,
883 jboolean is_touch_handle_event) {
884 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
885 // Avoid synthesizing a touch event if it cannot be forwarded.
886 if (!rwhv)
887 return false;
889 MotionEventAndroid::Pointer pointer0(pointer_id_0,
890 pos_x_0,
891 pos_y_0,
892 touch_major_0,
893 touch_minor_0,
894 orientation_0,
895 android_tool_type_0);
896 MotionEventAndroid::Pointer pointer1(pointer_id_1,
897 pos_x_1,
898 pos_y_1,
899 touch_major_1,
900 touch_minor_1,
901 orientation_1,
902 android_tool_type_1);
903 MotionEventAndroid event(1.f / dpi_scale(),
904 env,
905 motion_event,
906 time_ms,
907 android_action,
908 pointer_count,
909 history_size,
910 action_index,
911 android_button_state,
912 android_meta_state,
913 raw_pos_x - pos_x_0,
914 raw_pos_y - pos_y_0,
915 pointer0,
916 pointer1);
918 return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
919 : rwhv->OnTouchEvent(event);
922 float ContentViewCoreImpl::GetDpiScale() const {
923 return dpi_scale_;
926 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
927 jobject obj,
928 jlong time_ms,
929 jfloat x,
930 jfloat y) {
931 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
932 if (!rwhv)
933 return false;
935 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
936 WebInputEvent::MouseMove,
937 blink::WebMouseEvent::ButtonNone,
938 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
940 rwhv->SendMouseEvent(event);
941 return true;
944 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
945 jobject obj,
946 jlong time_ms,
947 jfloat x,
948 jfloat y,
949 jfloat vertical_axis) {
950 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
951 if (!rwhv)
952 return false;
954 WebMouseWheelEventBuilder::Direction direction;
955 if (vertical_axis > 0) {
956 direction = WebMouseWheelEventBuilder::DIRECTION_UP;
957 } else if (vertical_axis < 0) {
958 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
959 } else {
960 return false;
962 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
963 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
965 rwhv->SendMouseWheelEvent(event);
966 return true;
969 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
970 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
971 return WebGestureEventBuilder::Build(
972 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
975 void ContentViewCoreImpl::SendGestureEvent(
976 const blink::WebGestureEvent& event) {
977 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
978 if (rwhv)
979 rwhv->SendGestureEvent(event);
982 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
983 jobject obj,
984 jlong time_ms,
985 jfloat x,
986 jfloat y,
987 jfloat hintx,
988 jfloat hinty) {
989 WebGestureEvent event = MakeGestureEvent(
990 WebInputEvent::GestureScrollBegin, time_ms, x, y);
991 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
992 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
994 SendGestureEvent(event);
997 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
998 WebGestureEvent event = MakeGestureEvent(
999 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1000 SendGestureEvent(event);
1003 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1004 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1005 WebGestureEvent event = MakeGestureEvent(
1006 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1007 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1008 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1010 SendGestureEvent(event);
1013 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1014 jfloat x, jfloat y, jfloat vx, jfloat vy) {
1015 WebGestureEvent event = MakeGestureEvent(
1016 WebInputEvent::GestureFlingStart, time_ms, x, y);
1017 event.data.flingStart.velocityX = vx / dpi_scale();
1018 event.data.flingStart.velocityY = vy / dpi_scale();
1020 SendGestureEvent(event);
1023 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1024 WebGestureEvent event = MakeGestureEvent(
1025 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1026 SendGestureEvent(event);
1029 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1030 jfloat x, jfloat y) {
1031 // Tap gestures should always be preceded by a TapDown, ensuring consistency
1032 // with the touch-based gesture detection pipeline.
1033 WebGestureEvent tap_down_event = MakeGestureEvent(
1034 WebInputEvent::GestureTapDown, time_ms, x, y);
1035 tap_down_event.data.tap.tapCount = 1;
1036 SendGestureEvent(tap_down_event);
1038 WebGestureEvent tap_event = MakeGestureEvent(
1039 WebInputEvent::GestureTap, time_ms, x, y);
1040 tap_event.data.tap.tapCount = 1;
1041 SendGestureEvent(tap_event);
1044 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1045 jfloat x, jfloat y) {
1046 WebGestureEvent event = MakeGestureEvent(
1047 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1048 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1049 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1050 event.data.tap.tapCount = 1;
1052 SendGestureEvent(event);
1055 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1056 jfloat x, jfloat y) {
1057 WebGestureEvent event = MakeGestureEvent(
1058 WebInputEvent::GestureLongPress, time_ms, x, y);
1060 SendGestureEvent(event);
1063 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1064 jfloat x, jfloat y) {
1065 WebGestureEvent event = MakeGestureEvent(
1066 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1067 SendGestureEvent(event);
1070 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1071 WebGestureEvent event = MakeGestureEvent(
1072 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1073 SendGestureEvent(event);
1076 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1077 jfloat anchor_x, jfloat anchor_y,
1078 jfloat delta) {
1079 WebGestureEvent event = MakeGestureEvent(
1080 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1081 event.data.pinchUpdate.scale = delta;
1083 SendGestureEvent(event);
1086 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1087 jfloat x1, jfloat y1,
1088 jfloat x2, jfloat y2) {
1089 SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
1090 gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
1093 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1094 jfloat x, jfloat y) {
1095 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1096 if (rwhv)
1097 rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
1100 void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
1101 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1102 if (rwhv)
1103 rwhv->DismissTextHandles();
1106 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
1107 jobject obj,
1108 jboolean hidden) {
1109 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1110 if (rwhv)
1111 rwhv->SetTextHandlesTemporarilyHidden(hidden);
1114 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1115 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1116 if (rwhv)
1117 rwhv->ResetGestureDetection();
1120 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1121 jobject obj,
1122 jboolean enabled) {
1123 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1124 if (rwhv)
1125 rwhv->SetDoubleTapSupportEnabled(enabled);
1128 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1129 jobject obj,
1130 jboolean enabled) {
1131 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1132 if (rwhv)
1133 rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1136 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1137 JNIEnv* env,
1138 jobject obj,
1139 jboolean allow) {
1140 java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
1143 void ContentViewCoreImpl::AddJavascriptInterface(
1144 JNIEnv* env,
1145 jobject /* obj */,
1146 jobject object,
1147 jstring name,
1148 jclass safe_annotation_clazz) {
1149 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1150 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1151 java_bridge_dispatcher_host_->AddNamedObject(
1152 ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
1155 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1156 jobject /* obj */,
1157 jstring name) {
1158 java_bridge_dispatcher_host_->RemoveNamedObject(
1159 ConvertJavaStringToUTF8(env, name));
1162 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1163 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1164 gfx::Size physical_size(
1165 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1166 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1167 root_layer_->SetBounds(physical_size);
1169 if (view) {
1170 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1171 view->GetRenderWidgetHost());
1172 host->SendScreenRects();
1173 view->WasResized();
1177 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1178 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1179 if (!rwhva)
1180 return 0;
1181 return rwhva->GetNativeImeAdapter();
1184 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1185 int text_input_type,
1186 int text_input_flags,
1187 const std::string& text,
1188 int selection_start,
1189 int selection_end,
1190 int composition_start,
1191 int composition_end,
1192 bool show_ime_if_needed,
1193 bool is_non_ime_change) {
1194 JNIEnv* env = AttachCurrentThread();
1195 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1196 if (obj.is_null())
1197 return;
1199 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1200 Java_ContentViewCore_updateImeAdapter(env,
1201 obj.obj(),
1202 native_ime_adapter,
1203 text_input_type,
1204 text_input_flags,
1205 jstring_text.obj(),
1206 selection_start,
1207 selection_end,
1208 composition_start,
1209 composition_end,
1210 show_ime_if_needed,
1211 is_non_ime_change);
1214 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1215 bool enabled) {
1216 SetAccessibilityEnabledInternal(enabled);
1219 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1220 JNIEnv* env = AttachCurrentThread();
1221 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1222 if (obj.is_null())
1223 return true;
1224 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
1225 obj.obj());
1228 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1229 accessibility_enabled_ = enabled;
1230 BrowserAccessibilityStateImpl* accessibility_state =
1231 BrowserAccessibilityStateImpl::GetInstance();
1232 if (enabled) {
1233 // This enables accessibility globally unless it was explicitly disallowed
1234 // by a command-line flag.
1235 accessibility_state->OnScreenReaderDetected();
1236 // If it was actually enabled globally, enable it for this RenderWidget now.
1237 if (accessibility_state->IsAccessibleBrowser() && web_contents_)
1238 web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
1239 } else {
1240 accessibility_state->ResetAccessibilityMode();
1241 if (web_contents_) {
1242 web_contents_->SetAccessibilityMode(
1243 accessibility_state->accessibility_mode());
1248 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1249 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1250 if (rwhv)
1251 rwhv->UpdateScreenInfo(GetViewAndroid());
1253 static_cast<WebContentsImpl*>(web_contents())->
1254 screen_orientation_dispatcher_host()->OnOrientationChange();
1257 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1258 jobject obj,
1259 jint x,
1260 jint y,
1261 jint width,
1262 jint height) {
1263 gfx::Rect rect(
1264 static_cast<int>(x / dpi_scale()),
1265 static_cast<int>(y / dpi_scale()),
1266 static_cast<int>((width > 0 && width < dpi_scale()) ?
1267 1 : (int)(width / dpi_scale())),
1268 static_cast<int>((height > 0 && height < dpi_scale()) ?
1269 1 : (int)(height / dpi_scale())));
1270 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1271 GetWebContents()->GetRoutingID(), rect));
1274 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1275 return GetRenderProcessIdFromRenderViewHost(
1276 web_contents_->GetRenderViewHost());
1279 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1280 jboolean opaque) {
1281 if (GetRenderWidgetHostViewAndroid()) {
1282 if (opaque)
1283 GetRenderWidgetHostViewAndroid()->SetBackgroundColorToDefault();
1284 else
1285 GetRenderWidgetHostViewAndroid()->SetBackgroundColor(SK_ColorTRANSPARENT);
1289 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1290 int max_length,
1291 const base::Callback<
1292 void(const base::string16& content, int start_offset, int end_offset)>&
1293 callback) {
1294 DCHECK(!callback.is_null());
1295 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1296 if (!focused_frame)
1297 return;
1298 if (GetRenderWidgetHostViewAndroid()) {
1299 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1300 callback);
1301 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1302 focused_frame->GetRoutingID(), max_length));
1306 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1307 const base::string16& text,
1308 const base::string16& html,
1309 const gfx::Rect& clip_rect) {
1310 JNIEnv* env = AttachCurrentThread();
1311 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1312 if (obj.is_null())
1313 return;
1314 ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
1315 ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
1316 ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
1317 Java_ContentViewCore_onSmartClipDataExtracted(
1318 env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
1321 void ContentViewCoreImpl::WebContentsDestroyed() {
1322 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1323 static_cast<WebContentsImpl*>(web_contents())->GetView());
1324 DCHECK(wcva);
1325 wcva->SetContentViewCore(NULL);
1328 // This is called for each ContentView.
1329 jlong Init(JNIEnv* env,
1330 jobject obj,
1331 jlong native_web_contents,
1332 jlong view_android,
1333 jlong window_android,
1334 jobject retained_objects_set) {
1335 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1336 env, obj,
1337 reinterpret_cast<WebContents*>(native_web_contents),
1338 reinterpret_cast<ui::ViewAndroid*>(view_android),
1339 reinterpret_cast<ui::WindowAndroid*>(window_android),
1340 retained_objects_set);
1341 return reinterpret_cast<intptr_t>(view);
1344 bool RegisterContentViewCore(JNIEnv* env) {
1345 return RegisterNativesImpl(env);
1348 } // namespace content