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