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/output/begin_frame_args.h"
     19 #include "content/browser/android/interstitial_page_delegate_android.h"
     20 #include "content/browser/android/load_url_params.h"
     21 #include "content/browser/android/touch_point.h"
     22 #include "content/browser/frame_host/interstitial_page_impl.h"
     23 #include "content/browser/frame_host/navigation_controller_impl.h"
     24 #include "content/browser/frame_host/navigation_entry_impl.h"
     25 #include "content/browser/media/android/browser_media_player_manager.h"
     26 #include "content/browser/renderer_host/compositor_impl_android.h"
     27 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
     28 #include "content/browser/renderer_host/java/java_bound_object.h"
     29 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
     30 #include "content/browser/renderer_host/render_view_host_impl.h"
     31 #include "content/browser/renderer_host/render_widget_host_impl.h"
     32 #include "content/browser/renderer_host/render_widget_host_view_android.h"
     33 #include "content/browser/ssl/ssl_host_state.h"
     34 #include "content/browser/web_contents/web_contents_view_android.h"
     35 #include "content/common/input_messages.h"
     36 #include "content/common/view_messages.h"
     37 #include "content/public/browser/browser_accessibility_state.h"
     38 #include "content/public/browser/browser_context.h"
     39 #include "content/public/browser/favicon_status.h"
     40 #include "content/public/browser/notification_details.h"
     41 #include "content/public/browser/notification_service.h"
     42 #include "content/public/browser/notification_source.h"
     43 #include "content/public/browser/notification_types.h"
     44 #include "content/public/browser/web_contents.h"
     45 #include "content/public/common/content_client.h"
     46 #include "content/public/common/content_switches.h"
     47 #include "content/public/common/menu_item.h"
     48 #include "content/public/common/page_transition_types.h"
     49 #include "jni/ContentViewCore_jni.h"
     50 #include "third_party/WebKit/public/web/WebBindings.h"
     51 #include "third_party/WebKit/public/web/WebInputEvent.h"
     52 #include "ui/base/android/view_android.h"
     53 #include "ui/base/android/window_android.h"
     54 #include "ui/gfx/android/java_bitmap.h"
     55 #include "ui/gfx/screen.h"
     56 #include "ui/gfx/size_conversions.h"
     57 #include "ui/gfx/size_f.h"
     58 #include "webkit/common/user_agent/user_agent_util.h"
     59 
     60 using base::android::AttachCurrentThread;
     61 using base::android::ConvertJavaStringToUTF16;
     62 using base::android::ConvertJavaStringToUTF8;
     63 using base::android::ConvertUTF16ToJavaString;
     64 using base::android::ConvertUTF8ToJavaString;
     65 using base::android::ScopedJavaGlobalRef;
     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 unsigned int kDefaultVSyncIntervalMicros = 16666u;
     86 // TODO(brianderson): Use adaptive draw-time estimation.
     87 const float kDefaultBrowserCompositeVSyncFraction = 1.0f / 3;
     88 
     89 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
     90 
     91 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
     92   DCHECK(host);
     93   RenderProcessHost* render_process = host->GetProcess();
     94   DCHECK(render_process);
     95   if (render_process->HasConnection())
     96     return render_process->GetHandle();
     97   else
     98     return 0;
     99 }
    100 
    101 ScopedJavaLocalRef<jobject> CreateJavaRect(
    102     JNIEnv* env,
    103     const gfx::Rect& rect) {
    104   return ScopedJavaLocalRef<jobject>(
    105       Java_ContentViewCore_createRect(env,
    106                                       static_cast<int>(rect.x()),
    107                                       static_cast<int>(rect.y()),
    108                                       static_cast<int>(rect.right()),
    109                                       static_cast<int>(rect.bottom())));
    110 }
    111 
    112 }  // namespace
    113 
    114 // Enables a callback when the underlying WebContents is destroyed, to enable
    115 // nulling the back-pointer.
    116 class ContentViewCoreImpl::ContentViewUserData
    117     : public base::SupportsUserData::Data {
    118  public:
    119   explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
    120       : content_view_core_(content_view_core) {
    121   }
    122 
    123   virtual ~ContentViewUserData() {
    124     // TODO(joth): When chrome has finished removing the TabContents class (see
    125     // crbug.com/107201) consider inverting relationship, so ContentViewCore
    126     // would own WebContents. That effectively implies making the WebContents
    127     // destructor private on Android.
    128     delete content_view_core_;
    129   }
    130 
    131   ContentViewCoreImpl* get() const { return content_view_core_; }
    132 
    133  private:
    134   // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
    135   ContentViewCoreImpl* content_view_core_;
    136 
    137   DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
    138 };
    139 
    140 // static
    141 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
    142     content::WebContents* web_contents) {
    143   ContentViewCoreImpl::ContentViewUserData* data =
    144       reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
    145           web_contents->GetUserData(kContentViewUserDataKey));
    146   return data ? data->get() : NULL;
    147 }
    148 
    149 // static
    150 ContentViewCore* ContentViewCore::FromWebContents(
    151     content::WebContents* web_contents) {
    152   return ContentViewCoreImpl::FromWebContents(web_contents);
    153 }
    154 
    155 // static
    156 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
    157                                                            jobject obj) {
    158   return reinterpret_cast<ContentViewCore*>(
    159       Java_ContentViewCore_getNativeContentViewCore(env, obj));
    160 }
    161 
    162 ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, jobject obj,
    163                                          bool hardware_accelerated,
    164                                          WebContents* web_contents,
    165                                          ui::ViewAndroid* view_android,
    166                                          ui::WindowAndroid* window_android)
    167     : WebContentsObserver(web_contents),
    168       java_ref_(env, obj),
    169       web_contents_(static_cast<WebContentsImpl*>(web_contents)),
    170       root_layer_(cc::Layer::Create()),
    171       vsync_interval_(base::TimeDelta::FromMicroseconds(
    172           kDefaultVSyncIntervalMicros)),
    173       expected_browser_composite_time_(base::TimeDelta::FromMicroseconds(
    174           kDefaultVSyncIntervalMicros * kDefaultBrowserCompositeVSyncFraction)),
    175       view_android_(view_android),
    176       window_android_(window_android),
    177       device_orientation_(0),
    178       geolocation_needs_pause_(false) {
    179   CHECK(web_contents) <<
    180       "A ContentViewCoreImpl should be created with a valid WebContents.";
    181 
    182   // TODO(leandrogracia): make use of the hardware_accelerated argument.
    183 
    184   const gfx::Display& display =
    185       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
    186   dpi_scale_ = display.device_scale_factor();
    187 
    188   // Currently, the only use case we have for overriding a user agent involves
    189   // spoofing a desktop Linux user agent for "Request desktop site".
    190   // Automatically set it for all WebContents so that it is available when a
    191   // NavigationEntry requires the user agent to be overridden.
    192   const char kLinuxInfoStr[] = "X11; Linux x86_64";
    193   std::string product = content::GetContentClient()->GetProduct();
    194   std::string spoofed_ua =
    195       webkit_glue::BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
    196   web_contents->SetUserAgentOverride(spoofed_ua);
    197 
    198   InitWebContents();
    199 }
    200 
    201 ContentViewCoreImpl::~ContentViewCoreImpl() {
    202   JNIEnv* env = base::android::AttachCurrentThread();
    203   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    204   java_ref_.reset();
    205   if (!j_obj.is_null()) {
    206     Java_ContentViewCore_onNativeContentViewCoreDestroyed(
    207         env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
    208   }
    209   // Make sure nobody calls back into this object while we are tearing things
    210   // down.
    211   notification_registrar_.RemoveAll();
    212 }
    213 
    214 base::android::ScopedJavaLocalRef<jobject>
    215 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
    216   return web_contents_->GetJavaWebContents();
    217 }
    218 
    219 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
    220                                                          jobject obj) {
    221   DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
    222   java_ref_.reset();
    223 }
    224 
    225 void ContentViewCoreImpl::InitWebContents() {
    226   DCHECK(web_contents_);
    227   notification_registrar_.Add(
    228       this, NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
    229       Source<WebContents>(web_contents_));
    230   notification_registrar_.Add(
    231       this, NOTIFICATION_RENDERER_PROCESS_CREATED,
    232       content::NotificationService::AllBrowserContextsAndSources());
    233   notification_registrar_.Add(
    234       this, NOTIFICATION_WEB_CONTENTS_CONNECTED,
    235       Source<WebContents>(web_contents_));
    236 
    237   static_cast<WebContentsViewAndroid*>(web_contents_->GetView())->
    238       SetContentViewCore(this);
    239   DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
    240   web_contents_->SetUserData(kContentViewUserDataKey,
    241                              new ContentViewUserData(this));
    242 }
    243 
    244 void ContentViewCoreImpl::Observe(int type,
    245                                   const NotificationSource& source,
    246                                   const NotificationDetails& details) {
    247   switch (type) {
    248     case NOTIFICATION_RENDER_VIEW_HOST_CHANGED: {
    249       std::pair<RenderViewHost*, RenderViewHost*>* switched_details =
    250           Details<std::pair<RenderViewHost*, RenderViewHost*> >(details).ptr();
    251       int old_pid = 0;
    252       if (switched_details->first) {
    253         old_pid = GetRenderProcessIdFromRenderViewHost(
    254             switched_details->first);
    255 
    256         RenderWidgetHostViewAndroid* view =
    257             static_cast<RenderWidgetHostViewAndroid*>(
    258                 switched_details->first->GetView());
    259         if (view)
    260           view->SetContentViewCore(NULL);
    261       }
    262       int new_pid = GetRenderProcessIdFromRenderViewHost(
    263           web_contents_->GetRenderViewHost());
    264       if (new_pid != old_pid) {
    265         // Notify the Java side of the change of the current renderer process.
    266         JNIEnv* env = AttachCurrentThread();
    267         ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    268         if (!obj.is_null()) {
    269           Java_ContentViewCore_onRenderProcessSwap(
    270               env, obj.obj(), old_pid, new_pid);
    271         }
    272       }
    273       SetFocusInternal(HasFocus());
    274       if (geolocation_needs_pause_)
    275         PauseOrResumeGeolocation(true);
    276       break;
    277     }
    278     case NOTIFICATION_RENDERER_PROCESS_CREATED: {
    279       // Notify the Java side of the current renderer process.
    280       RenderProcessHost* source_process_host =
    281           Source<RenderProcessHost>(source).ptr();
    282       RenderProcessHost* current_process_host =
    283           web_contents_->GetRenderViewHost()->GetProcess();
    284 
    285       if (source_process_host == current_process_host) {
    286         int pid = GetRenderProcessIdFromRenderViewHost(
    287             web_contents_->GetRenderViewHost());
    288         JNIEnv* env = AttachCurrentThread();
    289         ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    290         if (!obj.is_null()) {
    291           Java_ContentViewCore_onRenderProcessSwap(env, obj.obj(), 0, pid);
    292         }
    293       }
    294       break;
    295     }
    296     case NOTIFICATION_WEB_CONTENTS_CONNECTED: {
    297       JNIEnv* env = AttachCurrentThread();
    298       ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    299       if (!obj.is_null()) {
    300         Java_ContentViewCore_onWebContentsConnected(env, obj.obj());
    301       }
    302       break;
    303     }
    304   }
    305 }
    306 
    307 void ContentViewCoreImpl::RenderViewReady() {
    308   if (device_orientation_ != 0)
    309     SendOrientationChangeEventInternal();
    310 }
    311 
    312 RenderWidgetHostViewAndroid*
    313     ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
    314   RenderWidgetHostView* rwhv = NULL;
    315   if (web_contents_) {
    316     rwhv = web_contents_->GetRenderWidgetHostView();
    317     if (web_contents_->ShowingInterstitialPage()) {
    318       rwhv = static_cast<InterstitialPageImpl*>(
    319           web_contents_->GetInterstitialPage())->
    320               GetRenderViewHost()->GetView();
    321     }
    322   }
    323   return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
    324 }
    325 
    326 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
    327   JNIEnv* env = AttachCurrentThread();
    328   return java_ref_.get(env);
    329 }
    330 
    331 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
    332   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
    333   if (!rwhva)
    334     return SK_ColorWHITE;
    335   return rwhva->GetCachedBackgroundColor();
    336 }
    337 
    338 void ContentViewCoreImpl::OnHide(JNIEnv* env, jobject obj) {
    339   Hide();
    340 }
    341 
    342 void ContentViewCoreImpl::OnShow(JNIEnv* env, jobject obj) {
    343   Show();
    344 }
    345 
    346 void ContentViewCoreImpl::Show() {
    347   GetWebContents()->WasShown();
    348 }
    349 
    350 void ContentViewCoreImpl::Hide() {
    351   GetWebContents()->WasHidden();
    352   PauseVideo();
    353 }
    354 
    355 void ContentViewCoreImpl::PauseVideo() {
    356   RenderViewHost* host = web_contents_->GetRenderViewHost();
    357   if (host)
    358     host->Send(new ViewMsg_PauseVideo(host->GetRoutingID()));
    359 }
    360 
    361 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
    362   geolocation_needs_pause_ = should_pause;
    363   RenderViewHostImpl* rvh =
    364       static_cast<RenderViewHostImpl*>(web_contents_->GetRenderViewHost());
    365   if (rvh) {
    366     scoped_refptr<GeolocationDispatcherHost> geolocation_dispatcher =
    367         static_cast<RenderProcessHostImpl*>(
    368             web_contents_->GetRenderProcessHost())->
    369             geolocation_dispatcher_host();
    370     if (geolocation_dispatcher.get()) {
    371       BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    372           base::Bind(&GeolocationDispatcherHost::PauseOrResume,
    373           geolocation_dispatcher,
    374           rvh->GetRoutingID(),
    375           should_pause));
    376       geolocation_needs_pause_ = false;
    377     }
    378   }
    379 }
    380 
    381 void ContentViewCoreImpl::OnTabCrashed() {
    382   JNIEnv* env = AttachCurrentThread();
    383   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    384   if (obj.is_null())
    385     return;
    386   Java_ContentViewCore_resetVSyncNotification(env, obj.obj());
    387 }
    388 
    389 // All positions and sizes are in CSS pixels.
    390 // Note that viewport_width/height is a best effort based.
    391 // ContentViewCore has the actual information about the physical viewport size.
    392 void ContentViewCoreImpl::UpdateFrameInfo(
    393     const gfx::Vector2dF& scroll_offset,
    394     float page_scale_factor,
    395     const gfx::Vector2dF& page_scale_factor_limits,
    396     const gfx::SizeF& content_size,
    397     const gfx::SizeF& viewport_size,
    398     const gfx::Vector2dF& controls_offset,
    399     const gfx::Vector2dF& content_offset,
    400     float overdraw_bottom_height) {
    401   JNIEnv* env = AttachCurrentThread();
    402   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    403   if (obj.is_null())
    404     return;
    405 
    406   if (window_android_) {
    407     gfx::Vector2dF window_offset(
    408         Java_ContentViewCore_getLocationInWindowX(env, obj.obj()),
    409         Java_ContentViewCore_getLocationInWindowY(env, obj.obj()));
    410     window_android_->set_content_offset(
    411         gfx::ScaleVector2d(content_offset, dpi_scale_) + window_offset);
    412   }
    413 
    414   Java_ContentViewCore_updateFrameInfo(
    415       env, obj.obj(),
    416       scroll_offset.x(),
    417       scroll_offset.y(),
    418       page_scale_factor,
    419       page_scale_factor_limits.x(),
    420       page_scale_factor_limits.y(),
    421       content_size.width(),
    422       content_size.height(),
    423       viewport_size.width(),
    424       viewport_size.height(),
    425       controls_offset.y(),
    426       content_offset.y(),
    427       overdraw_bottom_height);
    428 }
    429 
    430 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
    431   JNIEnv* env = AttachCurrentThread();
    432   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    433   if (obj.is_null())
    434     return;
    435   ScopedJavaLocalRef<jstring> jtitle =
    436       ConvertUTF8ToJavaString(env, UTF16ToUTF8(title));
    437   Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
    438 }
    439 
    440 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
    441   JNIEnv* env = AttachCurrentThread();
    442   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    443   if (obj.is_null())
    444     return;
    445   Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
    446 }
    447 
    448 void ContentViewCoreImpl::ShowSelectPopupMenu(
    449     const std::vector<MenuItem>& items, int selected_item, bool multiple) {
    450   JNIEnv* env = AttachCurrentThread();
    451   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    452   if (j_obj.is_null())
    453     return;
    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                                        items_array.obj(), enabled_array.obj(),
    493                                        multiple, selected_array.obj());
    494 }
    495 
    496 void ContentViewCoreImpl::ConfirmTouchEvent(InputEventAckState ack_result) {
    497   JNIEnv* env = AttachCurrentThread();
    498   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    499   if (j_obj.is_null())
    500     return;
    501   Java_ContentViewCore_confirmTouchEvent(env, j_obj.obj(),
    502                                          static_cast<jint>(ack_result));
    503 }
    504 
    505 void ContentViewCoreImpl::UnhandledFlingStartEvent() {
    506   JNIEnv* env = AttachCurrentThread();
    507   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    508   if (j_obj.is_null())
    509     return;
    510   Java_ContentViewCore_unhandledFlingStartEvent(env, j_obj.obj());
    511 }
    512 
    513 void ContentViewCoreImpl::OnScrollUpdateGestureConsumed() {
    514   JNIEnv* env = AttachCurrentThread();
    515   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    516   if (j_obj.is_null())
    517     return;
    518   Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
    519 }
    520 
    521 void ContentViewCoreImpl::HasTouchEventHandlers(bool need_touch_events) {
    522   JNIEnv* env = AttachCurrentThread();
    523   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    524   if (j_obj.is_null())
    525     return;
    526   Java_ContentViewCore_hasTouchEventHandlers(env,
    527                                              j_obj.obj(),
    528                                              need_touch_events);
    529 }
    530 
    531 bool ContentViewCoreImpl::HasFocus() {
    532   JNIEnv* env = AttachCurrentThread();
    533   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    534   if (obj.is_null())
    535     return false;
    536   return Java_ContentViewCore_hasFocus(env, obj.obj());
    537 }
    538 
    539 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
    540   JNIEnv* env = AttachCurrentThread();
    541   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    542   if (obj.is_null())
    543     return;
    544   ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
    545   Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
    546 }
    547 
    548 void ContentViewCoreImpl::OnSelectionBoundsChanged(
    549     const ViewHostMsg_SelectionBounds_Params& params) {
    550   JNIEnv* env = AttachCurrentThread();
    551   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    552   if (obj.is_null())
    553     return;
    554   ScopedJavaLocalRef<jobject> anchor_rect_dip(
    555       CreateJavaRect(env, params.anchor_rect));
    556   ScopedJavaLocalRef<jobject> focus_rect_dip(
    557       CreateJavaRect(env, params.focus_rect));
    558   Java_ContentViewCore_onSelectionBoundsChanged(env, obj.obj(),
    559                                                 anchor_rect_dip.obj(),
    560                                                 params.anchor_dir,
    561                                                 focus_rect_dip.obj(),
    562                                                 params.focus_dir,
    563                                                 params.is_anchor_first);
    564 }
    565 
    566 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
    567   JNIEnv* env = AttachCurrentThread();
    568   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    569   if (obj.is_null())
    570     return;
    571   Java_ContentViewCore_showPastePopup(env, obj.obj(),
    572                                       static_cast<jint>(x_dip),
    573                                       static_cast<jint>(y_dip));
    574 }
    575 
    576 unsigned int ContentViewCoreImpl::GetScaledContentTexture(
    577     float scale,
    578     gfx::Size* out_size) {
    579   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
    580   if (!view)
    581     return 0;
    582 
    583   return view->GetScaledContentTexture(scale, out_size);
    584 }
    585 
    586 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
    587   JNIEnv* env = AttachCurrentThread();
    588   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    589   if (j_obj.is_null())
    590     return;
    591   ScopedJavaLocalRef<jstring> jcontent_url =
    592       ConvertUTF8ToJavaString(env, content_url.spec());
    593   Java_ContentViewCore_startContentIntent(env,
    594                                           j_obj.obj(),
    595                                           jcontent_url.obj());
    596 }
    597 
    598 void ContentViewCoreImpl::ShowDisambiguationPopup(
    599     const gfx::Rect& target_rect,
    600     const SkBitmap& zoomed_bitmap) {
    601   JNIEnv* env = AttachCurrentThread();
    602 
    603   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    604   if (obj.is_null())
    605     return;
    606 
    607   ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, target_rect));
    608 
    609   ScopedJavaLocalRef<jobject> java_bitmap =
    610       gfx::ConvertToJavaBitmap(&zoomed_bitmap);
    611   DCHECK(!java_bitmap.is_null());
    612 
    613   Java_ContentViewCore_showDisambiguationPopup(env,
    614                                                obj.obj(),
    615                                                rect_object.obj(),
    616                                                java_bitmap.obj());
    617 }
    618 
    619 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
    620   JNIEnv* env = AttachCurrentThread();
    621 
    622   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    623   if (obj.is_null())
    624     return ScopedJavaLocalRef<jobject>();
    625   return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
    626 }
    627 
    628 void ContentViewCoreImpl::NotifyExternalSurface(
    629     int player_id, bool is_request, const gfx::RectF& rect) {
    630   JNIEnv* env = AttachCurrentThread();
    631 
    632   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    633   if (obj.is_null())
    634     return;
    635 
    636   Java_ContentViewCore_notifyExternalSurface(
    637       env,
    638       obj.obj(),
    639       static_cast<jint>(player_id),
    640       static_cast<jboolean>(is_request),
    641       static_cast<jfloat>(rect.x()),
    642       static_cast<jfloat>(rect.y()),
    643       static_cast<jfloat>(rect.width()),
    644       static_cast<jfloat>(rect.height()));
    645 }
    646 
    647 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
    648   JNIEnv* env = AttachCurrentThread();
    649 
    650   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    651   if (obj.is_null())
    652     return ScopedJavaLocalRef<jobject>();
    653 
    654   return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
    655 }
    656 
    657 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
    658   JNIEnv* env = AttachCurrentThread();
    659 
    660   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    661   if (obj.is_null())
    662     return ScopedJavaLocalRef<jobject>();
    663 
    664   return Java_ContentViewCore_getContext(env, obj.obj());
    665 }
    666 
    667 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
    668   JNIEnv* env = AttachCurrentThread();
    669 
    670   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    671   if (obj.is_null())
    672     return true;
    673   ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
    674   return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
    675                                                       j_url.obj());
    676 }
    677 
    678 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
    679   JNIEnv* env = AttachCurrentThread();
    680   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    681   if (j_obj.is_null())
    682     return gfx::Size();
    683   return gfx::Size(
    684       Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
    685       Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
    686 }
    687 
    688 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
    689   JNIEnv* env = AttachCurrentThread();
    690   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    691   if (j_obj.is_null())
    692     return gfx::Size();
    693   return gfx::Size(
    694       Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
    695       Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
    696 }
    697 
    698 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
    699   JNIEnv* env = AttachCurrentThread();
    700   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    701   if (j_obj.is_null())
    702     return gfx::Size();
    703   return gfx::Size(
    704       Java_ContentViewCore_getViewportSizeOffsetWidthPix(env, j_obj.obj()),
    705       Java_ContentViewCore_getViewportSizeOffsetHeightPix(env, j_obj.obj()));
    706 }
    707 
    708 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
    709   return gfx::ToCeiledSize(
    710       gfx::ScaleSize(GetViewportSizePix(), 1.0f / GetDpiScale()));
    711 }
    712 
    713 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
    714   return gfx::ToCeiledSize(
    715       gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f / GetDpiScale()));
    716 }
    717 
    718 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
    719   JNIEnv* env = AttachCurrentThread();
    720   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
    721   if (j_obj.is_null())
    722     return 0.f;
    723   return Java_ContentViewCore_getOverdrawBottomHeightPix(env, j_obj.obj())
    724       / GetDpiScale();
    725 }
    726 
    727 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
    728   root_layer_->AddChild(layer);
    729 }
    730 
    731 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
    732   layer->RemoveFromParent();
    733 }
    734 
    735 void ContentViewCoreImpl::LoadUrl(
    736     NavigationController::LoadURLParams& params) {
    737   GetWebContents()->GetController().LoadURLWithParams(params);
    738 }
    739 
    740 void ContentViewCoreImpl::AddBeginFrameSubscriber() {
    741   JNIEnv* env = AttachCurrentThread();
    742   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    743   if (obj.is_null())
    744     return;
    745   Java_ContentViewCore_addVSyncSubscriber(env, obj.obj());
    746 }
    747 
    748 void ContentViewCoreImpl::RemoveBeginFrameSubscriber() {
    749   JNIEnv* env = AttachCurrentThread();
    750   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    751   if (obj.is_null())
    752     return;
    753   Java_ContentViewCore_removeVSyncSubscriber(env, obj.obj());
    754 }
    755 
    756 void ContentViewCoreImpl::SetNeedsAnimate() {
    757   JNIEnv* env = AttachCurrentThread();
    758   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
    759   if (obj.is_null())
    760     return;
    761   Java_ContentViewCore_setNeedsAnimate(env, obj.obj());
    762 }
    763 
    764 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
    765   // view_android_ should never be null for Chrome.
    766   DCHECK(view_android_);
    767   return view_android_;
    768 }
    769 
    770 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
    771   // This should never be NULL for Chrome, but will be NULL for WebView.
    772   DCHECK(window_android_);
    773   return window_android_;
    774 }
    775 
    776 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
    777   return root_layer_.get();
    778 }
    779 
    780 // ----------------------------------------------------------------------------
    781 // Methods called from Java via JNI
    782 // ----------------------------------------------------------------------------
    783 
    784 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env, jobject obj,
    785                                                jintArray indices) {
    786   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
    787       web_contents_->GetRenderViewHost());
    788   DCHECK(rvhi);
    789   if (indices == NULL) {
    790     rvhi->DidCancelPopupMenu();
    791     return;
    792   }
    793 
    794   int selected_count = env->GetArrayLength(indices);
    795   std::vector<int> selected_indices;
    796   jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
    797   for (int i = 0; i < selected_count; ++i)
    798     selected_indices.push_back(indices_ptr[i]);
    799   env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
    800   rvhi->DidSelectPopupMenuItems(selected_indices);
    801 }
    802 
    803 void ContentViewCoreImpl::LoadUrl(
    804     JNIEnv* env, jobject obj,
    805     jstring url,
    806     jint load_url_type,
    807     jint transition_type,
    808     jint ua_override_option,
    809     jstring extra_headers,
    810     jbyteArray post_data,
    811     jstring base_url_for_data_url,
    812     jstring virtual_url_for_data_url,
    813     jboolean can_load_local_resources) {
    814   DCHECK(url);
    815   NavigationController::LoadURLParams params(
    816       GURL(ConvertJavaStringToUTF8(env, url)));
    817 
    818   params.load_type = static_cast<NavigationController::LoadURLType>(
    819       load_url_type);
    820   params.transition_type = PageTransitionFromInt(transition_type);
    821   params.override_user_agent =
    822       static_cast<NavigationController::UserAgentOverrideOption>(
    823           ua_override_option);
    824 
    825   if (extra_headers)
    826     params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
    827 
    828   if (post_data) {
    829     std::vector<uint8> http_body_vector;
    830     base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
    831     params.browser_initiated_post_data =
    832         base::RefCountedBytes::TakeVector(&http_body_vector);
    833   }
    834 
    835   if (base_url_for_data_url) {
    836     params.base_url_for_data_url =
    837         GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
    838   }
    839 
    840   if (virtual_url_for_data_url) {
    841     params.virtual_url_for_data_url =
    842         GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
    843   }
    844 
    845   params.can_load_local_resources = can_load_local_resources;
    846 
    847   LoadUrl(params);
    848 }
    849 
    850 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
    851   return GetRenderProcessIdFromRenderViewHost(
    852       web_contents_->GetRenderViewHost());
    853 }
    854 
    855 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetURL(
    856     JNIEnv* env, jobject) const {
    857   return ConvertUTF8ToJavaString(env, GetWebContents()->GetURL().spec());
    858 }
    859 
    860 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetTitle(
    861     JNIEnv* env, jobject obj) const {
    862   return ConvertUTF16ToJavaString(env, GetWebContents()->GetTitle());
    863 }
    864 
    865 jboolean ContentViewCoreImpl::IsIncognito(JNIEnv* env, jobject obj) {
    866   return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
    867 }
    868 
    869 WebContents* ContentViewCoreImpl::GetWebContents() const {
    870   return web_contents_;
    871 }
    872 
    873 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
    874   SetFocusInternal(focused);
    875 }
    876 
    877 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
    878   if (!GetRenderWidgetHostViewAndroid())
    879     return;
    880 
    881   if (focused)
    882     GetRenderWidgetHostViewAndroid()->Focus();
    883   else
    884     GetRenderWidgetHostViewAndroid()->Blur();
    885 }
    886 
    887 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
    888                                                      jobject obj,
    889                                                      jint orientation) {
    890   if (device_orientation_ != orientation) {
    891     device_orientation_ = orientation;
    892     SendOrientationChangeEventInternal();
    893   }
    894 }
    895 
    896 jboolean ContentViewCoreImpl::SendTouchEvent(JNIEnv* env,
    897                                              jobject obj,
    898                                              jlong time_ms,
    899                                              jint type,
    900                                              jobjectArray pts) {
    901   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
    902   if (rwhv) {
    903     using blink::WebTouchEvent;
    904     blink::WebTouchEvent event;
    905     TouchPoint::BuildWebTouchEvent(env, type, time_ms, GetDpiScale(), pts,
    906         event);
    907     rwhv->SendTouchEvent(event);
    908     return true;
    909   }
    910   return false;
    911 }
    912 
    913 float ContentViewCoreImpl::GetTouchPaddingDip() {
    914   return 48.0f / GetDpiScale();
    915 }
    916 
    917 float ContentViewCoreImpl::GetDpiScale() const {
    918   return dpi_scale_;
    919 }
    920 
    921 void ContentViewCoreImpl::RequestContentClipping(
    922     const gfx::Rect& clipping,
    923     const gfx::Size& content_size) {
    924   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
    925   if (rwhv)
    926     rwhv->RequestContentClipping(clipping, content_size);
    927 }
    928 
    929 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
    930                                                  jobject obj,
    931                                                  jlong time_ms,
    932                                                  jfloat x,
    933                                                  jfloat y) {
    934   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
    935   if (!rwhv)
    936     return false;
    937 
    938   blink::WebMouseEvent event = WebMouseEventBuilder::Build(
    939       WebInputEvent::MouseMove,
    940       blink::WebMouseEvent::ButtonNone,
    941       time_ms / 1000.0, x / GetDpiScale(), y / GetDpiScale(), 0, 1);
    942 
    943   rwhv->SendMouseEvent(event);
    944   return true;
    945 }
    946 
    947 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
    948                                                   jobject obj,
    949                                                   jlong time_ms,
    950                                                   jfloat x,
    951                                                   jfloat y,
    952                                                   jfloat vertical_axis) {
    953   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
    954   if (!rwhv)
    955     return false;
    956 
    957   WebMouseWheelEventBuilder::Direction direction;
    958   if (vertical_axis > 0) {
    959     direction = WebMouseWheelEventBuilder::DIRECTION_UP;
    960   } else if (vertical_axis < 0) {
    961     direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
    962   } else {
    963     return false;
    964   }
    965   blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
    966       direction, time_ms / 1000.0, x / GetDpiScale(), y / GetDpiScale());
    967 
    968   rwhv->SendMouseWheelEvent(event);
    969   return true;
    970 }
    971 
    972 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
    973     WebInputEvent::Type type, int64 time_ms, float x, float y) const {
    974   return WebGestureEventBuilder::Build(
    975       type, time_ms / 1000.0, x / GetDpiScale(), y / GetDpiScale());
    976 }
    977 
    978 void ContentViewCoreImpl::SendGestureEvent(
    979     const blink::WebGestureEvent& event) {
    980   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
    981   if (rwhv)
    982     rwhv->SendGestureEvent(event);
    983 }
    984 
    985 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env, jobject obj, jlong time_ms,
    986                                       jfloat x, jfloat y) {
    987   WebGestureEvent event = MakeGestureEvent(
    988       WebInputEvent::GestureScrollBegin, time_ms, x, y);
    989   SendGestureEvent(event);
    990 }
    991 
    992 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
    993   WebGestureEvent event = MakeGestureEvent(
    994       WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
    995   SendGestureEvent(event);
    996 }
    997 
    998 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
    999                                    jfloat x, jfloat y, jfloat dx, jfloat dy) {
   1000   WebGestureEvent event = MakeGestureEvent(
   1001       WebInputEvent::GestureScrollUpdate, time_ms, x, y);
   1002   event.data.scrollUpdate.deltaX = -dx / GetDpiScale();
   1003   event.data.scrollUpdate.deltaY = -dy / GetDpiScale();
   1004 
   1005   SendGestureEvent(event);
   1006 }
   1007 
   1008 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
   1009                                      jfloat x, jfloat y, jfloat vx, jfloat vy) {
   1010   WebGestureEvent event = MakeGestureEvent(
   1011       WebInputEvent::GestureFlingStart, time_ms, x, y);
   1012 
   1013   // Velocity should not be scaled by DIP since that interacts poorly with the
   1014   // deceleration constants.  The DIP scaling is done on the renderer.
   1015   event.data.flingStart.velocityX = vx;
   1016   event.data.flingStart.velocityY = vy;
   1017 
   1018   SendGestureEvent(event);
   1019 }
   1020 
   1021 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
   1022   WebGestureEvent event = MakeGestureEvent(
   1023       WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
   1024   SendGestureEvent(event);
   1025 }
   1026 
   1027 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
   1028                                     jfloat x, jfloat y,
   1029                                     jboolean disambiguation_popup_tap) {
   1030   WebGestureEvent event = MakeGestureEvent(
   1031       WebInputEvent::GestureTap, time_ms, x, y);
   1032 
   1033   event.data.tap.tapCount = 1;
   1034   if (!disambiguation_popup_tap) {
   1035     const float touch_padding_dip = GetTouchPaddingDip();
   1036     event.data.tap.width = touch_padding_dip;
   1037     event.data.tap.height = touch_padding_dip;
   1038   }
   1039 
   1040   SendGestureEvent(event);
   1041 }
   1042 
   1043 void ContentViewCoreImpl::SingleTapUnconfirmed(JNIEnv* env, jobject obj,
   1044                                                jlong time_ms,
   1045                                                jfloat x, jfloat y) {
   1046   WebGestureEvent event = MakeGestureEvent(
   1047       WebInputEvent::GestureTapUnconfirmed, time_ms, x, y);
   1048 
   1049   event.data.tap.tapCount = 1;
   1050 
   1051   const float touch_padding_dip = GetTouchPaddingDip();
   1052   event.data.tap.width = touch_padding_dip;
   1053   event.data.tap.height = touch_padding_dip;
   1054 
   1055   SendGestureEvent(event);
   1056 }
   1057 
   1058 void ContentViewCoreImpl::ShowPressState(JNIEnv* env, jobject obj,
   1059                                          jlong time_ms,
   1060                                          jfloat x, jfloat y) {
   1061   WebGestureEvent event = MakeGestureEvent(
   1062       WebInputEvent::GestureShowPress, time_ms, x, y);
   1063   SendGestureEvent(event);
   1064 }
   1065 
   1066 void ContentViewCoreImpl::TapCancel(JNIEnv* env,
   1067                                     jobject obj,
   1068                                     jlong time_ms,
   1069                                     jfloat x,
   1070                                     jfloat y) {
   1071   WebGestureEvent event = MakeGestureEvent(
   1072       WebInputEvent::GestureTapCancel, time_ms, x, y);
   1073   SendGestureEvent(event);
   1074 }
   1075 
   1076 void ContentViewCoreImpl::TapDown(JNIEnv* env, jobject obj,
   1077                                   jlong time_ms,
   1078                                   jfloat x, jfloat y) {
   1079   WebGestureEvent event = MakeGestureEvent(
   1080       WebInputEvent::GestureTapDown, time_ms, x, y);
   1081   SendGestureEvent(event);
   1082 }
   1083 
   1084 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
   1085                                     jfloat x, jfloat y) {
   1086   WebGestureEvent event = MakeGestureEvent(
   1087       WebInputEvent::GestureDoubleTap, time_ms, x, y);
   1088   SendGestureEvent(event);
   1089 }
   1090 
   1091 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
   1092                                     jfloat x, jfloat y,
   1093                                     jboolean disambiguation_popup_tap) {
   1094   WebGestureEvent event = MakeGestureEvent(
   1095       WebInputEvent::GestureLongPress, time_ms, x, y);
   1096 
   1097   if (!disambiguation_popup_tap) {
   1098     const float touch_padding_dip = GetTouchPaddingDip();
   1099     event.data.longPress.width = touch_padding_dip;
   1100     event.data.longPress.height = touch_padding_dip;
   1101   }
   1102 
   1103   SendGestureEvent(event);
   1104 }
   1105 
   1106 void ContentViewCoreImpl::LongTap(JNIEnv* env, jobject obj, jlong time_ms,
   1107                                   jfloat x, jfloat y,
   1108                                   jboolean disambiguation_popup_tap) {
   1109   WebGestureEvent event = MakeGestureEvent(
   1110       WebInputEvent::GestureLongTap, time_ms, x, y);
   1111 
   1112   if (!disambiguation_popup_tap) {
   1113     const float touch_padding_dip = GetTouchPaddingDip();
   1114     event.data.longPress.width = touch_padding_dip;
   1115     event.data.longPress.height = touch_padding_dip;
   1116   }
   1117 
   1118   SendGestureEvent(event);
   1119 }
   1120 
   1121 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
   1122                                      jfloat x, jfloat y) {
   1123   WebGestureEvent event = MakeGestureEvent(
   1124       WebInputEvent::GesturePinchBegin, time_ms, x, y);
   1125   SendGestureEvent(event);
   1126 }
   1127 
   1128 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
   1129   WebGestureEvent event = MakeGestureEvent(
   1130       WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
   1131   SendGestureEvent(event);
   1132 }
   1133 
   1134 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
   1135                                   jfloat anchor_x, jfloat anchor_y,
   1136                                   jfloat delta) {
   1137   WebGestureEvent event = MakeGestureEvent(
   1138       WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
   1139   event.data.pinchUpdate.scale = delta;
   1140 
   1141   SendGestureEvent(event);
   1142 }
   1143 
   1144 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
   1145                                                    jfloat x1, jfloat y1,
   1146                                                    jfloat x2, jfloat y2) {
   1147   if (GetRenderWidgetHostViewAndroid()) {
   1148     GetRenderWidgetHostViewAndroid()->SelectRange(
   1149         gfx::Point(x1 / GetDpiScale(), y1 / GetDpiScale()),
   1150         gfx::Point(x2 / GetDpiScale(), y2 / GetDpiScale()));
   1151   }
   1152 }
   1153 
   1154 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
   1155                                     jfloat x, jfloat y) {
   1156   if (GetRenderWidgetHostViewAndroid()) {
   1157     GetRenderWidgetHostViewAndroid()->MoveCaret(
   1158         gfx::Point(x / GetDpiScale(), y / GetDpiScale()));
   1159   }
   1160 }
   1161 
   1162 void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) {
   1163   web_contents_->GetController().LoadIfNecessary();
   1164 }
   1165 
   1166 void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv* env, jobject obj) {
   1167   web_contents_->GetController().SetNeedsReload();
   1168 }
   1169 
   1170 void ContentViewCoreImpl::StopLoading(JNIEnv* env, jobject obj) {
   1171   web_contents_->Stop();
   1172 }
   1173 
   1174 void ContentViewCoreImpl::Reload(JNIEnv* env,
   1175                                  jobject obj,
   1176                                  jboolean check_for_repost) {
   1177   if (web_contents_->GetController().NeedsReload())
   1178     web_contents_->GetController().LoadIfNecessary();
   1179   else
   1180     web_contents_->GetController().Reload(check_for_repost);
   1181 }
   1182 
   1183 void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv* env,
   1184                                               jobject obj,
   1185                                               jboolean check_for_repost) {
   1186   web_contents_->GetController().ReloadIgnoringCache(check_for_repost);
   1187 }
   1188 
   1189 void ContentViewCoreImpl::CancelPendingReload(JNIEnv* env, jobject obj) {
   1190   web_contents_->GetController().CancelPendingReload();
   1191 }
   1192 
   1193 void ContentViewCoreImpl::ContinuePendingReload(JNIEnv* env, jobject obj) {
   1194   web_contents_->GetController().ContinuePendingReload();
   1195 }
   1196 
   1197 void ContentViewCoreImpl::ClearHistory(JNIEnv* env, jobject obj) {
   1198   // TODO(creis): Do callers of this need to know if it fails?
   1199   if (web_contents_->GetController().CanPruneAllButLastCommitted())
   1200     web_contents_->GetController().PruneAllButLastCommitted();
   1201 }
   1202 
   1203 void ContentViewCoreImpl::AddJavascriptInterface(
   1204     JNIEnv* env,
   1205     jobject /* obj */,
   1206     jobject object,
   1207     jstring name,
   1208     jclass safe_annotation_clazz,
   1209     jobject retained_object_set) {
   1210   ScopedJavaLocalRef<jobject> scoped_object(env, object);
   1211   ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
   1212   JavaObjectWeakGlobalRef weak_retained_object_set(env, retained_object_set);
   1213 
   1214   // JavaBoundObject creates the NPObject with a ref count of 1, and
   1215   // JavaBridgeDispatcherHostManager takes its own ref.
   1216   JavaBridgeDispatcherHostManager* java_bridge =
   1217       web_contents_->java_bridge_dispatcher_host_manager();
   1218   java_bridge->SetRetainedObjectSet(weak_retained_object_set);
   1219   NPObject* bound_object = JavaBoundObject::Create(scoped_object, scoped_clazz,
   1220                                                    java_bridge->AsWeakPtr());
   1221   java_bridge->AddNamedObject(ConvertJavaStringToUTF16(env, name),
   1222                               bound_object);
   1223   blink::WebBindings::releaseObject(bound_object);
   1224 }
   1225 
   1226 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
   1227                                                     jobject /* obj */,
   1228                                                     jstring name) {
   1229   web_contents_->java_bridge_dispatcher_host_manager()->RemoveNamedObject(
   1230       ConvertJavaStringToUTF16(env, name));
   1231 }
   1232 
   1233 void ContentViewCoreImpl::UpdateVSyncParameters(JNIEnv* env, jobject /* obj */,
   1234                                                 jlong timebase_micros,
   1235                                                 jlong interval_micros) {
   1236   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   1237   if (!view)
   1238     return;
   1239 
   1240   RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
   1241       view->GetRenderWidgetHost());
   1242 
   1243   host->UpdateVSyncParameters(
   1244       base::TimeTicks::FromInternalValue(timebase_micros),
   1245       base::TimeDelta::FromMicroseconds(interval_micros));
   1246 
   1247   vsync_interval_ =
   1248       base::TimeDelta::FromMicroseconds(interval_micros);
   1249   expected_browser_composite_time_ =
   1250       vsync_interval_ * kDefaultBrowserCompositeVSyncFraction;
   1251 }
   1252 
   1253 void ContentViewCoreImpl::OnVSync(JNIEnv* env, jobject /* obj */,
   1254                                   jlong frame_time_micros) {
   1255   base::TimeTicks frame_time =
   1256       base::TimeTicks::FromInternalValue(frame_time_micros);
   1257   SendBeginFrame(frame_time);
   1258 }
   1259 
   1260 void ContentViewCoreImpl::SendBeginFrame(base::TimeTicks frame_time) {
   1261   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   1262   if (!view)
   1263     return;
   1264 
   1265   base::TimeTicks display_time = frame_time + vsync_interval_;
   1266   base::TimeTicks deadline = display_time - expected_browser_composite_time_;
   1267 
   1268   view->SendBeginFrame(
   1269       cc::BeginFrameArgs::Create(frame_time, deadline, vsync_interval_));
   1270 }
   1271 
   1272 jboolean ContentViewCoreImpl::OnAnimate(JNIEnv* env, jobject /* obj */,
   1273                                         jlong frame_time_micros) {
   1274   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   1275   if (!view)
   1276     return false;
   1277 
   1278   return view->Animate(base::TimeTicks::FromInternalValue(frame_time_micros));
   1279 }
   1280 
   1281 jboolean ContentViewCoreImpl::PopulateBitmapFromCompositor(JNIEnv* env,
   1282                                                            jobject obj,
   1283                                                            jobject jbitmap) {
   1284   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   1285   if (!view)
   1286     return false;
   1287 
   1288   return view->PopulateBitmapWithContents(jbitmap);
   1289 }
   1290 
   1291 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
   1292   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   1293   if (view)
   1294     view->WasResized();
   1295 }
   1296 
   1297 void ContentViewCoreImpl::ShowInterstitialPage(
   1298     JNIEnv* env, jobject obj, jstring jurl, jint delegate_ptr) {
   1299   GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
   1300   InterstitialPageDelegateAndroid* delegate =
   1301       reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
   1302   InterstitialPage* interstitial = InterstitialPage::Create(
   1303       web_contents_, false, url, delegate);
   1304   delegate->set_interstitial_page(interstitial);
   1305   interstitial->Show();
   1306 }
   1307 
   1308 jboolean ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv* env,
   1309                                                         jobject obj) {
   1310   return web_contents_->ShowingInterstitialPage();
   1311 }
   1312 
   1313 void ContentViewCoreImpl::AttachExternalVideoSurface(JNIEnv* env,
   1314                                                      jobject obj,
   1315                                                      jint player_id,
   1316                                                      jobject jsurface) {
   1317 #if defined(VIDEO_HOLE)
   1318   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
   1319       web_contents_->GetRenderViewHost());
   1320   if (rvhi && rvhi->media_player_manager()) {
   1321     rvhi->media_player_manager()->AttachExternalVideoSurface(
   1322         static_cast<int>(player_id), jsurface);
   1323   }
   1324 #endif  // defined(VIDEO_HOLE)
   1325 }
   1326 
   1327 void ContentViewCoreImpl::DetachExternalVideoSurface(JNIEnv* env,
   1328                                                      jobject obj,
   1329                                                      jint player_id) {
   1330 #if defined(VIDEO_HOLE)
   1331   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
   1332       web_contents_->GetRenderViewHost());
   1333   if (rvhi && rvhi->media_player_manager()) {
   1334     rvhi->media_player_manager()->DetachExternalVideoSurface(
   1335         static_cast<int>(player_id));
   1336   }
   1337 #endif  // defined(VIDEO_HOLE)
   1338 }
   1339 
   1340 jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
   1341                                                           jobject obj) {
   1342   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
   1343   return view && view->HasValidFrame();
   1344 }
   1345 
   1346 void ContentViewCoreImpl::ExitFullscreen(JNIEnv* env, jobject obj) {
   1347   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1348   if (!host)
   1349     return;
   1350   host->ExitFullscreen();
   1351 }
   1352 
   1353 void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv* env,
   1354                                                  jobject obj,
   1355                                                  bool enable_hiding,
   1356                                                  bool enable_showing,
   1357                                                  bool animate) {
   1358   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1359   if (!host)
   1360     return;
   1361   host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
   1362                                                 enable_hiding,
   1363                                                 enable_showing,
   1364                                                 animate));
   1365 }
   1366 
   1367 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
   1368   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1369   host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
   1370 }
   1371 
   1372 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv* env,
   1373                                                             jobject obj) {
   1374   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1375   host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
   1376       host->GetRoutingID(), gfx::Rect()));
   1377 }
   1378 
   1379 namespace {
   1380 
   1381 static void AddNavigationEntryToHistory(JNIEnv* env, jobject obj,
   1382                                         jobject history,
   1383                                         NavigationEntry* entry,
   1384                                         int index) {
   1385   // Get the details of the current entry
   1386   ScopedJavaLocalRef<jstring> j_url(
   1387       ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
   1388   ScopedJavaLocalRef<jstring> j_virtual_url(
   1389       ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
   1390   ScopedJavaLocalRef<jstring> j_original_url(
   1391       ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
   1392   ScopedJavaLocalRef<jstring> j_title(
   1393       ConvertUTF16ToJavaString(env, entry->GetTitle()));
   1394   ScopedJavaLocalRef<jobject> j_bitmap;
   1395   const FaviconStatus& status = entry->GetFavicon();
   1396   if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
   1397     j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
   1398 
   1399   // Add the item to the list
   1400   Java_ContentViewCore_addToNavigationHistory(
   1401       env, obj, history, index, j_url.obj(), j_virtual_url.obj(),
   1402       j_original_url.obj(), j_title.obj(), j_bitmap.obj());
   1403 }
   1404 
   1405 }  // namespace
   1406 
   1407 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env,
   1408                                               jobject obj,
   1409                                               jobject history) {
   1410   // Iterate through navigation entries to populate the list
   1411   const NavigationController& controller = web_contents_->GetController();
   1412   int count = controller.GetEntryCount();
   1413   for (int i = 0; i < count; ++i) {
   1414     AddNavigationEntryToHistory(
   1415         env, obj, history, controller.GetEntryAtIndex(i), i);
   1416   }
   1417 
   1418   return controller.GetCurrentEntryIndex();
   1419 }
   1420 
   1421 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv* env,
   1422                                                        jobject obj,
   1423                                                        jobject history,
   1424                                                        jboolean is_forward,
   1425                                                        jint max_entries) {
   1426   // Iterate through navigation entries to populate the list
   1427   const NavigationController& controller = web_contents_->GetController();
   1428   int count = controller.GetEntryCount();
   1429   int num_added = 0;
   1430   int increment_value = is_forward ? 1 : -1;
   1431   for (int i = controller.GetCurrentEntryIndex() + increment_value;
   1432        i >= 0 && i < count;
   1433        i += increment_value) {
   1434     if (num_added >= max_entries)
   1435       break;
   1436 
   1437     AddNavigationEntryToHistory(
   1438         env, obj, history, controller.GetEntryAtIndex(i), i);
   1439     num_added++;
   1440   }
   1441 }
   1442 
   1443 ScopedJavaLocalRef<jstring>
   1444 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv* env,
   1445                                                             jobject obj) {
   1446   NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
   1447   if (entry == NULL)
   1448     return ScopedJavaLocalRef<jstring>(env, NULL);
   1449   return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
   1450 }
   1451 
   1452 int ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
   1453   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
   1454   if (!rwhva)
   1455     return 0;
   1456   return rwhva->GetNativeImeAdapter();
   1457 }
   1458 
   1459 void ContentViewCoreImpl::UndoScrollFocusedEditableNodeIntoView(
   1460     JNIEnv* env,
   1461     jobject obj) {
   1462   RenderViewHost* host = web_contents_->GetRenderViewHost();
   1463   host->Send(
   1464       new ViewMsg_UndoScrollFocusedEditableNodeIntoView(host->GetRoutingID()));
   1465 }
   1466 
   1467 namespace {
   1468 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
   1469                               const base::Value* result) {
   1470   JNIEnv* env = base::android::AttachCurrentThread();
   1471   std::string json;
   1472   base::JSONWriter::Write(result, &json);
   1473   ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
   1474   Java_ContentViewCore_onEvaluateJavaScriptResult(env,
   1475                                                   j_json.obj(),
   1476                                                   callback.obj());
   1477 }
   1478 }  // namespace
   1479 
   1480 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env,
   1481                                              jobject obj,
   1482                                              jstring script,
   1483                                              jobject callback,
   1484                                              jboolean start_renderer) {
   1485   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
   1486   DCHECK(rvh);
   1487 
   1488   if (start_renderer && !rvh->IsRenderViewLive()) {
   1489     if (!web_contents_->CreateRenderViewForInitialEmptyDocument()) {
   1490       LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
   1491       return;
   1492     }
   1493   }
   1494 
   1495   if (!callback) {
   1496     // No callback requested.
   1497     rvh->ExecuteJavascriptInWebFrame(base::string16(),  // frame_xpath
   1498                                      ConvertJavaStringToUTF16(env, script));
   1499     return;
   1500   }
   1501 
   1502   // Secure the Java callback in a scoped object and give ownership of it to the
   1503   // base::Callback.
   1504   ScopedJavaGlobalRef<jobject> j_callback;
   1505   j_callback.Reset(env, callback);
   1506   content::RenderViewHost::JavascriptResultCallback c_callback =
   1507       base::Bind(&JavaScriptResultCallback, j_callback);
   1508 
   1509   rvh->ExecuteJavascriptInWebFrameCallbackResult(
   1510       base::string16(),  // frame_xpath
   1511       ConvertJavaStringToUTF16(env, script),
   1512       c_callback);
   1513 }
   1514 
   1515 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
   1516     JNIEnv* env, jobject obj) {
   1517   NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
   1518   return entry && entry->GetIsOverridingUserAgent();
   1519 }
   1520 
   1521 void ContentViewCoreImpl::UpdateImeAdapter(int native_ime_adapter,
   1522                                            int text_input_type,
   1523                                            const std::string& text,
   1524                                            int selection_start,
   1525                                            int selection_end,
   1526                                            int composition_start,
   1527                                            int composition_end,
   1528                                            bool show_ime_if_needed,
   1529                                            bool require_ack) {
   1530   JNIEnv* env = AttachCurrentThread();
   1531   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   1532   if (obj.is_null())
   1533     return;
   1534 
   1535   ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
   1536   Java_ContentViewCore_updateImeAdapter(env, obj.obj(),
   1537                                         native_ime_adapter, text_input_type,
   1538                                         jstring_text.obj(),
   1539                                         selection_start, selection_end,
   1540                                         composition_start, composition_end,
   1541                                         show_ime_if_needed, require_ack);
   1542 }
   1543 
   1544 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv* env, jobject obj) {
   1545   SSLHostState* state = SSLHostState::GetFor(
   1546       web_contents_->GetController().GetBrowserContext());
   1547   state->Clear();
   1548 }
   1549 
   1550 void ContentViewCoreImpl::SetUseDesktopUserAgent(
   1551     JNIEnv* env,
   1552     jobject obj,
   1553     jboolean enabled,
   1554     jboolean reload_on_state_change) {
   1555   if (GetUseDesktopUserAgent(env, obj) == enabled)
   1556     return;
   1557 
   1558   // Make sure the navigation entry actually exists.
   1559   NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
   1560   if (!entry)
   1561     return;
   1562 
   1563   // Set the flag in the NavigationEntry.
   1564   entry->SetIsOverridingUserAgent(enabled);
   1565 
   1566   // Send the override to the renderer.
   1567   if (reload_on_state_change) {
   1568     // Reloading the page will send the override down as part of the
   1569     // navigation IPC message.
   1570     NavigationControllerImpl& controller =
   1571         static_cast<NavigationControllerImpl&>(web_contents_->GetController());
   1572     controller.ReloadOriginalRequestURL(false);
   1573   }
   1574 }
   1575 
   1576 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
   1577                                                   bool enabled) {
   1578   RenderWidgetHostViewAndroid* host_view = GetRenderWidgetHostViewAndroid();
   1579   if (!host_view)
   1580     return;
   1581   RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(
   1582       host_view->GetRenderWidgetHost());
   1583   BrowserAccessibilityState* accessibility_state =
   1584       BrowserAccessibilityState::GetInstance();
   1585   if (enabled) {
   1586     // This enables accessibility globally unless it was explicitly disallowed
   1587     // by a command-line flag.
   1588     accessibility_state->OnScreenReaderDetected();
   1589     // If it was actually enabled globally, enable it for this RenderWidget now.
   1590     if (accessibility_state->IsAccessibleBrowser() && host_impl)
   1591       host_impl->SetAccessibilityMode(AccessibilityModeComplete);
   1592   } else {
   1593     accessibility_state->DisableAccessibility();
   1594     if (host_impl)
   1595       host_impl->SetAccessibilityMode(AccessibilityModeOff);
   1596   }
   1597 }
   1598 
   1599 void ContentViewCoreImpl::SendSingleTapUma(JNIEnv* env,
   1600                                            jobject obj,
   1601                                            jint type,
   1602                                            jint count) {
   1603   UMA_HISTOGRAM_ENUMERATION("Event.SingleTapType", type, count);
   1604 }
   1605 
   1606 void ContentViewCoreImpl::SendActionAfterDoubleTapUma(JNIEnv* env,
   1607                                                       jobject obj,
   1608                                                       jint type,
   1609                                                       jboolean has_delay,
   1610                                                       jint count) {
   1611   // This UMA stat tracks a user's action after a double tap within
   1612   // k seconds (where k == 5 currently). This UMA will tell us if
   1613   // removing the tap gesture delay will lead to significantly more
   1614   // accidental navigations after a double tap.
   1615   if (has_delay) {
   1616     UMA_HISTOGRAM_ENUMERATION("Event.ActionAfterDoubleTapWithDelay", type,
   1617                               count);
   1618   } else {
   1619     UMA_HISTOGRAM_ENUMERATION("Event.ActionAfterDoubleTapNoDelay", type,
   1620                               count);
   1621   }
   1622 }
   1623 
   1624 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
   1625   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   1626   if (rwhv)
   1627     rwhv->UpdateScreenInfo(rwhv->GetNativeView());
   1628 
   1629   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
   1630       web_contents_->GetRenderViewHost());
   1631   rvhi->SendOrientationChangeEvent(device_orientation_);
   1632 }
   1633 
   1634 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
   1635                                                jobject obj,
   1636                                                jint x,
   1637                                                jint y,
   1638                                                jint width,
   1639                                                jint height) {
   1640   gfx::Rect rect(
   1641       static_cast<int>(x / GetDpiScale()),
   1642       static_cast<int>(y / GetDpiScale()),
   1643       static_cast<int>((width > 0 && width < GetDpiScale()) ?
   1644           1 : (int)(width / GetDpiScale())),
   1645       static_cast<int>((height > 0 && height < GetDpiScale()) ?
   1646           1 : (int)(height / GetDpiScale())));
   1647   GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
   1648       GetWebContents()->GetRoutingID(), rect));
   1649 }
   1650 
   1651 void ContentViewCoreImpl::OnSmartClipDataExtracted(const string16& result) {
   1652   JNIEnv* env = AttachCurrentThread();
   1653   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   1654   if (obj.is_null())
   1655     return;
   1656   ScopedJavaLocalRef<jstring> jresult = ConvertUTF16ToJavaString(env, result);
   1657   Java_ContentViewCore_onSmartClipDataExtracted(
   1658       env, obj.obj(), jresult.obj());
   1659 }
   1660 
   1661 void ContentViewCoreImpl::WebContentsDestroyed(WebContents* web_contents) {
   1662   WebContentsViewAndroid* wcva =
   1663       static_cast<WebContentsViewAndroid*>(web_contents->GetView());
   1664   DCHECK(wcva);
   1665   wcva->SetContentViewCore(NULL);
   1666 }
   1667 
   1668 // This is called for each ContentView.
   1669 jlong Init(JNIEnv* env, jobject obj,
   1670            jboolean hardware_accelerated,
   1671            jlong native_web_contents,
   1672            jlong view_android,
   1673            jlong window_android) {
   1674   ContentViewCoreImpl* view = new ContentViewCoreImpl(
   1675       env, obj, hardware_accelerated,
   1676       reinterpret_cast<WebContents*>(native_web_contents),
   1677       reinterpret_cast<ui::ViewAndroid*>(view_android),
   1678       reinterpret_cast<ui::WindowAndroid*>(window_android));
   1679   return reinterpret_cast<intptr_t>(view);
   1680 }
   1681 
   1682 bool RegisterContentViewCore(JNIEnv* env) {
   1683   return RegisterNativesImpl(env);
   1684 }
   1685 
   1686 }  // namespace content
   1687