Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / content / browser / android / content_view_core_impl.cc
blobdd9bab868ac8c7921370b381c6b292f95a86996b
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/web_contents/web_contents_view_android.h"
36 #include "content/common/frame_messages.h"
37 #include "content/common/input/web_input_event_traits.h"
38 #include "content/common/input_messages.h"
39 #include "content/common/view_messages.h"
40 #include "content/public/browser/android/compositor.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/point_conversions.h"
58 #include "ui/gfx/geometry/size_conversions.h"
59 #include "ui/gfx/geometry/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 default:
151 NOTREACHED() << "Invalid source gesture type: "
152 << WebInputEventTraits::GetName(type);
153 return -1;
157 } // namespace
159 // Enables a callback when the underlying WebContents is destroyed, to enable
160 // nulling the back-pointer.
161 class ContentViewCoreImpl::ContentViewUserData
162 : public base::SupportsUserData::Data {
163 public:
164 explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
165 : content_view_core_(content_view_core) {
168 ~ContentViewUserData() override {
169 // TODO(joth): When chrome has finished removing the TabContents class (see
170 // crbug.com/107201) consider inverting relationship, so ContentViewCore
171 // would own WebContents. That effectively implies making the WebContents
172 // destructor private on Android.
173 delete content_view_core_;
176 ContentViewCoreImpl* get() const { return content_view_core_; }
178 private:
179 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
180 ContentViewCoreImpl* content_view_core_;
182 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
185 // static
186 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
187 content::WebContents* web_contents) {
188 ContentViewCoreImpl::ContentViewUserData* data =
189 static_cast<ContentViewCoreImpl::ContentViewUserData*>(
190 web_contents->GetUserData(kContentViewUserDataKey));
191 return data ? data->get() : NULL;
194 // static
195 ContentViewCore* ContentViewCore::FromWebContents(
196 content::WebContents* web_contents) {
197 return ContentViewCoreImpl::FromWebContents(web_contents);
200 // static
201 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
202 jobject obj) {
203 return reinterpret_cast<ContentViewCore*>(
204 Java_ContentViewCore_getNativeContentViewCore(env, obj));
207 ContentViewCoreImpl::ContentViewCoreImpl(
208 JNIEnv* env,
209 jobject obj,
210 WebContents* web_contents,
211 jobject view_android_delegate,
212 ui::WindowAndroid* window_android,
213 jobject java_bridge_retained_object_set)
214 : WebContentsObserver(web_contents),
215 java_ref_(env, obj),
216 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
217 root_layer_(cc::SolidColorLayer::Create(Compositor::LayerSettings())),
218 page_scale_(1),
219 view_android_(new ui::ViewAndroid(view_android_delegate, window_android)),
220 dpi_scale_(ui::GetScaleFactorForNativeView(view_android_.get())),
221 window_android_(window_android),
222 device_orientation_(0),
223 accessibility_enabled_(false) {
224 CHECK(web_contents) <<
225 "A ContentViewCoreImpl should be created with a valid WebContents.";
226 DCHECK(window_android_);
228 root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj));
229 gfx::Size physical_size(
230 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
231 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
232 root_layer_->SetBounds(physical_size);
233 root_layer_->SetIsDrawable(true);
235 // Currently, the only use case we have for overriding a user agent involves
236 // spoofing a desktop Linux user agent for "Request desktop site".
237 // Automatically set it for all WebContents so that it is available when a
238 // NavigationEntry requires the user agent to be overridden.
239 const char kLinuxInfoStr[] = "X11; Linux x86_64";
240 std::string product = content::GetContentClient()->GetProduct();
241 std::string spoofed_ua =
242 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
243 web_contents->SetUserAgentOverride(spoofed_ua);
245 java_bridge_dispatcher_host_ =
246 new GinJavaBridgeDispatcherHost(web_contents,
247 java_bridge_retained_object_set);
249 InitWebContents();
252 ContentViewCoreImpl::~ContentViewCoreImpl() {
253 root_layer_->RemoveFromParent();
255 JNIEnv* env = base::android::AttachCurrentThread();
256 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
257 java_ref_.reset();
258 if (!j_obj.is_null()) {
259 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
260 env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
264 base::android::ScopedJavaLocalRef<jobject>
265 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
266 return web_contents_->GetJavaWebContents();
269 base::android::ScopedJavaLocalRef<jobject>
270 ContentViewCoreImpl::GetJavaWindowAndroid(JNIEnv* env, jobject obj) {
271 if (!window_android_)
272 return ScopedJavaLocalRef<jobject>();
273 return window_android_->GetJavaObject();
276 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
277 jobject obj) {
278 DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
279 java_ref_.reset();
280 // Java peer has gone, ContentViewCore is not functional and waits to
281 // be destroyed with WebContents.
282 // We need to reset WebContentsViewAndroid's reference, otherwise, there
283 // could have call in when swapping the WebContents,
284 // see http://crbug.com/383939 .
285 DCHECK(web_contents_);
286 static_cast<WebContentsViewAndroid*>(
287 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
288 SetContentViewCore(NULL);
291 void ContentViewCoreImpl::InitWebContents() {
292 DCHECK(web_contents_);
293 static_cast<WebContentsViewAndroid*>(
294 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
295 SetContentViewCore(this);
296 DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
297 web_contents_->SetUserData(kContentViewUserDataKey,
298 new ContentViewUserData(this));
301 void ContentViewCoreImpl::RenderViewReady() {
302 JNIEnv* env = AttachCurrentThread();
303 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
304 if (!obj.is_null())
305 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
307 if (device_orientation_ != 0)
308 SendOrientationChangeEventInternal();
311 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host,
312 RenderViewHost* new_host) {
313 int old_pid = 0;
314 if (old_host) {
315 old_pid = GetRenderProcessIdFromRenderViewHost(old_host);
317 RenderWidgetHostViewAndroid* view =
318 static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView());
319 if (view)
320 view->SetContentViewCore(NULL);
322 view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView());
323 if (view)
324 view->SetContentViewCore(this);
326 int new_pid = GetRenderProcessIdFromRenderViewHost(
327 web_contents_->GetRenderViewHost());
328 if (new_pid != old_pid) {
329 // Notify the Java side that the renderer process changed.
330 JNIEnv* env = AttachCurrentThread();
331 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
332 if (!obj.is_null()) {
333 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
337 SetFocusInternal(HasFocus());
338 SetAccessibilityEnabledInternal(accessibility_enabled_);
341 RenderWidgetHostViewAndroid*
342 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() const {
343 RenderWidgetHostView* rwhv = NULL;
344 if (web_contents_) {
345 rwhv = web_contents_->GetRenderWidgetHostView();
346 if (web_contents_->ShowingInterstitialPage()) {
347 rwhv = web_contents_->GetInterstitialPage()
348 ->GetMainFrame()
349 ->GetRenderViewHost()
350 ->GetView();
353 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
356 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
357 JNIEnv* env = AttachCurrentThread();
358 return java_ref_.get(env);
361 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
362 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
363 if (!rwhva)
364 return SK_ColorWHITE;
365 return rwhva->GetCachedBackgroundColor();
368 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
369 if (should_pause)
370 web_contents_->GetGeolocationServiceContext()->PauseUpdates();
371 else
372 web_contents_->GetGeolocationServiceContext()->ResumeUpdates();
375 // All positions and sizes are in CSS pixels.
376 // Note that viewport_width/height is a best effort based.
377 // ContentViewCore has the actual information about the physical viewport size.
378 void ContentViewCoreImpl::UpdateFrameInfo(
379 const gfx::Vector2dF& scroll_offset,
380 float page_scale_factor,
381 const gfx::Vector2dF& page_scale_factor_limits,
382 const gfx::SizeF& content_size,
383 const gfx::SizeF& viewport_size,
384 const gfx::Vector2dF& controls_offset,
385 const gfx::Vector2dF& content_offset,
386 bool is_mobile_optimized_hint) {
387 JNIEnv* env = AttachCurrentThread();
388 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
389 if (obj.is_null())
390 return;
392 window_android_->set_content_offset(
393 gfx::ScaleVector2d(content_offset, dpi_scale_));
395 page_scale_ = page_scale_factor;
397 Java_ContentViewCore_updateFrameInfo(
398 env, obj.obj(),
399 scroll_offset.x(),
400 scroll_offset.y(),
401 page_scale_factor,
402 page_scale_factor_limits.x(),
403 page_scale_factor_limits.y(),
404 content_size.width(),
405 content_size.height(),
406 viewport_size.width(),
407 viewport_size.height(),
408 controls_offset.y(),
409 content_offset.y(),
410 is_mobile_optimized_hint);
413 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
414 JNIEnv* env = AttachCurrentThread();
415 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
416 if (obj.is_null())
417 return;
418 ScopedJavaLocalRef<jstring> jtitle =
419 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
420 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
423 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
424 root_layer_->SetBackgroundColor(color);
426 JNIEnv* env = AttachCurrentThread();
427 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
428 if (obj.is_null())
429 return;
430 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
433 void ContentViewCoreImpl::ShowSelectPopupMenu(
434 RenderFrameHost* frame,
435 const gfx::Rect& bounds,
436 const std::vector<MenuItem>& items,
437 int selected_item,
438 bool multiple) {
439 JNIEnv* env = AttachCurrentThread();
440 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
441 if (j_obj.is_null())
442 return;
444 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
446 // For multi-select list popups we find the list of previous selections by
447 // iterating through the items. But for single selection popups we take the
448 // given |selected_item| as is.
449 ScopedJavaLocalRef<jintArray> selected_array;
450 if (multiple) {
451 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
452 size_t selected_count = 0;
453 for (size_t i = 0; i < items.size(); ++i) {
454 if (items[i].checked)
455 native_selected_array[selected_count++] = i;
458 selected_array = ScopedJavaLocalRef<jintArray>(
459 env, env->NewIntArray(selected_count));
460 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
461 native_selected_array.get());
462 } else {
463 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
464 jint value = selected_item;
465 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
468 ScopedJavaLocalRef<jintArray> enabled_array(env,
469 env->NewIntArray(items.size()));
470 std::vector<base::string16> labels;
471 labels.reserve(items.size());
472 for (size_t i = 0; i < items.size(); ++i) {
473 labels.push_back(items[i].label);
474 jint enabled =
475 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
476 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
477 POPUP_ITEM_TYPE_DISABLED));
478 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
480 ScopedJavaLocalRef<jobjectArray> items_array(
481 base::android::ToJavaArrayOfStrings(env, labels));
482 Java_ContentViewCore_showSelectPopup(env,
483 j_obj.obj(),
484 reinterpret_cast<intptr_t>(frame),
485 bounds_rect.obj(),
486 items_array.obj(),
487 enabled_array.obj(),
488 multiple,
489 selected_array.obj());
492 void ContentViewCoreImpl::HideSelectPopupMenu() {
493 JNIEnv* env = AttachCurrentThread();
494 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
495 if (!j_obj.is_null())
496 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
499 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
500 InputEventAckState ack_result) {
501 JNIEnv* env = AttachCurrentThread();
502 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
503 if (j_obj.is_null())
504 return;
506 switch (event.type) {
507 case WebInputEvent::GestureFlingStart:
508 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
509 // The view expects the fling velocity in pixels/s.
510 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
511 event.data.flingStart.velocityX * dpi_scale(),
512 event.data.flingStart.velocityY * dpi_scale());
513 } else {
514 // If a scroll ends with a fling, a SCROLL_END event is never sent.
515 // However, if that fling went unconsumed, we still need to let the
516 // listeners know that scrolling has ended.
517 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
520 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
521 // The view expects the fling velocity in pixels/s.
522 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
523 event.data.flingStart.velocityX * dpi_scale(),
524 event.data.flingStart.velocityY * dpi_scale());
526 break;
527 case WebInputEvent::GestureFlingCancel:
528 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
529 break;
530 case WebInputEvent::GestureScrollBegin:
531 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
532 break;
533 case WebInputEvent::GestureScrollUpdate:
534 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
535 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
536 break;
537 case WebInputEvent::GestureScrollEnd:
538 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
539 break;
540 case WebInputEvent::GesturePinchBegin:
541 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
542 break;
543 case WebInputEvent::GesturePinchEnd:
544 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
545 break;
546 case WebInputEvent::GestureTap:
547 Java_ContentViewCore_onSingleTapEventAck(
548 env,
549 j_obj.obj(),
550 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
551 event.x * dpi_scale(),
552 event.y * dpi_scale());
553 break;
554 default:
555 break;
559 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
560 if (event.type != WebInputEvent::GestureTap &&
561 event.type != WebInputEvent::GestureDoubleTap &&
562 event.type != WebInputEvent::GestureLongTap &&
563 event.type != WebInputEvent::GestureLongPress)
564 return false;
566 JNIEnv* env = AttachCurrentThread();
567 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
568 if (j_obj.is_null())
569 return false;
571 const blink::WebGestureEvent& gesture =
572 static_cast<const blink::WebGestureEvent&>(event);
573 int gesture_type = ToGestureEventType(event.type);
574 return Java_ContentViewCore_filterTapOrPressEvent(env,
575 j_obj.obj(),
576 gesture_type,
577 gesture.x * dpi_scale(),
578 gesture.y * dpi_scale());
580 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
583 bool ContentViewCoreImpl::HasFocus() {
584 JNIEnv* env = AttachCurrentThread();
585 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
586 if (obj.is_null())
587 return false;
588 return Java_ContentViewCore_hasFocus(env, obj.obj());
591 void ContentViewCoreImpl::RequestDisallowInterceptTouchEvent() {
592 JNIEnv* env = AttachCurrentThread();
593 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
594 if (!obj.is_null())
595 Java_ContentViewCore_requestDisallowInterceptTouchEvent(env, obj.obj());
598 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
599 JNIEnv* env = AttachCurrentThread();
600 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
601 if (obj.is_null())
602 return;
603 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
604 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
607 void ContentViewCoreImpl::OnSelectionEvent(ui::SelectionEventType event,
608 const gfx::PointF& selection_anchor,
609 const gfx::RectF& selection_rect) {
610 JNIEnv* env = AttachCurrentThread();
611 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
612 if (j_obj.is_null())
613 return;
615 gfx::PointF selection_anchor_pix =
616 gfx::ScalePoint(selection_anchor, dpi_scale());
617 gfx::RectF selection_rect_pix = gfx::ScaleRect(selection_rect, dpi_scale());
618 Java_ContentViewCore_onSelectionEvent(
619 env, j_obj.obj(), event, selection_anchor_pix.x(),
620 selection_anchor_pix.y(), selection_rect_pix.x(), selection_rect_pix.y(),
621 selection_rect_pix.right(), selection_rect_pix.bottom());
624 scoped_ptr<ui::TouchHandleDrawable>
625 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
626 JNIEnv* env = AttachCurrentThread();
627 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
628 if (obj.is_null()) {
629 NOTREACHED();
630 return scoped_ptr<ui::TouchHandleDrawable>();
632 return scoped_ptr<ui::TouchHandleDrawable>(new PopupTouchHandleDrawable(
633 Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()),
634 dpi_scale_));
637 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
638 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
639 if (!view)
640 return;
642 view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
644 JNIEnv* env = AttachCurrentThread();
645 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
646 if (obj.is_null())
647 return;
648 Java_ContentViewCore_showPastePopupWithFeedback(
649 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
650 static_cast<jint>(y_dip * dpi_scale()));
653 void ContentViewCoreImpl::GetScaledContentBitmap(
654 float scale,
655 SkColorType preferred_color_type,
656 const gfx::Rect& src_subrect,
657 ReadbackRequestCallback& result_callback) {
658 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
659 if (!view || preferred_color_type == kUnknown_SkColorType) {
660 result_callback.Run(SkBitmap(), READBACK_FAILED);
661 return;
664 view->GetScaledContentBitmap(scale, preferred_color_type, src_subrect,
665 result_callback);
668 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
669 JNIEnv* env = AttachCurrentThread();
670 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
671 if (j_obj.is_null())
672 return;
673 ScopedJavaLocalRef<jstring> jcontent_url =
674 ConvertUTF8ToJavaString(env, content_url.spec());
675 Java_ContentViewCore_startContentIntent(env,
676 j_obj.obj(),
677 jcontent_url.obj());
680 void ContentViewCoreImpl::ShowDisambiguationPopup(
681 const gfx::Rect& rect_pixels,
682 const SkBitmap& zoomed_bitmap) {
683 JNIEnv* env = AttachCurrentThread();
685 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
686 if (obj.is_null())
687 return;
689 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
691 ScopedJavaLocalRef<jobject> java_bitmap =
692 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
693 DCHECK(!java_bitmap.is_null());
695 Java_ContentViewCore_showDisambiguationPopup(env,
696 obj.obj(),
697 rect_object.obj(),
698 java_bitmap.obj());
701 ScopedJavaLocalRef<jobject>
702 ContentViewCoreImpl::CreateMotionEventSynthesizer() {
703 JNIEnv* env = AttachCurrentThread();
705 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
706 if (obj.is_null())
707 return ScopedJavaLocalRef<jobject>();
708 return Java_ContentViewCore_createMotionEventSynthesizer(env, obj.obj());
711 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
712 JNIEnv* env = AttachCurrentThread();
714 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
715 if (obj.is_null())
716 return true;
717 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
718 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
719 j_url.obj());
722 void ContentViewCoreImpl::DidStopFlinging() {
723 JNIEnv* env = AttachCurrentThread();
725 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
726 if (!obj.is_null())
727 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
730 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() const {
731 JNIEnv* env = AttachCurrentThread();
733 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
734 if (obj.is_null())
735 return ScopedJavaLocalRef<jobject>();
737 return Java_ContentViewCore_getContext(env, obj.obj());
740 gfx::Size ContentViewCoreImpl::GetViewSize() const {
741 gfx::Size size = GetViewportSizeDip();
742 if (DoTopControlsShrinkBlinkSize())
743 size.Enlarge(0, -GetTopControlsHeightDip());
744 return size;
747 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
748 JNIEnv* env = AttachCurrentThread();
749 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
750 if (j_obj.is_null())
751 return gfx::Size();
752 return gfx::Size(
753 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
754 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
757 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
758 JNIEnv* env = AttachCurrentThread();
759 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
760 if (j_obj.is_null())
761 return gfx::Size();
762 return gfx::Size(
763 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
764 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
767 int ContentViewCoreImpl::GetTopControlsHeightPix() const {
768 JNIEnv* env = AttachCurrentThread();
769 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
770 if (j_obj.is_null())
771 return 0;
772 return Java_ContentViewCore_getTopControlsHeightPix(env, j_obj.obj());
775 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
776 return gfx::ToCeiledSize(
777 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
780 bool ContentViewCoreImpl::DoTopControlsShrinkBlinkSize() const {
781 JNIEnv* env = AttachCurrentThread();
782 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
783 if (j_obj.is_null())
784 return false;
785 return Java_ContentViewCore_doTopControlsShrinkBlinkSize(env, j_obj.obj());
788 float ContentViewCoreImpl::GetTopControlsHeightDip() const {
789 return GetTopControlsHeightPix() / dpi_scale();
792 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
793 root_layer_->InsertChild(layer, 0);
794 root_layer_->SetIsDrawable(false);
797 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
798 layer->RemoveFromParent();
800 if (!root_layer_->children().size())
801 root_layer_->SetIsDrawable(true);
804 void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF& extent) {
805 if (!web_contents_)
806 return;
808 web_contents_->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
811 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& base,
812 const gfx::PointF& extent) {
813 if (!web_contents_)
814 return;
816 gfx::Point base_point = gfx::ToRoundedPoint(base);
817 gfx::Point extent_point = gfx::ToRoundedPoint(extent);
818 if (base_point == extent_point)
819 return;
821 web_contents_->SelectRange(base_point, extent_point);
824 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
825 return view_android_.get();
828 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
829 return window_android_;
832 const scoped_refptr<cc::Layer>& ContentViewCoreImpl::GetLayer() const {
833 return root_layer_;
836 // ----------------------------------------------------------------------------
837 // Methods called from Java via JNI
838 // ----------------------------------------------------------------------------
840 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
841 jobject obj,
842 jlong selectPopupSourceFrame,
843 jintArray indices) {
844 RenderFrameHostImpl* rfhi =
845 reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
846 DCHECK(rfhi);
847 if (indices == NULL) {
848 rfhi->DidCancelPopupMenu();
849 return;
852 int selected_count = env->GetArrayLength(indices);
853 std::vector<int> selected_indices;
854 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
855 for (int i = 0; i < selected_count; ++i)
856 selected_indices.push_back(indices_ptr[i]);
857 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
858 rfhi->DidSelectPopupMenuItems(selected_indices);
861 WebContents* ContentViewCoreImpl::GetWebContents() const {
862 return web_contents_;
865 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
866 SetFocusInternal(focused);
869 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
870 if (!GetRenderWidgetHostViewAndroid())
871 return;
873 if (focused)
874 GetRenderWidgetHostViewAndroid()->Focus();
875 else
876 GetRenderWidgetHostViewAndroid()->Blur();
879 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
880 jobject obj,
881 jint orientation) {
882 if (device_orientation_ != orientation) {
883 device_orientation_ = orientation;
884 SendOrientationChangeEventInternal();
888 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
889 jobject obj,
890 jobject motion_event,
891 jlong time_ms,
892 jint android_action,
893 jint pointer_count,
894 jint history_size,
895 jint action_index,
896 jfloat pos_x_0,
897 jfloat pos_y_0,
898 jfloat pos_x_1,
899 jfloat pos_y_1,
900 jint pointer_id_0,
901 jint pointer_id_1,
902 jfloat touch_major_0,
903 jfloat touch_major_1,
904 jfloat touch_minor_0,
905 jfloat touch_minor_1,
906 jfloat orientation_0,
907 jfloat orientation_1,
908 jfloat raw_pos_x,
909 jfloat raw_pos_y,
910 jint android_tool_type_0,
911 jint android_tool_type_1,
912 jint android_button_state,
913 jint android_meta_state,
914 jboolean is_touch_handle_event) {
915 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
916 // Avoid synthesizing a touch event if it cannot be forwarded.
917 if (!rwhv)
918 return false;
920 MotionEventAndroid::Pointer pointer0(pointer_id_0,
921 pos_x_0,
922 pos_y_0,
923 touch_major_0,
924 touch_minor_0,
925 orientation_0,
926 android_tool_type_0);
927 MotionEventAndroid::Pointer pointer1(pointer_id_1,
928 pos_x_1,
929 pos_y_1,
930 touch_major_1,
931 touch_minor_1,
932 orientation_1,
933 android_tool_type_1);
934 MotionEventAndroid event(1.f / dpi_scale(),
935 env,
936 motion_event,
937 time_ms,
938 android_action,
939 pointer_count,
940 history_size,
941 action_index,
942 android_button_state,
943 android_meta_state,
944 raw_pos_x - pos_x_0,
945 raw_pos_y - pos_y_0,
946 pointer0,
947 pointer1);
949 return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
950 : rwhv->OnTouchEvent(event);
953 float ContentViewCoreImpl::GetDpiScale() const {
954 return dpi_scale_;
957 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
958 jobject obj,
959 jlong time_ms,
960 jfloat x,
961 jfloat y) {
962 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
963 if (!rwhv)
964 return false;
966 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
967 WebInputEvent::MouseMove,
968 blink::WebMouseEvent::ButtonNone,
969 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
971 rwhv->SendMouseEvent(event);
972 return true;
975 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
976 jobject obj,
977 jlong time_ms,
978 jfloat x,
979 jfloat y,
980 jfloat ticks_x,
981 jfloat ticks_y,
982 jfloat pixels_per_tick) {
983 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
984 if (!rwhv)
985 return false;
987 if (!ticks_x && !ticks_y)
988 return false;
990 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
991 ticks_x, ticks_y, pixels_per_tick / dpi_scale(), time_ms / 1000.0,
992 x / dpi_scale(), y / dpi_scale());
994 rwhv->SendMouseWheelEvent(event);
995 return true;
998 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
999 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
1000 return WebGestureEventBuilder::Build(
1001 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1004 void ContentViewCoreImpl::SendGestureEvent(
1005 const blink::WebGestureEvent& event) {
1006 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1007 if (rwhv)
1008 rwhv->SendGestureEvent(event);
1011 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
1012 jobject obj,
1013 jlong time_ms,
1014 jfloat x,
1015 jfloat y,
1016 jfloat hintx,
1017 jfloat hinty,
1018 jboolean target_viewport) {
1019 WebGestureEvent event = MakeGestureEvent(
1020 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1021 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1022 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1023 event.data.scrollBegin.targetViewport = target_viewport;
1025 SendGestureEvent(event);
1028 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1029 WebGestureEvent event = MakeGestureEvent(
1030 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1031 SendGestureEvent(event);
1034 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1035 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1036 WebGestureEvent event = MakeGestureEvent(
1037 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1038 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1039 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1041 SendGestureEvent(event);
1044 void ContentViewCoreImpl::FlingStart(JNIEnv* env,
1045 jobject obj,
1046 jlong time_ms,
1047 jfloat x,
1048 jfloat y,
1049 jfloat vx,
1050 jfloat vy,
1051 jboolean target_viewport) {
1052 WebGestureEvent event = MakeGestureEvent(
1053 WebInputEvent::GestureFlingStart, time_ms, x, y);
1054 event.data.flingStart.velocityX = vx / dpi_scale();
1055 event.data.flingStart.velocityY = vy / dpi_scale();
1056 event.data.flingStart.targetViewport = target_viewport;
1058 SendGestureEvent(event);
1061 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1062 WebGestureEvent event = MakeGestureEvent(
1063 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1064 event.data.flingCancel.preventBoosting = true;
1066 SendGestureEvent(event);
1069 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1070 jfloat x, jfloat y) {
1071 // Tap gestures should always be preceded by a TapDown, ensuring consistency
1072 // with the touch-based gesture detection pipeline.
1073 WebGestureEvent tap_down_event = MakeGestureEvent(
1074 WebInputEvent::GestureTapDown, time_ms, x, y);
1075 tap_down_event.data.tap.tapCount = 1;
1076 SendGestureEvent(tap_down_event);
1078 WebGestureEvent tap_event = MakeGestureEvent(
1079 WebInputEvent::GestureTap, time_ms, x, y);
1080 tap_event.data.tap.tapCount = 1;
1081 SendGestureEvent(tap_event);
1084 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1085 jfloat x, jfloat y) {
1086 WebGestureEvent event = MakeGestureEvent(
1087 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1088 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1089 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1090 event.data.tap.tapCount = 1;
1092 SendGestureEvent(event);
1095 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1096 jfloat x, jfloat y) {
1097 WebGestureEvent event = MakeGestureEvent(
1098 WebInputEvent::GestureLongPress, time_ms, x, y);
1100 SendGestureEvent(event);
1103 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1104 jfloat x, jfloat y) {
1105 WebGestureEvent event = MakeGestureEvent(
1106 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1107 SendGestureEvent(event);
1110 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1111 WebGestureEvent event = MakeGestureEvent(
1112 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1113 SendGestureEvent(event);
1116 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1117 jfloat anchor_x, jfloat anchor_y,
1118 jfloat delta) {
1119 WebGestureEvent event = MakeGestureEvent(
1120 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1121 event.data.pinchUpdate.scale = delta;
1123 SendGestureEvent(event);
1126 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1127 jfloat x1, jfloat y1,
1128 jfloat x2, jfloat y2) {
1129 SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
1130 gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
1133 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1134 jfloat x, jfloat y) {
1135 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1136 if (rwhv)
1137 rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
1140 void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
1141 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1142 if (rwhv)
1143 rwhv->DismissTextHandles();
1146 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
1147 jobject obj,
1148 jboolean hidden) {
1149 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1150 if (rwhv)
1151 rwhv->SetTextHandlesTemporarilyHidden(hidden);
1154 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1155 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1156 if (rwhv)
1157 rwhv->ResetGestureDetection();
1160 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1161 jobject obj,
1162 jboolean enabled) {
1163 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1164 if (rwhv)
1165 rwhv->SetDoubleTapSupportEnabled(enabled);
1168 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1169 jobject obj,
1170 jboolean enabled) {
1171 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1172 if (rwhv)
1173 rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1176 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1177 JNIEnv* env,
1178 jobject obj,
1179 jboolean allow) {
1180 java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
1183 void ContentViewCoreImpl::AddJavascriptInterface(
1184 JNIEnv* env,
1185 jobject /* obj */,
1186 jobject object,
1187 jstring name,
1188 jclass safe_annotation_clazz) {
1189 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1190 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1191 java_bridge_dispatcher_host_->AddNamedObject(
1192 ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
1195 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1196 jobject /* obj */,
1197 jstring name) {
1198 java_bridge_dispatcher_host_->RemoveNamedObject(
1199 ConvertJavaStringToUTF8(env, name));
1202 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1203 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1204 gfx::Size physical_size(
1205 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1206 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1207 root_layer_->SetBounds(physical_size);
1209 if (view) {
1210 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1211 view->GetRenderWidgetHost());
1212 host->SendScreenRects();
1213 view->WasResized();
1217 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1218 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1219 if (!rwhva)
1220 return 0;
1221 return rwhva->GetNativeImeAdapter();
1224 void ContentViewCoreImpl::ForceUpdateImeAdapter(long native_ime_adapter) {
1225 JNIEnv* env = AttachCurrentThread();
1226 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1227 if (obj.is_null())
1228 return;
1229 Java_ContentViewCore_forceUpdateImeAdapter(env, obj.obj(),
1230 native_ime_adapter);
1233 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1234 int text_input_type,
1235 int text_input_flags,
1236 const std::string& text,
1237 int selection_start,
1238 int selection_end,
1239 int composition_start,
1240 int composition_end,
1241 bool show_ime_if_needed,
1242 bool is_non_ime_change) {
1243 JNIEnv* env = AttachCurrentThread();
1244 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1245 if (obj.is_null())
1246 return;
1248 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1249 Java_ContentViewCore_updateImeAdapter(env,
1250 obj.obj(),
1251 native_ime_adapter,
1252 text_input_type,
1253 text_input_flags,
1254 jstring_text.obj(),
1255 selection_start,
1256 selection_end,
1257 composition_start,
1258 composition_end,
1259 show_ime_if_needed,
1260 is_non_ime_change);
1263 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1264 bool enabled) {
1265 SetAccessibilityEnabledInternal(enabled);
1268 void ContentViewCoreImpl::SetTextTrackSettings(JNIEnv* env,
1269 jobject obj,
1270 jboolean textTracksEnabled,
1271 jstring textTrackBackgroundColor,
1272 jstring textTrackFontFamily,
1273 jstring textTrackFontStyle,
1274 jstring textTrackFontVariant,
1275 jstring textTrackTextColor,
1276 jstring textTrackTextShadow,
1277 jstring textTrackTextSize) {
1278 FrameMsg_TextTrackSettings_Params params;
1279 params.text_tracks_enabled = textTracksEnabled;
1280 params.text_track_background_color = ConvertJavaStringToUTF8(
1281 env, textTrackBackgroundColor);
1282 params.text_track_font_family = ConvertJavaStringToUTF8(
1283 env, textTrackFontFamily);
1284 params.text_track_font_style = ConvertJavaStringToUTF8(
1285 env, textTrackFontStyle);
1286 params.text_track_font_variant = ConvertJavaStringToUTF8(
1287 env, textTrackFontVariant);
1288 params.text_track_text_color = ConvertJavaStringToUTF8(
1289 env, textTrackTextColor);
1290 params.text_track_text_shadow = ConvertJavaStringToUTF8(
1291 env, textTrackTextShadow);
1292 params.text_track_text_size = ConvertJavaStringToUTF8(
1293 env, textTrackTextSize);
1294 web_contents_->GetMainFrame()->SetTextTrackSettings(params);
1297 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1298 JNIEnv* env = AttachCurrentThread();
1299 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1300 if (obj.is_null())
1301 return true;
1302 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
1303 obj.obj());
1306 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1307 accessibility_enabled_ = enabled;
1308 BrowserAccessibilityStateImpl* accessibility_state =
1309 BrowserAccessibilityStateImpl::GetInstance();
1310 if (enabled) {
1311 // This enables accessibility globally unless it was explicitly disallowed
1312 // by a command-line flag.
1313 accessibility_state->OnScreenReaderDetected();
1314 // If it was actually enabled globally, enable it for this RenderWidget now.
1315 if (accessibility_state->IsAccessibleBrowser() && web_contents_)
1316 web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
1317 } else {
1318 accessibility_state->ResetAccessibilityMode();
1319 if (web_contents_) {
1320 web_contents_->SetAccessibilityMode(
1321 accessibility_state->accessibility_mode());
1326 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1327 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1328 if (rwhv)
1329 rwhv->UpdateScreenInfo(GetViewAndroid());
1331 static_cast<WebContentsImpl*>(web_contents())->
1332 screen_orientation_dispatcher_host()->OnOrientationChange();
1335 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1336 jobject obj,
1337 jint x,
1338 jint y,
1339 jint width,
1340 jint height) {
1341 gfx::Rect rect(
1342 static_cast<int>(x / dpi_scale()),
1343 static_cast<int>(y / dpi_scale()),
1344 static_cast<int>((width > 0 && width < dpi_scale()) ?
1345 1 : (int)(width / dpi_scale())),
1346 static_cast<int>((height > 0 && height < dpi_scale()) ?
1347 1 : (int)(height / dpi_scale())));
1348 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1349 GetWebContents()->GetRoutingID(), rect));
1352 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1353 return GetRenderProcessIdFromRenderViewHost(
1354 web_contents_->GetRenderViewHost());
1357 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1358 jboolean opaque) {
1359 if (GetRenderWidgetHostViewAndroid()) {
1360 if (opaque)
1361 GetRenderWidgetHostViewAndroid()->SetBackgroundColorToDefault();
1362 else
1363 GetRenderWidgetHostViewAndroid()->SetBackgroundColor(SK_ColorTRANSPARENT);
1367 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1368 int max_length,
1369 const base::Callback<
1370 void(const base::string16& content, int start_offset, int end_offset)>&
1371 callback) {
1372 DCHECK(!callback.is_null());
1373 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1374 if (!focused_frame)
1375 return;
1376 if (GetRenderWidgetHostViewAndroid()) {
1377 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1378 callback);
1379 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1380 focused_frame->GetRoutingID(), max_length));
1384 void ContentViewCoreImpl::OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip) {
1385 JNIEnv* env = AttachCurrentThread();
1386 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1387 if (obj.is_null())
1388 return;
1389 Java_ContentViewCore_onShowUnhandledTapUIIfNeeded(
1390 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
1391 static_cast<jint>(y_dip * dpi_scale()));
1394 float ContentViewCoreImpl::GetScaleFactor() const {
1395 return page_scale_ * dpi_scale_;
1398 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1399 const base::string16& text,
1400 const base::string16& html,
1401 const gfx::Rect& clip_rect) {
1402 JNIEnv* env = AttachCurrentThread();
1403 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1404 if (obj.is_null())
1405 return;
1406 ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
1407 ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
1408 ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
1409 Java_ContentViewCore_onSmartClipDataExtracted(
1410 env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
1413 void ContentViewCoreImpl::WebContentsDestroyed() {
1414 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1415 static_cast<WebContentsImpl*>(web_contents())->GetView());
1416 DCHECK(wcva);
1417 wcva->SetContentViewCore(NULL);
1420 bool ContentViewCoreImpl::PullStart() {
1421 JNIEnv* env = AttachCurrentThread();
1422 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1423 if (!obj.is_null())
1424 return Java_ContentViewCore_onOverscrollRefreshStart(env, obj.obj());
1425 return false;
1428 void ContentViewCoreImpl::PullUpdate(float delta) {
1429 JNIEnv* env = AttachCurrentThread();
1430 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1431 if (!obj.is_null())
1432 Java_ContentViewCore_onOverscrollRefreshUpdate(env, obj.obj(), delta);
1435 void ContentViewCoreImpl::PullRelease(bool allow_refresh) {
1436 JNIEnv* env = AttachCurrentThread();
1437 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1438 if (!obj.is_null()) {
1439 Java_ContentViewCore_onOverscrollRefreshRelease(env, obj.obj(),
1440 allow_refresh);
1444 void ContentViewCoreImpl::PullReset() {
1445 JNIEnv* env = AttachCurrentThread();
1446 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1447 if (!obj.is_null())
1448 Java_ContentViewCore_onOverscrollRefreshReset(env, obj.obj());
1451 // This is called for each ContentView.
1452 jlong Init(JNIEnv* env,
1453 jobject obj,
1454 jobject web_contents,
1455 jobject view_android_delegate,
1456 jlong window_android,
1457 jobject retained_objects_set) {
1458 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1459 env, obj, WebContents::FromJavaWebContents(web_contents),
1460 view_android_delegate,
1461 reinterpret_cast<ui::WindowAndroid*>(window_android),
1462 retained_objects_set);
1463 return reinterpret_cast<intptr_t>(view);
1466 static jobject FromWebContentsAndroid(
1467 JNIEnv* env,
1468 jclass clazz,
1469 jobject jweb_contents) {
1470 WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
1471 if (!web_contents)
1472 return NULL;
1474 ContentViewCore* view = ContentViewCore::FromWebContents(web_contents);
1475 if (!view)
1476 return NULL;
1478 return view->GetJavaObject().Release();
1481 bool RegisterContentViewCore(JNIEnv* env) {
1482 return RegisterNativesImpl(env);
1485 } // namespace content