Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / content / browser / android / content_view_core_impl.cc
blobe87fd3d51f9a87b1643cf46fe43fc777eaa9e092
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_delegate,
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_delegate, 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 InputEventAckState ContentViewCoreImpl::FilterInputEvent(
556 const blink::WebInputEvent& event) {
557 if (event.type != WebInputEvent::GestureTap &&
558 event.type != WebInputEvent::GestureDoubleTap &&
559 event.type != WebInputEvent::GestureLongTap &&
560 event.type != WebInputEvent::GestureLongPress &&
561 event.type != WebInputEvent::GestureFlingCancel) {
562 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
565 JNIEnv* env = AttachCurrentThread();
566 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
567 if (j_obj.is_null())
568 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
570 if (event.type == WebInputEvent::GestureFlingCancel) {
571 // If no fling is active, either in the compositor or externally-driven,
572 // there's no need to explicitly cancel the fling.
573 bool may_need_fling_cancel =
574 Java_ContentViewCore_isScrollInProgress(env, j_obj.obj());
575 return may_need_fling_cancel ? INPUT_EVENT_ACK_STATE_NOT_CONSUMED
576 : INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
579 const blink::WebGestureEvent& gesture =
580 static_cast<const blink::WebGestureEvent&>(event);
581 int gesture_type = ToGestureEventType(event.type);
582 if (Java_ContentViewCore_filterTapOrPressEvent(env,
583 j_obj.obj(),
584 gesture_type,
585 gesture.x * dpi_scale(),
586 gesture.y * dpi_scale())) {
587 return INPUT_EVENT_ACK_STATE_CONSUMED;
590 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
591 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
594 bool ContentViewCoreImpl::HasFocus() {
595 JNIEnv* env = AttachCurrentThread();
596 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
597 if (obj.is_null())
598 return false;
599 return Java_ContentViewCore_hasFocus(env, obj.obj());
602 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
603 JNIEnv* env = AttachCurrentThread();
604 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
605 if (obj.is_null())
606 return;
607 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
608 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
611 void ContentViewCoreImpl::OnSelectionEvent(ui::SelectionEventType event,
612 const gfx::PointF& selection_anchor,
613 const gfx::RectF& selection_rect) {
614 JNIEnv* env = AttachCurrentThread();
615 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
616 if (j_obj.is_null())
617 return;
619 gfx::PointF selection_anchor_pix =
620 gfx::ScalePoint(selection_anchor, dpi_scale());
621 gfx::RectF selection_rect_pix = gfx::ScaleRect(selection_rect, dpi_scale());
622 Java_ContentViewCore_onSelectionEvent(
623 env, j_obj.obj(), event, selection_anchor_pix.x(),
624 selection_anchor_pix.y(), selection_rect_pix.x(), selection_rect_pix.y(),
625 selection_rect_pix.right(), selection_rect_pix.bottom());
628 scoped_ptr<ui::TouchHandleDrawable>
629 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
630 JNIEnv* env = AttachCurrentThread();
631 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
632 if (obj.is_null()) {
633 NOTREACHED();
634 return scoped_ptr<ui::TouchHandleDrawable>();
636 return scoped_ptr<ui::TouchHandleDrawable>(new PopupTouchHandleDrawable(
637 Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()),
638 dpi_scale_));
641 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
642 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
643 if (!view)
644 return;
646 view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
648 JNIEnv* env = AttachCurrentThread();
649 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
650 if (obj.is_null())
651 return;
652 Java_ContentViewCore_showPastePopupWithFeedback(
653 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
654 static_cast<jint>(y_dip * dpi_scale()));
657 void ContentViewCoreImpl::GetScaledContentBitmap(
658 float scale,
659 SkColorType color_type,
660 gfx::Rect src_subrect,
661 ReadbackRequestCallback& result_callback) {
662 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
663 if (!view || color_type == kUnknown_SkColorType) {
664 result_callback.Run(SkBitmap(), READBACK_FAILED);
665 return;
668 view->GetScaledContentBitmap(scale, color_type, src_subrect,
669 result_callback);
672 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
673 JNIEnv* env = AttachCurrentThread();
674 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
675 if (j_obj.is_null())
676 return;
677 ScopedJavaLocalRef<jstring> jcontent_url =
678 ConvertUTF8ToJavaString(env, content_url.spec());
679 Java_ContentViewCore_startContentIntent(env,
680 j_obj.obj(),
681 jcontent_url.obj());
684 void ContentViewCoreImpl::ShowDisambiguationPopup(
685 const gfx::Rect& rect_pixels,
686 const SkBitmap& zoomed_bitmap) {
687 JNIEnv* env = AttachCurrentThread();
689 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
690 if (obj.is_null())
691 return;
693 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
695 ScopedJavaLocalRef<jobject> java_bitmap =
696 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
697 DCHECK(!java_bitmap.is_null());
699 Java_ContentViewCore_showDisambiguationPopup(env,
700 obj.obj(),
701 rect_object.obj(),
702 java_bitmap.obj());
705 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
706 JNIEnv* env = AttachCurrentThread();
708 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
709 if (obj.is_null())
710 return ScopedJavaLocalRef<jobject>();
711 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
714 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
715 JNIEnv* env = AttachCurrentThread();
717 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
718 if (obj.is_null())
719 return true;
720 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
721 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
722 j_url.obj());
725 void ContentViewCoreImpl::DidStopFlinging() {
726 JNIEnv* env = AttachCurrentThread();
728 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
729 if (!obj.is_null())
730 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
733 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() const {
734 JNIEnv* env = AttachCurrentThread();
736 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
737 if (obj.is_null())
738 return ScopedJavaLocalRef<jobject>();
740 return Java_ContentViewCore_getContext(env, obj.obj());
743 gfx::Size ContentViewCoreImpl::GetViewSize() const {
744 gfx::Size size = GetViewportSizeDip();
745 if (DoTopControlsShrinkBlinkSize())
746 size.Enlarge(0, -GetTopControlsHeightDip());
747 return size;
750 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
751 JNIEnv* env = AttachCurrentThread();
752 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
753 if (j_obj.is_null())
754 return gfx::Size();
755 return gfx::Size(
756 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
757 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
760 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
761 JNIEnv* env = AttachCurrentThread();
762 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
763 if (j_obj.is_null())
764 return gfx::Size();
765 return gfx::Size(
766 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
767 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
770 int ContentViewCoreImpl::GetTopControlsHeightPix() const {
771 JNIEnv* env = AttachCurrentThread();
772 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
773 if (j_obj.is_null())
774 return 0;
775 return Java_ContentViewCore_getTopControlsHeightPix(env, j_obj.obj());
778 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
779 return gfx::ToCeiledSize(
780 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
783 bool ContentViewCoreImpl::DoTopControlsShrinkBlinkSize() const {
784 JNIEnv* env = AttachCurrentThread();
785 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
786 if (j_obj.is_null())
787 return false;
788 return Java_ContentViewCore_doTopControlsShrinkBlinkSize(env, j_obj.obj());
791 float ContentViewCoreImpl::GetTopControlsHeightDip() const {
792 return GetTopControlsHeightPix() / dpi_scale();
795 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
796 root_layer_->InsertChild(layer, 0);
797 root_layer_->SetIsDrawable(false);
800 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
801 layer->RemoveFromParent();
803 if (!root_layer_->children().size())
804 root_layer_->SetIsDrawable(true);
807 void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF& extent) {
808 if (!web_contents_)
809 return;
811 web_contents_->MoveRangeSelectionExtent(gfx::Point(extent.x(), extent.y()));
814 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& base,
815 const gfx::PointF& extent) {
816 if (!web_contents_)
817 return;
819 gfx::Point base_point = gfx::Point(base.x(), base.y());
820 gfx::Point extent_point = gfx::Point(extent.x(), extent.y());
821 if (base_point == extent_point)
822 return;
824 web_contents_->SelectRange(base_point, extent_point);
827 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
828 return view_android_.get();
831 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
832 return window_android_;
835 const scoped_refptr<cc::Layer>& ContentViewCoreImpl::GetLayer() const {
836 return root_layer_;
839 // ----------------------------------------------------------------------------
840 // Methods called from Java via JNI
841 // ----------------------------------------------------------------------------
843 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
844 jobject obj,
845 jlong selectPopupSourceFrame,
846 jintArray indices) {
847 RenderFrameHostImpl* rfhi =
848 reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
849 DCHECK(rfhi);
850 if (indices == NULL) {
851 rfhi->DidCancelPopupMenu();
852 return;
855 int selected_count = env->GetArrayLength(indices);
856 std::vector<int> selected_indices;
857 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
858 for (int i = 0; i < selected_count; ++i)
859 selected_indices.push_back(indices_ptr[i]);
860 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
861 rfhi->DidSelectPopupMenuItems(selected_indices);
864 WebContents* ContentViewCoreImpl::GetWebContents() const {
865 return web_contents_;
868 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
869 SetFocusInternal(focused);
872 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
873 if (!GetRenderWidgetHostViewAndroid())
874 return;
876 if (focused)
877 GetRenderWidgetHostViewAndroid()->Focus();
878 else
879 GetRenderWidgetHostViewAndroid()->Blur();
882 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
883 jobject obj,
884 jint orientation) {
885 if (device_orientation_ != orientation) {
886 device_orientation_ = orientation;
887 SendOrientationChangeEventInternal();
891 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
892 jobject obj,
893 jobject motion_event,
894 jlong time_ms,
895 jint android_action,
896 jint pointer_count,
897 jint history_size,
898 jint action_index,
899 jfloat pos_x_0,
900 jfloat pos_y_0,
901 jfloat pos_x_1,
902 jfloat pos_y_1,
903 jint pointer_id_0,
904 jint pointer_id_1,
905 jfloat touch_major_0,
906 jfloat touch_major_1,
907 jfloat touch_minor_0,
908 jfloat touch_minor_1,
909 jfloat orientation_0,
910 jfloat orientation_1,
911 jfloat raw_pos_x,
912 jfloat raw_pos_y,
913 jint android_tool_type_0,
914 jint android_tool_type_1,
915 jint android_button_state,
916 jint android_meta_state,
917 jboolean is_touch_handle_event) {
918 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
919 // Avoid synthesizing a touch event if it cannot be forwarded.
920 if (!rwhv)
921 return false;
923 MotionEventAndroid::Pointer pointer0(pointer_id_0,
924 pos_x_0,
925 pos_y_0,
926 touch_major_0,
927 touch_minor_0,
928 orientation_0,
929 android_tool_type_0);
930 MotionEventAndroid::Pointer pointer1(pointer_id_1,
931 pos_x_1,
932 pos_y_1,
933 touch_major_1,
934 touch_minor_1,
935 orientation_1,
936 android_tool_type_1);
937 MotionEventAndroid event(1.f / dpi_scale(),
938 env,
939 motion_event,
940 time_ms,
941 android_action,
942 pointer_count,
943 history_size,
944 action_index,
945 android_button_state,
946 android_meta_state,
947 raw_pos_x - pos_x_0,
948 raw_pos_y - pos_y_0,
949 pointer0,
950 pointer1);
952 return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
953 : rwhv->OnTouchEvent(event);
956 float ContentViewCoreImpl::GetDpiScale() const {
957 return dpi_scale_;
960 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
961 jobject obj,
962 jlong time_ms,
963 jfloat x,
964 jfloat y) {
965 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
966 if (!rwhv)
967 return false;
969 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
970 WebInputEvent::MouseMove,
971 blink::WebMouseEvent::ButtonNone,
972 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
974 rwhv->SendMouseEvent(event);
975 return true;
978 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
979 jobject obj,
980 jlong time_ms,
981 jfloat x,
982 jfloat y,
983 jfloat vertical_axis,
984 jfloat horizontal_axis) {
985 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
986 if (!rwhv)
987 return false;
989 WebMouseWheelEventBuilder::Direction direction;
990 if (vertical_axis > 0) {
991 direction = WebMouseWheelEventBuilder::DIRECTION_UP;
992 } else if (vertical_axis < 0) {
993 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
994 } else if (horizontal_axis > 0) {
995 direction = WebMouseWheelEventBuilder::DIRECTION_RIGHT;
996 } else if (horizontal_axis < 0) {
997 direction = WebMouseWheelEventBuilder::DIRECTION_LEFT;
998 } else {
999 return false;
1001 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
1002 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1004 rwhv->SendMouseWheelEvent(event);
1005 return true;
1008 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
1009 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
1010 return WebGestureEventBuilder::Build(
1011 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1014 void ContentViewCoreImpl::SendGestureEvent(
1015 const blink::WebGestureEvent& event) {
1016 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1017 if (rwhv)
1018 rwhv->SendGestureEvent(event);
1021 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
1022 jobject obj,
1023 jlong time_ms,
1024 jfloat x,
1025 jfloat y,
1026 jfloat hintx,
1027 jfloat hinty) {
1028 WebGestureEvent event = MakeGestureEvent(
1029 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1030 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1031 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1033 SendGestureEvent(event);
1036 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1037 WebGestureEvent event = MakeGestureEvent(
1038 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1039 SendGestureEvent(event);
1042 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1043 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1044 WebGestureEvent event = MakeGestureEvent(
1045 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1046 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1047 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1049 SendGestureEvent(event);
1052 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1053 jfloat x, jfloat y, jfloat vx, jfloat vy) {
1054 WebGestureEvent event = MakeGestureEvent(
1055 WebInputEvent::GestureFlingStart, time_ms, x, y);
1056 event.data.flingStart.velocityX = vx / dpi_scale();
1057 event.data.flingStart.velocityY = vy / dpi_scale();
1059 SendGestureEvent(event);
1062 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1063 WebGestureEvent event = MakeGestureEvent(
1064 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1065 event.data.flingCancel.preventBoosting = true;
1067 SendGestureEvent(event);
1070 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1071 jfloat x, jfloat y) {
1072 // Tap gestures should always be preceded by a TapDown, ensuring consistency
1073 // with the touch-based gesture detection pipeline.
1074 WebGestureEvent tap_down_event = MakeGestureEvent(
1075 WebInputEvent::GestureTapDown, time_ms, x, y);
1076 tap_down_event.data.tap.tapCount = 1;
1077 SendGestureEvent(tap_down_event);
1079 WebGestureEvent tap_event = MakeGestureEvent(
1080 WebInputEvent::GestureTap, time_ms, x, y);
1081 tap_event.data.tap.tapCount = 1;
1082 SendGestureEvent(tap_event);
1085 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1086 jfloat x, jfloat y) {
1087 WebGestureEvent event = MakeGestureEvent(
1088 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1089 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1090 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1091 event.data.tap.tapCount = 1;
1093 SendGestureEvent(event);
1096 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1097 jfloat x, jfloat y) {
1098 WebGestureEvent event = MakeGestureEvent(
1099 WebInputEvent::GestureLongPress, time_ms, x, y);
1101 SendGestureEvent(event);
1104 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1105 jfloat x, jfloat y) {
1106 WebGestureEvent event = MakeGestureEvent(
1107 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1108 SendGestureEvent(event);
1111 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1112 WebGestureEvent event = MakeGestureEvent(
1113 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1114 SendGestureEvent(event);
1117 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1118 jfloat anchor_x, jfloat anchor_y,
1119 jfloat delta) {
1120 WebGestureEvent event = MakeGestureEvent(
1121 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1122 event.data.pinchUpdate.scale = delta;
1124 SendGestureEvent(event);
1127 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1128 jfloat x1, jfloat y1,
1129 jfloat x2, jfloat y2) {
1130 SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
1131 gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
1134 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1135 jfloat x, jfloat y) {
1136 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1137 if (rwhv)
1138 rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
1141 void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
1142 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1143 if (rwhv)
1144 rwhv->DismissTextHandles();
1147 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
1148 jobject obj,
1149 jboolean hidden) {
1150 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1151 if (rwhv)
1152 rwhv->SetTextHandlesTemporarilyHidden(hidden);
1155 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1156 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1157 if (rwhv)
1158 rwhv->ResetGestureDetection();
1161 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1162 jobject obj,
1163 jboolean enabled) {
1164 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1165 if (rwhv)
1166 rwhv->SetDoubleTapSupportEnabled(enabled);
1169 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1170 jobject obj,
1171 jboolean enabled) {
1172 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1173 if (rwhv)
1174 rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1177 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1178 JNIEnv* env,
1179 jobject obj,
1180 jboolean allow) {
1181 java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
1184 void ContentViewCoreImpl::AddJavascriptInterface(
1185 JNIEnv* env,
1186 jobject /* obj */,
1187 jobject object,
1188 jstring name,
1189 jclass safe_annotation_clazz) {
1190 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1191 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1192 java_bridge_dispatcher_host_->AddNamedObject(
1193 ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
1196 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1197 jobject /* obj */,
1198 jstring name) {
1199 java_bridge_dispatcher_host_->RemoveNamedObject(
1200 ConvertJavaStringToUTF8(env, name));
1203 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1204 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1205 gfx::Size physical_size(
1206 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1207 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1208 root_layer_->SetBounds(physical_size);
1210 if (view) {
1211 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1212 view->GetRenderWidgetHost());
1213 host->SendScreenRects();
1214 view->WasResized();
1218 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1219 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1220 if (!rwhva)
1221 return 0;
1222 return rwhva->GetNativeImeAdapter();
1225 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1226 int text_input_type,
1227 int text_input_flags,
1228 const std::string& text,
1229 int selection_start,
1230 int selection_end,
1231 int composition_start,
1232 int composition_end,
1233 bool show_ime_if_needed,
1234 bool is_non_ime_change) {
1235 JNIEnv* env = AttachCurrentThread();
1236 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1237 if (obj.is_null())
1238 return;
1240 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1241 Java_ContentViewCore_updateImeAdapter(env,
1242 obj.obj(),
1243 native_ime_adapter,
1244 text_input_type,
1245 text_input_flags,
1246 jstring_text.obj(),
1247 selection_start,
1248 selection_end,
1249 composition_start,
1250 composition_end,
1251 show_ime_if_needed,
1252 is_non_ime_change);
1255 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1256 bool enabled) {
1257 SetAccessibilityEnabledInternal(enabled);
1260 void ContentViewCoreImpl::SetTextTrackSettings(JNIEnv* env,
1261 jobject obj,
1262 jstring textTrackBackgroundColor,
1263 jstring textTrackFontFamily,
1264 jstring textTrackFontStyle,
1265 jstring textTrackFontVariant,
1266 jstring textTrackTextColor,
1267 jstring textTrackTextShadow,
1268 jstring textTrackTextSize) {
1269 FrameMsg_TextTrackSettings_Params params;
1270 params.text_track_background_color = ConvertJavaStringToUTF8(
1271 env, textTrackBackgroundColor);
1272 params.text_track_font_family = ConvertJavaStringToUTF8(
1273 env, textTrackFontFamily);
1274 params.text_track_font_style = ConvertJavaStringToUTF8(
1275 env, textTrackFontStyle);
1276 params.text_track_font_variant = ConvertJavaStringToUTF8(
1277 env, textTrackFontVariant);
1278 params.text_track_text_color = ConvertJavaStringToUTF8(
1279 env, textTrackTextColor);
1280 params.text_track_text_shadow = ConvertJavaStringToUTF8(
1281 env, textTrackTextShadow);
1282 params.text_track_text_size = ConvertJavaStringToUTF8(
1283 env, textTrackTextSize);
1285 web_contents_->GetMainFrame()->SetTextTrackSettings(params);
1288 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1289 JNIEnv* env = AttachCurrentThread();
1290 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1291 if (obj.is_null())
1292 return true;
1293 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
1294 obj.obj());
1297 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1298 accessibility_enabled_ = enabled;
1299 BrowserAccessibilityStateImpl* accessibility_state =
1300 BrowserAccessibilityStateImpl::GetInstance();
1301 if (enabled) {
1302 // This enables accessibility globally unless it was explicitly disallowed
1303 // by a command-line flag.
1304 accessibility_state->OnScreenReaderDetected();
1305 // If it was actually enabled globally, enable it for this RenderWidget now.
1306 if (accessibility_state->IsAccessibleBrowser() && web_contents_)
1307 web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
1308 } else {
1309 accessibility_state->ResetAccessibilityMode();
1310 if (web_contents_) {
1311 web_contents_->SetAccessibilityMode(
1312 accessibility_state->accessibility_mode());
1317 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1318 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1319 if (rwhv)
1320 rwhv->UpdateScreenInfo(GetViewAndroid());
1322 static_cast<WebContentsImpl*>(web_contents())->
1323 screen_orientation_dispatcher_host()->OnOrientationChange();
1326 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1327 jobject obj,
1328 jint x,
1329 jint y,
1330 jint width,
1331 jint height) {
1332 gfx::Rect rect(
1333 static_cast<int>(x / dpi_scale()),
1334 static_cast<int>(y / dpi_scale()),
1335 static_cast<int>((width > 0 && width < dpi_scale()) ?
1336 1 : (int)(width / dpi_scale())),
1337 static_cast<int>((height > 0 && height < dpi_scale()) ?
1338 1 : (int)(height / dpi_scale())));
1339 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1340 GetWebContents()->GetRoutingID(), rect));
1343 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1344 return GetRenderProcessIdFromRenderViewHost(
1345 web_contents_->GetRenderViewHost());
1348 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1349 jboolean opaque) {
1350 if (GetRenderWidgetHostViewAndroid()) {
1351 if (opaque)
1352 GetRenderWidgetHostViewAndroid()->SetBackgroundColorToDefault();
1353 else
1354 GetRenderWidgetHostViewAndroid()->SetBackgroundColor(SK_ColorTRANSPARENT);
1358 void ContentViewCoreImpl::SetDrawsContent(JNIEnv* env,
1359 jobject jobj,
1360 jboolean draws) {
1361 GetLayer()->SetHideLayerAndSubtree(!draws);
1364 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1365 int max_length,
1366 const base::Callback<
1367 void(const base::string16& content, int start_offset, int end_offset)>&
1368 callback) {
1369 DCHECK(!callback.is_null());
1370 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1371 if (!focused_frame)
1372 return;
1373 if (GetRenderWidgetHostViewAndroid()) {
1374 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1375 callback);
1376 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1377 focused_frame->GetRoutingID(), max_length));
1381 void ContentViewCoreImpl::OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip) {
1382 JNIEnv* env = AttachCurrentThread();
1383 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1384 if (obj.is_null())
1385 return;
1386 Java_ContentViewCore_onShowUnhandledTapUIIfNeeded(
1387 env, obj.obj(), static_cast<jint>(x_dip * dpi_scale()),
1388 static_cast<jint>(y_dip * dpi_scale()));
1391 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1392 const base::string16& text,
1393 const base::string16& html,
1394 const gfx::Rect& clip_rect) {
1395 JNIEnv* env = AttachCurrentThread();
1396 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1397 if (obj.is_null())
1398 return;
1399 ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
1400 ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
1401 ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
1402 Java_ContentViewCore_onSmartClipDataExtracted(
1403 env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
1406 void ContentViewCoreImpl::WebContentsDestroyed() {
1407 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1408 static_cast<WebContentsImpl*>(web_contents())->GetView());
1409 DCHECK(wcva);
1410 wcva->SetContentViewCore(NULL);
1413 bool ContentViewCoreImpl::PullStart() {
1414 JNIEnv* env = AttachCurrentThread();
1415 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1416 if (!obj.is_null())
1417 return Java_ContentViewCore_onOverscrollRefreshStart(env, obj.obj());
1418 return false;
1421 void ContentViewCoreImpl::PullUpdate(float delta) {
1422 JNIEnv* env = AttachCurrentThread();
1423 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1424 if (!obj.is_null())
1425 Java_ContentViewCore_onOverscrollRefreshUpdate(env, obj.obj(), delta);
1428 void ContentViewCoreImpl::PullRelease(bool allow_refresh) {
1429 JNIEnv* env = AttachCurrentThread();
1430 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1431 if (!obj.is_null()) {
1432 Java_ContentViewCore_onOverscrollRefreshRelease(env, obj.obj(),
1433 allow_refresh);
1437 void ContentViewCoreImpl::PullReset() {
1438 JNIEnv* env = AttachCurrentThread();
1439 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1440 if (!obj.is_null())
1441 Java_ContentViewCore_onOverscrollRefreshReset(env, obj.obj());
1444 // This is called for each ContentView.
1445 jlong Init(JNIEnv* env,
1446 jobject obj,
1447 jobject web_contents,
1448 jobject view_android_delegate,
1449 jlong window_android,
1450 jobject retained_objects_set) {
1451 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1452 env, obj, WebContents::FromJavaWebContents(web_contents),
1453 view_android_delegate,
1454 reinterpret_cast<ui::WindowAndroid*>(window_android),
1455 retained_objects_set);
1456 return reinterpret_cast<intptr_t>(view);
1459 static jobject FromWebContentsAndroid(
1460 JNIEnv* env,
1461 jclass clazz,
1462 jobject jweb_contents) {
1463 WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
1464 if (!web_contents)
1465 return NULL;
1467 ContentViewCore* view = ContentViewCore::FromWebContents(web_contents);
1468 if (!view)
1469 return NULL;
1471 return view->GetJavaObject().Release();
1474 bool RegisterContentViewCore(JNIEnv* env) {
1475 return RegisterNativesImpl(env);
1478 } // namespace content