Home | History | Annotate | Download | only in android
      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_ =
    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   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1081   if (rwhv)
   1082     rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
   1083 }
   1084 
   1085 void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
   1086   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1087   if (rwhv)
   1088     rwhv->DismissTextHandles();
   1089 }
   1090 
   1091 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
   1092                                                           jobject obj,
   1093                                                           jboolean hidden) {
   1094   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1095   if (rwhv)
   1096     rwhv->SetTextHandlesTemporarilyHidden(hidden);
   1097 }
   1098 
   1099 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
   1100   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1101   if (rwhv)
   1102     rwhv->ResetGestureDetection();
   1103 }
   1104 
   1105 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
   1106                                                      jobject obj,
   1107                                                      jboolean enabled) {
   1108   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1109   if (rwhv)
   1110     rwhv->SetDoubleTapSupportEnabled(enabled);
   1111 }
   1112 
   1113 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
   1114                                                           jobject obj,
   1115                                                           jboolean enabled) {
   1116   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1117   if (rwhv)
   1118     rwhv->SetMultiTouchZoomSupportEnabled(enabled);
   1119 }
   1120 
   1121 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
   1122     JNIEnv* env,
   1123     jobject obj,
   1124     jboolean allow) {
   1125   java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
   1126 }
   1127 
   1128 void ContentViewCoreImpl::AddJavascriptInterface(
   1129     JNIEnv* env,
   1130     jobject /* obj */,
   1131     jobject object,
   1132     jstring name,
   1133     jclass safe_annotation_clazz) {
   1134   ScopedJavaLocalRef<jobject> scoped_object(env, object);
   1135   ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
   1136   java_bridge_dispatcher_host_->AddNamedObject(
   1137       ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
   1138 }
   1139 
   1140 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
   1141                                                     jobject /* obj */,
   1142                                                     jstring name) {
   1143   java_bridge_dispatcher_host_->RemoveNamedObject(
   1144       ConvertJavaStringToUTF8(env, name));
   1145 }
   1146 
   1147 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
   1148   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   1149   gfx::Size physical_size(
   1150       Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
   1151       Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
   1152   root_layer_->SetBounds(physical_size);
   1153 
   1154   if (view) {
   1155     RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
   1156         view->GetRenderWidgetHost());
   1157     host->SendScreenRects();
   1158     view->WasResized();
   1159   }
   1160 }
   1161 
   1162 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
   1163   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
   1164   if (!rwhva)
   1165     return 0;
   1166   return rwhva->GetNativeImeAdapter();
   1167 }
   1168 
   1169 // TODO(sgurun) add support for posting a frame whose name is known (only
   1170 //               main frame is supported at this time, see crbug.com/389721)
   1171 // TODO(sgurun) add support for passing message ports
   1172 void ContentViewCoreImpl::PostMessageToFrame(JNIEnv* env, jobject obj,
   1173     jstring frame_name, jstring message, jstring source_origin,
   1174     jstring target_origin) {
   1175 
   1176   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1177   if (!host)
   1178       return;
   1179   ViewMsg_PostMessage_Params params;
   1180   params.source_origin = ConvertJavaStringToUTF16(env, source_origin);
   1181   params.target_origin = ConvertJavaStringToUTF16(env, target_origin);
   1182   params.data = ConvertJavaStringToUTF16(env, message);
   1183   params.is_data_raw_string = true;
   1184   params.source_routing_id = MSG_ROUTING_NONE;
   1185   host->Send(new ViewMsg_PostMessageEvent(host->GetRoutingID(), params));
   1186 }
   1187 
   1188 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
   1189                                            int text_input_type,
   1190                                            int text_input_flags,
   1191                                            const std::string& text,
   1192                                            int selection_start,
   1193                                            int selection_end,
   1194                                            int composition_start,
   1195                                            int composition_end,
   1196                                            bool show_ime_if_needed,
   1197                                            bool is_non_ime_change) {
   1198   JNIEnv* env = AttachCurrentThread();
   1199   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   1200   if (obj.is_null())
   1201     return;
   1202 
   1203   ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
   1204   Java_ContentViewCore_updateImeAdapter(env,
   1205                                         obj.obj(),
   1206                                         native_ime_adapter,
   1207                                         text_input_type,
   1208                                         text_input_flags,
   1209                                         jstring_text.obj(),
   1210                                         selection_start,
   1211                                         selection_end,
   1212                                         composition_start,
   1213                                         composition_end,
   1214                                         show_ime_if_needed,
   1215                                         is_non_ime_change);
   1216 }
   1217 
   1218 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
   1219                                                   bool enabled) {
   1220   SetAccessibilityEnabledInternal(enabled);
   1221 }
   1222 
   1223 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
   1224   JNIEnv* env = AttachCurrentThread();
   1225   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   1226   if (obj.is_null())
   1227     return true;
   1228   return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
   1229                                                                      obj.obj());
   1230 }
   1231 
   1232 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
   1233   accessibility_enabled_ = enabled;
   1234   BrowserAccessibilityStateImpl* accessibility_state =
   1235       BrowserAccessibilityStateImpl::GetInstance();
   1236   if (enabled) {
   1237     // This enables accessibility globally unless it was explicitly disallowed
   1238     // by a command-line flag.
   1239     accessibility_state->OnScreenReaderDetected();
   1240     // If it was actually enabled globally, enable it for this RenderWidget now.
   1241     if (accessibility_state->IsAccessibleBrowser() && web_contents_)
   1242       web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
   1243   } else {
   1244     accessibility_state->ResetAccessibilityMode();
   1245     if (web_contents_) {
   1246       web_contents_->SetAccessibilityMode(
   1247           accessibility_state->accessibility_mode());
   1248     }
   1249   }
   1250 }
   1251 
   1252 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
   1253   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1254   if (rwhv)
   1255     rwhv->UpdateScreenInfo(GetViewAndroid());
   1256 
   1257   static_cast<WebContentsImpl*>(web_contents())->
   1258       screen_orientation_dispatcher_host()->OnOrientationChange();
   1259 }
   1260 
   1261 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
   1262                                                jobject obj,
   1263                                                jint x,
   1264                                                jint y,
   1265                                                jint width,
   1266                                                jint height) {
   1267   gfx::Rect rect(
   1268       static_cast<int>(x / dpi_scale()),
   1269       static_cast<int>(y / dpi_scale()),
   1270       static_cast<int>((width > 0 && width < dpi_scale()) ?
   1271           1 : (int)(width / dpi_scale())),
   1272       static_cast<int>((height > 0 && height < dpi_scale()) ?
   1273           1 : (int)(height / dpi_scale())));
   1274   GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
   1275       GetWebContents()->GetRoutingID(), rect));
   1276 }
   1277 
   1278 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
   1279   return GetRenderProcessIdFromRenderViewHost(
   1280       web_contents_->GetRenderViewHost());
   1281 }
   1282 
   1283 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
   1284     jboolean opaque) {
   1285   if (GetRenderWidgetHostViewAndroid())
   1286     GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque);
   1287 }
   1288 
   1289 void ContentViewCoreImpl::RequestTextSurroundingSelection(
   1290     int max_length,
   1291     const base::Callback<
   1292         void(const base::string16& content, int start_offset, int end_offset)>&
   1293         callback) {
   1294   DCHECK(!callback.is_null());
   1295   RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
   1296   if (!focused_frame)
   1297     return;
   1298   if (GetRenderWidgetHostViewAndroid()) {
   1299     GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
   1300         callback);
   1301     focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
   1302         focused_frame->GetRoutingID(), max_length));
   1303   }
   1304 }
   1305 
   1306 void ContentViewCoreImpl::OnSmartClipDataExtracted(
   1307     const base::string16& text,
   1308     const base::string16& html,
   1309     const gfx::Rect& clip_rect) {
   1310   JNIEnv* env = AttachCurrentThread();
   1311   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   1312   if (obj.is_null())
   1313     return;
   1314   ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
   1315   ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
   1316   ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
   1317   Java_ContentViewCore_onSmartClipDataExtracted(
   1318       env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
   1319 }
   1320 
   1321 void ContentViewCoreImpl::WebContentsDestroyed() {
   1322   WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
   1323       static_cast<WebContentsImpl*>(web_contents())->GetView());
   1324   DCHECK(wcva);
   1325   wcva->SetContentViewCore(NULL);
   1326 }
   1327 
   1328 // This is called for each ContentView.
   1329 jlong Init(JNIEnv* env,
   1330            jobject obj,
   1331            jlong native_web_contents,
   1332            jlong view_android,
   1333            jlong window_android,
   1334            jobject retained_objects_set) {
   1335   ContentViewCoreImpl* view = new ContentViewCoreImpl(
   1336       env, obj,
   1337       reinterpret_cast<WebContents*>(native_web_contents),
   1338       reinterpret_cast<ui::ViewAndroid*>(view_android),
   1339       reinterpret_cast<ui::WindowAndroid*>(window_android),
   1340       retained_objects_set);
   1341   return reinterpret_cast<intptr_t>(view);
   1342 }
   1343 
   1344 bool RegisterContentViewCore(JNIEnv* env) {
   1345   return RegisterNativesImpl(env);
   1346 }
   1347 
   1348 }  // namespace content
   1349