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