Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / android / content_view_core_impl.cc
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.
4
5 #include "content/browser/android/content_view_core_impl.h"
6
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_dispatcher_host.h"
27 #include "content/browser/media/media_web_contents_observer.h"
28 #include "content/browser/renderer_host/compositor_impl_android.h"
29 #include "content/browser/renderer_host/input/motion_event_android.h"
30 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
31 #include "content/browser/renderer_host/input/web_input_event_util.h"
32 #include "content/browser/renderer_host/render_view_host_impl.h"
33 #include "content/browser/renderer_host/render_widget_host_impl.h"
34 #include "content/browser/renderer_host/render_widget_host_view_android.h"
35 #include "content/browser/transition_request_manager.h"
36 #include "content/browser/web_contents/web_contents_view_android.h"
37 #include "content/common/frame_messages.h"
38 #include "content/common/input/web_input_event_traits.h"
39 #include "content/common/input_messages.h"
40 #include "content/common/view_messages.h"
41 #include "content/public/browser/browser_context.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/favicon_status.h"
44 #include "content/public/browser/render_frame_host.h"
45 #include "content/public/browser/screen_orientation_dispatcher_host.h"
46 #include "content/public/browser/ssl_host_state_delegate.h"
47 #include "content/public/browser/web_contents.h"
48 #include "content/public/common/content_client.h"
49 #include "content/public/common/content_switches.h"
50 #include "content/public/common/menu_item.h"
51 #include "content/public/common/user_agent.h"
52 #include "jni/ContentViewCore_jni.h"
53 #include "third_party/WebKit/public/web/WebInputEvent.h"
54 #include "ui/base/android/view_android.h"
55 #include "ui/base/android/window_android.h"
56 #include "ui/gfx/android/java_bitmap.h"
57 #include "ui/gfx/screen.h"
58 #include "ui/gfx/size_conversions.h"
59 #include "ui/gfx/size_f.h"
60
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;
69
70 // Describes the type and enabled state of a select popup item.
71 namespace {
72
73 enum {
74 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
75 #include "content/browser/android/popup_item_type_list.h"
76 #undef DEFINE_POPUP_ITEM_TYPE
77 };
78
79 } //namespace
80
81 namespace content {
82
83 namespace {
84
85 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
86
87 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
88   DCHECK(host);
89   RenderProcessHost* render_process = host->GetProcess();
90   DCHECK(render_process);
91   if (render_process->HasConnection())
92     return render_process->GetHandle();
93   else
94     return 0;
95 }
96
97 ScopedJavaLocalRef<jobject> CreateJavaRect(
98     JNIEnv* env,
99     const gfx::Rect& rect) {
100   return ScopedJavaLocalRef<jobject>(
101       Java_ContentViewCore_createRect(env,
102                                       static_cast<int>(rect.x()),
103                                       static_cast<int>(rect.y()),
104                                       static_cast<int>(rect.right()),
105                                       static_cast<int>(rect.bottom())));
106 }
107
108 int ToGestureEventType(WebInputEvent::Type type) {
109   switch (type) {
110     case WebInputEvent::GestureScrollBegin:
111       return SCROLL_START;
112     case WebInputEvent::GestureScrollEnd:
113       return SCROLL_END;
114     case WebInputEvent::GestureScrollUpdate:
115       return SCROLL_BY;
116     case WebInputEvent::GestureFlingStart:
117       return FLING_START;
118     case WebInputEvent::GestureFlingCancel:
119       return FLING_CANCEL;
120     case WebInputEvent::GestureShowPress:
121       return SHOW_PRESS;
122     case WebInputEvent::GestureTap:
123       return SINGLE_TAP_CONFIRMED;
124     case WebInputEvent::GestureTapUnconfirmed:
125       return SINGLE_TAP_UNCONFIRMED;
126     case WebInputEvent::GestureTapDown:
127       return TAP_DOWN;
128     case WebInputEvent::GestureTapCancel:
129       return TAP_CANCEL;
130     case WebInputEvent::GestureDoubleTap:
131       return DOUBLE_TAP;
132     case WebInputEvent::GestureLongPress:
133       return LONG_PRESS;
134     case WebInputEvent::GestureLongTap:
135       return LONG_TAP;
136     case WebInputEvent::GesturePinchBegin:
137       return PINCH_BEGIN;
138     case WebInputEvent::GesturePinchEnd:
139       return PINCH_END;
140     case WebInputEvent::GesturePinchUpdate:
141       return PINCH_BY;
142     case WebInputEvent::GestureTwoFingerTap:
143     case WebInputEvent::GestureScrollUpdateWithoutPropagation:
144     default:
145       NOTREACHED() << "Invalid source gesture type: "
146                    << WebInputEventTraits::GetName(type);
147       return -1;
148   };
149 }
150
151 float GetPrimaryDisplayDeviceScaleFactor() {
152   const gfx::Display& display =
153       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
154   return display.device_scale_factor();
155 }
156
157 }  // namespace
158
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) {
166   }
167
168   virtual ~ContentViewUserData() {
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_;
174   }
175
176   ContentViewCoreImpl* get() const { return content_view_core_; }
177
178  private:
179   // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
180   ContentViewCoreImpl* content_view_core_;
181
182   DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
183 };
184
185 // static
186 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
187     content::WebContents* web_contents) {
188   ContentViewCoreImpl::ContentViewUserData* data =
189       reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
190           web_contents->GetUserData(kContentViewUserDataKey));
191   return data ? data->get() : NULL;
192 }
193
194 // static
195 ContentViewCore* ContentViewCore::FromWebContents(
196     content::WebContents* web_contents) {
197   return ContentViewCoreImpl::FromWebContents(web_contents);
198 }
199
200 // static
201 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
202                                                            jobject obj) {
203   return reinterpret_cast<ContentViewCore*>(
204       Java_ContentViewCore_getNativeContentViewCore(env, obj));
205 }
206
207 ContentViewCoreImpl::ContentViewCoreImpl(
208     JNIEnv* env,
209     jobject obj,
210     WebContents* web_contents,
211     ui::ViewAndroid* view_android,
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()),
218       dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
219       view_android_(view_android),
220       window_android_(window_android),
221       device_orientation_(0),
222       accessibility_enabled_(false) {
223   CHECK(web_contents) <<
224       "A ContentViewCoreImpl should be created with a valid WebContents.";
225   DCHECK(view_android_);
226   DCHECK(window_android_);
227
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);
234
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);
244
245   java_bridge_dispatcher_host_.reset(
246       new GinJavaBridgeDispatcherHost(web_contents,
247                                       java_bridge_retained_object_set));
248
249   InitWebContents();
250 }
251
252 ContentViewCoreImpl::~ContentViewCoreImpl() {
253   JNIEnv* env = base::android::AttachCurrentThread();
254   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
255   java_ref_.reset();
256   if (!j_obj.is_null()) {
257     Java_ContentViewCore_onNativeContentViewCoreDestroyed(
258         env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
259   }
260 }
261
262 base::android::ScopedJavaLocalRef<jobject>
263 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
264   return web_contents_->GetJavaWebContents();
265 }
266
267 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
268                                                          jobject obj) {
269   DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
270   java_ref_.reset();
271   // Java peer has gone, ContentViewCore is not functional and waits to
272   // be destroyed with WebContents.
273   // We need to reset WebContentsViewAndroid's reference, otherwise, there
274   // could have call in when swapping the WebContents,
275   // see http://crbug.com/383939 .
276   DCHECK(web_contents_);
277   static_cast<WebContentsViewAndroid*>(
278       static_cast<WebContentsImpl*>(web_contents_)->GetView())->
279           SetContentViewCore(NULL);
280 }
281
282 void ContentViewCoreImpl::InitWebContents() {
283   DCHECK(web_contents_);
284   static_cast<WebContentsViewAndroid*>(
285       static_cast<WebContentsImpl*>(web_contents_)->GetView())->
286           SetContentViewCore(this);
287   DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
288   web_contents_->SetUserData(kContentViewUserDataKey,
289                              new ContentViewUserData(this));
290 }
291
292 void ContentViewCoreImpl::RenderViewReady() {
293   JNIEnv* env = AttachCurrentThread();
294   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
295   if (!obj.is_null())
296     Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
297
298   if (device_orientation_ != 0)
299     SendOrientationChangeEventInternal();
300 }
301
302 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host,
303                                                 RenderViewHost* new_host) {
304   int old_pid = 0;
305   if (old_host) {
306     old_pid = GetRenderProcessIdFromRenderViewHost(old_host);
307
308     RenderWidgetHostViewAndroid* view =
309         static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView());
310     if (view)
311       view->SetContentViewCore(NULL);
312
313     view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView());
314     if (view)
315       view->SetContentViewCore(this);
316   }
317   int new_pid = GetRenderProcessIdFromRenderViewHost(
318       web_contents_->GetRenderViewHost());
319   if (new_pid != old_pid) {
320     // Notify the Java side that the renderer process changed.
321     JNIEnv* env = AttachCurrentThread();
322     ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
323     if (!obj.is_null()) {
324       Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
325     }
326   }
327
328   SetFocusInternal(HasFocus());
329   SetAccessibilityEnabledInternal(accessibility_enabled_);
330 }
331
332 RenderWidgetHostViewAndroid*
333     ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
334   RenderWidgetHostView* rwhv = NULL;
335   if (web_contents_) {
336     rwhv = web_contents_->GetRenderWidgetHostView();
337     if (web_contents_->ShowingInterstitialPage()) {
338       rwhv = static_cast<InterstitialPageImpl*>(
339           web_contents_->GetInterstitialPage())->
340               GetRenderViewHost()->GetView();
341     }
342   }
343   return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
344 }
345
346 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
347   JNIEnv* env = AttachCurrentThread();
348   return java_ref_.get(env);
349 }
350
351 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
352   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
353   if (!rwhva)
354     return SK_ColorWHITE;
355   return rwhva->GetCachedBackgroundColor();
356 }
357
358 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
359   web_contents_->geolocation_dispatcher_host()->PauseOrResume(should_pause);
360 }
361
362 // All positions and sizes are in CSS pixels.
363 // Note that viewport_width/height is a best effort based.
364 // ContentViewCore has the actual information about the physical viewport size.
365 void ContentViewCoreImpl::UpdateFrameInfo(
366     const gfx::Vector2dF& scroll_offset,
367     float page_scale_factor,
368     const gfx::Vector2dF& page_scale_factor_limits,
369     const gfx::SizeF& content_size,
370     const gfx::SizeF& viewport_size,
371     const gfx::Vector2dF& controls_offset,
372     const gfx::Vector2dF& content_offset) {
373   JNIEnv* env = AttachCurrentThread();
374   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
375   if (obj.is_null())
376     return;
377
378   window_android_->set_content_offset(
379       gfx::ScaleVector2d(content_offset, dpi_scale_));
380
381   Java_ContentViewCore_updateFrameInfo(
382       env, obj.obj(),
383       scroll_offset.x(),
384       scroll_offset.y(),
385       page_scale_factor,
386       page_scale_factor_limits.x(),
387       page_scale_factor_limits.y(),
388       content_size.width(),
389       content_size.height(),
390       viewport_size.width(),
391       viewport_size.height(),
392       controls_offset.y(),
393       content_offset.y());
394 }
395
396 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
397   JNIEnv* env = AttachCurrentThread();
398   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
399   if (obj.is_null())
400     return;
401   ScopedJavaLocalRef<jstring> jtitle =
402       ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
403   Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
404 }
405
406 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
407   root_layer_->SetBackgroundColor(color);
408
409   JNIEnv* env = AttachCurrentThread();
410   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
411   if (obj.is_null())
412     return;
413   Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
414 }
415
416 void ContentViewCoreImpl::ShowSelectPopupMenu(
417     RenderFrameHost* frame,
418     const gfx::Rect& bounds,
419     const std::vector<MenuItem>& items,
420     int selected_item,
421     bool multiple) {
422   JNIEnv* env = AttachCurrentThread();
423   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
424   if (j_obj.is_null())
425     return;
426
427   ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
428
429   // For multi-select list popups we find the list of previous selections by
430   // iterating through the items. But for single selection popups we take the
431   // given |selected_item| as is.
432   ScopedJavaLocalRef<jintArray> selected_array;
433   if (multiple) {
434     scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
435     size_t selected_count = 0;
436     for (size_t i = 0; i < items.size(); ++i) {
437       if (items[i].checked)
438         native_selected_array[selected_count++] = i;
439     }
440
441     selected_array = ScopedJavaLocalRef<jintArray>(
442         env, env->NewIntArray(selected_count));
443     env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
444                            native_selected_array.get());
445   } else {
446     selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
447     jint value = selected_item;
448     env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
449   }
450
451   ScopedJavaLocalRef<jintArray> enabled_array(env,
452                                               env->NewIntArray(items.size()));
453   std::vector<base::string16> labels;
454   labels.reserve(items.size());
455   for (size_t i = 0; i < items.size(); ++i) {
456     labels.push_back(items[i].label);
457     jint enabled =
458         (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
459             (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
460                 POPUP_ITEM_TYPE_DISABLED));
461     env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
462   }
463   ScopedJavaLocalRef<jobjectArray> items_array(
464       base::android::ToJavaArrayOfStrings(env, labels));
465   Java_ContentViewCore_showSelectPopup(env,
466                                        j_obj.obj(),
467                                        reinterpret_cast<intptr_t>(frame),
468                                        bounds_rect.obj(),
469                                        items_array.obj(),
470                                        enabled_array.obj(),
471                                        multiple,
472                                        selected_array.obj());
473 }
474
475 void ContentViewCoreImpl::HideSelectPopupMenu() {
476   JNIEnv* env = AttachCurrentThread();
477   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
478   if (!j_obj.is_null())
479     Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
480 }
481
482 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
483                                             InputEventAckState ack_result) {
484   JNIEnv* env = AttachCurrentThread();
485   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
486   if (j_obj.is_null())
487     return;
488
489   switch (event.type) {
490     case WebInputEvent::GestureFlingStart:
491       if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
492         // The view expects the fling velocity in pixels/s.
493         Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
494             event.data.flingStart.velocityX * dpi_scale(),
495             event.data.flingStart.velocityY * dpi_scale());
496       } else {
497         // If a scroll ends with a fling, a SCROLL_END event is never sent.
498         // However, if that fling went unconsumed, we still need to let the
499         // listeners know that scrolling has ended.
500         Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
501       }
502
503       if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
504         // The view expects the fling velocity in pixels/s.
505         Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
506             event.data.flingStart.velocityX * dpi_scale(),
507             event.data.flingStart.velocityY * dpi_scale());
508       }
509       break;
510     case WebInputEvent::GestureFlingCancel:
511       Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
512       break;
513     case WebInputEvent::GestureScrollBegin:
514       Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
515       break;
516     case WebInputEvent::GestureScrollUpdate:
517       if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
518         Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
519       break;
520     case WebInputEvent::GestureScrollEnd:
521       Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
522       break;
523     case WebInputEvent::GesturePinchBegin:
524       Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
525       break;
526     case WebInputEvent::GesturePinchEnd:
527       Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
528       break;
529     case WebInputEvent::GestureTap:
530       Java_ContentViewCore_onSingleTapEventAck(
531           env,
532           j_obj.obj(),
533           ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
534           event.x * dpi_scale(),
535           event.y * dpi_scale());
536       break;
537     default:
538       break;
539   }
540 }
541
542 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
543   if (event.type != WebInputEvent::GestureTap &&
544       event.type != WebInputEvent::GestureDoubleTap &&
545       event.type != WebInputEvent::GestureLongTap &&
546       event.type != WebInputEvent::GestureLongPress)
547     return false;
548
549   JNIEnv* env = AttachCurrentThread();
550   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
551   if (j_obj.is_null())
552     return false;
553
554   const blink::WebGestureEvent& gesture =
555       static_cast<const blink::WebGestureEvent&>(event);
556   int gesture_type = ToGestureEventType(event.type);
557   return Java_ContentViewCore_filterTapOrPressEvent(env,
558                                                     j_obj.obj(),
559                                                     gesture_type,
560                                                     gesture.x * dpi_scale(),
561                                                     gesture.y * dpi_scale());
562
563   // TODO(jdduke): Also report double-tap UMA, crbug/347568.
564 }
565
566 bool ContentViewCoreImpl::HasFocus() {
567   JNIEnv* env = AttachCurrentThread();
568   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
569   if (obj.is_null())
570     return false;
571   return Java_ContentViewCore_hasFocus(env, obj.obj());
572 }
573
574 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
575   JNIEnv* env = AttachCurrentThread();
576   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
577   if (obj.is_null())
578     return;
579   ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
580   Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
581 }
582
583 void ContentViewCoreImpl::OnSelectionEvent(SelectionEventType event,
584                                            const gfx::PointF& position) {
585   JNIEnv* env = AttachCurrentThread();
586   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
587   if (j_obj.is_null())
588     return;
589   Java_ContentViewCore_onSelectionEvent(
590       env, j_obj.obj(), event, position.x(), position.y());
591 }
592
593 scoped_ptr<TouchHandleDrawable>
594 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
595   JNIEnv* env = AttachCurrentThread();
596   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
597   if (obj.is_null()) {
598     NOTREACHED();
599     return scoped_ptr<TouchHandleDrawable>();
600   }
601   return scoped_ptr<TouchHandleDrawable>(new PopupTouchHandleDrawable(
602       Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()),
603       dpi_scale_));
604 }
605
606 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
607   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
608   if (!view)
609     return;
610
611   view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
612
613   JNIEnv* env = AttachCurrentThread();
614   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
615   if (obj.is_null())
616     return;
617   Java_ContentViewCore_showPastePopupWithFeedback(env, obj.obj(),
618                                                   static_cast<jint>(x_dip),
619                                                   static_cast<jint>(y_dip));
620 }
621
622 void ContentViewCoreImpl::GetScaledContentBitmap(
623     float scale,
624     SkColorType color_type,
625     gfx::Rect src_subrect,
626     const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
627   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
628   if (!view) {
629     result_callback.Run(false, SkBitmap());
630     return;
631   }
632
633   view->GetScaledContentBitmap(scale, color_type, src_subrect,
634       result_callback);
635 }
636
637 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
638   JNIEnv* env = AttachCurrentThread();
639   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
640   if (j_obj.is_null())
641     return;
642   ScopedJavaLocalRef<jstring> jcontent_url =
643       ConvertUTF8ToJavaString(env, content_url.spec());
644   Java_ContentViewCore_startContentIntent(env,
645                                           j_obj.obj(),
646                                           jcontent_url.obj());
647 }
648
649 void ContentViewCoreImpl::ShowDisambiguationPopup(
650     const gfx::Rect& rect_pixels,
651     const SkBitmap& zoomed_bitmap) {
652   JNIEnv* env = AttachCurrentThread();
653
654   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
655   if (obj.is_null())
656     return;
657
658   ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
659
660   ScopedJavaLocalRef<jobject> java_bitmap =
661       gfx::ConvertToJavaBitmap(&zoomed_bitmap);
662   DCHECK(!java_bitmap.is_null());
663
664   Java_ContentViewCore_showDisambiguationPopup(env,
665                                                obj.obj(),
666                                                rect_object.obj(),
667                                                java_bitmap.obj());
668 }
669
670 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
671   JNIEnv* env = AttachCurrentThread();
672
673   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
674   if (obj.is_null())
675     return ScopedJavaLocalRef<jobject>();
676   return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
677 }
678
679 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
680   JNIEnv* env = AttachCurrentThread();
681
682   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
683   if (obj.is_null())
684     return ScopedJavaLocalRef<jobject>();
685
686   return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
687 }
688
689 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
690   JNIEnv* env = AttachCurrentThread();
691
692   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
693   if (obj.is_null())
694     return ScopedJavaLocalRef<jobject>();
695
696   return Java_ContentViewCore_getContext(env, obj.obj());
697 }
698
699 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
700   JNIEnv* env = AttachCurrentThread();
701
702   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
703   if (obj.is_null())
704     return true;
705   ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
706   return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
707                                                       j_url.obj());
708 }
709
710 void ContentViewCoreImpl::DidStopFlinging() {
711   JNIEnv* env = AttachCurrentThread();
712
713   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
714   if (!obj.is_null())
715     Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
716 }
717
718 gfx::Size ContentViewCoreImpl::GetViewSize() const {
719   gfx::Size size = GetViewportSizeDip();
720   size.Enlarge(0, -GetTopControlsLayoutHeightDip());
721   return size;
722 }
723
724 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
725   JNIEnv* env = AttachCurrentThread();
726   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
727   if (j_obj.is_null())
728     return gfx::Size();
729   return gfx::Size(
730       Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
731       Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
732 }
733
734 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
735   JNIEnv* env = AttachCurrentThread();
736   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
737   if (j_obj.is_null())
738     return gfx::Size();
739   return gfx::Size(
740       Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
741       Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
742 }
743
744 int ContentViewCoreImpl::GetTopControlsLayoutHeightPix() const {
745   JNIEnv* env = AttachCurrentThread();
746   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
747   if (j_obj.is_null())
748     return 0;
749   return Java_ContentViewCore_getTopControlsLayoutHeightPix(env, j_obj.obj());
750 }
751
752 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
753   return gfx::ToCeiledSize(
754       gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
755 }
756
757 float ContentViewCoreImpl::GetTopControlsLayoutHeightDip() const {
758   return GetTopControlsLayoutHeightPix() / dpi_scale();
759 }
760
761 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
762   root_layer_->InsertChild(layer, 0);
763   root_layer_->SetIsDrawable(false);
764 }
765
766 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
767   layer->RemoveFromParent();
768
769   if (!root_layer_->children().size())
770     root_layer_->SetIsDrawable(true);
771 }
772
773 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& start,
774                                                    const gfx::PointF& end) {
775   if (!web_contents_)
776     return;
777
778   gfx::Point start_point = gfx::Point(start.x(), start.y());
779   gfx::Point end_point = gfx::Point(end.x(), end.y());
780   if (start_point == end_point)
781     return;
782
783   web_contents_->SelectRange(start_point, end_point);
784 }
785
786 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
787   return view_android_;
788 }
789
790 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
791   return window_android_;
792 }
793
794 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
795   return root_layer_.get();
796 }
797
798 // ----------------------------------------------------------------------------
799 // Methods called from Java via JNI
800 // ----------------------------------------------------------------------------
801
802 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
803                                                jobject obj,
804                                                jlong selectPopupSourceFrame,
805                                                jintArray indices) {
806   RenderFrameHostImpl* rfhi =
807       reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
808   DCHECK(rfhi);
809   if (indices == NULL) {
810     rfhi->DidCancelPopupMenu();
811     return;
812   }
813
814   int selected_count = env->GetArrayLength(indices);
815   std::vector<int> selected_indices;
816   jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
817   for (int i = 0; i < selected_count; ++i)
818     selected_indices.push_back(indices_ptr[i]);
819   env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
820   rfhi->DidSelectPopupMenuItems(selected_indices);
821 }
822
823 WebContents* ContentViewCoreImpl::GetWebContents() const {
824   return web_contents_;
825 }
826
827 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
828   SetFocusInternal(focused);
829 }
830
831 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
832   if (!GetRenderWidgetHostViewAndroid())
833     return;
834
835   if (focused)
836     GetRenderWidgetHostViewAndroid()->Focus();
837   else
838     GetRenderWidgetHostViewAndroid()->Blur();
839 }
840
841 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
842                                                      jobject obj,
843                                                      jint orientation) {
844   if (device_orientation_ != orientation) {
845     device_orientation_ = orientation;
846     SendOrientationChangeEventInternal();
847   }
848 }
849
850 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
851                                            jobject obj,
852                                            jobject motion_event,
853                                            jlong time_ms,
854                                            jint android_action,
855                                            jint pointer_count,
856                                            jint history_size,
857                                            jint action_index,
858                                            jfloat pos_x_0,
859                                            jfloat pos_y_0,
860                                            jfloat pos_x_1,
861                                            jfloat pos_y_1,
862                                            jint pointer_id_0,
863                                            jint pointer_id_1,
864                                            jfloat touch_major_0,
865                                            jfloat touch_major_1,
866                                            jfloat touch_minor_0,
867                                            jfloat touch_minor_1,
868                                            jfloat orientation_0,
869                                            jfloat orientation_1,
870                                            jfloat raw_pos_x,
871                                            jfloat raw_pos_y,
872                                            jint android_tool_type_0,
873                                            jint android_tool_type_1,
874                                            jint android_button_state,
875                                            jint android_meta_state,
876                                            jboolean is_touch_handle_event) {
877   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
878   // Avoid synthesizing a touch event if it cannot be forwarded.
879   if (!rwhv)
880     return false;
881
882   MotionEventAndroid event(1.f / dpi_scale(),
883                            env,
884                            motion_event,
885                            time_ms,
886                            android_action,
887                            pointer_count,
888                            history_size,
889                            action_index,
890                            pos_x_0,
891                            pos_y_0,
892                            pos_x_1,
893                            pos_y_1,
894                            pointer_id_0,
895                            pointer_id_1,
896                            touch_major_0,
897                            touch_major_1,
898                            touch_minor_0,
899                            touch_minor_1,
900                            orientation_0,
901                            orientation_1,
902                            raw_pos_x,
903                            raw_pos_y,
904                            android_tool_type_0,
905                            android_tool_type_1,
906                            android_button_state,
907                            android_meta_state);
908
909   return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
910                                : rwhv->OnTouchEvent(event);
911 }
912
913 float ContentViewCoreImpl::GetDpiScale() const {
914   return dpi_scale_;
915 }
916
917 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
918                                                  jobject obj,
919                                                  jlong time_ms,
920                                                  jfloat x,
921                                                  jfloat y) {
922   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
923   if (!rwhv)
924     return false;
925
926   blink::WebMouseEvent event = WebMouseEventBuilder::Build(
927       WebInputEvent::MouseMove,
928       blink::WebMouseEvent::ButtonNone,
929       time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
930
931   rwhv->SendMouseEvent(event);
932   return true;
933 }
934
935 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
936                                                   jobject obj,
937                                                   jlong time_ms,
938                                                   jfloat x,
939                                                   jfloat y,
940                                                   jfloat vertical_axis) {
941   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
942   if (!rwhv)
943     return false;
944
945   WebMouseWheelEventBuilder::Direction direction;
946   if (vertical_axis > 0) {
947     direction = WebMouseWheelEventBuilder::DIRECTION_UP;
948   } else if (vertical_axis < 0) {
949     direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
950   } else {
951     return false;
952   }
953   blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
954       direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
955
956   rwhv->SendMouseWheelEvent(event);
957   return true;
958 }
959
960 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
961     WebInputEvent::Type type, int64 time_ms, float x, float y) const {
962   return WebGestureEventBuilder::Build(
963       type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
964 }
965
966 void ContentViewCoreImpl::SendGestureEvent(
967     const blink::WebGestureEvent& event) {
968   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
969   if (rwhv)
970     rwhv->SendGestureEvent(event);
971 }
972
973 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
974                                       jobject obj,
975                                       jlong time_ms,
976                                       jfloat x,
977                                       jfloat y,
978                                       jfloat hintx,
979                                       jfloat hinty) {
980   WebGestureEvent event = MakeGestureEvent(
981       WebInputEvent::GestureScrollBegin, time_ms, x, y);
982   event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
983   event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
984
985   SendGestureEvent(event);
986 }
987
988 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
989   WebGestureEvent event = MakeGestureEvent(
990       WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
991   SendGestureEvent(event);
992 }
993
994 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
995                                    jfloat x, jfloat y, jfloat dx, jfloat dy) {
996   WebGestureEvent event = MakeGestureEvent(
997       WebInputEvent::GestureScrollUpdate, time_ms, x, y);
998   event.data.scrollUpdate.deltaX = -dx / dpi_scale();
999   event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1000
1001   SendGestureEvent(event);
1002 }
1003
1004 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1005                                      jfloat x, jfloat y, jfloat vx, jfloat vy) {
1006   WebGestureEvent event = MakeGestureEvent(
1007       WebInputEvent::GestureFlingStart, time_ms, x, y);
1008   event.data.flingStart.velocityX = vx / dpi_scale();
1009   event.data.flingStart.velocityY = vy / dpi_scale();
1010
1011   SendGestureEvent(event);
1012 }
1013
1014 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1015   WebGestureEvent event = MakeGestureEvent(
1016       WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1017   SendGestureEvent(event);
1018 }
1019
1020 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1021                                     jfloat x, jfloat y) {
1022   WebGestureEvent event = MakeGestureEvent(
1023       WebInputEvent::GestureTap, time_ms, x, y);
1024   event.data.tap.tapCount = 1;
1025
1026   SendGestureEvent(event);
1027 }
1028
1029 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1030                                     jfloat x, jfloat y) {
1031   WebGestureEvent event = MakeGestureEvent(
1032       WebInputEvent::GestureDoubleTap, time_ms, x, y);
1033   // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1034   // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1035   event.data.tap.tapCount = 1;
1036
1037   SendGestureEvent(event);
1038 }
1039
1040 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1041                                     jfloat x, jfloat y) {
1042   WebGestureEvent event = MakeGestureEvent(
1043       WebInputEvent::GestureLongPress, time_ms, x, y);
1044
1045   SendGestureEvent(event);
1046 }
1047
1048 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1049                                      jfloat x, jfloat y) {
1050   WebGestureEvent event = MakeGestureEvent(
1051       WebInputEvent::GesturePinchBegin, time_ms, x, y);
1052   SendGestureEvent(event);
1053 }
1054
1055 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1056   WebGestureEvent event = MakeGestureEvent(
1057       WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1058   SendGestureEvent(event);
1059 }
1060
1061 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1062                                   jfloat anchor_x, jfloat anchor_y,
1063                                   jfloat delta) {
1064   WebGestureEvent event = MakeGestureEvent(
1065       WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1066   event.data.pinchUpdate.scale = delta;
1067
1068   SendGestureEvent(event);
1069 }
1070
1071 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1072                                                    jfloat x1, jfloat y1,
1073                                                    jfloat x2, jfloat y2) {
1074   SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
1075                            gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
1076 }
1077
1078 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1079                                     jfloat x, jfloat y) {
1080   if (GetRenderWidgetHostViewAndroid()) {
1081     GetRenderWidgetHostViewAndroid()->MoveCaret(
1082         gfx::Point(x / dpi_scale_, y / dpi_scale_));
1083   }
1084 }
1085
1086 void ContentViewCoreImpl::HideTextHandles(JNIEnv* env, jobject obj) {
1087   if (GetRenderWidgetHostViewAndroid())
1088     GetRenderWidgetHostViewAndroid()->HideTextHandles();
1089 }
1090
1091 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1092   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1093   if (rwhv)
1094     rwhv->ResetGestureDetection();
1095 }
1096
1097 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1098                                                      jobject obj,
1099                                                      jboolean enabled) {
1100   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1101   if (rwhv)
1102     rwhv->SetDoubleTapSupportEnabled(enabled);
1103 }
1104
1105 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1106                                                           jobject obj,
1107                                                           jboolean enabled) {
1108   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1109   if (rwhv)
1110     rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1111 }
1112
1113 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1114     JNIEnv* env,
1115     jobject obj,
1116     jboolean allow) {
1117   java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
1118 }
1119
1120 void ContentViewCoreImpl::AddJavascriptInterface(
1121     JNIEnv* env,
1122     jobject /* obj */,
1123     jobject object,
1124     jstring name,
1125     jclass safe_annotation_clazz) {
1126   ScopedJavaLocalRef<jobject> scoped_object(env, object);
1127   ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1128   java_bridge_dispatcher_host_->AddNamedObject(
1129       ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
1130 }
1131
1132 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1133                                                     jobject /* obj */,
1134                                                     jstring name) {
1135   java_bridge_dispatcher_host_->RemoveNamedObject(
1136       ConvertJavaStringToUTF8(env, name));
1137 }
1138
1139 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1140   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1141   gfx::Size physical_size(
1142       Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1143       Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1144   root_layer_->SetBounds(physical_size);
1145
1146   if (view) {
1147     RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1148         view->GetRenderWidgetHost());
1149     host->SendScreenRects();
1150     view->WasResized();
1151   }
1152 }
1153
1154 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1155   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1156   if (!rwhva)
1157     return 0;
1158   return rwhva->GetNativeImeAdapter();
1159 }
1160
1161 // TODO(sgurun) add support for posting a frame whose name is known (only
1162 //               main frame is supported at this time, see crbug.com/389721)
1163 // TODO(sgurun) add support for passing message ports
1164 void ContentViewCoreImpl::PostMessageToFrame(JNIEnv* env, jobject obj,
1165     jstring frame_name, jstring message, jstring source_origin,
1166     jstring target_origin) {
1167
1168   RenderViewHost* host = web_contents_->GetRenderViewHost();
1169   if (!host)
1170       return;
1171   ViewMsg_PostMessage_Params params;
1172   params.source_origin = ConvertJavaStringToUTF16(env, source_origin);
1173   params.target_origin = ConvertJavaStringToUTF16(env, target_origin);
1174   params.data = ConvertJavaStringToUTF16(env, message);
1175   params.is_data_raw_string = true;
1176   params.source_routing_id = MSG_ROUTING_NONE;
1177   host->Send(new ViewMsg_PostMessageEvent(host->GetRoutingID(), params));
1178 }
1179
1180 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1181                                            int text_input_type,
1182                                            int text_input_flags,
1183                                            const std::string& text,
1184                                            int selection_start,
1185                                            int selection_end,
1186                                            int composition_start,
1187                                            int composition_end,
1188                                            bool show_ime_if_needed,
1189                                            bool is_non_ime_change) {
1190   JNIEnv* env = AttachCurrentThread();
1191   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1192   if (obj.is_null())
1193     return;
1194
1195   ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1196   Java_ContentViewCore_updateImeAdapter(env,
1197                                         obj.obj(),
1198                                         native_ime_adapter,
1199                                         text_input_type,
1200                                         text_input_flags,
1201                                         jstring_text.obj(),
1202                                         selection_start,
1203                                         selection_end,
1204                                         composition_start,
1205                                         composition_end,
1206                                         show_ime_if_needed,
1207                                         is_non_ime_change);
1208 }
1209
1210 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1211                                                   bool enabled) {
1212   SetAccessibilityEnabledInternal(enabled);
1213 }
1214
1215 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1216   JNIEnv* env = AttachCurrentThread();
1217   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1218   if (obj.is_null())
1219     return true;
1220   return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
1221                                                                      obj.obj());
1222 }
1223
1224 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1225   accessibility_enabled_ = enabled;
1226   BrowserAccessibilityStateImpl* accessibility_state =
1227       BrowserAccessibilityStateImpl::GetInstance();
1228   if (enabled) {
1229     // This enables accessibility globally unless it was explicitly disallowed
1230     // by a command-line flag.
1231     accessibility_state->OnScreenReaderDetected();
1232     // If it was actually enabled globally, enable it for this RenderWidget now.
1233     if (accessibility_state->IsAccessibleBrowser() && web_contents_)
1234       web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
1235   } else {
1236     accessibility_state->ResetAccessibilityMode();
1237     if (web_contents_) {
1238       web_contents_->SetAccessibilityMode(
1239           accessibility_state->accessibility_mode());
1240     }
1241   }
1242 }
1243
1244 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1245   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1246   if (rwhv)
1247     rwhv->UpdateScreenInfo(GetViewAndroid());
1248
1249   static_cast<WebContentsImpl*>(web_contents())->
1250       screen_orientation_dispatcher_host()->OnOrientationChange();
1251 }
1252
1253 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1254                                                jobject obj,
1255                                                jint x,
1256                                                jint y,
1257                                                jint width,
1258                                                jint height) {
1259   gfx::Rect rect(
1260       static_cast<int>(x / dpi_scale()),
1261       static_cast<int>(y / dpi_scale()),
1262       static_cast<int>((width > 0 && width < dpi_scale()) ?
1263           1 : (int)(width / dpi_scale())),
1264       static_cast<int>((height > 0 && height < dpi_scale()) ?
1265           1 : (int)(height / dpi_scale())));
1266   GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1267       GetWebContents()->GetRoutingID(), rect));
1268 }
1269
1270 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1271   return GetRenderProcessIdFromRenderViewHost(
1272       web_contents_->GetRenderViewHost());
1273 }
1274
1275 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1276     jboolean opaque) {
1277   if (GetRenderWidgetHostViewAndroid())
1278     GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque);
1279 }
1280
1281 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1282     int max_length,
1283     const base::Callback<
1284         void(const base::string16& content, int start_offset, int end_offset)>&
1285         callback) {
1286   DCHECK(!callback.is_null());
1287   RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1288   if (!focused_frame)
1289     return;
1290   if (GetRenderWidgetHostViewAndroid()) {
1291     GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1292         callback);
1293     focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1294         focused_frame->GetRoutingID(), max_length));
1295   }
1296 }
1297
1298 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1299     const base::string16& text,
1300     const base::string16& html,
1301     const gfx::Rect& clip_rect) {
1302   JNIEnv* env = AttachCurrentThread();
1303   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1304   if (obj.is_null())
1305     return;
1306   ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
1307   ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
1308   ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
1309   Java_ContentViewCore_onSmartClipDataExtracted(
1310       env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
1311 }
1312
1313 void ContentViewCoreImpl::WebContentsDestroyed() {
1314   WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1315       static_cast<WebContentsImpl*>(web_contents())->GetView());
1316   DCHECK(wcva);
1317   wcva->SetContentViewCore(NULL);
1318 }
1319
1320 // This is called for each ContentView.
1321 jlong Init(JNIEnv* env,
1322            jobject obj,
1323            jlong native_web_contents,
1324            jlong view_android,
1325            jlong window_android,
1326            jobject retained_objects_set) {
1327   ContentViewCoreImpl* view = new ContentViewCoreImpl(
1328       env, obj,
1329       reinterpret_cast<WebContents*>(native_web_contents),
1330       reinterpret_cast<ui::ViewAndroid*>(view_android),
1331       reinterpret_cast<ui::WindowAndroid*>(window_android),
1332       retained_objects_set);
1333   return reinterpret_cast<intptr_t>(view);
1334 }
1335
1336 bool RegisterContentViewCore(JNIEnv* env) {
1337   return RegisterNativesImpl(env);
1338 }
1339
1340 }  // namespace content