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/json/json_writer.h"
     13 #include "base/logging.h"
     14 #include "base/metrics/histogram.h"
     15 #include "base/strings/utf_string_conversions.h"
     16 #include "base/values.h"
     17 #include "cc/layers/layer.h"
     18 #include "cc/layers/solid_color_layer.h"
     19 #include "cc/output/begin_frame_args.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/frame_host/interstitial_page_impl.h"
     25 #include "content/browser/frame_host/navigation_controller_impl.h"
     26 #include "content/browser/frame_host/navigation_entry_impl.h"
     27 #include "content/browser/geolocation/geolocation_dispatcher_host.h"
     28 #include "content/browser/media/media_web_contents_observer.h"
     29 #include "content/browser/renderer_host/compositor_impl_android.h"
     30 #include "content/browser/renderer_host/input/motion_event_android.h"
     31 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
     32 #include "content/browser/renderer_host/input/web_input_event_util.h"
     33 #include "content/browser/renderer_host/render_view_host_impl.h"
     34 #include "content/browser/renderer_host/render_widget_host_impl.h"
     35 #include "content/browser/renderer_host/render_widget_host_view_android.h"
     36 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
     37 #include "content/browser/ssl/ssl_host_state.h"
     38 #include "content/browser/web_contents/web_contents_view_android.h"
     39 #include "content/common/frame_messages.h"
     40 #include "content/common/input/web_input_event_traits.h"
     41 #include "content/common/input_messages.h"
     42 #include "content/common/view_messages.h"
     43 #include "content/public/browser/browser_accessibility_state.h"
     44 #include "content/public/browser/browser_context.h"
     45 #include "content/public/browser/favicon_status.h"
     46 #include "content/public/browser/render_frame_host.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/page_transition_types.h"
     52 #include "content/public/common/user_agent.h"
     53 #include "jni/ContentViewCore_jni.h"
     54 #include "third_party/WebKit/public/web/WebInputEvent.h"
     55 #include "ui/base/android/view_android.h"
     56 #include "ui/base/android/window_android.h"
     57 #include "ui/gfx/android/java_bitmap.h"
     58 #include "ui/gfx/screen.h"
     59 #include "ui/gfx/size_conversions.h"
     60 #include "ui/gfx/size_f.h"
     61 
     62 using base::android::AttachCurrentThread;
     63 using base::android::ConvertJavaStringToUTF16;
     64 using base::android::ConvertJavaStringToUTF8;
     65 using base::android::ConvertUTF16ToJavaString;
     66 using base::android::ConvertUTF8ToJavaString;
     67 using base::android::ScopedJavaGlobalRef;
     68 using base::android::ScopedJavaLocalRef;
     69 using blink::WebGestureEvent;
     70 using blink::WebInputEvent;
     71 
     72 // Describes the type and enabled state of a select popup item.
     73 namespace {
     74 
     75 enum {
     76 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
     77 #include "content/browser/android/popup_item_type_list.h"
     78 #undef DEFINE_POPUP_ITEM_TYPE
     79 };
     80 
     81 } //namespace
     82 
     83 namespace content {
     84 
     85 namespace {
     86 
     87 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
     88 
     89 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
     90   DCHECK(host);
     91   RenderProcessHost* render_process = host->GetProcess();
     92   DCHECK(render_process);
     93   if (render_process->HasConnection())
     94     return render_process->GetHandle();
     95   else
     96     return 0;
     97 }
     98 
     99 ScopedJavaLocalRef<jobject> CreateJavaRect(
    100     JNIEnv* env,
    101     const gfx::Rect& rect) {
    102   return ScopedJavaLocalRef<jobject>(
    103       Java_ContentViewCore_createRect(env,
    104                                       static_cast<int>(rect.x()),
    105                                       static_cast<int>(rect.y()),
    106                                       static_cast<int>(rect.right()),
    107                                       static_cast<int>(rect.bottom())));
    108 }
    109 
    110 int ToGestureEventType(WebInputEvent::Type type) {
    111   switch (type) {
    112     case WebInputEvent::GestureScrollBegin:
    113       return SCROLL_START;
    114     case WebInputEvent::GestureScrollEnd:
    115       return SCROLL_END;
    116     case WebInputEvent::GestureScrollUpdate:
    117       return SCROLL_BY;
    118     case WebInputEvent::GestureFlingStart:
    119       return FLING_START;
    120     case WebInputEvent::GestureFlingCancel:
    121       return FLING_CANCEL;
    122     case WebInputEvent::GestureShowPress:
    123       return SHOW_PRESS;
    124     case WebInputEvent::GestureTap:
    125       return SINGLE_TAP_CONFIRMED;
    126     case WebInputEvent::GestureTapUnconfirmed:
    127       return SINGLE_TAP_UNCONFIRMED;
    128     case WebInputEvent::GestureTapDown:
    129       return TAP_DOWN;
    130     case WebInputEvent::GestureTapCancel:
    131       return TAP_CANCEL;
    132     case WebInputEvent::GestureDoubleTap:
    133       return DOUBLE_TAP;
    134     case WebInputEvent::GestureLongPress:
    135       return LONG_PRESS;
    136     case WebInputEvent::GestureLongTap:
    137       return LONG_TAP;
    138     case WebInputEvent::GesturePinchBegin:
    139       return PINCH_BEGIN;
    140     case WebInputEvent::GesturePinchEnd:
    141       return PINCH_END;
    142     case WebInputEvent::GesturePinchUpdate:
    143       return PINCH_BY;
    144     case WebInputEvent::GestureTwoFingerTap:
    145     case WebInputEvent::GestureScrollUpdateWithoutPropagation:
    146     default:
    147       NOTREACHED() << "Invalid source gesture type: "
    148                    << WebInputEventTraits::GetName(type);
    149       return -1;
    150   };
    151 }
    152 
    153 float GetPrimaryDisplayDeviceScaleFactor() {
    154   const gfx::Display& display =
    155       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
    156   return display.device_scale_factor();
    157 }
    158 
    159 }  // namespace
    160 
    161 // Enables a callback when the underlying WebContents is destroyed, to enable
    162 // nulling the back-pointer.
    163 class ContentViewCoreImpl::ContentViewUserData
    164     : public base::SupportsUserData::Data {
    165  public:
    166   explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
    167       : content_view_core_(content_view_core) {
    168   }
    169 
    170   virtual ~ContentViewUserData() {
    171     // TODO(joth): When chrome has finished removing the TabContents class (see
    172     // crbug.com/107201) consider inverting relationship, so ContentViewCore
    173     // would own WebContents. That effectively implies making the WebContents
    174     // destructor private on Android.
    175     delete content_view_core_;
    176   }
    177 
    178   ContentViewCoreImpl* get() const { return content_view_core_; }
    179 
    180  private:
    181   // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
    182   ContentViewCoreImpl* content_view_core_;
    183 
    184   DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
    185 };
    186 
    187 // static
    188 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
    189     content::WebContents* web_contents) {
    190   ContentViewCoreImpl::ContentViewUserData* data =
    191       reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
    192           web_contents->GetUserData(kContentViewUserDataKey));
    193   return data ? data->get() : NULL;
    194 }
    195 
    196 // static
    197 ContentViewCore* ContentViewCore::FromWebContents(
    198     content::WebContents* web_contents) {
    199   return ContentViewCoreImpl::FromWebContents(web_contents);
    200 }
    201 
    202 // static
    203 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
    204                                                            jobject obj) {
    205   return reinterpret_cast<ContentViewCore*>(
    206       Java_ContentViewCore_getNativeContentViewCore(env, obj));
    207 }
    208 
    209 ContentViewCoreImpl::ContentViewCoreImpl(
    210     JNIEnv* env,
    211     jobject obj,
    212     WebContents* web_contents,
    213     ui::ViewAndroid* view_android,
    214     ui::WindowAndroid* window_android,
    215     jobject java_bridge_retained_object_set)
    216     : WebContentsObserver(web_contents),
    217       java_ref_(env, obj),
    218       web_contents_(static_cast<WebContentsImpl*>(web_contents)),
    219       root_layer_(cc::SolidColorLayer::Create()),
    220       dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
    221       view_android_(view_android),
    222       window_android_(window_android),
    223       device_orientation_(0),
    224       accessibility_enabled_(false) {
    225   CHECK(web_contents) <<
    226       "A ContentViewCoreImpl should be created with a valid WebContents.";
    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 }
    272 
    273 void ContentViewCoreImpl::InitWebContents() {
    274   DCHECK(web_contents_);
    275   static_cast<WebContentsViewAndroid*>(
    276       static_cast<WebContentsImpl*>(web_contents_)->GetView())->
    277           SetContentViewCore(this);
    278   DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
    279   web_contents_->SetUserData(kContentViewUserDataKey,
    280                              new ContentViewUserData(this));
    281 }
    282 
    283 void ContentViewCoreImpl::RenderViewReady() {
    284   JNIEnv* env = AttachCurrentThread();
    285   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    286   if (!obj.is_null())
    287     Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
    288 
    289   if (device_orientation_ != 0)
    290     SendOrientationChangeEventInternal();
    291 }
    292 
    293 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host,
    294                                                 RenderViewHost* new_host) {
    295   int old_pid = 0;
    296   if (old_host) {
    297     old_pid = GetRenderProcessIdFromRenderViewHost(old_host);
    298 
    299     RenderWidgetHostViewAndroid* view =
    300         static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView());
    301     if (view)
    302       view->SetContentViewCore(NULL);
    303 
    304     view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView());
    305     if (view)
    306       view->SetContentViewCore(this);
    307   }
    308   int new_pid = GetRenderProcessIdFromRenderViewHost(
    309       web_contents_->GetRenderViewHost());
    310   if (new_pid != old_pid) {
    311     // Notify the Java side that the renderer process changed.
    312     JNIEnv* env = AttachCurrentThread();
    313     ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    314     if (!obj.is_null()) {
    315       Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
    316     }
    317   }
    318 
    319   SetFocusInternal(HasFocus());
    320   SetAccessibilityEnabledInternal(accessibility_enabled_);
    321 }
    322 
    323 RenderWidgetHostViewAndroid*
    324     ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
    325   RenderWidgetHostView* rwhv = NULL;
    326   if (web_contents_) {
    327     rwhv = web_contents_->GetRenderWidgetHostView();
    328     if (web_contents_->ShowingInterstitialPage()) {
    329       rwhv = static_cast<InterstitialPageImpl*>(
    330           web_contents_->GetInterstitialPage())->
    331               GetRenderViewHost()->GetView();
    332     }
    333   }
    334   return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
    335 }
    336 
    337 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
    338   JNIEnv* env = AttachCurrentThread();
    339   return java_ref_.get(env);
    340 }
    341 
    342 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
    343   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
    344   if (!rwhva)
    345     return SK_ColorWHITE;
    346   return rwhva->GetCachedBackgroundColor();
    347 }
    348 
    349 void ContentViewCoreImpl::OnHide(JNIEnv* env, jobject obj) {
    350   Hide();
    351 }
    352 
    353 void ContentViewCoreImpl::OnShow(JNIEnv* env, jobject obj) {
    354   Show();
    355 }
    356 
    357 void ContentViewCoreImpl::Show() {
    358   GetWebContents()->WasShown();
    359 }
    360 
    361 void ContentViewCoreImpl::Hide() {
    362   GetWebContents()->WasHidden();
    363   PauseVideo();
    364 }
    365 
    366 void ContentViewCoreImpl::PauseVideo() {
    367   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
    368       web_contents_->GetRenderViewHost());
    369   if (rvhi)
    370     rvhi->media_web_contents_observer()->PauseVideo();
    371 }
    372 
    373 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
    374   web_contents_->geolocation_dispatcher_host()->PauseOrResume(should_pause);
    375 }
    376 
    377 void ContentViewCoreImpl::PauseOrResumeVideoCaptureStream(bool should_pause) {
    378   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
    379       web_contents_->GetRenderViewHost());
    380   if (!rvhi)
    381     return;
    382   if (should_pause)
    383     rvhi->Send(new ViewMsg_PauseVideoCaptureStream(rvhi->GetRoutingID()));
    384   else
    385     rvhi->Send(new ViewMsg_ResumeVideoCaptureStream(rvhi->GetRoutingID()));
    386 }
    387 
    388 // All positions and sizes are in CSS pixels.
    389 // Note that viewport_width/height is a best effort based.
    390 // ContentViewCore has the actual information about the physical viewport size.
    391 void ContentViewCoreImpl::UpdateFrameInfo(
    392     const gfx::Vector2dF& scroll_offset,
    393     float page_scale_factor,
    394     const gfx::Vector2dF& page_scale_factor_limits,
    395     const gfx::SizeF& content_size,
    396     const gfx::SizeF& viewport_size,
    397     const gfx::Vector2dF& controls_offset,
    398     const gfx::Vector2dF& content_offset,
    399     float overdraw_bottom_height) {
    400   JNIEnv* env = AttachCurrentThread();
    401   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    402   if (obj.is_null())
    403     return;
    404 
    405   if (window_android_) {
    406     window_android_->set_content_offset(
    407         gfx::ScaleVector2d(content_offset, dpi_scale_));
    408   }
    409 
    410   Java_ContentViewCore_updateFrameInfo(
    411       env, obj.obj(),
    412       scroll_offset.x(),
    413       scroll_offset.y(),
    414       page_scale_factor,
    415       page_scale_factor_limits.x(),
    416       page_scale_factor_limits.y(),
    417       content_size.width(),
    418       content_size.height(),
    419       viewport_size.width(),
    420       viewport_size.height(),
    421       controls_offset.y(),
    422       content_offset.y(),
    423       overdraw_bottom_height);
    424 }
    425 
    426 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
    427   JNIEnv* env = AttachCurrentThread();
    428   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    429   if (obj.is_null())
    430     return;
    431   ScopedJavaLocalRef<jstring> jtitle =
    432       ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
    433   Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
    434 }
    435 
    436 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
    437   root_layer_->SetBackgroundColor(color);
    438 
    439   JNIEnv* env = AttachCurrentThread();
    440   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    441   if (obj.is_null())
    442     return;
    443   Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
    444 }
    445 
    446 void ContentViewCoreImpl::ShowSelectPopupMenu(const gfx::Rect& bounds,
    447     const std::vector<MenuItem>& items, int selected_item, bool multiple) {
    448   JNIEnv* env = AttachCurrentThread();
    449   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    450   if (j_obj.is_null())
    451     return;
    452 
    453   ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
    454 
    455   // For multi-select list popups we find the list of previous selections by
    456   // iterating through the items. But for single selection popups we take the
    457   // given |selected_item| as is.
    458   ScopedJavaLocalRef<jintArray> selected_array;
    459   if (multiple) {
    460     scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
    461     size_t selected_count = 0;
    462     for (size_t i = 0; i < items.size(); ++i) {
    463       if (items[i].checked)
    464         native_selected_array[selected_count++] = i;
    465     }
    466 
    467     selected_array = ScopedJavaLocalRef<jintArray>(
    468         env, env->NewIntArray(selected_count));
    469     env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
    470                            native_selected_array.get());
    471   } else {
    472     selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
    473     jint value = selected_item;
    474     env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
    475   }
    476 
    477   ScopedJavaLocalRef<jintArray> enabled_array(env,
    478                                               env->NewIntArray(items.size()));
    479   std::vector<base::string16> labels;
    480   labels.reserve(items.size());
    481   for (size_t i = 0; i < items.size(); ++i) {
    482     labels.push_back(items[i].label);
    483     jint enabled =
    484         (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
    485             (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
    486                 POPUP_ITEM_TYPE_DISABLED));
    487     env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
    488   }
    489   ScopedJavaLocalRef<jobjectArray> items_array(
    490       base::android::ToJavaArrayOfStrings(env, labels));
    491   Java_ContentViewCore_showSelectPopup(env, j_obj.obj(),
    492                                        bounds_rect.obj(),
    493                                        items_array.obj(),
    494                                        enabled_array.obj(),
    495                                        multiple,
    496                                        selected_array.obj());
    497 }
    498 
    499 void ContentViewCoreImpl::HideSelectPopupMenu() {
    500   JNIEnv* env = AttachCurrentThread();
    501   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    502   if (!j_obj.is_null())
    503     Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
    504 }
    505 
    506 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
    507                                             InputEventAckState ack_result) {
    508   JNIEnv* env = AttachCurrentThread();
    509   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    510   if (j_obj.is_null())
    511     return;
    512 
    513   switch (event.type) {
    514     case WebInputEvent::GestureFlingStart:
    515       if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
    516         // The view expects the fling velocity in pixels/s.
    517         Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
    518             event.data.flingStart.velocityX * dpi_scale(),
    519             event.data.flingStart.velocityY * dpi_scale());
    520       } else {
    521         // If a scroll ends with a fling, a SCROLL_END event is never sent.
    522         // However, if that fling went unconsumed, we still need to let the
    523         // listeners know that scrolling has ended.
    524         Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
    525       }
    526 
    527       if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
    528         // The view expects the fling velocity in pixels/s.
    529         Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
    530             event.data.flingStart.velocityX * dpi_scale(),
    531             event.data.flingStart.velocityY * dpi_scale());
    532       }
    533       break;
    534     case WebInputEvent::GestureFlingCancel:
    535       Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
    536       break;
    537     case WebInputEvent::GestureScrollBegin:
    538       Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
    539       break;
    540     case WebInputEvent::GestureScrollUpdate:
    541       if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
    542         Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
    543       break;
    544     case WebInputEvent::GestureScrollEnd:
    545       Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
    546       break;
    547     case WebInputEvent::GesturePinchBegin:
    548       Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
    549       break;
    550     case WebInputEvent::GesturePinchEnd:
    551       Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
    552       break;
    553     case WebInputEvent::GestureTap:
    554       Java_ContentViewCore_onSingleTapEventAck(
    555           env,
    556           j_obj.obj(),
    557           ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
    558           event.x * dpi_scale(),
    559           event.y * dpi_scale());
    560       break;
    561     case WebInputEvent::GestureDoubleTap:
    562       Java_ContentViewCore_onDoubleTapEventAck(env, j_obj.obj());
    563       break;
    564     default:
    565       break;
    566   }
    567 }
    568 
    569 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
    570   if (event.type != WebInputEvent::GestureTap &&
    571       event.type != WebInputEvent::GestureDoubleTap &&
    572       event.type != WebInputEvent::GestureLongTap &&
    573       event.type != WebInputEvent::GestureLongPress)
    574     return false;
    575 
    576   JNIEnv* env = AttachCurrentThread();
    577   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    578   if (j_obj.is_null())
    579     return false;
    580 
    581   const blink::WebGestureEvent& gesture =
    582       static_cast<const blink::WebGestureEvent&>(event);
    583   int gesture_type = ToGestureEventType(event.type);
    584   return Java_ContentViewCore_filterTapOrPressEvent(env,
    585                                                     j_obj.obj(),
    586                                                     gesture_type,
    587                                                     gesture.x * dpi_scale(),
    588                                                     gesture.y * dpi_scale());
    589 
    590   // TODO(jdduke): Also report double-tap UMA, crbug/347568.
    591 }
    592 
    593 bool ContentViewCoreImpl::HasFocus() {
    594   JNIEnv* env = AttachCurrentThread();
    595   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    596   if (obj.is_null())
    597     return false;
    598   return Java_ContentViewCore_hasFocus(env, obj.obj());
    599 }
    600 
    601 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
    602   JNIEnv* env = AttachCurrentThread();
    603   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    604   if (obj.is_null())
    605     return;
    606   ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
    607   Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
    608 }
    609 
    610 void ContentViewCoreImpl::OnSelectionBoundsChanged(
    611     const ViewHostMsg_SelectionBounds_Params& params) {
    612   JNIEnv* env = AttachCurrentThread();
    613   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    614   if (obj.is_null())
    615     return;
    616   ScopedJavaLocalRef<jobject> anchor_rect_dip(
    617       CreateJavaRect(env, params.anchor_rect));
    618   ScopedJavaLocalRef<jobject> focus_rect_dip(
    619       CreateJavaRect(env, params.focus_rect));
    620   Java_ContentViewCore_onSelectionBoundsChanged(env, obj.obj(),
    621                                                 anchor_rect_dip.obj(),
    622                                                 params.anchor_dir,
    623                                                 focus_rect_dip.obj(),
    624                                                 params.focus_dir,
    625                                                 params.is_anchor_first);
    626 }
    627 
    628 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
    629   JNIEnv* env = AttachCurrentThread();
    630   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    631   if (obj.is_null())
    632     return;
    633   Java_ContentViewCore_showPastePopup(env, obj.obj(),
    634                                       static_cast<jint>(x_dip),
    635                                       static_cast<jint>(y_dip));
    636 }
    637 
    638 void ContentViewCoreImpl::GetScaledContentBitmap(
    639     float scale,
    640     jobject jbitmap_config,
    641     gfx::Rect src_subrect,
    642     const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
    643   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
    644   if (!view) {
    645     result_callback.Run(false, SkBitmap());
    646     return;
    647   }
    648   SkBitmap::Config skbitmap_format = gfx::ConvertToSkiaConfig(jbitmap_config);
    649   view->GetScaledContentBitmap(scale, skbitmap_format, src_subrect,
    650       result_callback);
    651 }
    652 
    653 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
    654   JNIEnv* env = AttachCurrentThread();
    655   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    656   if (j_obj.is_null())
    657     return;
    658   ScopedJavaLocalRef<jstring> jcontent_url =
    659       ConvertUTF8ToJavaString(env, content_url.spec());
    660   Java_ContentViewCore_startContentIntent(env,
    661                                           j_obj.obj(),
    662                                           jcontent_url.obj());
    663 }
    664 
    665 void ContentViewCoreImpl::ShowDisambiguationPopup(
    666     const gfx::Rect& target_rect,
    667     const SkBitmap& zoomed_bitmap) {
    668   JNIEnv* env = AttachCurrentThread();
    669 
    670   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    671   if (obj.is_null())
    672     return;
    673 
    674   ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, target_rect));
    675 
    676   ScopedJavaLocalRef<jobject> java_bitmap =
    677       gfx::ConvertToJavaBitmap(&zoomed_bitmap);
    678   DCHECK(!java_bitmap.is_null());
    679 
    680   Java_ContentViewCore_showDisambiguationPopup(env,
    681                                                obj.obj(),
    682                                                rect_object.obj(),
    683                                                java_bitmap.obj());
    684 }
    685 
    686 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
    687   JNIEnv* env = AttachCurrentThread();
    688 
    689   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    690   if (obj.is_null())
    691     return ScopedJavaLocalRef<jobject>();
    692   return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
    693 }
    694 
    695 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
    696   JNIEnv* env = AttachCurrentThread();
    697 
    698   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    699   if (obj.is_null())
    700     return ScopedJavaLocalRef<jobject>();
    701 
    702   return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
    703 }
    704 
    705 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
    706   JNIEnv* env = AttachCurrentThread();
    707 
    708   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    709   if (obj.is_null())
    710     return ScopedJavaLocalRef<jobject>();
    711 
    712   return Java_ContentViewCore_getContext(env, obj.obj());
    713 }
    714 
    715 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
    716   JNIEnv* env = AttachCurrentThread();
    717 
    718   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    719   if (obj.is_null())
    720     return true;
    721   ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
    722   return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
    723                                                       j_url.obj());
    724 }
    725 
    726 void ContentViewCoreImpl::DidStopFlinging() {
    727   JNIEnv* env = AttachCurrentThread();
    728 
    729   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    730   if (!obj.is_null())
    731     Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
    732 }
    733 
    734 gfx::Size ContentViewCoreImpl::GetViewSize() const {
    735   gfx::Size size = GetViewportSizeDip();
    736   gfx::Size offset = GetViewportSizeOffsetDip();
    737   size.Enlarge(-offset.width(), -offset.height());
    738   return size;
    739 }
    740 
    741 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
    742   JNIEnv* env = AttachCurrentThread();
    743   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    744   if (j_obj.is_null())
    745     return gfx::Size();
    746   return gfx::Size(
    747       Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
    748       Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
    749 }
    750 
    751 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
    752   JNIEnv* env = AttachCurrentThread();
    753   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    754   if (j_obj.is_null())
    755     return gfx::Size();
    756   return gfx::Size(
    757       Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
    758       Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
    759 }
    760 
    761 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
    762   JNIEnv* env = AttachCurrentThread();
    763   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    764   if (j_obj.is_null())
    765     return gfx::Size();
    766   return gfx::Size(
    767       Java_ContentViewCore_getViewportSizeOffsetWidthPix(env, j_obj.obj()),
    768       Java_ContentViewCore_getViewportSizeOffsetHeightPix(env, j_obj.obj()));
    769 }
    770 
    771 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
    772   return gfx::ToCeiledSize(
    773       gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
    774 }
    775 
    776 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
    777   return gfx::ToCeiledSize(
    778       gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f / dpi_scale()));
    779 }
    780 
    781 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
    782   JNIEnv* env = AttachCurrentThread();
    783   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    784   if (j_obj.is_null())
    785     return 0.f;
    786   return Java_ContentViewCore_getOverdrawBottomHeightPix(env, j_obj.obj())
    787       / dpi_scale();
    788 }
    789 
    790 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
    791   root_layer_->AddChild(layer);
    792   root_layer_->SetIsDrawable(false);
    793 }
    794 
    795 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
    796   layer->RemoveFromParent();
    797 
    798   if (!root_layer_->children().size())
    799     root_layer_->SetIsDrawable(true);
    800 }
    801 
    802 void ContentViewCoreImpl::LoadUrl(
    803     NavigationController::LoadURLParams& params) {
    804   GetWebContents()->GetController().LoadURLWithParams(params);
    805 }
    806 
    807 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
    808   // view_android_ should never be null for Chrome.
    809   DCHECK(view_android_);
    810   return view_android_;
    811 }
    812 
    813 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
    814   // This should never be NULL for Chrome, but will be NULL for WebView.
    815   DCHECK(window_android_);
    816   return window_android_;
    817 }
    818 
    819 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
    820   return root_layer_.get();
    821 }
    822 
    823 // ----------------------------------------------------------------------------
    824 // Methods called from Java via JNI
    825 // ----------------------------------------------------------------------------
    826 
    827 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env, jobject obj,
    828                                                jintArray indices) {
    829   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
    830       web_contents_->GetRenderViewHost());
    831   DCHECK(rvhi);
    832   if (indices == NULL) {
    833     rvhi->DidCancelPopupMenu();
    834     return;
    835   }
    836 
    837   int selected_count = env->GetArrayLength(indices);
    838   std::vector<int> selected_indices;
    839   jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
    840   for (int i = 0; i < selected_count; ++i)
    841     selected_indices.push_back(indices_ptr[i]);
    842   env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
    843   rvhi->DidSelectPopupMenuItems(selected_indices);
    844 }
    845 
    846 void ContentViewCoreImpl::LoadUrl(
    847     JNIEnv* env, jobject obj,
    848     jstring url,
    849     jint load_url_type,
    850     jint transition_type,
    851     jstring j_referrer_url,
    852     jint referrer_policy,
    853     jint ua_override_option,
    854     jstring extra_headers,
    855     jbyteArray post_data,
    856     jstring base_url_for_data_url,
    857     jstring virtual_url_for_data_url,
    858     jboolean can_load_local_resources,
    859     jboolean is_renderer_initiated) {
    860   DCHECK(url);
    861   NavigationController::LoadURLParams params(
    862       GURL(ConvertJavaStringToUTF8(env, url)));
    863 
    864   params.load_type = static_cast<NavigationController::LoadURLType>(
    865       load_url_type);
    866   params.transition_type = PageTransitionFromInt(transition_type);
    867   params.override_user_agent =
    868       static_cast<NavigationController::UserAgentOverrideOption>(
    869           ua_override_option);
    870 
    871   if (extra_headers)
    872     params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
    873 
    874   if (post_data) {
    875     std::vector<uint8> http_body_vector;
    876     base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
    877     params.browser_initiated_post_data =
    878         base::RefCountedBytes::TakeVector(&http_body_vector);
    879   }
    880 
    881   if (base_url_for_data_url) {
    882     params.base_url_for_data_url =
    883         GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
    884   }
    885 
    886   if (virtual_url_for_data_url) {
    887     params.virtual_url_for_data_url =
    888         GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
    889   }
    890 
    891   params.can_load_local_resources = can_load_local_resources;
    892   if (j_referrer_url) {
    893     params.referrer = content::Referrer(
    894         GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
    895         static_cast<blink::WebReferrerPolicy>(referrer_policy));
    896   }
    897 
    898   params.is_renderer_initiated = is_renderer_initiated;
    899 
    900   LoadUrl(params);
    901 }
    902 
    903 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetURL(
    904     JNIEnv* env, jobject) const {
    905   return ConvertUTF8ToJavaString(env, GetWebContents()->GetURL().spec());
    906 }
    907 
    908 jboolean ContentViewCoreImpl::IsIncognito(JNIEnv* env, jobject obj) {
    909   return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
    910 }
    911 
    912 WebContents* ContentViewCoreImpl::GetWebContents() const {
    913   return web_contents_;
    914 }
    915 
    916 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
    917   SetFocusInternal(focused);
    918 }
    919 
    920 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
    921   if (!GetRenderWidgetHostViewAndroid())
    922     return;
    923 
    924   if (focused)
    925     GetRenderWidgetHostViewAndroid()->Focus();
    926   else
    927     GetRenderWidgetHostViewAndroid()->Blur();
    928 }
    929 
    930 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
    931                                                      jobject obj,
    932                                                      jint orientation) {
    933   if (device_orientation_ != orientation) {
    934     device_orientation_ = orientation;
    935     SendOrientationChangeEventInternal();
    936   }
    937 }
    938 
    939 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
    940                                            jobject obj,
    941                                            jobject motion_event,
    942                                            jlong time_ms,
    943                                            jint android_action,
    944                                            jint pointer_count,
    945                                            jint history_size,
    946                                            jint action_index,
    947                                            jfloat pos_x_0,
    948                                            jfloat pos_y_0,
    949                                            jfloat pos_x_1,
    950                                            jfloat pos_y_1,
    951                                            jint pointer_id_0,
    952                                            jint pointer_id_1,
    953                                            jfloat touch_major_0,
    954                                            jfloat touch_major_1,
    955                                            jfloat raw_pos_x,
    956                                            jfloat raw_pos_y,
    957                                            jint android_tool_type_0,
    958                                            jint android_tool_type_1,
    959                                            jint android_button_state) {
    960   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
    961   // Avoid synthesizing a touch event if it cannot be forwarded.
    962   if (!rwhv)
    963     return false;
    964 
    965   MotionEventAndroid event(1.f / dpi_scale(),
    966                            env,
    967                            motion_event,
    968                            time_ms,
    969                            android_action,
    970                            pointer_count,
    971                            history_size,
    972                            action_index,
    973                            pos_x_0,
    974                            pos_y_0,
    975                            pos_x_1,
    976                            pos_y_1,
    977                            pointer_id_0,
    978                            pointer_id_1,
    979                            touch_major_0,
    980                            touch_major_1,
    981                            raw_pos_x,
    982                            raw_pos_y,
    983                            android_tool_type_0,
    984                            android_tool_type_1,
    985                            android_button_state);
    986 
    987   return rwhv->OnTouchEvent(event);
    988 }
    989 
    990 float ContentViewCoreImpl::GetDpiScale() const {
    991   return dpi_scale_;
    992 }
    993 
    994 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
    995                                                  jobject obj,
    996                                                  jlong time_ms,
    997                                                  jfloat x,
    998                                                  jfloat y) {
    999   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1000   if (!rwhv)
   1001     return false;
   1002 
   1003   blink::WebMouseEvent event = WebMouseEventBuilder::Build(
   1004       WebInputEvent::MouseMove,
   1005       blink::WebMouseEvent::ButtonNone,
   1006       time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
   1007 
   1008   rwhv->SendMouseEvent(event);
   1009   return true;
   1010 }
   1011 
   1012 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
   1013                                                   jobject obj,
   1014                                                   jlong time_ms,
   1015                                                   jfloat x,
   1016                                                   jfloat y,
   1017                                                   jfloat vertical_axis) {
   1018   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1019   if (!rwhv)
   1020     return false;
   1021 
   1022   WebMouseWheelEventBuilder::Direction direction;
   1023   if (vertical_axis > 0) {
   1024     direction = WebMouseWheelEventBuilder::DIRECTION_UP;
   1025   } else if (vertical_axis < 0) {
   1026     direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
   1027   } else {
   1028     return false;
   1029   }
   1030   blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
   1031       direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
   1032 
   1033   rwhv->SendMouseWheelEvent(event);
   1034   return true;
   1035 }
   1036 
   1037 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
   1038     WebInputEvent::Type type, int64 time_ms, float x, float y) const {
   1039   return WebGestureEventBuilder::Build(
   1040       type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
   1041 }
   1042 
   1043 void ContentViewCoreImpl::SendGestureEvent(
   1044     const blink::WebGestureEvent& event) {
   1045   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1046   if (rwhv)
   1047     rwhv->SendGestureEvent(event);
   1048 }
   1049 
   1050 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
   1051                                       jobject obj,
   1052                                       jlong time_ms,
   1053                                       jfloat x,
   1054                                       jfloat y,
   1055                                       jfloat hintx,
   1056                                       jfloat hinty) {
   1057   WebGestureEvent event = MakeGestureEvent(
   1058       WebInputEvent::GestureScrollBegin, time_ms, x, y);
   1059   event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
   1060   event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
   1061 
   1062   SendGestureEvent(event);
   1063 }
   1064 
   1065 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
   1066   WebGestureEvent event = MakeGestureEvent(
   1067       WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
   1068   SendGestureEvent(event);
   1069 }
   1070 
   1071 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
   1072                                    jfloat x, jfloat y, jfloat dx, jfloat dy) {
   1073   WebGestureEvent event = MakeGestureEvent(
   1074       WebInputEvent::GestureScrollUpdate, time_ms, x, y);
   1075   event.data.scrollUpdate.deltaX = -dx / dpi_scale();
   1076   event.data.scrollUpdate.deltaY = -dy / dpi_scale();
   1077 
   1078   SendGestureEvent(event);
   1079 }
   1080 
   1081 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
   1082                                      jfloat x, jfloat y, jfloat vx, jfloat vy) {
   1083   WebGestureEvent event = MakeGestureEvent(
   1084       WebInputEvent::GestureFlingStart, time_ms, x, y);
   1085   event.data.flingStart.velocityX = vx / dpi_scale();
   1086   event.data.flingStart.velocityY = vy / dpi_scale();
   1087 
   1088   SendGestureEvent(event);
   1089 }
   1090 
   1091 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
   1092   WebGestureEvent event = MakeGestureEvent(
   1093       WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
   1094   SendGestureEvent(event);
   1095 }
   1096 
   1097 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
   1098                                     jfloat x, jfloat y) {
   1099   WebGestureEvent event = MakeGestureEvent(
   1100       WebInputEvent::GestureTap, time_ms, x, y);
   1101   event.data.tap.tapCount = 1;
   1102 
   1103   SendGestureEvent(event);
   1104 }
   1105 
   1106 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
   1107                                     jfloat x, jfloat y) {
   1108   WebGestureEvent event = MakeGestureEvent(
   1109       WebInputEvent::GestureDoubleTap, time_ms, x, y);
   1110   // Set the tap count to 1 even for DoubleTap, in order to be consistent with
   1111   // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
   1112   event.data.tap.tapCount = 1;
   1113 
   1114   SendGestureEvent(event);
   1115 }
   1116 
   1117 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
   1118                                     jfloat x, jfloat y) {
   1119   WebGestureEvent event = MakeGestureEvent(
   1120       WebInputEvent::GestureLongPress, time_ms, x, y);
   1121 
   1122   SendGestureEvent(event);
   1123 }
   1124 
   1125 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
   1126                                      jfloat x, jfloat y) {
   1127   WebGestureEvent event = MakeGestureEvent(
   1128       WebInputEvent::GesturePinchBegin, time_ms, x, y);
   1129   SendGestureEvent(event);
   1130 }
   1131 
   1132 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
   1133   WebGestureEvent event = MakeGestureEvent(
   1134       WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
   1135   SendGestureEvent(event);
   1136 }
   1137 
   1138 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
   1139                                   jfloat anchor_x, jfloat anchor_y,
   1140                                   jfloat delta) {
   1141   WebGestureEvent event = MakeGestureEvent(
   1142       WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
   1143   event.data.pinchUpdate.scale = delta;
   1144 
   1145   SendGestureEvent(event);
   1146 }
   1147 
   1148 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
   1149                                                    jfloat x1, jfloat y1,
   1150                                                    jfloat x2, jfloat y2) {
   1151   if (!web_contents_)
   1152     return;
   1153 
   1154   web_contents_->SelectRange(
   1155       gfx::Point(x1 / dpi_scale(), y1 / dpi_scale()),
   1156       gfx::Point(x2 / dpi_scale(), y2 / dpi_scale()));
   1157 }
   1158 
   1159 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
   1160                                     jfloat x, jfloat y) {
   1161   if (GetRenderWidgetHostViewAndroid()) {
   1162     GetRenderWidgetHostViewAndroid()->MoveCaret(
   1163         gfx::Point(x / dpi_scale(), y / dpi_scale()));
   1164   }
   1165 }
   1166 
   1167 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
   1168   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1169   if (rwhv)
   1170     rwhv->ResetGestureDetection();
   1171 }
   1172 
   1173 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
   1174                                                      jobject obj,
   1175                                                      jboolean enabled) {
   1176   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1177   if (rwhv)
   1178     rwhv->SetDoubleTapSupportEnabled(enabled);
   1179 }
   1180 
   1181 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
   1182                                                           jobject obj,
   1183                                                           jboolean enabled) {
   1184   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1185   if (rwhv)
   1186     rwhv->SetMultiTouchZoomSupportEnabled(enabled);
   1187 }
   1188 
   1189 void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) {
   1190   web_contents_->GetController().LoadIfNecessary();
   1191 }
   1192 
   1193 void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv* env, jobject obj) {
   1194   web_contents_->GetController().SetNeedsReload();
   1195 }
   1196 
   1197 void ContentViewCoreImpl::Reload(JNIEnv* env,
   1198                                  jobject obj,
   1199                                  jboolean check_for_repost) {
   1200   if (web_contents_->GetController().NeedsReload())
   1201     web_contents_->GetController().LoadIfNecessary();
   1202   else
   1203     web_contents_->GetController().Reload(check_for_repost);
   1204 }
   1205 
   1206 void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv* env,
   1207                                               jobject obj,
   1208                                               jboolean check_for_repost) {
   1209   web_contents_->GetController().ReloadIgnoringCache(check_for_repost);
   1210 }
   1211 
   1212 void ContentViewCoreImpl::CancelPendingReload(JNIEnv* env, jobject obj) {
   1213   web_contents_->GetController().CancelPendingReload();
   1214 }
   1215 
   1216 void ContentViewCoreImpl::ContinuePendingReload(JNIEnv* env, jobject obj) {
   1217   web_contents_->GetController().ContinuePendingReload();
   1218 }
   1219 
   1220 void ContentViewCoreImpl::ClearHistory(JNIEnv* env, jobject obj) {
   1221   // TODO(creis): Do callers of this need to know if it fails?
   1222   if (web_contents_->GetController().CanPruneAllButLastCommitted())
   1223     web_contents_->GetController().PruneAllButLastCommitted();
   1224 }
   1225 
   1226 void ContentViewCoreImpl::AddStyleSheetByURL(
   1227     JNIEnv* env, jobject obj, jstring url) {
   1228   if (!web_contents_)
   1229     return;
   1230 
   1231   web_contents_->GetMainFrame()->Send(new FrameMsg_AddStyleSheetByURL(
   1232       web_contents_->GetMainFrame()->GetRoutingID(),
   1233       ConvertJavaStringToUTF8(env, url)));
   1234 }
   1235 
   1236 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
   1237     JNIEnv* env,
   1238     jobject obj,
   1239     jboolean allow) {
   1240   java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
   1241 }
   1242 
   1243 void ContentViewCoreImpl::AddJavascriptInterface(
   1244     JNIEnv* env,
   1245     jobject /* obj */,
   1246     jobject object,
   1247     jstring name,
   1248     jclass safe_annotation_clazz) {
   1249   ScopedJavaLocalRef<jobject> scoped_object(env, object);
   1250   ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
   1251   java_bridge_dispatcher_host_->AddNamedObject(
   1252       ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
   1253 }
   1254 
   1255 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
   1256                                                     jobject /* obj */,
   1257                                                     jstring name) {
   1258   java_bridge_dispatcher_host_->RemoveNamedObject(
   1259       ConvertJavaStringToUTF8(env, name));
   1260 }
   1261 
   1262 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
   1263   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   1264   gfx::Size physical_size(
   1265       Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
   1266       Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
   1267   root_layer_->SetBounds(physical_size);
   1268 
   1269   if (view) {
   1270     RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
   1271         view->GetRenderWidgetHost());
   1272     host->SendScreenRects();
   1273     view->WasResized();
   1274   }
   1275 }
   1276 
   1277 void ContentViewCoreImpl::ShowInterstitialPage(
   1278     JNIEnv* env, jobject obj, jstring jurl, jlong delegate_ptr) {
   1279   GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
   1280   InterstitialPageDelegateAndroid* delegate =
   1281       reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
   1282   InterstitialPage* interstitial = InterstitialPage::Create(
   1283       web_contents_, false, url, delegate);
   1284   delegate->set_interstitial_page(interstitial);
   1285   interstitial->Show();
   1286 }
   1287 
   1288 jboolean ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv* env,
   1289                                                         jobject obj) {
   1290   return web_contents_->ShowingInterstitialPage();
   1291 }
   1292 
   1293 jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
   1294                                                           jobject obj) {
   1295   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   1296   return view && view->HasValidFrame();
   1297 }
   1298 
   1299 void ContentViewCoreImpl::ExitFullscreen(JNIEnv* env, jobject obj) {
   1300   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1301   if (!host)
   1302     return;
   1303   host->ExitFullscreen();
   1304 }
   1305 
   1306 void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv* env,
   1307                                                  jobject obj,
   1308                                                  bool enable_hiding,
   1309                                                  bool enable_showing,
   1310                                                  bool animate) {
   1311   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1312   if (!host)
   1313     return;
   1314   host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
   1315                                                 enable_hiding,
   1316                                                 enable_showing,
   1317                                                 animate));
   1318 }
   1319 
   1320 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
   1321   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1322   host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
   1323 }
   1324 
   1325 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv* env,
   1326                                                             jobject obj) {
   1327   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1328   host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
   1329       host->GetRoutingID(), gfx::Rect()));
   1330 }
   1331 
   1332 void ContentViewCoreImpl::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
   1333   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1334   if (!host)
   1335     return;
   1336   host->SelectWordAroundCaret();
   1337 }
   1338 
   1339 namespace {
   1340 
   1341 static void AddNavigationEntryToHistory(JNIEnv* env, jobject obj,
   1342                                         jobject history,
   1343                                         NavigationEntry* entry,
   1344                                         int index) {
   1345   // Get the details of the current entry
   1346   ScopedJavaLocalRef<jstring> j_url(
   1347       ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
   1348   ScopedJavaLocalRef<jstring> j_virtual_url(
   1349       ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
   1350   ScopedJavaLocalRef<jstring> j_original_url(
   1351       ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
   1352   ScopedJavaLocalRef<jstring> j_title(
   1353       ConvertUTF16ToJavaString(env, entry->GetTitle()));
   1354   ScopedJavaLocalRef<jobject> j_bitmap;
   1355   const FaviconStatus& status = entry->GetFavicon();
   1356   if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
   1357     j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
   1358 
   1359   // Add the item to the list
   1360   Java_ContentViewCore_addToNavigationHistory(
   1361       env, obj, history, index, j_url.obj(), j_virtual_url.obj(),
   1362       j_original_url.obj(), j_title.obj(), j_bitmap.obj());
   1363 }
   1364 
   1365 }  // namespace
   1366 
   1367 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env,
   1368                                               jobject obj,
   1369                                               jobject history) {
   1370   // Iterate through navigation entries to populate the list
   1371   const NavigationController& controller = web_contents_->GetController();
   1372   int count = controller.GetEntryCount();
   1373   for (int i = 0; i < count; ++i) {
   1374     AddNavigationEntryToHistory(
   1375         env, obj, history, controller.GetEntryAtIndex(i), i);
   1376   }
   1377 
   1378   return controller.GetCurrentEntryIndex();
   1379 }
   1380 
   1381 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv* env,
   1382                                                        jobject obj,
   1383                                                        jobject history,
   1384                                                        jboolean is_forward,
   1385                                                        jint max_entries) {
   1386   // Iterate through navigation entries to populate the list
   1387   const NavigationController& controller = web_contents_->GetController();
   1388   int count = controller.GetEntryCount();
   1389   int num_added = 0;
   1390   int increment_value = is_forward ? 1 : -1;
   1391   for (int i = controller.GetCurrentEntryIndex() + increment_value;
   1392        i >= 0 && i < count;
   1393        i += increment_value) {
   1394     if (num_added >= max_entries)
   1395       break;
   1396 
   1397     AddNavigationEntryToHistory(
   1398         env, obj, history, controller.GetEntryAtIndex(i), i);
   1399     num_added++;
   1400   }
   1401 }
   1402 
   1403 ScopedJavaLocalRef<jstring>
   1404 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv* env,
   1405                                                             jobject obj) {
   1406   NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
   1407   if (entry == NULL)
   1408     return ScopedJavaLocalRef<jstring>(env, NULL);
   1409   return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
   1410 }
   1411 
   1412 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
   1413   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
   1414   if (!rwhva)
   1415     return 0;
   1416   return rwhva->GetNativeImeAdapter();
   1417 }
   1418 
   1419 namespace {
   1420 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
   1421                               const base::Value* result) {
   1422   JNIEnv* env = base::android::AttachCurrentThread();
   1423   std::string json;
   1424   base::JSONWriter::Write(result, &json);
   1425   ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
   1426   Java_ContentViewCore_onEvaluateJavaScriptResult(env,
   1427                                                   j_json.obj(),
   1428                                                   callback.obj());
   1429 }
   1430 }  // namespace
   1431 
   1432 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env,
   1433                                              jobject obj,
   1434                                              jstring script,
   1435                                              jobject callback,
   1436                                              jboolean start_renderer) {
   1437   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
   1438   DCHECK(rvh);
   1439 
   1440   if (start_renderer && !rvh->IsRenderViewLive()) {
   1441     if (!web_contents_->CreateRenderViewForInitialEmptyDocument()) {
   1442       LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
   1443       return;
   1444     }
   1445   }
   1446 
   1447   if (!callback) {
   1448     // No callback requested.
   1449     web_contents_->GetMainFrame()->ExecuteJavaScript(
   1450         ConvertJavaStringToUTF16(env, script));
   1451     return;
   1452   }
   1453 
   1454   // Secure the Java callback in a scoped object and give ownership of it to the
   1455   // base::Callback.
   1456   ScopedJavaGlobalRef<jobject> j_callback;
   1457   j_callback.Reset(env, callback);
   1458   content::RenderFrameHost::JavaScriptResultCallback c_callback =
   1459       base::Bind(&JavaScriptResultCallback, j_callback);
   1460 
   1461   web_contents_->GetMainFrame()->ExecuteJavaScript(
   1462       ConvertJavaStringToUTF16(env, script),
   1463       c_callback);
   1464 }
   1465 
   1466 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
   1467     JNIEnv* env, jobject obj) {
   1468   NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
   1469   return entry && entry->GetIsOverridingUserAgent();
   1470 }
   1471 
   1472 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
   1473                                            int text_input_type,
   1474                                            const std::string& text,
   1475                                            int selection_start,
   1476                                            int selection_end,
   1477                                            int composition_start,
   1478                                            int composition_end,
   1479                                            bool show_ime_if_needed,
   1480                                            bool is_non_ime_change) {
   1481   JNIEnv* env = AttachCurrentThread();
   1482   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   1483   if (obj.is_null())
   1484     return;
   1485 
   1486   ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
   1487   Java_ContentViewCore_updateImeAdapter(env, obj.obj(),
   1488                                         native_ime_adapter, text_input_type,
   1489                                         jstring_text.obj(),
   1490                                         selection_start, selection_end,
   1491                                         composition_start, composition_end,
   1492                                         show_ime_if_needed, is_non_ime_change);
   1493 }
   1494 
   1495 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv* env, jobject obj) {
   1496   SSLHostState* state = SSLHostState::GetFor(
   1497       web_contents_->GetController().GetBrowserContext());
   1498   state->Clear();
   1499 }
   1500 
   1501 void ContentViewCoreImpl::SetUseDesktopUserAgent(
   1502     JNIEnv* env,
   1503     jobject obj,
   1504     jboolean enabled,
   1505     jboolean reload_on_state_change) {
   1506   if (GetUseDesktopUserAgent(env, obj) == enabled)
   1507     return;
   1508 
   1509   // Make sure the navigation entry actually exists.
   1510   NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
   1511   if (!entry)
   1512     return;
   1513 
   1514   // Set the flag in the NavigationEntry.
   1515   entry->SetIsOverridingUserAgent(enabled);
   1516 
   1517   // Send the override to the renderer.
   1518   if (reload_on_state_change) {
   1519     // Reloading the page will send the override down as part of the
   1520     // navigation IPC message.
   1521     NavigationControllerImpl& controller =
   1522         static_cast<NavigationControllerImpl&>(web_contents_->GetController());
   1523     controller.ReloadOriginalRequestURL(false);
   1524   }
   1525 }
   1526 
   1527 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
   1528                                                   bool enabled) {
   1529   SetAccessibilityEnabledInternal(enabled);
   1530 }
   1531 
   1532 void ContentViewCoreImpl::ShowSelectionHandlesAutomatically() const {
   1533   JNIEnv* env = AttachCurrentThread();
   1534   ScopedJavaLocalRef<jobject> obj(java_ref_.get(env));
   1535   if (obj.is_null())
   1536     return;
   1537   Java_ContentViewCore_showSelectionHandlesAutomatically(env, obj.obj());
   1538 }
   1539 
   1540 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
   1541   accessibility_enabled_ = enabled;
   1542   RenderWidgetHostViewAndroid* host_view = GetRenderWidgetHostViewAndroid();
   1543   if (!host_view)
   1544     return;
   1545   RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(
   1546       host_view->GetRenderWidgetHost());
   1547   BrowserAccessibilityState* accessibility_state =
   1548       BrowserAccessibilityState::GetInstance();
   1549   if (enabled) {
   1550     // This enables accessibility globally unless it was explicitly disallowed
   1551     // by a command-line flag.
   1552     accessibility_state->OnScreenReaderDetected();
   1553     // If it was actually enabled globally, enable it for this RenderWidget now.
   1554     if (accessibility_state->IsAccessibleBrowser() && host_impl)
   1555       host_impl->AddAccessibilityMode(AccessibilityModeComplete);
   1556   } else {
   1557     accessibility_state->ResetAccessibilityMode();
   1558     if (host_impl)
   1559       host_impl->ResetAccessibilityMode();
   1560   }
   1561 }
   1562 
   1563 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
   1564   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1565   if (rwhv)
   1566     rwhv->UpdateScreenInfo(GetViewAndroid());
   1567 }
   1568 
   1569 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
   1570                                                jobject obj,
   1571                                                jint x,
   1572                                                jint y,
   1573                                                jint width,
   1574                                                jint height) {
   1575   gfx::Rect rect(
   1576       static_cast<int>(x / dpi_scale()),
   1577       static_cast<int>(y / dpi_scale()),
   1578       static_cast<int>((width > 0 && width < dpi_scale()) ?
   1579           1 : (int)(width / dpi_scale())),
   1580       static_cast<int>((height > 0 && height < dpi_scale()) ?
   1581           1 : (int)(height / dpi_scale())));
   1582   GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
   1583       GetWebContents()->GetRoutingID(), rect));
   1584 }
   1585 
   1586 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
   1587   return GetRenderProcessIdFromRenderViewHost(
   1588       web_contents_->GetRenderViewHost());
   1589 }
   1590 
   1591 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
   1592     jboolean opaque) {
   1593   if (GetRenderWidgetHostViewAndroid())
   1594     GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque);
   1595 }
   1596 
   1597 void ContentViewCoreImpl::RequestTextSurroundingSelection(
   1598     int max_length,
   1599     const base::Callback<
   1600         void(const base::string16& content, int start_offset, int end_offset)>&
   1601         callback) {
   1602   DCHECK(!callback.is_null());
   1603   RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
   1604   if (!focused_frame)
   1605     return;
   1606   if (GetRenderWidgetHostViewAndroid()) {
   1607     GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
   1608         callback);
   1609     focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
   1610         focused_frame->GetRoutingID(), max_length));
   1611   }
   1612 }
   1613 
   1614 void ContentViewCoreImpl::OnSmartClipDataExtracted(
   1615     const base::string16& text,
   1616     const base::string16& html,
   1617     const gfx::Rect& clip_rect) {
   1618   JNIEnv* env = AttachCurrentThread();
   1619   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   1620   if (obj.is_null())
   1621     return;
   1622   ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
   1623   ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
   1624   ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
   1625   Java_ContentViewCore_onSmartClipDataExtracted(
   1626       env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
   1627 }
   1628 
   1629 void ContentViewCoreImpl::WebContentsDestroyed() {
   1630   WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
   1631       static_cast<WebContentsImpl*>(web_contents())->GetView());
   1632   DCHECK(wcva);
   1633   wcva->SetContentViewCore(NULL);
   1634 }
   1635 
   1636 // This is called for each ContentView.
   1637 jlong Init(JNIEnv* env,
   1638            jobject obj,
   1639            jlong native_web_contents,
   1640            jlong view_android,
   1641            jlong window_android,
   1642            jobject retained_objects_set) {
   1643   ContentViewCoreImpl* view = new ContentViewCoreImpl(
   1644       env, obj,
   1645       reinterpret_cast<WebContents*>(native_web_contents),
   1646       reinterpret_cast<ui::ViewAndroid*>(view_android),
   1647       reinterpret_cast<ui::WindowAndroid*>(window_android),
   1648       retained_objects_set);
   1649   return reinterpret_cast<intptr_t>(view);
   1650 }
   1651 
   1652 bool RegisterContentViewCore(JNIEnv* env) {
   1653   return RegisterNativesImpl(env);
   1654 }
   1655 
   1656 }  // namespace content
   1657