Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / browser / android / content_view_core_impl.cc
blob57c48a2faf5119dca6e67f27d097cf5c84eae37d
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/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "cc/layers/layer.h"
17 #include "cc/layers/solid_color_layer.h"
18 #include "cc/output/begin_frame_args.h"
19 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
20 #include "content/browser/android/gesture_event_type.h"
21 #include "content/browser/android/interstitial_page_delegate_android.h"
22 #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
23 #include "content/browser/android/load_url_params.h"
24 #include "content/browser/android/popup_touch_handle_drawable.h"
25 #include "content/browser/frame_host/interstitial_page_impl.h"
26 #include "content/browser/frame_host/navigation_controller_impl.h"
27 #include "content/browser/frame_host/navigation_entry_impl.h"
28 #include "content/browser/frame_host/render_frame_host_impl.h"
29 #include "content/browser/geolocation/geolocation_dispatcher_host.h"
30 #include "content/browser/media/media_web_contents_observer.h"
31 #include "content/browser/renderer_host/compositor_impl_android.h"
32 #include "content/browser/renderer_host/input/motion_event_android.h"
33 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
34 #include "content/browser/renderer_host/input/web_input_event_util.h"
35 #include "content/browser/renderer_host/render_view_host_impl.h"
36 #include "content/browser/renderer_host/render_widget_host_impl.h"
37 #include "content/browser/renderer_host/render_widget_host_view_android.h"
38 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
39 #include "content/browser/transition_request_manager.h"
40 #include "content/browser/web_contents/web_contents_view_android.h"
41 #include "content/common/frame_messages.h"
42 #include "content/common/input/web_input_event_traits.h"
43 #include "content/common/input_messages.h"
44 #include "content/common/view_messages.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/ssl_host_state_delegate.h"
50 #include "content/public/browser/web_contents.h"
51 #include "content/public/common/content_client.h"
52 #include "content/public/common/content_switches.h"
53 #include "content/public/common/menu_item.h"
54 #include "content/public/common/page_transition_types.h"
55 #include "content/public/common/user_agent.h"
56 #include "jni/ContentViewCore_jni.h"
57 #include "third_party/WebKit/public/web/WebInputEvent.h"
58 #include "ui/base/android/view_android.h"
59 #include "ui/base/android/window_android.h"
60 #include "ui/gfx/android/java_bitmap.h"
61 #include "ui/gfx/screen.h"
62 #include "ui/gfx/size_conversions.h"
63 #include "ui/gfx/size_f.h"
65 using base::android::AttachCurrentThread;
66 using base::android::ConvertJavaStringToUTF16;
67 using base::android::ConvertJavaStringToUTF8;
68 using base::android::ConvertUTF16ToJavaString;
69 using base::android::ConvertUTF8ToJavaString;
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();
275 // Java peer has gone, ContentViewCore is not functional and waits to
276 // be destroyed with WebContents.
277 // We need to reset WebContentsViewAndroid's reference, otherwise, there
278 // could have call in when swapping the WebContents,
279 // see http://crbug.com/383939 .
280 DCHECK(web_contents_);
281 static_cast<WebContentsViewAndroid*>(
282 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
283 SetContentViewCore(NULL);
286 void ContentViewCoreImpl::InitWebContents() {
287 DCHECK(web_contents_);
288 static_cast<WebContentsViewAndroid*>(
289 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
290 SetContentViewCore(this);
291 DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
292 web_contents_->SetUserData(kContentViewUserDataKey,
293 new ContentViewUserData(this));
296 void ContentViewCoreImpl::RenderViewReady() {
297 JNIEnv* env = AttachCurrentThread();
298 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
299 if (!obj.is_null())
300 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
302 if (device_orientation_ != 0)
303 SendOrientationChangeEventInternal();
306 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host,
307 RenderViewHost* new_host) {
308 int old_pid = 0;
309 if (old_host) {
310 old_pid = GetRenderProcessIdFromRenderViewHost(old_host);
312 RenderWidgetHostViewAndroid* view =
313 static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView());
314 if (view)
315 view->SetContentViewCore(NULL);
317 view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView());
318 if (view)
319 view->SetContentViewCore(this);
321 int new_pid = GetRenderProcessIdFromRenderViewHost(
322 web_contents_->GetRenderViewHost());
323 if (new_pid != old_pid) {
324 // Notify the Java side that the renderer process changed.
325 JNIEnv* env = AttachCurrentThread();
326 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
327 if (!obj.is_null()) {
328 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
332 SetFocusInternal(HasFocus());
333 SetAccessibilityEnabledInternal(accessibility_enabled_);
336 RenderWidgetHostViewAndroid*
337 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
338 RenderWidgetHostView* rwhv = NULL;
339 if (web_contents_) {
340 rwhv = web_contents_->GetRenderWidgetHostView();
341 if (web_contents_->ShowingInterstitialPage()) {
342 rwhv = static_cast<InterstitialPageImpl*>(
343 web_contents_->GetInterstitialPage())->
344 GetRenderViewHost()->GetView();
347 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
350 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
351 JNIEnv* env = AttachCurrentThread();
352 return java_ref_.get(env);
355 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
356 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
357 if (!rwhva)
358 return SK_ColorWHITE;
359 return rwhva->GetCachedBackgroundColor();
362 void ContentViewCoreImpl::PauseVideo() {
363 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
364 web_contents_->GetRenderViewHost());
365 if (rvhi)
366 rvhi->media_web_contents_observer()->PauseVideo();
369 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
370 web_contents_->geolocation_dispatcher_host()->PauseOrResume(should_pause);
373 // All positions and sizes are in CSS pixels.
374 // Note that viewport_width/height is a best effort based.
375 // ContentViewCore has the actual information about the physical viewport size.
376 void ContentViewCoreImpl::UpdateFrameInfo(
377 const gfx::Vector2dF& scroll_offset,
378 float page_scale_factor,
379 const gfx::Vector2dF& page_scale_factor_limits,
380 const gfx::SizeF& content_size,
381 const gfx::SizeF& viewport_size,
382 const gfx::Vector2dF& controls_offset,
383 const gfx::Vector2dF& content_offset) {
384 JNIEnv* env = AttachCurrentThread();
385 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
386 if (obj.is_null())
387 return;
389 window_android_->set_content_offset(
390 gfx::ScaleVector2d(content_offset, dpi_scale_));
392 Java_ContentViewCore_updateFrameInfo(
393 env, obj.obj(),
394 scroll_offset.x(),
395 scroll_offset.y(),
396 page_scale_factor,
397 page_scale_factor_limits.x(),
398 page_scale_factor_limits.y(),
399 content_size.width(),
400 content_size.height(),
401 viewport_size.width(),
402 viewport_size.height(),
403 controls_offset.y(),
404 content_offset.y());
407 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
408 JNIEnv* env = AttachCurrentThread();
409 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
410 if (obj.is_null())
411 return;
412 ScopedJavaLocalRef<jstring> jtitle =
413 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
414 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
417 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
418 root_layer_->SetBackgroundColor(color);
420 JNIEnv* env = AttachCurrentThread();
421 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
422 if (obj.is_null())
423 return;
424 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
427 void ContentViewCoreImpl::ShowSelectPopupMenu(
428 RenderFrameHost* frame,
429 const gfx::Rect& bounds,
430 const std::vector<MenuItem>& items,
431 int selected_item,
432 bool multiple) {
433 JNIEnv* env = AttachCurrentThread();
434 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
435 if (j_obj.is_null())
436 return;
438 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
440 // For multi-select list popups we find the list of previous selections by
441 // iterating through the items. But for single selection popups we take the
442 // given |selected_item| as is.
443 ScopedJavaLocalRef<jintArray> selected_array;
444 if (multiple) {
445 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
446 size_t selected_count = 0;
447 for (size_t i = 0; i < items.size(); ++i) {
448 if (items[i].checked)
449 native_selected_array[selected_count++] = i;
452 selected_array = ScopedJavaLocalRef<jintArray>(
453 env, env->NewIntArray(selected_count));
454 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
455 native_selected_array.get());
456 } else {
457 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
458 jint value = selected_item;
459 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
462 ScopedJavaLocalRef<jintArray> enabled_array(env,
463 env->NewIntArray(items.size()));
464 std::vector<base::string16> labels;
465 labels.reserve(items.size());
466 for (size_t i = 0; i < items.size(); ++i) {
467 labels.push_back(items[i].label);
468 jint enabled =
469 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
470 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
471 POPUP_ITEM_TYPE_DISABLED));
472 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
474 ScopedJavaLocalRef<jobjectArray> items_array(
475 base::android::ToJavaArrayOfStrings(env, labels));
476 Java_ContentViewCore_showSelectPopup(env,
477 j_obj.obj(),
478 reinterpret_cast<intptr_t>(frame),
479 bounds_rect.obj(),
480 items_array.obj(),
481 enabled_array.obj(),
482 multiple,
483 selected_array.obj());
486 void ContentViewCoreImpl::HideSelectPopupMenu() {
487 JNIEnv* env = AttachCurrentThread();
488 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
489 if (!j_obj.is_null())
490 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
493 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
494 InputEventAckState ack_result) {
495 JNIEnv* env = AttachCurrentThread();
496 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
497 if (j_obj.is_null())
498 return;
500 switch (event.type) {
501 case WebInputEvent::GestureFlingStart:
502 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
503 // The view expects the fling velocity in pixels/s.
504 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
505 event.data.flingStart.velocityX * dpi_scale(),
506 event.data.flingStart.velocityY * dpi_scale());
507 } else {
508 // If a scroll ends with a fling, a SCROLL_END event is never sent.
509 // However, if that fling went unconsumed, we still need to let the
510 // listeners know that scrolling has ended.
511 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
514 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
515 // The view expects the fling velocity in pixels/s.
516 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
517 event.data.flingStart.velocityX * dpi_scale(),
518 event.data.flingStart.velocityY * dpi_scale());
520 break;
521 case WebInputEvent::GestureFlingCancel:
522 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
523 break;
524 case WebInputEvent::GestureScrollBegin:
525 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
526 break;
527 case WebInputEvent::GestureScrollUpdate:
528 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
529 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
530 break;
531 case WebInputEvent::GestureScrollEnd:
532 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
533 break;
534 case WebInputEvent::GesturePinchBegin:
535 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
536 break;
537 case WebInputEvent::GesturePinchEnd:
538 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
539 break;
540 case WebInputEvent::GestureTap:
541 Java_ContentViewCore_onSingleTapEventAck(
542 env,
543 j_obj.obj(),
544 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
545 event.x * dpi_scale(),
546 event.y * dpi_scale());
547 break;
548 default:
549 break;
553 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
554 if (event.type != WebInputEvent::GestureTap &&
555 event.type != WebInputEvent::GestureDoubleTap &&
556 event.type != WebInputEvent::GestureLongTap &&
557 event.type != WebInputEvent::GestureLongPress)
558 return false;
560 JNIEnv* env = AttachCurrentThread();
561 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
562 if (j_obj.is_null())
563 return false;
565 const blink::WebGestureEvent& gesture =
566 static_cast<const blink::WebGestureEvent&>(event);
567 int gesture_type = ToGestureEventType(event.type);
568 return Java_ContentViewCore_filterTapOrPressEvent(env,
569 j_obj.obj(),
570 gesture_type,
571 gesture.x * dpi_scale(),
572 gesture.y * dpi_scale());
574 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
577 bool ContentViewCoreImpl::HasFocus() {
578 JNIEnv* env = AttachCurrentThread();
579 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
580 if (obj.is_null())
581 return false;
582 return Java_ContentViewCore_hasFocus(env, obj.obj());
585 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
586 JNIEnv* env = AttachCurrentThread();
587 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
588 if (obj.is_null())
589 return;
590 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
591 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
594 void ContentViewCoreImpl::OnSelectionEvent(SelectionEventType event,
595 const gfx::PointF& position) {
596 JNIEnv* env = AttachCurrentThread();
597 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
598 if (j_obj.is_null())
599 return;
600 Java_ContentViewCore_onSelectionEvent(
601 env, j_obj.obj(), event, position.x(), position.y());
604 scoped_ptr<TouchHandleDrawable>
605 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
606 JNIEnv* env = AttachCurrentThread();
607 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
608 if (obj.is_null()) {
609 NOTREACHED();
610 return scoped_ptr<TouchHandleDrawable>();
612 return scoped_ptr<TouchHandleDrawable>(new PopupTouchHandleDrawable(
613 Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()),
614 dpi_scale_));
617 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
618 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
619 if (!view)
620 return;
622 view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
624 JNIEnv* env = AttachCurrentThread();
625 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
626 if (obj.is_null())
627 return;
628 Java_ContentViewCore_showPastePopupWithFeedback(env, obj.obj(),
629 static_cast<jint>(x_dip),
630 static_cast<jint>(y_dip));
633 void ContentViewCoreImpl::GetScaledContentBitmap(
634 float scale,
635 SkColorType color_type,
636 gfx::Rect src_subrect,
637 const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
638 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
639 if (!view) {
640 result_callback.Run(false, SkBitmap());
641 return;
644 view->GetScaledContentBitmap(scale, color_type, src_subrect,
645 result_callback);
648 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
649 JNIEnv* env = AttachCurrentThread();
650 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
651 if (j_obj.is_null())
652 return;
653 ScopedJavaLocalRef<jstring> jcontent_url =
654 ConvertUTF8ToJavaString(env, content_url.spec());
655 Java_ContentViewCore_startContentIntent(env,
656 j_obj.obj(),
657 jcontent_url.obj());
660 void ContentViewCoreImpl::ShowDisambiguationPopup(
661 const gfx::Rect& target_rect,
662 const SkBitmap& zoomed_bitmap) {
663 JNIEnv* env = AttachCurrentThread();
665 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
666 if (obj.is_null())
667 return;
669 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, target_rect));
671 ScopedJavaLocalRef<jobject> java_bitmap =
672 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
673 DCHECK(!java_bitmap.is_null());
675 Java_ContentViewCore_showDisambiguationPopup(env,
676 obj.obj(),
677 rect_object.obj(),
678 java_bitmap.obj());
681 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
682 JNIEnv* env = AttachCurrentThread();
684 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
685 if (obj.is_null())
686 return ScopedJavaLocalRef<jobject>();
687 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
690 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
691 JNIEnv* env = AttachCurrentThread();
693 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
694 if (obj.is_null())
695 return ScopedJavaLocalRef<jobject>();
697 return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
700 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
701 JNIEnv* env = AttachCurrentThread();
703 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
704 if (obj.is_null())
705 return ScopedJavaLocalRef<jobject>();
707 return Java_ContentViewCore_getContext(env, obj.obj());
710 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
711 JNIEnv* env = AttachCurrentThread();
713 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
714 if (obj.is_null())
715 return true;
716 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
717 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
718 j_url.obj());
721 void ContentViewCoreImpl::DidStopFlinging() {
722 JNIEnv* env = AttachCurrentThread();
724 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
725 if (!obj.is_null())
726 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
729 gfx::Size ContentViewCoreImpl::GetViewSize() const {
730 gfx::Size size = GetViewportSizeDip();
731 size.Enlarge(0, -GetTopControlsLayoutHeightDip());
732 return size;
735 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
736 JNIEnv* env = AttachCurrentThread();
737 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
738 if (j_obj.is_null())
739 return gfx::Size();
740 return gfx::Size(
741 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
742 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
745 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
746 JNIEnv* env = AttachCurrentThread();
747 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
748 if (j_obj.is_null())
749 return gfx::Size();
750 return gfx::Size(
751 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
752 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
755 int ContentViewCoreImpl::GetTopControlsLayoutHeightPix() const {
756 JNIEnv* env = AttachCurrentThread();
757 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
758 if (j_obj.is_null())
759 return 0;
760 return Java_ContentViewCore_getTopControlsLayoutHeightPix(env, j_obj.obj());
763 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
764 return gfx::ToCeiledSize(
765 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
768 float ContentViewCoreImpl::GetTopControlsLayoutHeightDip() const {
769 return GetTopControlsLayoutHeightPix() / dpi_scale();
772 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
773 root_layer_->InsertChild(layer, 0);
774 root_layer_->SetIsDrawable(false);
777 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
778 layer->RemoveFromParent();
780 if (!root_layer_->children().size())
781 root_layer_->SetIsDrawable(true);
784 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& start,
785 const gfx::PointF& end) {
786 if (!web_contents_)
787 return;
789 gfx::Point start_point = gfx::Point(start.x(), start.y());
790 gfx::Point end_point = gfx::Point(end.x(), end.y());
791 if (start_point == end_point)
792 return;
794 web_contents_->SelectRange(start_point, end_point);
797 void ContentViewCoreImpl::LoadUrl(
798 NavigationController::LoadURLParams& params) {
799 GetWebContents()->GetController().LoadURLWithParams(params);
802 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
803 return view_android_;
806 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
807 return window_android_;
810 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
811 return root_layer_.get();
814 // ----------------------------------------------------------------------------
815 // Methods called from Java via JNI
816 // ----------------------------------------------------------------------------
818 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
819 jobject obj,
820 jlong selectPopupSourceFrame,
821 jintArray indices) {
822 RenderFrameHostImpl* rfhi =
823 reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
824 DCHECK(rfhi);
825 if (indices == NULL) {
826 rfhi->DidCancelPopupMenu();
827 return;
830 int selected_count = env->GetArrayLength(indices);
831 std::vector<int> selected_indices;
832 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
833 for (int i = 0; i < selected_count; ++i)
834 selected_indices.push_back(indices_ptr[i]);
835 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
836 rfhi->DidSelectPopupMenuItems(selected_indices);
839 void ContentViewCoreImpl::LoadUrl(
840 JNIEnv* env, jobject obj,
841 jstring url,
842 jint load_url_type,
843 jint transition_type,
844 jstring j_referrer_url,
845 jint referrer_policy,
846 jint ua_override_option,
847 jstring extra_headers,
848 jbyteArray post_data,
849 jstring base_url_for_data_url,
850 jstring virtual_url_for_data_url,
851 jboolean can_load_local_resources,
852 jboolean is_renderer_initiated) {
853 DCHECK(url);
854 NavigationController::LoadURLParams params(
855 GURL(ConvertJavaStringToUTF8(env, url)));
857 params.load_type = static_cast<NavigationController::LoadURLType>(
858 load_url_type);
859 params.transition_type = PageTransitionFromInt(transition_type);
860 params.override_user_agent =
861 static_cast<NavigationController::UserAgentOverrideOption>(
862 ua_override_option);
864 if (extra_headers)
865 params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
867 if (post_data) {
868 std::vector<uint8> http_body_vector;
869 base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
870 params.browser_initiated_post_data =
871 base::RefCountedBytes::TakeVector(&http_body_vector);
874 if (base_url_for_data_url) {
875 params.base_url_for_data_url =
876 GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
879 if (virtual_url_for_data_url) {
880 params.virtual_url_for_data_url =
881 GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
884 params.can_load_local_resources = can_load_local_resources;
885 if (j_referrer_url) {
886 params.referrer = content::Referrer(
887 GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
888 static_cast<blink::WebReferrerPolicy>(referrer_policy));
891 params.is_renderer_initiated = is_renderer_initiated;
893 LoadUrl(params);
896 WebContents* ContentViewCoreImpl::GetWebContents() const {
897 return web_contents_;
900 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
901 SetFocusInternal(focused);
904 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
905 if (!GetRenderWidgetHostViewAndroid())
906 return;
908 if (focused)
909 GetRenderWidgetHostViewAndroid()->Focus();
910 else
911 GetRenderWidgetHostViewAndroid()->Blur();
914 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
915 jobject obj,
916 jint orientation) {
917 if (device_orientation_ != orientation) {
918 device_orientation_ = orientation;
919 SendOrientationChangeEventInternal();
923 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
924 jobject obj,
925 jobject motion_event,
926 jlong time_ms,
927 jint android_action,
928 jint pointer_count,
929 jint history_size,
930 jint action_index,
931 jfloat pos_x_0,
932 jfloat pos_y_0,
933 jfloat pos_x_1,
934 jfloat pos_y_1,
935 jint pointer_id_0,
936 jint pointer_id_1,
937 jfloat touch_major_0,
938 jfloat touch_major_1,
939 jfloat raw_pos_x,
940 jfloat raw_pos_y,
941 jint android_tool_type_0,
942 jint android_tool_type_1,
943 jint android_button_state,
944 jboolean is_touch_handle_event) {
945 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
946 // Avoid synthesizing a touch event if it cannot be forwarded.
947 if (!rwhv)
948 return false;
950 MotionEventAndroid event(1.f / dpi_scale(),
951 env,
952 motion_event,
953 time_ms,
954 android_action,
955 pointer_count,
956 history_size,
957 action_index,
958 pos_x_0,
959 pos_y_0,
960 pos_x_1,
961 pos_y_1,
962 pointer_id_0,
963 pointer_id_1,
964 touch_major_0,
965 touch_major_1,
966 raw_pos_x,
967 raw_pos_y,
968 android_tool_type_0,
969 android_tool_type_1,
970 android_button_state);
972 return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
973 : rwhv->OnTouchEvent(event);
976 float ContentViewCoreImpl::GetDpiScale() const {
977 return dpi_scale_;
980 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
981 jobject obj,
982 jlong time_ms,
983 jfloat x,
984 jfloat y) {
985 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
986 if (!rwhv)
987 return false;
989 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
990 WebInputEvent::MouseMove,
991 blink::WebMouseEvent::ButtonNone,
992 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
994 rwhv->SendMouseEvent(event);
995 return true;
998 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
999 jobject obj,
1000 jlong time_ms,
1001 jfloat x,
1002 jfloat y,
1003 jfloat vertical_axis) {
1004 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1005 if (!rwhv)
1006 return false;
1008 WebMouseWheelEventBuilder::Direction direction;
1009 if (vertical_axis > 0) {
1010 direction = WebMouseWheelEventBuilder::DIRECTION_UP;
1011 } else if (vertical_axis < 0) {
1012 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
1013 } else {
1014 return false;
1016 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
1017 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1019 rwhv->SendMouseWheelEvent(event);
1020 return true;
1023 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
1024 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
1025 return WebGestureEventBuilder::Build(
1026 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1029 void ContentViewCoreImpl::SendGestureEvent(
1030 const blink::WebGestureEvent& event) {
1031 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1032 if (rwhv)
1033 rwhv->SendGestureEvent(event);
1036 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
1037 jobject obj,
1038 jlong time_ms,
1039 jfloat x,
1040 jfloat y,
1041 jfloat hintx,
1042 jfloat hinty) {
1043 WebGestureEvent event = MakeGestureEvent(
1044 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1045 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1046 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1048 SendGestureEvent(event);
1051 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1052 WebGestureEvent event = MakeGestureEvent(
1053 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1054 SendGestureEvent(event);
1057 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1058 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1059 WebGestureEvent event = MakeGestureEvent(
1060 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1061 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1062 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1064 SendGestureEvent(event);
1067 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1068 jfloat x, jfloat y, jfloat vx, jfloat vy) {
1069 WebGestureEvent event = MakeGestureEvent(
1070 WebInputEvent::GestureFlingStart, time_ms, x, y);
1071 event.data.flingStart.velocityX = vx / dpi_scale();
1072 event.data.flingStart.velocityY = vy / dpi_scale();
1074 SendGestureEvent(event);
1077 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1078 WebGestureEvent event = MakeGestureEvent(
1079 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1080 SendGestureEvent(event);
1083 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1084 jfloat x, jfloat y) {
1085 WebGestureEvent event = MakeGestureEvent(
1086 WebInputEvent::GestureTap, time_ms, x, y);
1087 event.data.tap.tapCount = 1;
1089 SendGestureEvent(event);
1092 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1093 jfloat x, jfloat y) {
1094 WebGestureEvent event = MakeGestureEvent(
1095 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1096 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1097 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1098 event.data.tap.tapCount = 1;
1100 SendGestureEvent(event);
1103 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1104 jfloat x, jfloat y) {
1105 WebGestureEvent event = MakeGestureEvent(
1106 WebInputEvent::GestureLongPress, time_ms, x, y);
1108 SendGestureEvent(event);
1111 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1112 jfloat x, jfloat y) {
1113 WebGestureEvent event = MakeGestureEvent(
1114 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1115 SendGestureEvent(event);
1118 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1119 WebGestureEvent event = MakeGestureEvent(
1120 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1121 SendGestureEvent(event);
1124 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1125 jfloat anchor_x, jfloat anchor_y,
1126 jfloat delta) {
1127 WebGestureEvent event = MakeGestureEvent(
1128 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1129 event.data.pinchUpdate.scale = delta;
1131 SendGestureEvent(event);
1134 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1135 jfloat x1, jfloat y1,
1136 jfloat x2, jfloat y2) {
1137 SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
1138 gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
1141 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1142 jfloat x, jfloat y) {
1143 if (GetRenderWidgetHostViewAndroid()) {
1144 GetRenderWidgetHostViewAndroid()->MoveCaret(
1145 gfx::Point(x / dpi_scale_, y / dpi_scale_));
1149 void ContentViewCoreImpl::HideTextHandles(JNIEnv* env, jobject obj) {
1150 if (GetRenderWidgetHostViewAndroid())
1151 GetRenderWidgetHostViewAndroid()->HideTextHandles();
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::SetAllowJavascriptInterfacesInspection(
1183 JNIEnv* env,
1184 jobject obj,
1185 jboolean allow) {
1186 java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
1189 void ContentViewCoreImpl::AddJavascriptInterface(
1190 JNIEnv* env,
1191 jobject /* obj */,
1192 jobject object,
1193 jstring name,
1194 jclass safe_annotation_clazz) {
1195 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1196 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1197 java_bridge_dispatcher_host_->AddNamedObject(
1198 ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
1201 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1202 jobject /* obj */,
1203 jstring name) {
1204 java_bridge_dispatcher_host_->RemoveNamedObject(
1205 ConvertJavaStringToUTF8(env, name));
1208 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1209 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1210 gfx::Size physical_size(
1211 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1212 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1213 root_layer_->SetBounds(physical_size);
1215 if (view) {
1216 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1217 view->GetRenderWidgetHost());
1218 host->SendScreenRects();
1219 view->WasResized();
1223 namespace {
1225 static void AddNavigationEntryToHistory(JNIEnv* env, jobject obj,
1226 jobject history,
1227 NavigationEntry* entry,
1228 int index) {
1229 // Get the details of the current entry
1230 ScopedJavaLocalRef<jstring> j_url(
1231 ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
1232 ScopedJavaLocalRef<jstring> j_virtual_url(
1233 ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
1234 ScopedJavaLocalRef<jstring> j_original_url(
1235 ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
1236 ScopedJavaLocalRef<jstring> j_title(
1237 ConvertUTF16ToJavaString(env, entry->GetTitle()));
1238 ScopedJavaLocalRef<jobject> j_bitmap;
1239 const FaviconStatus& status = entry->GetFavicon();
1240 if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
1241 j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
1243 // Add the item to the list
1244 Java_ContentViewCore_addToNavigationHistory(
1245 env, obj, history, index, j_url.obj(), j_virtual_url.obj(),
1246 j_original_url.obj(), j_title.obj(), j_bitmap.obj());
1249 } // namespace
1251 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env,
1252 jobject obj,
1253 jobject history) {
1254 // Iterate through navigation entries to populate the list
1255 const NavigationController& controller = web_contents_->GetController();
1256 int count = controller.GetEntryCount();
1257 for (int i = 0; i < count; ++i) {
1258 AddNavigationEntryToHistory(
1259 env, obj, history, controller.GetEntryAtIndex(i), i);
1262 return controller.GetCurrentEntryIndex();
1265 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv* env,
1266 jobject obj,
1267 jobject history,
1268 jboolean is_forward,
1269 jint max_entries) {
1270 // Iterate through navigation entries to populate the list
1271 const NavigationController& controller = web_contents_->GetController();
1272 int count = controller.GetEntryCount();
1273 int num_added = 0;
1274 int increment_value = is_forward ? 1 : -1;
1275 for (int i = controller.GetCurrentEntryIndex() + increment_value;
1276 i >= 0 && i < count;
1277 i += increment_value) {
1278 if (num_added >= max_entries)
1279 break;
1281 AddNavigationEntryToHistory(
1282 env, obj, history, controller.GetEntryAtIndex(i), i);
1283 num_added++;
1287 ScopedJavaLocalRef<jstring>
1288 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv* env,
1289 jobject obj) {
1290 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1291 if (entry == NULL)
1292 return ScopedJavaLocalRef<jstring>(env, NULL);
1293 return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
1296 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1297 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1298 if (!rwhva)
1299 return 0;
1300 return rwhva->GetNativeImeAdapter();
1303 // TODO(sgurun) add support for posting a frame whose name is known (only
1304 // main frame is supported at this time, see crbug.com/389721)
1305 // TODO(sgurun) add support for passing message ports
1306 void ContentViewCoreImpl::PostMessageToFrame(JNIEnv* env, jobject obj,
1307 jstring frame_name, jstring message, jstring source_origin,
1308 jstring target_origin) {
1310 RenderViewHost* host = web_contents_->GetRenderViewHost();
1311 if (!host)
1312 return;
1313 ViewMsg_PostMessage_Params params;
1314 params.source_origin = ConvertJavaStringToUTF16(env, source_origin);
1315 params.target_origin = ConvertJavaStringToUTF16(env, target_origin);
1316 params.data = ConvertJavaStringToUTF16(env, message);
1317 params.is_data_raw_string = true;
1318 params.source_routing_id = MSG_ROUTING_NONE;
1319 host->Send(new ViewMsg_PostMessageEvent(host->GetRoutingID(), params));
1323 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
1324 JNIEnv* env, jobject obj) {
1325 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1326 return entry && entry->GetIsOverridingUserAgent();
1329 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1330 int text_input_type,
1331 int text_input_flags,
1332 const std::string& text,
1333 int selection_start,
1334 int selection_end,
1335 int composition_start,
1336 int composition_end,
1337 bool show_ime_if_needed,
1338 bool is_non_ime_change) {
1339 JNIEnv* env = AttachCurrentThread();
1340 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1341 if (obj.is_null())
1342 return;
1344 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1345 Java_ContentViewCore_updateImeAdapter(env,
1346 obj.obj(),
1347 native_ime_adapter,
1348 text_input_type,
1349 text_input_flags,
1350 jstring_text.obj(),
1351 selection_start,
1352 selection_end,
1353 composition_start,
1354 composition_end,
1355 show_ime_if_needed,
1356 is_non_ime_change);
1359 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv* env, jobject obj) {
1360 content::SSLHostStateDelegate* delegate =
1361 web_contents_->
1362 GetController().
1363 GetBrowserContext()->
1364 GetSSLHostStateDelegate();
1365 if (delegate)
1366 delegate->Clear();
1369 void ContentViewCoreImpl::SetUseDesktopUserAgent(
1370 JNIEnv* env,
1371 jobject obj,
1372 jboolean enabled,
1373 jboolean reload_on_state_change) {
1374 if (GetUseDesktopUserAgent(env, obj) == enabled)
1375 return;
1377 // Make sure the navigation entry actually exists.
1378 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1379 if (!entry)
1380 return;
1382 // Set the flag in the NavigationEntry.
1383 entry->SetIsOverridingUserAgent(enabled);
1385 // Send the override to the renderer.
1386 if (reload_on_state_change) {
1387 // Reloading the page will send the override down as part of the
1388 // navigation IPC message.
1389 NavigationControllerImpl& controller =
1390 static_cast<NavigationControllerImpl&>(web_contents_->GetController());
1391 controller.ReloadOriginalRequestURL(false);
1395 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1396 bool enabled) {
1397 SetAccessibilityEnabledInternal(enabled);
1400 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
1401 JNIEnv* env = AttachCurrentThread();
1402 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1403 if (obj.is_null())
1404 return true;
1405 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
1406 obj.obj());
1409 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1410 accessibility_enabled_ = enabled;
1411 BrowserAccessibilityStateImpl* accessibility_state =
1412 BrowserAccessibilityStateImpl::GetInstance();
1413 if (enabled) {
1414 // This enables accessibility globally unless it was explicitly disallowed
1415 // by a command-line flag.
1416 accessibility_state->OnScreenReaderDetected();
1417 // If it was actually enabled globally, enable it for this RenderWidget now.
1418 if (accessibility_state->IsAccessibleBrowser() && web_contents_)
1419 web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
1420 } else {
1421 accessibility_state->ResetAccessibilityMode();
1422 if (web_contents_) {
1423 web_contents_->SetAccessibilityMode(
1424 accessibility_state->accessibility_mode());
1429 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1430 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1431 if (rwhv)
1432 rwhv->UpdateScreenInfo(GetViewAndroid());
1434 static_cast<WebContentsImpl*>(web_contents())->
1435 screen_orientation_dispatcher_host()->OnOrientationChange();
1438 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1439 jobject obj,
1440 jint x,
1441 jint y,
1442 jint width,
1443 jint height) {
1444 gfx::Rect rect(
1445 static_cast<int>(x / dpi_scale()),
1446 static_cast<int>(y / dpi_scale()),
1447 static_cast<int>((width > 0 && width < dpi_scale()) ?
1448 1 : (int)(width / dpi_scale())),
1449 static_cast<int>((height > 0 && height < dpi_scale()) ?
1450 1 : (int)(height / dpi_scale())));
1451 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1452 GetWebContents()->GetRoutingID(), rect));
1455 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1456 return GetRenderProcessIdFromRenderViewHost(
1457 web_contents_->GetRenderViewHost());
1460 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1461 jboolean opaque) {
1462 if (GetRenderWidgetHostViewAndroid())
1463 GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque);
1466 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1467 int max_length,
1468 const base::Callback<
1469 void(const base::string16& content, int start_offset, int end_offset)>&
1470 callback) {
1471 DCHECK(!callback.is_null());
1472 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1473 if (!focused_frame)
1474 return;
1475 if (GetRenderWidgetHostViewAndroid()) {
1476 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1477 callback);
1478 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1479 focused_frame->GetRoutingID(), max_length));
1483 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1484 const base::string16& text,
1485 const base::string16& html,
1486 const gfx::Rect& clip_rect) {
1487 JNIEnv* env = AttachCurrentThread();
1488 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1489 if (obj.is_null())
1490 return;
1491 ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
1492 ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
1493 ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
1494 Java_ContentViewCore_onSmartClipDataExtracted(
1495 env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
1498 void ContentViewCoreImpl::WebContentsDestroyed() {
1499 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1500 static_cast<WebContentsImpl*>(web_contents())->GetView());
1501 DCHECK(wcva);
1502 wcva->SetContentViewCore(NULL);
1505 // This is called for each ContentView.
1506 jlong Init(JNIEnv* env,
1507 jobject obj,
1508 jlong native_web_contents,
1509 jlong view_android,
1510 jlong window_android,
1511 jobject retained_objects_set) {
1512 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1513 env, obj,
1514 reinterpret_cast<WebContents*>(native_web_contents),
1515 reinterpret_cast<ui::ViewAndroid*>(view_android),
1516 reinterpret_cast<ui::WindowAndroid*>(window_android),
1517 retained_objects_set);
1518 return reinterpret_cast<intptr_t>(view);
1521 bool RegisterContentViewCore(JNIEnv* env) {
1522 return RegisterNativesImpl(env);
1525 } // namespace content