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