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