Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / android / content_view_core_impl.cc
blob38886f9d6d36195114d9847c44fc5546112cc6c0
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 jobject 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_(new ui::ViewAndroid(view_android, window_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(window_android_);
233 root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj));
234 gfx::Size physical_size(
235 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
236 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
237 root_layer_->SetBounds(physical_size);
238 root_layer_->SetIsDrawable(true);
240 // Currently, the only use case we have for overriding a user agent involves
241 // spoofing a desktop Linux user agent for "Request desktop site".
242 // Automatically set it for all WebContents so that it is available when a
243 // NavigationEntry requires the user agent to be overridden.
244 const char kLinuxInfoStr[] = "X11; Linux x86_64";
245 std::string product = content::GetContentClient()->GetProduct();
246 std::string spoofed_ua =
247 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
248 web_contents->SetUserAgentOverride(spoofed_ua);
250 java_bridge_dispatcher_host_ =
251 new GinJavaBridgeDispatcherHost(web_contents,
252 java_bridge_retained_object_set);
254 InitWebContents();
257 ContentViewCoreImpl::~ContentViewCoreImpl() {
258 root_layer_->RemoveFromParent();
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 = web_contents_->GetInterstitialPage()
346 ->GetMainFrame()
347 ->GetRenderViewHost()
348 ->GetView();
351 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
354 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
355 JNIEnv* env = AttachCurrentThread();
356 return java_ref_.get(env);
359 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
360 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
361 if (!rwhva)
362 return SK_ColorWHITE;
363 return rwhva->GetCachedBackgroundColor();
366 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
367 if (should_pause)
368 web_contents_->GetGeolocationServiceContext()->PauseUpdates();
369 else
370 web_contents_->GetGeolocationServiceContext()->ResumeUpdates();
373 // All positions and sizes are in CSS pixels.
374 // Note that viewport_width/height is a best effort based.
375 // ContentViewCore has the actual information about the physical viewport size.
376 void ContentViewCoreImpl::UpdateFrameInfo(
377 const gfx::Vector2dF& scroll_offset,
378 float page_scale_factor,
379 const gfx::Vector2dF& page_scale_factor_limits,
380 const gfx::SizeF& content_size,
381 const gfx::SizeF& viewport_size,
382 const gfx::Vector2dF& controls_offset,
383 const gfx::Vector2dF& content_offset,
384 bool is_mobile_optimized_hint) {
385 JNIEnv* env = AttachCurrentThread();
386 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
387 if (obj.is_null())
388 return;
390 window_android_->set_content_offset(
391 gfx::ScaleVector2d(content_offset, dpi_scale_));
393 Java_ContentViewCore_updateFrameInfo(
394 env, obj.obj(),
395 scroll_offset.x(),
396 scroll_offset.y(),
397 page_scale_factor,
398 page_scale_factor_limits.x(),
399 page_scale_factor_limits.y(),
400 content_size.width(),
401 content_size.height(),
402 viewport_size.width(),
403 viewport_size.height(),
404 controls_offset.y(),
405 content_offset.y(),
406 is_mobile_optimized_hint);
409 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
410 JNIEnv* env = AttachCurrentThread();
411 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
412 if (obj.is_null())
413 return;
414 ScopedJavaLocalRef<jstring> jtitle =
415 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
416 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
419 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
420 root_layer_->SetBackgroundColor(color);
422 JNIEnv* env = AttachCurrentThread();
423 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
424 if (obj.is_null())
425 return;
426 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
429 void ContentViewCoreImpl::ShowSelectPopupMenu(
430 RenderFrameHost* frame,
431 const gfx::Rect& bounds,
432 const std::vector<MenuItem>& items,
433 int selected_item,
434 bool multiple) {
435 JNIEnv* env = AttachCurrentThread();
436 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
437 if (j_obj.is_null())
438 return;
440 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
442 // For multi-select list popups we find the list of previous selections by
443 // iterating through the items. But for single selection popups we take the
444 // given |selected_item| as is.
445 ScopedJavaLocalRef<jintArray> selected_array;
446 if (multiple) {
447 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
448 size_t selected_count = 0;
449 for (size_t i = 0; i < items.size(); ++i) {
450 if (items[i].checked)
451 native_selected_array[selected_count++] = i;
454 selected_array = ScopedJavaLocalRef<jintArray>(
455 env, env->NewIntArray(selected_count));
456 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
457 native_selected_array.get());
458 } else {
459 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
460 jint value = selected_item;
461 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
464 ScopedJavaLocalRef<jintArray> enabled_array(env,
465 env->NewIntArray(items.size()));
466 std::vector<base::string16> labels;
467 labels.reserve(items.size());
468 for (size_t i = 0; i < items.size(); ++i) {
469 labels.push_back(items[i].label);
470 jint enabled =
471 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
472 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
473 POPUP_ITEM_TYPE_DISABLED));
474 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
476 ScopedJavaLocalRef<jobjectArray> items_array(
477 base::android::ToJavaArrayOfStrings(env, labels));
478 Java_ContentViewCore_showSelectPopup(env,
479 j_obj.obj(),
480 reinterpret_cast<intptr_t>(frame),
481 bounds_rect.obj(),
482 items_array.obj(),
483 enabled_array.obj(),
484 multiple,
485 selected_array.obj());
488 void ContentViewCoreImpl::HideSelectPopupMenu() {
489 JNIEnv* env = AttachCurrentThread();
490 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
491 if (!j_obj.is_null())
492 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
495 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
496 InputEventAckState ack_result) {
497 JNIEnv* env = AttachCurrentThread();
498 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
499 if (j_obj.is_null())
500 return;
502 switch (event.type) {
503 case WebInputEvent::GestureFlingStart:
504 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
505 // The view expects the fling velocity in pixels/s.
506 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
507 event.data.flingStart.velocityX * dpi_scale(),
508 event.data.flingStart.velocityY * dpi_scale());
509 } else {
510 // If a scroll ends with a fling, a SCROLL_END event is never sent.
511 // However, if that fling went unconsumed, we still need to let the
512 // listeners know that scrolling has ended.
513 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
516 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
517 // The view expects the fling velocity in pixels/s.
518 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
519 event.data.flingStart.velocityX * dpi_scale(),
520 event.data.flingStart.velocityY * dpi_scale());
522 break;
523 case WebInputEvent::GestureFlingCancel:
524 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
525 break;
526 case WebInputEvent::GestureScrollBegin:
527 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
528 break;
529 case WebInputEvent::GestureScrollUpdate:
530 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
531 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
532 break;
533 case WebInputEvent::GestureScrollEnd:
534 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
535 break;
536 case WebInputEvent::GesturePinchBegin:
537 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
538 break;
539 case WebInputEvent::GesturePinchEnd:
540 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
541 break;
542 case WebInputEvent::GestureTap:
543 Java_ContentViewCore_onSingleTapEventAck(
544 env,
545 j_obj.obj(),
546 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
547 event.x * dpi_scale(),
548 event.y * dpi_scale());
549 break;
550 default:
551 break;
555 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
556 if (event.type != WebInputEvent::GestureTap &&
557 event.type != WebInputEvent::GestureDoubleTap &&
558 event.type != WebInputEvent::GestureLongTap &&
559 event.type != WebInputEvent::GestureLongPress &&
560 event.type != WebInputEvent::GestureFlingCancel)
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 if (event.type == WebInputEvent::GestureFlingCancel) {
569 // If no fling is active, either in the compositor or externally-driven,
570 // there's no need to explicitly cancel the fling.
571 bool may_need_fling_cancel =
572 Java_ContentViewCore_isScrollInProgress(env, j_obj.obj());
573 return !may_need_fling_cancel;
576 const blink::WebGestureEvent& gesture =
577 static_cast<const blink::WebGestureEvent&>(event);
578 int gesture_type = ToGestureEventType(event.type);
579 return Java_ContentViewCore_filterTapOrPressEvent(env,
580 j_obj.obj(),
581 gesture_type,
582 gesture.x * dpi_scale(),
583 gesture.y * dpi_scale());
585 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
588 bool ContentViewCoreImpl::HasFocus() {
589 JNIEnv* env = AttachCurrentThread();
590 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
591 if (obj.is_null())
592 return false;
593 return Java_ContentViewCore_hasFocus(env, obj.obj());
596 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
597 JNIEnv* env = AttachCurrentThread();
598 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
599 if (obj.is_null())
600 return;
601 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
602 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
605 void ContentViewCoreImpl::OnSelectionEvent(ui::SelectionEventType event,
606 const gfx::PointF& position) {
607 JNIEnv* env = AttachCurrentThread();
608 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
609 if (j_obj.is_null())
610 return;
611 Java_ContentViewCore_onSelectionEvent(env, j_obj.obj(), event,
612 position.x() * dpi_scale(),
613 position.y() * dpi_scale());
616 scoped_ptr<ui::TouchHandleDrawable>
617 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
618 JNIEnv* env = AttachCurrentThread();
619 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
620 if (obj.is_null()) {
621 NOTREACHED();
622 return scoped_ptr<ui::TouchHandleDrawable>();
624 return scoped_ptr<ui::TouchHandleDrawable>(new PopupTouchHandleDrawable(
625 Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()),
626 dpi_scale_));
629 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
630 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
631 if (!view)
632 return;
634 view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
636 JNIEnv* env = AttachCurrentThread();
637 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
638 if (obj.is_null())
639 return;
640 Java_ContentViewCore_showPastePopupWithFeedback(
641 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
642 static_cast<jint>(y_dip * dpi_scale()));
645 void ContentViewCoreImpl::GetScaledContentBitmap(
646 float scale,
647 SkColorType color_type,
648 gfx::Rect src_subrect,
649 ReadbackRequestCallback& result_callback) {
650 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
651 if (!view || color_type == kUnknown_SkColorType) {
652 result_callback.Run(SkBitmap(), READBACK_FAILED);
653 return;
656 view->GetScaledContentBitmap(scale, color_type, src_subrect,
657 result_callback);
660 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
661 JNIEnv* env = AttachCurrentThread();
662 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
663 if (j_obj.is_null())
664 return;
665 ScopedJavaLocalRef<jstring> jcontent_url =
666 ConvertUTF8ToJavaString(env, content_url.spec());
667 Java_ContentViewCore_startContentIntent(env,
668 j_obj.obj(),
669 jcontent_url.obj());
672 void ContentViewCoreImpl::ShowDisambiguationPopup(
673 const gfx::Rect& rect_pixels,
674 const SkBitmap& zoomed_bitmap) {
675 JNIEnv* env = AttachCurrentThread();
677 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
678 if (obj.is_null())
679 return;
681 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
683 ScopedJavaLocalRef<jobject> java_bitmap =
684 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
685 DCHECK(!java_bitmap.is_null());
687 Java_ContentViewCore_showDisambiguationPopup(env,
688 obj.obj(),
689 rect_object.obj(),
690 java_bitmap.obj());
693 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
694 JNIEnv* env = AttachCurrentThread();
696 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
697 if (obj.is_null())
698 return ScopedJavaLocalRef<jobject>();
699 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
702 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
703 JNIEnv* env = AttachCurrentThread();
705 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
706 if (obj.is_null())
707 return true;
708 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
709 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
710 j_url.obj());
713 void ContentViewCoreImpl::DidStopFlinging() {
714 JNIEnv* env = AttachCurrentThread();
716 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
717 if (!obj.is_null())
718 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
721 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() const {
722 JNIEnv* env = AttachCurrentThread();
724 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
725 if (obj.is_null())
726 return ScopedJavaLocalRef<jobject>();
728 return Java_ContentViewCore_getContext(env, obj.obj());
731 gfx::Size ContentViewCoreImpl::GetViewSize() const {
732 gfx::Size size = GetViewportSizeDip();
733 if (DoTopControlsShrinkBlinkSize())
734 size.Enlarge(0, -GetTopControlsHeightDip());
735 return size;
738 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
739 JNIEnv* env = AttachCurrentThread();
740 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
741 if (j_obj.is_null())
742 return gfx::Size();
743 return gfx::Size(
744 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
745 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
748 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
749 JNIEnv* env = AttachCurrentThread();
750 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
751 if (j_obj.is_null())
752 return gfx::Size();
753 return gfx::Size(
754 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
755 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
758 int ContentViewCoreImpl::GetTopControlsHeightPix() const {
759 JNIEnv* env = AttachCurrentThread();
760 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
761 if (j_obj.is_null())
762 return 0;
763 return Java_ContentViewCore_getTopControlsHeightPix(env, j_obj.obj());
766 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
767 return gfx::ToCeiledSize(
768 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
771 bool ContentViewCoreImpl::DoTopControlsShrinkBlinkSize() const {
772 JNIEnv* env = AttachCurrentThread();
773 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
774 if (j_obj.is_null())
775 return false;
776 return Java_ContentViewCore_doTopControlsShrinkBlinkSize(env, j_obj.obj());
779 float ContentViewCoreImpl::GetTopControlsHeightDip() const {
780 return GetTopControlsHeightPix() / dpi_scale();
783 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
784 root_layer_->InsertChild(layer, 0);
785 root_layer_->SetIsDrawable(false);
788 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
789 layer->RemoveFromParent();
791 if (!root_layer_->children().size())
792 root_layer_->SetIsDrawable(true);
795 void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF& extent) {
796 if (!web_contents_)
797 return;
799 web_contents_->MoveRangeSelectionExtent(gfx::Point(extent.x(), extent.y()));
802 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& base,
803 const gfx::PointF& extent) {
804 if (!web_contents_)
805 return;
807 gfx::Point base_point = gfx::Point(base.x(), base.y());
808 gfx::Point extent_point = gfx::Point(extent.x(), extent.y());
809 if (base_point == extent_point)
810 return;
812 web_contents_->SelectRange(base_point, extent_point);
815 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
816 return view_android_.get();
819 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
820 return window_android_;
823 const scoped_refptr<cc::Layer>& ContentViewCoreImpl::GetLayer() const {
824 return root_layer_;
827 // ----------------------------------------------------------------------------
828 // Methods called from Java via JNI
829 // ----------------------------------------------------------------------------
831 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
832 jobject obj,
833 jlong selectPopupSourceFrame,
834 jintArray indices) {
835 RenderFrameHostImpl* rfhi =
836 reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
837 DCHECK(rfhi);
838 if (indices == NULL) {
839 rfhi->DidCancelPopupMenu();
840 return;
843 int selected_count = env->GetArrayLength(indices);
844 std::vector<int> selected_indices;
845 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
846 for (int i = 0; i < selected_count; ++i)
847 selected_indices.push_back(indices_ptr[i]);
848 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
849 rfhi->DidSelectPopupMenuItems(selected_indices);
852 WebContents* ContentViewCoreImpl::GetWebContents() const {
853 return web_contents_;
856 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
857 SetFocusInternal(focused);
860 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
861 if (!GetRenderWidgetHostViewAndroid())
862 return;
864 if (focused)
865 GetRenderWidgetHostViewAndroid()->Focus();
866 else
867 GetRenderWidgetHostViewAndroid()->Blur();
870 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
871 jobject obj,
872 jint orientation) {
873 if (device_orientation_ != orientation) {
874 device_orientation_ = orientation;
875 SendOrientationChangeEventInternal();
879 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
880 jobject obj,
881 jobject motion_event,
882 jlong time_ms,
883 jint android_action,
884 jint pointer_count,
885 jint history_size,
886 jint action_index,
887 jfloat pos_x_0,
888 jfloat pos_y_0,
889 jfloat pos_x_1,
890 jfloat pos_y_1,
891 jint pointer_id_0,
892 jint pointer_id_1,
893 jfloat touch_major_0,
894 jfloat touch_major_1,
895 jfloat touch_minor_0,
896 jfloat touch_minor_1,
897 jfloat orientation_0,
898 jfloat orientation_1,
899 jfloat raw_pos_x,
900 jfloat raw_pos_y,
901 jint android_tool_type_0,
902 jint android_tool_type_1,
903 jint android_button_state,
904 jint android_meta_state,
905 jboolean is_touch_handle_event) {
906 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
907 // Avoid synthesizing a touch event if it cannot be forwarded.
908 if (!rwhv)
909 return false;
911 MotionEventAndroid::Pointer pointer0(pointer_id_0,
912 pos_x_0,
913 pos_y_0,
914 touch_major_0,
915 touch_minor_0,
916 orientation_0,
917 android_tool_type_0);
918 MotionEventAndroid::Pointer pointer1(pointer_id_1,
919 pos_x_1,
920 pos_y_1,
921 touch_major_1,
922 touch_minor_1,
923 orientation_1,
924 android_tool_type_1);
925 MotionEventAndroid event(1.f / dpi_scale(),
926 env,
927 motion_event,
928 time_ms,
929 android_action,
930 pointer_count,
931 history_size,
932 action_index,
933 android_button_state,
934 android_meta_state,
935 raw_pos_x - pos_x_0,
936 raw_pos_y - pos_y_0,
937 pointer0,
938 pointer1);
940 return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
941 : rwhv->OnTouchEvent(event);
944 float ContentViewCoreImpl::GetDpiScale() const {
945 return dpi_scale_;
948 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
949 jobject obj,
950 jlong time_ms,
951 jfloat x,
952 jfloat y) {
953 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
954 if (!rwhv)
955 return false;
957 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
958 WebInputEvent::MouseMove,
959 blink::WebMouseEvent::ButtonNone,
960 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
962 rwhv->SendMouseEvent(event);
963 return true;
966 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
967 jobject obj,
968 jlong time_ms,
969 jfloat x,
970 jfloat y,
971 jfloat vertical_axis,
972 jfloat horizontal_axis) {
973 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
974 if (!rwhv)
975 return false;
977 WebMouseWheelEventBuilder::Direction direction;
978 if (vertical_axis > 0) {
979 direction = WebMouseWheelEventBuilder::DIRECTION_UP;
980 } else if (vertical_axis < 0) {
981 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
982 } else if (horizontal_axis > 0) {
983 direction = WebMouseWheelEventBuilder::DIRECTION_RIGHT;
984 } else if (horizontal_axis < 0) {
985 direction = WebMouseWheelEventBuilder::DIRECTION_LEFT;
986 } else {
987 return false;
989 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
990 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
992 rwhv->SendMouseWheelEvent(event);
993 return true;
996 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
997 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
998 return WebGestureEventBuilder::Build(
999 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1002 void ContentViewCoreImpl::SendGestureEvent(
1003 const blink::WebGestureEvent& event) {
1004 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1005 if (rwhv)
1006 rwhv->SendGestureEvent(event);
1009 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
1010 jobject obj,
1011 jlong time_ms,
1012 jfloat x,
1013 jfloat y,
1014 jfloat hintx,
1015 jfloat hinty) {
1016 WebGestureEvent event = MakeGestureEvent(
1017 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1018 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1019 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1021 SendGestureEvent(event);
1024 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1025 WebGestureEvent event = MakeGestureEvent(
1026 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1027 SendGestureEvent(event);
1030 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1031 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1032 WebGestureEvent event = MakeGestureEvent(
1033 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1034 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1035 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1037 SendGestureEvent(event);
1040 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1041 jfloat x, jfloat y, jfloat vx, jfloat vy) {
1042 WebGestureEvent event = MakeGestureEvent(
1043 WebInputEvent::GestureFlingStart, time_ms, x, y);
1044 event.data.flingStart.velocityX = vx / dpi_scale();
1045 event.data.flingStart.velocityY = vy / dpi_scale();
1047 SendGestureEvent(event);
1050 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1051 WebGestureEvent event = MakeGestureEvent(
1052 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1053 event.data.flingCancel.preventBoosting = true;
1055 SendGestureEvent(event);
1058 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1059 jfloat x, jfloat y) {
1060 // Tap gestures should always be preceded by a TapDown, ensuring consistency
1061 // with the touch-based gesture detection pipeline.
1062 WebGestureEvent tap_down_event = MakeGestureEvent(
1063 WebInputEvent::GestureTapDown, time_ms, x, y);
1064 tap_down_event.data.tap.tapCount = 1;
1065 SendGestureEvent(tap_down_event);
1067 WebGestureEvent tap_event = MakeGestureEvent(
1068 WebInputEvent::GestureTap, time_ms, x, y);
1069 tap_event.data.tap.tapCount = 1;
1070 SendGestureEvent(tap_event);
1073 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1074 jfloat x, jfloat y) {
1075 WebGestureEvent event = MakeGestureEvent(
1076 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1077 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1078 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1079 event.data.tap.tapCount = 1;
1081 SendGestureEvent(event);
1084 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1085 jfloat x, jfloat y) {
1086 WebGestureEvent event = MakeGestureEvent(
1087 WebInputEvent::GestureLongPress, time_ms, x, y);
1089 SendGestureEvent(event);
1092 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1093 jfloat x, jfloat y) {
1094 WebGestureEvent event = MakeGestureEvent(
1095 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1096 SendGestureEvent(event);
1099 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1100 WebGestureEvent event = MakeGestureEvent(
1101 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1102 SendGestureEvent(event);
1105 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1106 jfloat anchor_x, jfloat anchor_y,
1107 jfloat delta) {
1108 WebGestureEvent event = MakeGestureEvent(
1109 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1110 event.data.pinchUpdate.scale = delta;
1112 SendGestureEvent(event);
1115 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1116 jfloat x1, jfloat y1,
1117 jfloat x2, jfloat y2) {
1118 SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
1119 gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
1122 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1123 jfloat x, jfloat y) {
1124 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1125 if (rwhv)
1126 rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
1129 void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
1130 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1131 if (rwhv)
1132 rwhv->DismissTextHandles();
1135 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
1136 jobject obj,
1137 jboolean hidden) {
1138 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1139 if (rwhv)
1140 rwhv->SetTextHandlesTemporarilyHidden(hidden);
1143 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1144 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1145 if (rwhv)
1146 rwhv->ResetGestureDetection();
1149 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1150 jobject obj,
1151 jboolean enabled) {
1152 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1153 if (rwhv)
1154 rwhv->SetDoubleTapSupportEnabled(enabled);
1157 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1158 jobject obj,
1159 jboolean enabled) {
1160 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1161 if (rwhv)
1162 rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1165 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1166 JNIEnv* env,
1167 jobject obj,
1168 jboolean allow) {
1169 java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
1172 void ContentViewCoreImpl::AddJavascriptInterface(
1173 JNIEnv* env,
1174 jobject /* obj */,
1175 jobject object,
1176 jstring name,
1177 jclass safe_annotation_clazz) {
1178 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1179 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1180 java_bridge_dispatcher_host_->AddNamedObject(
1181 ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
1184 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1185 jobject /* obj */,
1186 jstring name) {
1187 java_bridge_dispatcher_host_->RemoveNamedObject(
1188 ConvertJavaStringToUTF8(env, name));
1191 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1192 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1193 gfx::Size physical_size(
1194 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1195 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1196 root_layer_->SetBounds(physical_size);
1198 if (view) {
1199 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1200 view->GetRenderWidgetHost());
1201 host->SendScreenRects();
1202 view->WasResized();
1206 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1207 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1208 if (!rwhva)
1209 return 0;
1210 return rwhva->GetNativeImeAdapter();
1213 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1214 int text_input_type,
1215 int text_input_flags,
1216 const std::string& text,
1217 int selection_start,
1218 int selection_end,
1219 int composition_start,
1220 int composition_end,
1221 bool show_ime_if_needed,
1222 bool is_non_ime_change) {
1223 JNIEnv* env = AttachCurrentThread();
1224 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1225 if (obj.is_null())
1226 return;
1228 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1229 Java_ContentViewCore_updateImeAdapter(env,
1230 obj.obj(),
1231 native_ime_adapter,
1232 text_input_type,
1233 text_input_flags,
1234 jstring_text.obj(),
1235 selection_start,
1236 selection_end,
1237 composition_start,
1238 composition_end,
1239 show_ime_if_needed,
1240 is_non_ime_change);
1243 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1244 bool enabled) {
1245 SetAccessibilityEnabledInternal(enabled);
1248 void ContentViewCoreImpl::SetTextTrackSettings(JNIEnv* env,
1249 jobject obj,
1250 jstring textTrackBackgroundColor,
1251 jstring textTrackFontFamily,
1252 jstring textTrackFontStyle,
1253 jstring textTrackFontVariant,
1254 jstring textTrackTextColor,
1255 jstring textTrackTextShadow,
1256 jstring textTrackTextSize) {
1257 FrameMsg_TextTrackSettings_Params params;
1258 params.text_track_background_color = ConvertJavaStringToUTF8(
1259 env, textTrackBackgroundColor);
1260 params.text_track_font_family = ConvertJavaStringToUTF8(
1261 env, textTrackFontFamily);
1262 params.text_track_font_style = ConvertJavaStringToUTF8(
1263 env, textTrackFontStyle);
1264 params.text_track_font_variant = ConvertJavaStringToUTF8(
1265 env, textTrackFontVariant);
1266 params.text_track_text_color = ConvertJavaStringToUTF8(
1267 env, textTrackTextColor);
1268 params.text_track_text_shadow = ConvertJavaStringToUTF8(
1269 env, textTrackTextShadow);
1270 params.text_track_text_size = ConvertJavaStringToUTF8(
1271 env, textTrackTextSize);
1273 web_contents_->GetMainFrame()->SetTextTrackSettings(params);
1276 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1277 JNIEnv* env = AttachCurrentThread();
1278 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1279 if (obj.is_null())
1280 return true;
1281 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
1282 obj.obj());
1285 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1286 accessibility_enabled_ = enabled;
1287 BrowserAccessibilityStateImpl* accessibility_state =
1288 BrowserAccessibilityStateImpl::GetInstance();
1289 if (enabled) {
1290 // This enables accessibility globally unless it was explicitly disallowed
1291 // by a command-line flag.
1292 accessibility_state->OnScreenReaderDetected();
1293 // If it was actually enabled globally, enable it for this RenderWidget now.
1294 if (accessibility_state->IsAccessibleBrowser() && web_contents_)
1295 web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
1296 } else {
1297 accessibility_state->ResetAccessibilityMode();
1298 if (web_contents_) {
1299 web_contents_->SetAccessibilityMode(
1300 accessibility_state->accessibility_mode());
1305 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1306 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1307 if (rwhv)
1308 rwhv->UpdateScreenInfo(GetViewAndroid());
1310 static_cast<WebContentsImpl*>(web_contents())->
1311 screen_orientation_dispatcher_host()->OnOrientationChange();
1314 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1315 jobject obj,
1316 jint x,
1317 jint y,
1318 jint width,
1319 jint height) {
1320 gfx::Rect rect(
1321 static_cast<int>(x / dpi_scale()),
1322 static_cast<int>(y / dpi_scale()),
1323 static_cast<int>((width > 0 && width < dpi_scale()) ?
1324 1 : (int)(width / dpi_scale())),
1325 static_cast<int>((height > 0 && height < dpi_scale()) ?
1326 1 : (int)(height / dpi_scale())));
1327 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1328 GetWebContents()->GetRoutingID(), rect));
1331 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1332 return GetRenderProcessIdFromRenderViewHost(
1333 web_contents_->GetRenderViewHost());
1336 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1337 jboolean opaque) {
1338 if (GetRenderWidgetHostViewAndroid()) {
1339 if (opaque)
1340 GetRenderWidgetHostViewAndroid()->SetBackgroundColorToDefault();
1341 else
1342 GetRenderWidgetHostViewAndroid()->SetBackgroundColor(SK_ColorTRANSPARENT);
1346 void ContentViewCoreImpl::SetDrawsContent(JNIEnv* env,
1347 jobject jobj,
1348 jboolean draws) {
1349 GetLayer()->SetHideLayerAndSubtree(!draws);
1352 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1353 int max_length,
1354 const base::Callback<
1355 void(const base::string16& content, int start_offset, int end_offset)>&
1356 callback) {
1357 DCHECK(!callback.is_null());
1358 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1359 if (!focused_frame)
1360 return;
1361 if (GetRenderWidgetHostViewAndroid()) {
1362 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1363 callback);
1364 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1365 focused_frame->GetRoutingID(), max_length));
1369 void ContentViewCoreImpl::OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip) {
1370 JNIEnv* env = AttachCurrentThread();
1371 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1372 if (obj.is_null())
1373 return;
1374 Java_ContentViewCore_onShowUnhandledTapUIIfNeeded(
1375 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
1376 static_cast<jint>(y_dip * dpi_scale()));
1379 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1380 const base::string16& text,
1381 const base::string16& html,
1382 const gfx::Rect& clip_rect) {
1383 JNIEnv* env = AttachCurrentThread();
1384 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1385 if (obj.is_null())
1386 return;
1387 ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
1388 ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
1389 ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
1390 Java_ContentViewCore_onSmartClipDataExtracted(
1391 env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
1394 void ContentViewCoreImpl::WebContentsDestroyed() {
1395 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1396 static_cast<WebContentsImpl*>(web_contents())->GetView());
1397 DCHECK(wcva);
1398 wcva->SetContentViewCore(NULL);
1401 // This is called for each ContentView.
1402 jlong Init(JNIEnv* env,
1403 jobject obj,
1404 jobject web_contents,
1405 jobject view_android,
1406 jlong window_android,
1407 jobject retained_objects_set) {
1408 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1409 env, obj, WebContents::FromJavaWebContents(web_contents), view_android,
1410 reinterpret_cast<ui::WindowAndroid*>(window_android),
1411 retained_objects_set);
1412 return reinterpret_cast<intptr_t>(view);
1415 static jobject FromWebContentsAndroid(
1416 JNIEnv* env,
1417 jclass clazz,
1418 jobject jweb_contents) {
1419 WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
1420 if (!web_contents)
1421 return NULL;
1423 ContentViewCore* view = ContentViewCore::FromWebContents(web_contents);
1424 if (!view)
1425 return NULL;
1427 return view->GetJavaObject().Release();
1430 bool RegisterContentViewCore(JNIEnv* env) {
1431 return RegisterNativesImpl(env);
1434 } // namespace content