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