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