• 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/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "cc/layers/layer.h"
17 #include "cc/layers/solid_color_layer.h"
18 #include "cc/output/begin_frame_args.h"
19 #include "content/browser/accessibility/browser_accessibility_state_impl.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/android/popup_touch_handle_drawable.h"
25 #include "content/browser/frame_host/interstitial_page_impl.h"
26 #include "content/browser/geolocation/geolocation_dispatcher_host.h"
27 #include "content/browser/media/media_web_contents_observer.h"
28 #include "content/browser/renderer_host/compositor_impl_android.h"
29 #include "content/browser/renderer_host/input/motion_event_android.h"
30 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
31 #include "content/browser/renderer_host/input/web_input_event_util.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/transition_request_manager.h"
36 #include "content/browser/web_contents/web_contents_view_android.h"
37 #include "content/common/frame_messages.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/browser_context.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/favicon_status.h"
44 #include "content/public/browser/render_frame_host.h"
45 #include "content/public/browser/screen_orientation_dispatcher_host.h"
46 #include "content/public/browser/ssl_host_state_delegate.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/user_agent.h"
52 #include "jni/ContentViewCore_jni.h"
53 #include "third_party/WebKit/public/web/WebInputEvent.h"
54 #include "ui/base/android/view_android.h"
55 #include "ui/base/android/window_android.h"
56 #include "ui/gfx/android/java_bitmap.h"
57 #include "ui/gfx/screen.h"
58 #include "ui/gfx/size_conversions.h"
59 #include "ui/gfx/size_f.h"
60 
61 using base::android::AttachCurrentThread;
62 using base::android::ConvertJavaStringToUTF16;
63 using base::android::ConvertJavaStringToUTF8;
64 using base::android::ConvertUTF16ToJavaString;
65 using base::android::ConvertUTF8ToJavaString;
66 using base::android::ScopedJavaLocalRef;
67 using blink::WebGestureEvent;
68 using blink::WebInputEvent;
69 
70 // Describes the type and enabled state of a select popup item.
71 namespace {
72 
73 enum {
74 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
75 #include "content/browser/android/popup_item_type_list.h"
76 #undef DEFINE_POPUP_ITEM_TYPE
77 };
78 
79 } //namespace
80 
81 namespace content {
82 
83 namespace {
84 
85 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
86 
GetRenderProcessIdFromRenderViewHost(RenderViewHost * host)87 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
88   DCHECK(host);
89   RenderProcessHost* render_process = host->GetProcess();
90   DCHECK(render_process);
91   if (render_process->HasConnection())
92     return render_process->GetHandle();
93   else
94     return 0;
95 }
96 
CreateJavaRect(JNIEnv * env,const gfx::Rect & rect)97 ScopedJavaLocalRef<jobject> CreateJavaRect(
98     JNIEnv* env,
99     const gfx::Rect& rect) {
100   return ScopedJavaLocalRef<jobject>(
101       Java_ContentViewCore_createRect(env,
102                                       static_cast<int>(rect.x()),
103                                       static_cast<int>(rect.y()),
104                                       static_cast<int>(rect.right()),
105                                       static_cast<int>(rect.bottom())));
106 }
107 
ToGestureEventType(WebInputEvent::Type type)108 int ToGestureEventType(WebInputEvent::Type type) {
109   switch (type) {
110     case WebInputEvent::GestureScrollBegin:
111       return SCROLL_START;
112     case WebInputEvent::GestureScrollEnd:
113       return SCROLL_END;
114     case WebInputEvent::GestureScrollUpdate:
115       return SCROLL_BY;
116     case WebInputEvent::GestureFlingStart:
117       return FLING_START;
118     case WebInputEvent::GestureFlingCancel:
119       return FLING_CANCEL;
120     case WebInputEvent::GestureShowPress:
121       return SHOW_PRESS;
122     case WebInputEvent::GestureTap:
123       return SINGLE_TAP_CONFIRMED;
124     case WebInputEvent::GestureTapUnconfirmed:
125       return SINGLE_TAP_UNCONFIRMED;
126     case WebInputEvent::GestureTapDown:
127       return TAP_DOWN;
128     case WebInputEvent::GestureTapCancel:
129       return TAP_CANCEL;
130     case WebInputEvent::GestureDoubleTap:
131       return DOUBLE_TAP;
132     case WebInputEvent::GestureLongPress:
133       return LONG_PRESS;
134     case WebInputEvent::GestureLongTap:
135       return LONG_TAP;
136     case WebInputEvent::GesturePinchBegin:
137       return PINCH_BEGIN;
138     case WebInputEvent::GesturePinchEnd:
139       return PINCH_END;
140     case WebInputEvent::GesturePinchUpdate:
141       return PINCH_BY;
142     case WebInputEvent::GestureTwoFingerTap:
143     case WebInputEvent::GestureScrollUpdateWithoutPropagation:
144     default:
145       NOTREACHED() << "Invalid source gesture type: "
146                    << WebInputEventTraits::GetName(type);
147       return -1;
148   };
149 }
150 
GetPrimaryDisplayDeviceScaleFactor()151 float GetPrimaryDisplayDeviceScaleFactor() {
152   const gfx::Display& display =
153       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
154   return display.device_scale_factor();
155 }
156 
157 }  // namespace
158 
159 // Enables a callback when the underlying WebContents is destroyed, to enable
160 // nulling the back-pointer.
161 class ContentViewCoreImpl::ContentViewUserData
162     : public base::SupportsUserData::Data {
163  public:
ContentViewUserData(ContentViewCoreImpl * content_view_core)164   explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
165       : content_view_core_(content_view_core) {
166   }
167 
~ContentViewUserData()168   virtual ~ContentViewUserData() {
169     // TODO(joth): When chrome has finished removing the TabContents class (see
170     // crbug.com/107201) consider inverting relationship, so ContentViewCore
171     // would own WebContents. That effectively implies making the WebContents
172     // destructor private on Android.
173     delete content_view_core_;
174   }
175 
get() const176   ContentViewCoreImpl* get() const { return content_view_core_; }
177 
178  private:
179   // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
180   ContentViewCoreImpl* content_view_core_;
181 
182   DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
183 };
184 
185 // static
FromWebContents(content::WebContents * web_contents)186 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
187     content::WebContents* web_contents) {
188   ContentViewCoreImpl::ContentViewUserData* data =
189       reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
190           web_contents->GetUserData(kContentViewUserDataKey));
191   return data ? data->get() : NULL;
192 }
193 
194 // static
FromWebContents(content::WebContents * web_contents)195 ContentViewCore* ContentViewCore::FromWebContents(
196     content::WebContents* web_contents) {
197   return ContentViewCoreImpl::FromWebContents(web_contents);
198 }
199 
200 // static
GetNativeContentViewCore(JNIEnv * env,jobject obj)201 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
202                                                            jobject obj) {
203   return reinterpret_cast<ContentViewCore*>(
204       Java_ContentViewCore_getNativeContentViewCore(env, obj));
205 }
206 
ContentViewCoreImpl(JNIEnv * env,jobject obj,WebContents * web_contents,ui::ViewAndroid * view_android,ui::WindowAndroid * window_android,jobject java_bridge_retained_object_set)207 ContentViewCoreImpl::ContentViewCoreImpl(
208     JNIEnv* env,
209     jobject obj,
210     WebContents* web_contents,
211     ui::ViewAndroid* view_android,
212     ui::WindowAndroid* window_android,
213     jobject java_bridge_retained_object_set)
214     : WebContentsObserver(web_contents),
215       java_ref_(env, obj),
216       web_contents_(static_cast<WebContentsImpl*>(web_contents)),
217       root_layer_(cc::SolidColorLayer::Create()),
218       dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
219       view_android_(view_android),
220       window_android_(window_android),
221       device_orientation_(0),
222       accessibility_enabled_(false) {
223   CHECK(web_contents) <<
224       "A ContentViewCoreImpl should be created with a valid WebContents.";
225   DCHECK(view_android_);
226   DCHECK(window_android_);
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_ =
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   // Java peer has gone, ContentViewCore is not functional and waits to
272   // be destroyed with WebContents.
273   // We need to reset WebContentsViewAndroid's reference, otherwise, there
274   // could have call in when swapping the WebContents,
275   // see http://crbug.com/383939 .
276   DCHECK(web_contents_);
277   static_cast<WebContentsViewAndroid*>(
278       static_cast<WebContentsImpl*>(web_contents_)->GetView())->
279           SetContentViewCore(NULL);
280 }
281 
InitWebContents()282 void ContentViewCoreImpl::InitWebContents() {
283   DCHECK(web_contents_);
284   static_cast<WebContentsViewAndroid*>(
285       static_cast<WebContentsImpl*>(web_contents_)->GetView())->
286           SetContentViewCore(this);
287   DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
288   web_contents_->SetUserData(kContentViewUserDataKey,
289                              new ContentViewUserData(this));
290 }
291 
RenderViewReady()292 void ContentViewCoreImpl::RenderViewReady() {
293   JNIEnv* env = AttachCurrentThread();
294   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
295   if (!obj.is_null())
296     Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
297 
298   if (device_orientation_ != 0)
299     SendOrientationChangeEventInternal();
300 }
301 
RenderViewHostChanged(RenderViewHost * old_host,RenderViewHost * new_host)302 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host,
303                                                 RenderViewHost* new_host) {
304   int old_pid = 0;
305   if (old_host) {
306     old_pid = GetRenderProcessIdFromRenderViewHost(old_host);
307 
308     RenderWidgetHostViewAndroid* view =
309         static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView());
310     if (view)
311       view->SetContentViewCore(NULL);
312 
313     view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView());
314     if (view)
315       view->SetContentViewCore(this);
316   }
317   int new_pid = GetRenderProcessIdFromRenderViewHost(
318       web_contents_->GetRenderViewHost());
319   if (new_pid != old_pid) {
320     // Notify the Java side that the renderer process changed.
321     JNIEnv* env = AttachCurrentThread();
322     ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
323     if (!obj.is_null()) {
324       Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
325     }
326   }
327 
328   SetFocusInternal(HasFocus());
329   SetAccessibilityEnabledInternal(accessibility_enabled_);
330 }
331 
332 RenderWidgetHostViewAndroid*
GetRenderWidgetHostViewAndroid()333     ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
334   RenderWidgetHostView* rwhv = NULL;
335   if (web_contents_) {
336     rwhv = web_contents_->GetRenderWidgetHostView();
337     if (web_contents_->ShowingInterstitialPage()) {
338       rwhv = static_cast<InterstitialPageImpl*>(
339           web_contents_->GetInterstitialPage())->
340               GetRenderViewHost()->GetView();
341     }
342   }
343   return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
344 }
345 
GetJavaObject()346 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
347   JNIEnv* env = AttachCurrentThread();
348   return java_ref_.get(env);
349 }
350 
GetBackgroundColor(JNIEnv * env,jobject obj)351 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
352   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
353   if (!rwhva)
354     return SK_ColorWHITE;
355   return rwhva->GetCachedBackgroundColor();
356 }
357 
PauseOrResumeGeolocation(bool should_pause)358 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
359   web_contents_->geolocation_dispatcher_host()->PauseOrResume(should_pause);
360 }
361 
362 // All positions and sizes are in CSS pixels.
363 // Note that viewport_width/height is a best effort based.
364 // 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)365 void ContentViewCoreImpl::UpdateFrameInfo(
366     const gfx::Vector2dF& scroll_offset,
367     float page_scale_factor,
368     const gfx::Vector2dF& page_scale_factor_limits,
369     const gfx::SizeF& content_size,
370     const gfx::SizeF& viewport_size,
371     const gfx::Vector2dF& controls_offset,
372     const gfx::Vector2dF& content_offset) {
373   JNIEnv* env = AttachCurrentThread();
374   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
375   if (obj.is_null())
376     return;
377 
378   window_android_->set_content_offset(
379       gfx::ScaleVector2d(content_offset, dpi_scale_));
380 
381   Java_ContentViewCore_updateFrameInfo(
382       env, obj.obj(),
383       scroll_offset.x(),
384       scroll_offset.y(),
385       page_scale_factor,
386       page_scale_factor_limits.x(),
387       page_scale_factor_limits.y(),
388       content_size.width(),
389       content_size.height(),
390       viewport_size.width(),
391       viewport_size.height(),
392       controls_offset.y(),
393       content_offset.y());
394 }
395 
SetTitle(const base::string16 & title)396 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
397   JNIEnv* env = AttachCurrentThread();
398   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
399   if (obj.is_null())
400     return;
401   ScopedJavaLocalRef<jstring> jtitle =
402       ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
403   Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
404 }
405 
OnBackgroundColorChanged(SkColor color)406 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
407   root_layer_->SetBackgroundColor(color);
408 
409   JNIEnv* env = AttachCurrentThread();
410   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
411   if (obj.is_null())
412     return;
413   Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
414 }
415 
ShowSelectPopupMenu(RenderFrameHost * frame,const gfx::Rect & bounds,const std::vector<MenuItem> & items,int selected_item,bool multiple)416 void ContentViewCoreImpl::ShowSelectPopupMenu(
417     RenderFrameHost* frame,
418     const gfx::Rect& bounds,
419     const std::vector<MenuItem>& items,
420     int selected_item,
421     bool multiple) {
422   JNIEnv* env = AttachCurrentThread();
423   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
424   if (j_obj.is_null())
425     return;
426 
427   ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
428 
429   // For multi-select list popups we find the list of previous selections by
430   // iterating through the items. But for single selection popups we take the
431   // given |selected_item| as is.
432   ScopedJavaLocalRef<jintArray> selected_array;
433   if (multiple) {
434     scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
435     size_t selected_count = 0;
436     for (size_t i = 0; i < items.size(); ++i) {
437       if (items[i].checked)
438         native_selected_array[selected_count++] = i;
439     }
440 
441     selected_array = ScopedJavaLocalRef<jintArray>(
442         env, env->NewIntArray(selected_count));
443     env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
444                            native_selected_array.get());
445   } else {
446     selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
447     jint value = selected_item;
448     env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
449   }
450 
451   ScopedJavaLocalRef<jintArray> enabled_array(env,
452                                               env->NewIntArray(items.size()));
453   std::vector<base::string16> labels;
454   labels.reserve(items.size());
455   for (size_t i = 0; i < items.size(); ++i) {
456     labels.push_back(items[i].label);
457     jint enabled =
458         (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
459             (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
460                 POPUP_ITEM_TYPE_DISABLED));
461     env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
462   }
463   ScopedJavaLocalRef<jobjectArray> items_array(
464       base::android::ToJavaArrayOfStrings(env, labels));
465   Java_ContentViewCore_showSelectPopup(env,
466                                        j_obj.obj(),
467                                        reinterpret_cast<intptr_t>(frame),
468                                        bounds_rect.obj(),
469                                        items_array.obj(),
470                                        enabled_array.obj(),
471                                        multiple,
472                                        selected_array.obj());
473 }
474 
HideSelectPopupMenu()475 void ContentViewCoreImpl::HideSelectPopupMenu() {
476   JNIEnv* env = AttachCurrentThread();
477   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
478   if (!j_obj.is_null())
479     Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
480 }
481 
OnGestureEventAck(const blink::WebGestureEvent & event,InputEventAckState ack_result)482 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
483                                             InputEventAckState ack_result) {
484   JNIEnv* env = AttachCurrentThread();
485   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
486   if (j_obj.is_null())
487     return;
488 
489   switch (event.type) {
490     case WebInputEvent::GestureFlingStart:
491       if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
492         // The view expects the fling velocity in pixels/s.
493         Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
494             event.data.flingStart.velocityX * dpi_scale(),
495             event.data.flingStart.velocityY * dpi_scale());
496       } else {
497         // If a scroll ends with a fling, a SCROLL_END event is never sent.
498         // However, if that fling went unconsumed, we still need to let the
499         // listeners know that scrolling has ended.
500         Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
501       }
502 
503       if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
504         // The view expects the fling velocity in pixels/s.
505         Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
506             event.data.flingStart.velocityX * dpi_scale(),
507             event.data.flingStart.velocityY * dpi_scale());
508       }
509       break;
510     case WebInputEvent::GestureFlingCancel:
511       Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
512       break;
513     case WebInputEvent::GestureScrollBegin:
514       Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
515       break;
516     case WebInputEvent::GestureScrollUpdate:
517       if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
518         Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
519       break;
520     case WebInputEvent::GestureScrollEnd:
521       Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
522       break;
523     case WebInputEvent::GesturePinchBegin:
524       Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
525       break;
526     case WebInputEvent::GesturePinchEnd:
527       Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
528       break;
529     case WebInputEvent::GestureTap:
530       Java_ContentViewCore_onSingleTapEventAck(
531           env,
532           j_obj.obj(),
533           ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
534           event.x * dpi_scale(),
535           event.y * dpi_scale());
536       break;
537     default:
538       break;
539   }
540 }
541 
FilterInputEvent(const blink::WebInputEvent & event)542 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
543   if (event.type != WebInputEvent::GestureTap &&
544       event.type != WebInputEvent::GestureDoubleTap &&
545       event.type != WebInputEvent::GestureLongTap &&
546       event.type != WebInputEvent::GestureLongPress)
547     return false;
548 
549   JNIEnv* env = AttachCurrentThread();
550   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
551   if (j_obj.is_null())
552     return false;
553 
554   const blink::WebGestureEvent& gesture =
555       static_cast<const blink::WebGestureEvent&>(event);
556   int gesture_type = ToGestureEventType(event.type);
557   return Java_ContentViewCore_filterTapOrPressEvent(env,
558                                                     j_obj.obj(),
559                                                     gesture_type,
560                                                     gesture.x * dpi_scale(),
561                                                     gesture.y * dpi_scale());
562 
563   // TODO(jdduke): Also report double-tap UMA, crbug/347568.
564 }
565 
HasFocus()566 bool ContentViewCoreImpl::HasFocus() {
567   JNIEnv* env = AttachCurrentThread();
568   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
569   if (obj.is_null())
570     return false;
571   return Java_ContentViewCore_hasFocus(env, obj.obj());
572 }
573 
OnSelectionChanged(const std::string & text)574 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
575   JNIEnv* env = AttachCurrentThread();
576   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
577   if (obj.is_null())
578     return;
579   ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
580   Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
581 }
582 
OnSelectionEvent(SelectionEventType event,const gfx::PointF & position)583 void ContentViewCoreImpl::OnSelectionEvent(SelectionEventType event,
584                                            const gfx::PointF& position) {
585   JNIEnv* env = AttachCurrentThread();
586   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
587   if (j_obj.is_null())
588     return;
589   Java_ContentViewCore_onSelectionEvent(
590       env, j_obj.obj(), event, position.x(), position.y());
591 }
592 
593 scoped_ptr<TouchHandleDrawable>
CreatePopupTouchHandleDrawable()594 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
595   JNIEnv* env = AttachCurrentThread();
596   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
597   if (obj.is_null()) {
598     NOTREACHED();
599     return scoped_ptr<TouchHandleDrawable>();
600   }
601   return scoped_ptr<TouchHandleDrawable>(new PopupTouchHandleDrawable(
602       Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()),
603       dpi_scale_));
604 }
605 
ShowPastePopup(int x_dip,int y_dip)606 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
607   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
608   if (!view)
609     return;
610 
611   view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
612 
613   JNIEnv* env = AttachCurrentThread();
614   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
615   if (obj.is_null())
616     return;
617   Java_ContentViewCore_showPastePopupWithFeedback(env, obj.obj(),
618                                                   static_cast<jint>(x_dip),
619                                                   static_cast<jint>(y_dip));
620 }
621 
GetScaledContentBitmap(float scale,SkColorType color_type,gfx::Rect src_subrect,const base::Callback<void (bool,const SkBitmap &)> & result_callback)622 void ContentViewCoreImpl::GetScaledContentBitmap(
623     float scale,
624     SkColorType color_type,
625     gfx::Rect src_subrect,
626     const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
627   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
628   if (!view) {
629     result_callback.Run(false, SkBitmap());
630     return;
631   }
632 
633   view->GetScaledContentBitmap(scale, color_type, src_subrect,
634       result_callback);
635 }
636 
StartContentIntent(const GURL & content_url)637 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
638   JNIEnv* env = AttachCurrentThread();
639   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
640   if (j_obj.is_null())
641     return;
642   ScopedJavaLocalRef<jstring> jcontent_url =
643       ConvertUTF8ToJavaString(env, content_url.spec());
644   Java_ContentViewCore_startContentIntent(env,
645                                           j_obj.obj(),
646                                           jcontent_url.obj());
647 }
648 
ShowDisambiguationPopup(const gfx::Rect & rect_pixels,const SkBitmap & zoomed_bitmap)649 void ContentViewCoreImpl::ShowDisambiguationPopup(
650     const gfx::Rect& rect_pixels,
651     const SkBitmap& zoomed_bitmap) {
652   JNIEnv* env = AttachCurrentThread();
653 
654   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
655   if (obj.is_null())
656     return;
657 
658   ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
659 
660   ScopedJavaLocalRef<jobject> java_bitmap =
661       gfx::ConvertToJavaBitmap(&zoomed_bitmap);
662   DCHECK(!java_bitmap.is_null());
663 
664   Java_ContentViewCore_showDisambiguationPopup(env,
665                                                obj.obj(),
666                                                rect_object.obj(),
667                                                java_bitmap.obj());
668 }
669 
CreateTouchEventSynthesizer()670 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
671   JNIEnv* env = AttachCurrentThread();
672 
673   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
674   if (obj.is_null())
675     return ScopedJavaLocalRef<jobject>();
676   return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
677 }
678 
GetContentVideoViewClient()679 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
680   JNIEnv* env = AttachCurrentThread();
681 
682   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
683   if (obj.is_null())
684     return ScopedJavaLocalRef<jobject>();
685 
686   return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
687 }
688 
GetContext()689 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
690   JNIEnv* env = AttachCurrentThread();
691 
692   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
693   if (obj.is_null())
694     return ScopedJavaLocalRef<jobject>();
695 
696   return Java_ContentViewCore_getContext(env, obj.obj());
697 }
698 
ShouldBlockMediaRequest(const GURL & url)699 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
700   JNIEnv* env = AttachCurrentThread();
701 
702   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
703   if (obj.is_null())
704     return true;
705   ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
706   return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
707                                                       j_url.obj());
708 }
709 
DidStopFlinging()710 void ContentViewCoreImpl::DidStopFlinging() {
711   JNIEnv* env = AttachCurrentThread();
712 
713   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
714   if (!obj.is_null())
715     Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
716 }
717 
GetViewSize() const718 gfx::Size ContentViewCoreImpl::GetViewSize() const {
719   gfx::Size size = GetViewportSizeDip();
720   size.Enlarge(0, -GetTopControlsLayoutHeightDip());
721   return size;
722 }
723 
GetPhysicalBackingSize() const724 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
725   JNIEnv* env = AttachCurrentThread();
726   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
727   if (j_obj.is_null())
728     return gfx::Size();
729   return gfx::Size(
730       Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
731       Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
732 }
733 
GetViewportSizePix() const734 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
735   JNIEnv* env = AttachCurrentThread();
736   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
737   if (j_obj.is_null())
738     return gfx::Size();
739   return gfx::Size(
740       Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
741       Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
742 }
743 
GetTopControlsLayoutHeightPix() const744 int ContentViewCoreImpl::GetTopControlsLayoutHeightPix() const {
745   JNIEnv* env = AttachCurrentThread();
746   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
747   if (j_obj.is_null())
748     return 0;
749   return Java_ContentViewCore_getTopControlsLayoutHeightPix(env, j_obj.obj());
750 }
751 
GetViewportSizeDip() const752 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
753   return gfx::ToCeiledSize(
754       gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
755 }
756 
GetTopControlsLayoutHeightDip() const757 float ContentViewCoreImpl::GetTopControlsLayoutHeightDip() const {
758   return GetTopControlsLayoutHeightPix() / dpi_scale();
759 }
760 
AttachLayer(scoped_refptr<cc::Layer> layer)761 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
762   root_layer_->InsertChild(layer, 0);
763   root_layer_->SetIsDrawable(false);
764 }
765 
RemoveLayer(scoped_refptr<cc::Layer> layer)766 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
767   layer->RemoveFromParent();
768 
769   if (!root_layer_->children().size())
770     root_layer_->SetIsDrawable(true);
771 }
772 
SelectBetweenCoordinates(const gfx::PointF & start,const gfx::PointF & end)773 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& start,
774                                                    const gfx::PointF& end) {
775   if (!web_contents_)
776     return;
777 
778   gfx::Point start_point = gfx::Point(start.x(), start.y());
779   gfx::Point end_point = gfx::Point(end.x(), end.y());
780   if (start_point == end_point)
781     return;
782 
783   web_contents_->SelectRange(start_point, end_point);
784 }
785 
GetViewAndroid() const786 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
787   return view_android_;
788 }
789 
GetWindowAndroid() const790 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
791   return window_android_;
792 }
793 
GetLayer() const794 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
795   return root_layer_.get();
796 }
797 
798 // ----------------------------------------------------------------------------
799 // Methods called from Java via JNI
800 // ----------------------------------------------------------------------------
801 
SelectPopupMenuItems(JNIEnv * env,jobject obj,jlong selectPopupSourceFrame,jintArray indices)802 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
803                                                jobject obj,
804                                                jlong selectPopupSourceFrame,
805                                                jintArray indices) {
806   RenderFrameHostImpl* rfhi =
807       reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
808   DCHECK(rfhi);
809   if (indices == NULL) {
810     rfhi->DidCancelPopupMenu();
811     return;
812   }
813 
814   int selected_count = env->GetArrayLength(indices);
815   std::vector<int> selected_indices;
816   jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
817   for (int i = 0; i < selected_count; ++i)
818     selected_indices.push_back(indices_ptr[i]);
819   env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
820   rfhi->DidSelectPopupMenuItems(selected_indices);
821 }
822 
GetWebContents() const823 WebContents* ContentViewCoreImpl::GetWebContents() const {
824   return web_contents_;
825 }
826 
SetFocus(JNIEnv * env,jobject obj,jboolean focused)827 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
828   SetFocusInternal(focused);
829 }
830 
SetFocusInternal(bool focused)831 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
832   if (!GetRenderWidgetHostViewAndroid())
833     return;
834 
835   if (focused)
836     GetRenderWidgetHostViewAndroid()->Focus();
837   else
838     GetRenderWidgetHostViewAndroid()->Blur();
839 }
840 
SendOrientationChangeEvent(JNIEnv * env,jobject obj,jint orientation)841 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
842                                                      jobject obj,
843                                                      jint orientation) {
844   if (device_orientation_ != orientation) {
845     device_orientation_ = orientation;
846     SendOrientationChangeEventInternal();
847   }
848 }
849 
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 touch_minor_0,jfloat touch_minor_1,jfloat orientation_0,jfloat orientation_1,jfloat raw_pos_x,jfloat raw_pos_y,jint android_tool_type_0,jint android_tool_type_1,jint android_button_state,jint android_meta_state,jboolean is_touch_handle_event)850 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
851                                            jobject obj,
852                                            jobject motion_event,
853                                            jlong time_ms,
854                                            jint android_action,
855                                            jint pointer_count,
856                                            jint history_size,
857                                            jint action_index,
858                                            jfloat pos_x_0,
859                                            jfloat pos_y_0,
860                                            jfloat pos_x_1,
861                                            jfloat pos_y_1,
862                                            jint pointer_id_0,
863                                            jint pointer_id_1,
864                                            jfloat touch_major_0,
865                                            jfloat touch_major_1,
866                                            jfloat touch_minor_0,
867                                            jfloat touch_minor_1,
868                                            jfloat orientation_0,
869                                            jfloat orientation_1,
870                                            jfloat raw_pos_x,
871                                            jfloat raw_pos_y,
872                                            jint android_tool_type_0,
873                                            jint android_tool_type_1,
874                                            jint android_button_state,
875                                            jint android_meta_state,
876                                            jboolean is_touch_handle_event) {
877   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
878   // Avoid synthesizing a touch event if it cannot be forwarded.
879   if (!rwhv)
880     return false;
881 
882   MotionEventAndroid event(1.f / dpi_scale(),
883                            env,
884                            motion_event,
885                            time_ms,
886                            android_action,
887                            pointer_count,
888                            history_size,
889                            action_index,
890                            pos_x_0,
891                            pos_y_0,
892                            pos_x_1,
893                            pos_y_1,
894                            pointer_id_0,
895                            pointer_id_1,
896                            touch_major_0,
897                            touch_major_1,
898                            touch_minor_0,
899                            touch_minor_1,
900                            orientation_0,
901                            orientation_1,
902                            raw_pos_x,
903                            raw_pos_y,
904                            android_tool_type_0,
905                            android_tool_type_1,
906                            android_button_state,
907                            android_meta_state);
908 
909   return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
910                                : rwhv->OnTouchEvent(event);
911 }
912 
GetDpiScale() const913 float ContentViewCoreImpl::GetDpiScale() const {
914   return dpi_scale_;
915 }
916 
SendMouseMoveEvent(JNIEnv * env,jobject obj,jlong time_ms,jfloat x,jfloat y)917 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
918                                                  jobject obj,
919                                                  jlong time_ms,
920                                                  jfloat x,
921                                                  jfloat y) {
922   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
923   if (!rwhv)
924     return false;
925 
926   blink::WebMouseEvent event = WebMouseEventBuilder::Build(
927       WebInputEvent::MouseMove,
928       blink::WebMouseEvent::ButtonNone,
929       time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
930 
931   rwhv->SendMouseEvent(event);
932   return true;
933 }
934 
SendMouseWheelEvent(JNIEnv * env,jobject obj,jlong time_ms,jfloat x,jfloat y,jfloat vertical_axis)935 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
936                                                   jobject obj,
937                                                   jlong time_ms,
938                                                   jfloat x,
939                                                   jfloat y,
940                                                   jfloat vertical_axis) {
941   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
942   if (!rwhv)
943     return false;
944 
945   WebMouseWheelEventBuilder::Direction direction;
946   if (vertical_axis > 0) {
947     direction = WebMouseWheelEventBuilder::DIRECTION_UP;
948   } else if (vertical_axis < 0) {
949     direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
950   } else {
951     return false;
952   }
953   blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
954       direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
955 
956   rwhv->SendMouseWheelEvent(event);
957   return true;
958 }
959 
MakeGestureEvent(WebInputEvent::Type type,int64 time_ms,float x,float y) const960 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
961     WebInputEvent::Type type, int64 time_ms, float x, float y) const {
962   return WebGestureEventBuilder::Build(
963       type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
964 }
965 
SendGestureEvent(const blink::WebGestureEvent & event)966 void ContentViewCoreImpl::SendGestureEvent(
967     const blink::WebGestureEvent& event) {
968   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
969   if (rwhv)
970     rwhv->SendGestureEvent(event);
971 }
972 
ScrollBegin(JNIEnv * env,jobject obj,jlong time_ms,jfloat x,jfloat y,jfloat hintx,jfloat hinty)973 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
974                                       jobject obj,
975                                       jlong time_ms,
976                                       jfloat x,
977                                       jfloat y,
978                                       jfloat hintx,
979                                       jfloat hinty) {
980   WebGestureEvent event = MakeGestureEvent(
981       WebInputEvent::GestureScrollBegin, time_ms, x, y);
982   event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
983   event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
984 
985   SendGestureEvent(event);
986 }
987 
ScrollEnd(JNIEnv * env,jobject obj,jlong time_ms)988 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
989   WebGestureEvent event = MakeGestureEvent(
990       WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
991   SendGestureEvent(event);
992 }
993 
ScrollBy(JNIEnv * env,jobject obj,jlong time_ms,jfloat x,jfloat y,jfloat dx,jfloat dy)994 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
995                                    jfloat x, jfloat y, jfloat dx, jfloat dy) {
996   WebGestureEvent event = MakeGestureEvent(
997       WebInputEvent::GestureScrollUpdate, time_ms, x, y);
998   event.data.scrollUpdate.deltaX = -dx / dpi_scale();
999   event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1000 
1001   SendGestureEvent(event);
1002 }
1003 
FlingStart(JNIEnv * env,jobject obj,jlong time_ms,jfloat x,jfloat y,jfloat vx,jfloat vy)1004 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1005                                      jfloat x, jfloat y, jfloat vx, jfloat vy) {
1006   WebGestureEvent event = MakeGestureEvent(
1007       WebInputEvent::GestureFlingStart, time_ms, x, y);
1008   event.data.flingStart.velocityX = vx / dpi_scale();
1009   event.data.flingStart.velocityY = vy / dpi_scale();
1010 
1011   SendGestureEvent(event);
1012 }
1013 
FlingCancel(JNIEnv * env,jobject obj,jlong time_ms)1014 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1015   WebGestureEvent event = MakeGestureEvent(
1016       WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1017   SendGestureEvent(event);
1018 }
1019 
SingleTap(JNIEnv * env,jobject obj,jlong time_ms,jfloat x,jfloat y)1020 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1021                                     jfloat x, jfloat y) {
1022   WebGestureEvent event = MakeGestureEvent(
1023       WebInputEvent::GestureTap, time_ms, x, y);
1024   event.data.tap.tapCount = 1;
1025 
1026   SendGestureEvent(event);
1027 }
1028 
DoubleTap(JNIEnv * env,jobject obj,jlong time_ms,jfloat x,jfloat y)1029 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1030                                     jfloat x, jfloat y) {
1031   WebGestureEvent event = MakeGestureEvent(
1032       WebInputEvent::GestureDoubleTap, time_ms, x, y);
1033   // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1034   // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1035   event.data.tap.tapCount = 1;
1036 
1037   SendGestureEvent(event);
1038 }
1039 
LongPress(JNIEnv * env,jobject obj,jlong time_ms,jfloat x,jfloat y)1040 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1041                                     jfloat x, jfloat y) {
1042   WebGestureEvent event = MakeGestureEvent(
1043       WebInputEvent::GestureLongPress, time_ms, x, y);
1044 
1045   SendGestureEvent(event);
1046 }
1047 
PinchBegin(JNIEnv * env,jobject obj,jlong time_ms,jfloat x,jfloat y)1048 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1049                                      jfloat x, jfloat y) {
1050   WebGestureEvent event = MakeGestureEvent(
1051       WebInputEvent::GesturePinchBegin, time_ms, x, y);
1052   SendGestureEvent(event);
1053 }
1054 
PinchEnd(JNIEnv * env,jobject obj,jlong time_ms)1055 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1056   WebGestureEvent event = MakeGestureEvent(
1057       WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1058   SendGestureEvent(event);
1059 }
1060 
PinchBy(JNIEnv * env,jobject obj,jlong time_ms,jfloat anchor_x,jfloat anchor_y,jfloat delta)1061 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1062                                   jfloat anchor_x, jfloat anchor_y,
1063                                   jfloat delta) {
1064   WebGestureEvent event = MakeGestureEvent(
1065       WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1066   event.data.pinchUpdate.scale = delta;
1067 
1068   SendGestureEvent(event);
1069 }
1070 
SelectBetweenCoordinates(JNIEnv * env,jobject obj,jfloat x1,jfloat y1,jfloat x2,jfloat y2)1071 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1072                                                    jfloat x1, jfloat y1,
1073                                                    jfloat x2, jfloat y2) {
1074   SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
1075                            gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
1076 }
1077 
MoveCaret(JNIEnv * env,jobject obj,jfloat x,jfloat y)1078 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1079                                     jfloat x, jfloat y) {
1080   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1081   if (rwhv)
1082     rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
1083 }
1084 
DismissTextHandles(JNIEnv * env,jobject obj)1085 void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
1086   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1087   if (rwhv)
1088     rwhv->DismissTextHandles();
1089 }
1090 
SetTextHandlesTemporarilyHidden(JNIEnv * env,jobject obj,jboolean hidden)1091 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
1092                                                           jobject obj,
1093                                                           jboolean hidden) {
1094   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1095   if (rwhv)
1096     rwhv->SetTextHandlesTemporarilyHidden(hidden);
1097 }
1098 
ResetGestureDetection(JNIEnv * env,jobject obj)1099 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1100   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1101   if (rwhv)
1102     rwhv->ResetGestureDetection();
1103 }
1104 
SetDoubleTapSupportEnabled(JNIEnv * env,jobject obj,jboolean enabled)1105 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1106                                                      jobject obj,
1107                                                      jboolean enabled) {
1108   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1109   if (rwhv)
1110     rwhv->SetDoubleTapSupportEnabled(enabled);
1111 }
1112 
SetMultiTouchZoomSupportEnabled(JNIEnv * env,jobject obj,jboolean enabled)1113 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1114                                                           jobject obj,
1115                                                           jboolean enabled) {
1116   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1117   if (rwhv)
1118     rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1119 }
1120 
SetAllowJavascriptInterfacesInspection(JNIEnv * env,jobject obj,jboolean allow)1121 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1122     JNIEnv* env,
1123     jobject obj,
1124     jboolean allow) {
1125   java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
1126 }
1127 
AddJavascriptInterface(JNIEnv * env,jobject,jobject object,jstring name,jclass safe_annotation_clazz)1128 void ContentViewCoreImpl::AddJavascriptInterface(
1129     JNIEnv* env,
1130     jobject /* obj */,
1131     jobject object,
1132     jstring name,
1133     jclass safe_annotation_clazz) {
1134   ScopedJavaLocalRef<jobject> scoped_object(env, object);
1135   ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1136   java_bridge_dispatcher_host_->AddNamedObject(
1137       ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
1138 }
1139 
RemoveJavascriptInterface(JNIEnv * env,jobject,jstring name)1140 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1141                                                     jobject /* obj */,
1142                                                     jstring name) {
1143   java_bridge_dispatcher_host_->RemoveNamedObject(
1144       ConvertJavaStringToUTF8(env, name));
1145 }
1146 
WasResized(JNIEnv * env,jobject obj)1147 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1148   RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1149   gfx::Size physical_size(
1150       Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1151       Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1152   root_layer_->SetBounds(physical_size);
1153 
1154   if (view) {
1155     RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1156         view->GetRenderWidgetHost());
1157     host->SendScreenRects();
1158     view->WasResized();
1159   }
1160 }
1161 
GetNativeImeAdapter(JNIEnv * env,jobject obj)1162 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1163   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1164   if (!rwhva)
1165     return 0;
1166   return rwhva->GetNativeImeAdapter();
1167 }
1168 
1169 // TODO(sgurun) add support for posting a frame whose name is known (only
1170 //               main frame is supported at this time, see crbug.com/389721)
1171 // TODO(sgurun) add support for passing message ports
PostMessageToFrame(JNIEnv * env,jobject obj,jstring frame_name,jstring message,jstring source_origin,jstring target_origin)1172 void ContentViewCoreImpl::PostMessageToFrame(JNIEnv* env, jobject obj,
1173     jstring frame_name, jstring message, jstring source_origin,
1174     jstring target_origin) {
1175 
1176   RenderViewHost* host = web_contents_->GetRenderViewHost();
1177   if (!host)
1178       return;
1179   ViewMsg_PostMessage_Params params;
1180   params.source_origin = ConvertJavaStringToUTF16(env, source_origin);
1181   params.target_origin = ConvertJavaStringToUTF16(env, target_origin);
1182   params.data = ConvertJavaStringToUTF16(env, message);
1183   params.is_data_raw_string = true;
1184   params.source_routing_id = MSG_ROUTING_NONE;
1185   host->Send(new ViewMsg_PostMessageEvent(host->GetRoutingID(), params));
1186 }
1187 
UpdateImeAdapter(long native_ime_adapter,int text_input_type,int text_input_flags,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)1188 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1189                                            int text_input_type,
1190                                            int text_input_flags,
1191                                            const std::string& text,
1192                                            int selection_start,
1193                                            int selection_end,
1194                                            int composition_start,
1195                                            int composition_end,
1196                                            bool show_ime_if_needed,
1197                                            bool is_non_ime_change) {
1198   JNIEnv* env = AttachCurrentThread();
1199   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1200   if (obj.is_null())
1201     return;
1202 
1203   ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1204   Java_ContentViewCore_updateImeAdapter(env,
1205                                         obj.obj(),
1206                                         native_ime_adapter,
1207                                         text_input_type,
1208                                         text_input_flags,
1209                                         jstring_text.obj(),
1210                                         selection_start,
1211                                         selection_end,
1212                                         composition_start,
1213                                         composition_end,
1214                                         show_ime_if_needed,
1215                                         is_non_ime_change);
1216 }
1217 
SetAccessibilityEnabled(JNIEnv * env,jobject obj,bool enabled)1218 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1219                                                   bool enabled) {
1220   SetAccessibilityEnabledInternal(enabled);
1221 }
1222 
IsFullscreenRequiredForOrientationLock() const1223 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1224   JNIEnv* env = AttachCurrentThread();
1225   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1226   if (obj.is_null())
1227     return true;
1228   return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
1229                                                                      obj.obj());
1230 }
1231 
SetAccessibilityEnabledInternal(bool enabled)1232 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1233   accessibility_enabled_ = enabled;
1234   BrowserAccessibilityStateImpl* accessibility_state =
1235       BrowserAccessibilityStateImpl::GetInstance();
1236   if (enabled) {
1237     // This enables accessibility globally unless it was explicitly disallowed
1238     // by a command-line flag.
1239     accessibility_state->OnScreenReaderDetected();
1240     // If it was actually enabled globally, enable it for this RenderWidget now.
1241     if (accessibility_state->IsAccessibleBrowser() && web_contents_)
1242       web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
1243   } else {
1244     accessibility_state->ResetAccessibilityMode();
1245     if (web_contents_) {
1246       web_contents_->SetAccessibilityMode(
1247           accessibility_state->accessibility_mode());
1248     }
1249   }
1250 }
1251 
SendOrientationChangeEventInternal()1252 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1253   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1254   if (rwhv)
1255     rwhv->UpdateScreenInfo(GetViewAndroid());
1256 
1257   static_cast<WebContentsImpl*>(web_contents())->
1258       screen_orientation_dispatcher_host()->OnOrientationChange();
1259 }
1260 
ExtractSmartClipData(JNIEnv * env,jobject obj,jint x,jint y,jint width,jint height)1261 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1262                                                jobject obj,
1263                                                jint x,
1264                                                jint y,
1265                                                jint width,
1266                                                jint height) {
1267   gfx::Rect rect(
1268       static_cast<int>(x / dpi_scale()),
1269       static_cast<int>(y / dpi_scale()),
1270       static_cast<int>((width > 0 && width < dpi_scale()) ?
1271           1 : (int)(width / dpi_scale())),
1272       static_cast<int>((height > 0 && height < dpi_scale()) ?
1273           1 : (int)(height / dpi_scale())));
1274   GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1275       GetWebContents()->GetRoutingID(), rect));
1276 }
1277 
GetCurrentRenderProcessId(JNIEnv * env,jobject obj)1278 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1279   return GetRenderProcessIdFromRenderViewHost(
1280       web_contents_->GetRenderViewHost());
1281 }
1282 
SetBackgroundOpaque(JNIEnv * env,jobject jobj,jboolean opaque)1283 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1284     jboolean opaque) {
1285   if (GetRenderWidgetHostViewAndroid())
1286     GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque);
1287 }
1288 
RequestTextSurroundingSelection(int max_length,const base::Callback<void (const base::string16 & content,int start_offset,int end_offset)> & callback)1289 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1290     int max_length,
1291     const base::Callback<
1292         void(const base::string16& content, int start_offset, int end_offset)>&
1293         callback) {
1294   DCHECK(!callback.is_null());
1295   RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1296   if (!focused_frame)
1297     return;
1298   if (GetRenderWidgetHostViewAndroid()) {
1299     GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1300         callback);
1301     focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1302         focused_frame->GetRoutingID(), max_length));
1303   }
1304 }
1305 
OnSmartClipDataExtracted(const base::string16 & text,const base::string16 & html,const gfx::Rect & clip_rect)1306 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1307     const base::string16& text,
1308     const base::string16& html,
1309     const gfx::Rect& clip_rect) {
1310   JNIEnv* env = AttachCurrentThread();
1311   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1312   if (obj.is_null())
1313     return;
1314   ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
1315   ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
1316   ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
1317   Java_ContentViewCore_onSmartClipDataExtracted(
1318       env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
1319 }
1320 
WebContentsDestroyed()1321 void ContentViewCoreImpl::WebContentsDestroyed() {
1322   WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1323       static_cast<WebContentsImpl*>(web_contents())->GetView());
1324   DCHECK(wcva);
1325   wcva->SetContentViewCore(NULL);
1326 }
1327 
1328 // 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)1329 jlong Init(JNIEnv* env,
1330            jobject obj,
1331            jlong native_web_contents,
1332            jlong view_android,
1333            jlong window_android,
1334            jobject retained_objects_set) {
1335   ContentViewCoreImpl* view = new ContentViewCoreImpl(
1336       env, obj,
1337       reinterpret_cast<WebContents*>(native_web_contents),
1338       reinterpret_cast<ui::ViewAndroid*>(view_android),
1339       reinterpret_cast<ui::WindowAndroid*>(window_android),
1340       retained_objects_set);
1341   return reinterpret_cast<intptr_t>(view);
1342 }
1343 
RegisterContentViewCore(JNIEnv * env)1344 bool RegisterContentViewCore(JNIEnv* env) {
1345   return RegisterNativesImpl(env);
1346 }
1347 
1348 }  // namespace content
1349