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/output/begin_frame_args.h"
19 #include "content/browser/android/gesture_event_type.h"
20 #include "content/browser/android/interstitial_page_delegate_android.h"
21 #include "content/browser/android/load_url_params.h"
22 #include "content/browser/frame_host/interstitial_page_impl.h"
23 #include "content/browser/frame_host/navigation_controller_impl.h"
24 #include "content/browser/frame_host/navigation_entry_impl.h"
25 #include "content/browser/media/android/browser_media_player_manager.h"
26 #include "content/browser/renderer_host/compositor_impl_android.h"
27 #include "content/browser/renderer_host/input/motion_event_android.h"
28 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
29 #include "content/browser/renderer_host/input/web_input_event_util.h"
30 #include "content/browser/renderer_host/java/java_bound_object.h"
31 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
32 #include "content/browser/renderer_host/render_view_host_impl.h"
33 #include "content/browser/renderer_host/render_widget_host_impl.h"
34 #include "content/browser/renderer_host/render_widget_host_view_android.h"
35 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
36 #include "content/browser/ssl/ssl_host_state.h"
37 #include "content/browser/web_contents/web_contents_view_android.h"
38 #include "content/common/input/web_input_event_traits.h"
39 #include "content/common/input_messages.h"
40 #include "content/common/view_messages.h"
41 #include "content/public/browser/android/external_video_surface_container.h"
42 #include "content/public/browser/browser_accessibility_state.h"
43 #include "content/public/browser/browser_context.h"
44 #include "content/public/browser/favicon_status.h"
45 #include "content/public/browser/notification_details.h"
46 #include "content/public/browser/notification_service.h"
47 #include "content/public/browser/notification_source.h"
48 #include "content/public/browser/notification_types.h"
49 #include "content/public/browser/render_frame_host.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/WebBindings.h"
58 #include "third_party/WebKit/public/web/WebInputEvent.h"
59 #include "ui/base/android/view_android.h"
60 #include "ui/base/android/window_android.h"
61 #include "ui/events/gesture_detection/gesture_config_helper.h"
62 #include "ui/gfx/android/java_bitmap.h"
63 #include "ui/gfx/screen.h"
64 #include "ui/gfx/size_conversions.h"
65 #include "ui/gfx/size_f.h"
67 using base::android::AttachCurrentThread;
68 using base::android::ConvertJavaStringToUTF16;
69 using base::android::ConvertJavaStringToUTF8;
70 using base::android::ConvertUTF16ToJavaString;
71 using base::android::ConvertUTF8ToJavaString;
72 using base::android::ScopedJavaGlobalRef;
73 using base::android::ScopedJavaLocalRef;
74 using blink::WebGestureEvent;
75 using blink::WebInputEvent;
77 // Describes the type and enabled state of a select popup item.
81 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
82 #include "content/browser/android/popup_item_type_list.h"
83 #undef DEFINE_POPUP_ITEM_TYPE
92 const unsigned int kDefaultVSyncIntervalMicros = 16666u;
93 // TODO(brianderson): Use adaptive draw-time estimation.
94 const float kDefaultBrowserCompositeVSyncFraction = 1.0f / 3;
96 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
98 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
100 RenderProcessHost* render_process = host->GetProcess();
101 DCHECK(render_process);
102 if (render_process->HasConnection())
103 return render_process->GetHandle();
108 ScopedJavaLocalRef<jobject> CreateJavaRect(
110 const gfx::Rect& rect) {
111 return ScopedJavaLocalRef<jobject>(
112 Java_ContentViewCore_createRect(env,
113 static_cast<int>(rect.x()),
114 static_cast<int>(rect.y()),
115 static_cast<int>(rect.right()),
116 static_cast<int>(rect.bottom())));
119 int ToGestureEventType(WebInputEvent::Type type) {
121 case WebInputEvent::GestureScrollBegin:
123 case WebInputEvent::GestureScrollEnd:
125 case WebInputEvent::GestureScrollUpdate:
127 case WebInputEvent::GestureFlingStart:
129 case WebInputEvent::GestureFlingCancel:
131 case WebInputEvent::GestureShowPress:
133 case WebInputEvent::GestureTap:
134 return SINGLE_TAP_CONFIRMED;
135 case WebInputEvent::GestureTapUnconfirmed:
136 return SINGLE_TAP_UNCONFIRMED;
137 case WebInputEvent::GestureTapDown:
139 case WebInputEvent::GestureTapCancel:
141 case WebInputEvent::GestureDoubleTap:
143 case WebInputEvent::GestureLongPress:
145 case WebInputEvent::GestureLongTap:
147 case WebInputEvent::GesturePinchBegin:
149 case WebInputEvent::GesturePinchEnd:
151 case WebInputEvent::GesturePinchUpdate:
153 case WebInputEvent::GestureTwoFingerTap:
154 case WebInputEvent::GestureScrollUpdateWithoutPropagation:
156 NOTREACHED() << "Invalid source gesture type: "
157 << WebInputEventTraits::GetName(type);
162 float GetPrimaryDisplayDeviceScaleFactor() {
163 const gfx::Display& display =
164 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
165 return display.device_scale_factor();
168 ui::GestureProvider::Config GetGestureProviderConfig() {
169 ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig();
170 config.disable_click_delay =
171 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableClickDelay);
177 // Enables a callback when the underlying WebContents is destroyed, to enable
178 // nulling the back-pointer.
179 class ContentViewCoreImpl::ContentViewUserData
180 : public base::SupportsUserData::Data {
182 explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
183 : content_view_core_(content_view_core) {
186 virtual ~ContentViewUserData() {
187 // TODO(joth): When chrome has finished removing the TabContents class (see
188 // crbug.com/107201) consider inverting relationship, so ContentViewCore
189 // would own WebContents. That effectively implies making the WebContents
190 // destructor private on Android.
191 delete content_view_core_;
194 ContentViewCoreImpl* get() const { return content_view_core_; }
197 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
198 ContentViewCoreImpl* content_view_core_;
200 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
204 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
205 content::WebContents* web_contents) {
206 ContentViewCoreImpl::ContentViewUserData* data =
207 reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
208 web_contents->GetUserData(kContentViewUserDataKey));
209 return data ? data->get() : NULL;
213 ContentViewCore* ContentViewCore::FromWebContents(
214 content::WebContents* web_contents) {
215 return ContentViewCoreImpl::FromWebContents(web_contents);
219 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
221 return reinterpret_cast<ContentViewCore*>(
222 Java_ContentViewCore_getNativeContentViewCore(env, obj));
225 ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env,
227 WebContents* web_contents,
228 ui::ViewAndroid* view_android,
229 ui::WindowAndroid* window_android)
230 : WebContentsObserver(web_contents),
232 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
233 root_layer_(cc::Layer::Create()),
234 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
235 vsync_interval_(base::TimeDelta::FromMicroseconds(
236 kDefaultVSyncIntervalMicros)),
237 expected_browser_composite_time_(base::TimeDelta::FromMicroseconds(
238 kDefaultVSyncIntervalMicros * kDefaultBrowserCompositeVSyncFraction)),
239 view_android_(view_android),
240 window_android_(window_android),
241 gesture_provider_(GetGestureProviderConfig(), this),
242 device_orientation_(0),
243 geolocation_needs_pause_(false) {
244 CHECK(web_contents) <<
245 "A ContentViewCoreImpl should be created with a valid WebContents.";
247 // Currently, the only use case we have for overriding a user agent involves
248 // spoofing a desktop Linux user agent for "Request desktop site".
249 // Automatically set it for all WebContents so that it is available when a
250 // NavigationEntry requires the user agent to be overridden.
251 const char kLinuxInfoStr[] = "X11; Linux x86_64";
252 std::string product = content::GetContentClient()->GetProduct();
253 std::string spoofed_ua =
254 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
255 web_contents->SetUserAgentOverride(spoofed_ua);
260 ContentViewCoreImpl::~ContentViewCoreImpl() {
261 JNIEnv* env = base::android::AttachCurrentThread();
262 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
264 if (!j_obj.is_null()) {
265 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
266 env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
268 // Make sure nobody calls back into this object while we are tearing things
270 notification_registrar_.RemoveAll();
273 base::android::ScopedJavaLocalRef<jobject>
274 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
275 return web_contents_->GetJavaWebContents();
278 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
280 DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
284 void ContentViewCoreImpl::InitWebContents() {
285 DCHECK(web_contents_);
286 notification_registrar_.Add(
287 this, NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
288 Source<WebContents>(web_contents_));
289 notification_registrar_.Add(
290 this, NOTIFICATION_RENDERER_PROCESS_CREATED,
291 content::NotificationService::AllBrowserContextsAndSources());
292 notification_registrar_.Add(
293 this, NOTIFICATION_WEB_CONTENTS_CONNECTED,
294 Source<WebContents>(web_contents_));
296 static_cast<WebContentsViewAndroid*>(web_contents_->GetView())->
297 SetContentViewCore(this);
298 DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
299 web_contents_->SetUserData(kContentViewUserDataKey,
300 new ContentViewUserData(this));
303 void ContentViewCoreImpl::Observe(int type,
304 const NotificationSource& source,
305 const NotificationDetails& details) {
307 case NOTIFICATION_RENDER_VIEW_HOST_CHANGED: {
308 std::pair<RenderViewHost*, RenderViewHost*>* switched_details =
309 Details<std::pair<RenderViewHost*, RenderViewHost*> >(details).ptr();
311 if (switched_details->first) {
312 old_pid = GetRenderProcessIdFromRenderViewHost(
313 switched_details->first);
315 RenderWidgetHostViewAndroid* view =
316 static_cast<RenderWidgetHostViewAndroid*>(
317 switched_details->first->GetView());
319 view->SetContentViewCore(NULL);
321 view = static_cast<RenderWidgetHostViewAndroid*>(
322 switched_details->second->GetView());
325 view->SetContentViewCore(this);
327 int new_pid = GetRenderProcessIdFromRenderViewHost(
328 web_contents_->GetRenderViewHost());
329 if (new_pid != old_pid) {
330 // Notify the Java side of the change of the current renderer process.
331 JNIEnv* env = AttachCurrentThread();
332 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
333 if (!obj.is_null()) {
334 Java_ContentViewCore_onRenderProcessSwap(
335 env, obj.obj(), old_pid, new_pid);
338 SetFocusInternal(HasFocus());
339 if (geolocation_needs_pause_)
340 PauseOrResumeGeolocation(true);
343 case NOTIFICATION_RENDERER_PROCESS_CREATED: {
344 // Notify the Java side of the current renderer process.
345 RenderProcessHost* source_process_host =
346 Source<RenderProcessHost>(source).ptr();
347 RenderProcessHost* current_process_host =
348 web_contents_->GetRenderViewHost()->GetProcess();
350 if (source_process_host == current_process_host) {
351 int pid = GetRenderProcessIdFromRenderViewHost(
352 web_contents_->GetRenderViewHost());
353 JNIEnv* env = AttachCurrentThread();
354 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
355 if (!obj.is_null()) {
356 Java_ContentViewCore_onRenderProcessSwap(env, obj.obj(), 0, pid);
361 case NOTIFICATION_WEB_CONTENTS_CONNECTED: {
362 JNIEnv* env = AttachCurrentThread();
363 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
364 if (!obj.is_null()) {
365 Java_ContentViewCore_onWebContentsConnected(env, obj.obj());
372 void ContentViewCoreImpl::RenderViewReady() {
373 if (device_orientation_ != 0)
374 SendOrientationChangeEventInternal();
377 void ContentViewCoreImpl::OnGestureEvent(const ui::GestureEventData& gesture) {
379 CreateWebGestureEventFromGestureEventData(gesture, 1.f / dpi_scale()));
382 RenderWidgetHostViewAndroid*
383 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
384 RenderWidgetHostView* rwhv = NULL;
386 rwhv = web_contents_->GetRenderWidgetHostView();
387 if (web_contents_->ShowingInterstitialPage()) {
388 rwhv = static_cast<InterstitialPageImpl*>(
389 web_contents_->GetInterstitialPage())->
390 GetRenderViewHost()->GetView();
393 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
396 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
397 JNIEnv* env = AttachCurrentThread();
398 return java_ref_.get(env);
401 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
402 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
404 return SK_ColorWHITE;
405 return rwhva->GetCachedBackgroundColor();
408 void ContentViewCoreImpl::OnHide(JNIEnv* env, jobject obj) {
412 void ContentViewCoreImpl::OnShow(JNIEnv* env, jobject obj) {
416 void ContentViewCoreImpl::Show() {
417 GetWebContents()->WasShown();
420 void ContentViewCoreImpl::Hide() {
421 GetWebContents()->WasHidden();
425 void ContentViewCoreImpl::PauseVideo() {
426 RenderViewHost* host = web_contents_->GetRenderViewHost();
428 host->Send(new ViewMsg_PauseVideo(host->GetRoutingID()));
431 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
432 geolocation_needs_pause_ = should_pause;
433 RenderViewHostImpl* rvh =
434 static_cast<RenderViewHostImpl*>(web_contents_->GetRenderViewHost());
436 scoped_refptr<GeolocationDispatcherHost> geolocation_dispatcher =
437 static_cast<RenderProcessHostImpl*>(
438 web_contents_->GetRenderProcessHost())->
439 geolocation_dispatcher_host();
440 if (geolocation_dispatcher.get()) {
441 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
442 base::Bind(&GeolocationDispatcherHost::PauseOrResume,
443 geolocation_dispatcher,
446 geolocation_needs_pause_ = false;
451 void ContentViewCoreImpl::OnTabCrashed() {
452 JNIEnv* env = AttachCurrentThread();
453 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
456 Java_ContentViewCore_resetVSyncNotification(env, obj.obj());
459 // All positions and sizes are in CSS pixels.
460 // Note that viewport_width/height is a best effort based.
461 // ContentViewCore has the actual information about the physical viewport size.
462 void ContentViewCoreImpl::UpdateFrameInfo(
463 const gfx::Vector2dF& scroll_offset,
464 float page_scale_factor,
465 const gfx::Vector2dF& page_scale_factor_limits,
466 const gfx::SizeF& content_size,
467 const gfx::SizeF& viewport_size,
468 const gfx::Vector2dF& controls_offset,
469 const gfx::Vector2dF& content_offset,
470 float overdraw_bottom_height) {
471 JNIEnv* env = AttachCurrentThread();
472 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
476 if (window_android_) {
477 gfx::Vector2dF window_offset(
478 Java_ContentViewCore_getLocationInWindowX(env, obj.obj()),
479 Java_ContentViewCore_getLocationInWindowY(env, obj.obj()));
480 window_android_->set_content_offset(
481 gfx::ScaleVector2d(content_offset, dpi_scale_) + window_offset);
484 Java_ContentViewCore_updateFrameInfo(
489 page_scale_factor_limits.x(),
490 page_scale_factor_limits.y(),
491 content_size.width(),
492 content_size.height(),
493 viewport_size.width(),
494 viewport_size.height(),
497 overdraw_bottom_height);
498 #if defined(VIDEO_HOLE)
499 ExternalVideoSurfaceContainer* surface_container =
500 ExternalVideoSurfaceContainer::FromWebContents(web_contents_);
501 if (surface_container)
502 surface_container->OnFrameInfoUpdated();
503 #endif // defined(VIDEO_HOLE)
506 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
507 JNIEnv* env = AttachCurrentThread();
508 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
511 ScopedJavaLocalRef<jstring> jtitle =
512 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
513 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
516 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
517 JNIEnv* env = AttachCurrentThread();
518 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
521 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
524 void ContentViewCoreImpl::ShowSelectPopupMenu(
525 const std::vector<MenuItem>& items, int selected_item, bool multiple) {
526 JNIEnv* env = AttachCurrentThread();
527 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
531 // For multi-select list popups we find the list of previous selections by
532 // iterating through the items. But for single selection popups we take the
533 // given |selected_item| as is.
534 ScopedJavaLocalRef<jintArray> selected_array;
536 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
537 size_t selected_count = 0;
538 for (size_t i = 0; i < items.size(); ++i) {
539 if (items[i].checked)
540 native_selected_array[selected_count++] = i;
543 selected_array = ScopedJavaLocalRef<jintArray>(
544 env, env->NewIntArray(selected_count));
545 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
546 native_selected_array.get());
548 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
549 jint value = selected_item;
550 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
553 ScopedJavaLocalRef<jintArray> enabled_array(env,
554 env->NewIntArray(items.size()));
555 std::vector<base::string16> labels;
556 labels.reserve(items.size());
557 for (size_t i = 0; i < items.size(); ++i) {
558 labels.push_back(items[i].label);
560 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
561 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
562 POPUP_ITEM_TYPE_DISABLED));
563 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
565 ScopedJavaLocalRef<jobjectArray> items_array(
566 base::android::ToJavaArrayOfStrings(env, labels));
567 Java_ContentViewCore_showSelectPopup(env, j_obj.obj(),
568 items_array.obj(), enabled_array.obj(),
569 multiple, selected_array.obj());
572 void ContentViewCoreImpl::ConfirmTouchEvent(InputEventAckState ack_result) {
573 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
574 gesture_provider_.OnTouchEventAck(event_consumed);
577 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
578 InputEventAckState ack_result) {
579 JNIEnv* env = AttachCurrentThread();
580 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
584 switch (event.type) {
585 case WebInputEvent::GestureFlingStart:
586 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
587 // The view expects the fling velocity in pixels/s.
588 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
589 event.data.flingStart.velocityX * dpi_scale(),
590 event.data.flingStart.velocityY * dpi_scale());
592 // If a scroll ends with a fling, a SCROLL_END event is never sent.
593 // However, if that fling went unconsumed, we still need to let the
594 // listeners know that scrolling has ended.
595 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
598 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
599 // The view expects the fling velocity in pixels/s.
600 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
601 event.data.flingStart.velocityX * dpi_scale(),
602 event.data.flingStart.velocityY * dpi_scale());
605 case WebInputEvent::GestureFlingCancel:
606 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
608 case WebInputEvent::GestureScrollBegin:
609 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
611 case WebInputEvent::GestureScrollUpdate:
612 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
613 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
615 case WebInputEvent::GestureScrollEnd:
616 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
618 case WebInputEvent::GesturePinchBegin:
619 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
621 case WebInputEvent::GesturePinchEnd:
622 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
624 case WebInputEvent::GestureDoubleTap:
625 Java_ContentViewCore_onDoubleTapEventAck(env, j_obj.obj());
632 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
633 if (event.type != WebInputEvent::GestureTap &&
634 event.type != WebInputEvent::GestureDoubleTap &&
635 event.type != WebInputEvent::GestureLongTap &&
636 event.type != WebInputEvent::GestureLongPress)
639 JNIEnv* env = AttachCurrentThread();
640 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
644 const blink::WebGestureEvent& gesture =
645 static_cast<const blink::WebGestureEvent&>(event);
646 int gesture_type = ToGestureEventType(event.type);
647 return Java_ContentViewCore_filterTapOrPressEvent(env,
650 gesture.x * dpi_scale(),
651 gesture.y * dpi_scale());
653 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
656 bool ContentViewCoreImpl::HasFocus() {
657 JNIEnv* env = AttachCurrentThread();
658 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
661 return Java_ContentViewCore_hasFocus(env, obj.obj());
664 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
665 JNIEnv* env = AttachCurrentThread();
666 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
669 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
670 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
673 void ContentViewCoreImpl::OnSelectionBoundsChanged(
674 const ViewHostMsg_SelectionBounds_Params& params) {
675 JNIEnv* env = AttachCurrentThread();
676 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
679 ScopedJavaLocalRef<jobject> anchor_rect_dip(
680 CreateJavaRect(env, params.anchor_rect));
681 ScopedJavaLocalRef<jobject> focus_rect_dip(
682 CreateJavaRect(env, params.focus_rect));
683 Java_ContentViewCore_onSelectionBoundsChanged(env, obj.obj(),
684 anchor_rect_dip.obj(),
686 focus_rect_dip.obj(),
688 params.is_anchor_first);
691 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
692 JNIEnv* env = AttachCurrentThread();
693 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
696 Java_ContentViewCore_showPastePopup(env, obj.obj(),
697 static_cast<jint>(x_dip),
698 static_cast<jint>(y_dip));
701 void ContentViewCoreImpl::GetScaledContentBitmap(
703 jobject jbitmap_config,
704 gfx::Rect src_subrect,
705 const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
706 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
708 result_callback.Run(false, SkBitmap());
711 SkBitmap::Config skbitmap_format = gfx::ConvertToSkiaConfig(jbitmap_config);
712 view->GetScaledContentBitmap(scale, skbitmap_format, src_subrect,
716 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
717 JNIEnv* env = AttachCurrentThread();
718 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
721 ScopedJavaLocalRef<jstring> jcontent_url =
722 ConvertUTF8ToJavaString(env, content_url.spec());
723 Java_ContentViewCore_startContentIntent(env,
728 void ContentViewCoreImpl::ShowDisambiguationPopup(
729 const gfx::Rect& target_rect,
730 const SkBitmap& zoomed_bitmap) {
731 JNIEnv* env = AttachCurrentThread();
733 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
737 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, target_rect));
739 ScopedJavaLocalRef<jobject> java_bitmap =
740 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
741 DCHECK(!java_bitmap.is_null());
743 Java_ContentViewCore_showDisambiguationPopup(env,
749 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
750 JNIEnv* env = AttachCurrentThread();
752 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
754 return ScopedJavaLocalRef<jobject>();
755 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
758 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
759 JNIEnv* env = AttachCurrentThread();
761 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
763 return ScopedJavaLocalRef<jobject>();
765 return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
768 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
769 JNIEnv* env = AttachCurrentThread();
771 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
773 return ScopedJavaLocalRef<jobject>();
775 return Java_ContentViewCore_getContext(env, obj.obj());
778 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
779 JNIEnv* env = AttachCurrentThread();
781 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
784 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
785 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
789 void ContentViewCoreImpl::DidStopFlinging() {
790 JNIEnv* env = AttachCurrentThread();
792 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
794 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
797 gfx::Size ContentViewCoreImpl::GetViewSize() const {
798 gfx::Size size = GetViewportSizeDip();
799 gfx::Size offset = GetViewportSizeOffsetDip();
800 size.Enlarge(-offset.width(), -offset.height());
804 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
805 JNIEnv* env = AttachCurrentThread();
806 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
810 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
811 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
814 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
815 JNIEnv* env = AttachCurrentThread();
816 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
820 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
821 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
824 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
825 JNIEnv* env = AttachCurrentThread();
826 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
830 Java_ContentViewCore_getViewportSizeOffsetWidthPix(env, j_obj.obj()),
831 Java_ContentViewCore_getViewportSizeOffsetHeightPix(env, j_obj.obj()));
834 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
835 return gfx::ToCeiledSize(
836 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
839 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
840 return gfx::ToCeiledSize(
841 gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f / dpi_scale()));
844 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
845 JNIEnv* env = AttachCurrentThread();
846 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
849 return Java_ContentViewCore_getOverdrawBottomHeightPix(env, j_obj.obj())
853 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
854 root_layer_->AddChild(layer);
857 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
858 layer->RemoveFromParent();
861 void ContentViewCoreImpl::LoadUrl(
862 NavigationController::LoadURLParams& params) {
863 GetWebContents()->GetController().LoadURLWithParams(params);
866 void ContentViewCoreImpl::AddBeginFrameSubscriber() {
867 JNIEnv* env = AttachCurrentThread();
868 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
871 Java_ContentViewCore_addVSyncSubscriber(env, obj.obj());
874 void ContentViewCoreImpl::RemoveBeginFrameSubscriber() {
875 JNIEnv* env = AttachCurrentThread();
876 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
879 Java_ContentViewCore_removeVSyncSubscriber(env, obj.obj());
882 void ContentViewCoreImpl::SetNeedsAnimate() {
883 JNIEnv* env = AttachCurrentThread();
884 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
887 Java_ContentViewCore_setNeedsAnimate(env, obj.obj());
890 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
891 // view_android_ should never be null for Chrome.
892 DCHECK(view_android_);
893 return view_android_;
896 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
897 // This should never be NULL for Chrome, but will be NULL for WebView.
898 DCHECK(window_android_);
899 return window_android_;
902 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
903 return root_layer_.get();
906 // ----------------------------------------------------------------------------
907 // Methods called from Java via JNI
908 // ----------------------------------------------------------------------------
910 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env, jobject obj,
912 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
913 web_contents_->GetRenderViewHost());
915 if (indices == NULL) {
916 rvhi->DidCancelPopupMenu();
920 int selected_count = env->GetArrayLength(indices);
921 std::vector<int> selected_indices;
922 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
923 for (int i = 0; i < selected_count; ++i)
924 selected_indices.push_back(indices_ptr[i]);
925 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
926 rvhi->DidSelectPopupMenuItems(selected_indices);
929 void ContentViewCoreImpl::LoadUrl(
930 JNIEnv* env, jobject obj,
933 jint transition_type,
934 jint ua_override_option,
935 jstring extra_headers,
936 jbyteArray post_data,
937 jstring base_url_for_data_url,
938 jstring virtual_url_for_data_url,
939 jboolean can_load_local_resources) {
941 NavigationController::LoadURLParams params(
942 GURL(ConvertJavaStringToUTF8(env, url)));
944 params.load_type = static_cast<NavigationController::LoadURLType>(
946 params.transition_type = PageTransitionFromInt(transition_type);
947 params.override_user_agent =
948 static_cast<NavigationController::UserAgentOverrideOption>(
952 params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
955 std::vector<uint8> http_body_vector;
956 base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
957 params.browser_initiated_post_data =
958 base::RefCountedBytes::TakeVector(&http_body_vector);
961 if (base_url_for_data_url) {
962 params.base_url_for_data_url =
963 GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
966 if (virtual_url_for_data_url) {
967 params.virtual_url_for_data_url =
968 GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
971 params.can_load_local_resources = can_load_local_resources;
976 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetURL(
977 JNIEnv* env, jobject) const {
978 return ConvertUTF8ToJavaString(env, GetWebContents()->GetURL().spec());
981 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetTitle(
982 JNIEnv* env, jobject obj) const {
983 return ConvertUTF16ToJavaString(env, GetWebContents()->GetTitle());
986 jboolean ContentViewCoreImpl::IsIncognito(JNIEnv* env, jobject obj) {
987 return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
990 WebContents* ContentViewCoreImpl::GetWebContents() const {
991 return web_contents_;
994 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
995 SetFocusInternal(focused);
998 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
999 if (!GetRenderWidgetHostViewAndroid())
1003 GetRenderWidgetHostViewAndroid()->Focus();
1005 GetRenderWidgetHostViewAndroid()->Blur();
1008 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
1011 if (device_orientation_ != orientation) {
1012 device_orientation_ = orientation;
1013 SendOrientationChangeEventInternal();
1017 void ContentViewCoreImpl::CancelActiveTouchSequenceIfNecessary() {
1018 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1019 // Avoid synthesizing a touch cancel event if it cannot be forwarded.
1023 const ui::MotionEvent* current_down_event =
1024 gesture_provider_.GetCurrentDownEvent();
1025 if (!current_down_event)
1028 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
1029 DCHECK(cancel_event);
1030 if (!gesture_provider_.OnTouchEvent(*cancel_event))
1033 rwhv->SendTouchEvent(
1034 CreateWebTouchEventFromMotionEvent(*cancel_event, 1.f / dpi_scale()));
1037 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
1039 jobject motion_event,
1041 jint android_action,
1051 jfloat touch_major_0,
1052 jfloat touch_major_1) {
1053 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1057 MotionEventAndroid event(env,
1073 if (!gesture_provider_.OnTouchEvent(event))
1076 rwhv->SendTouchEvent(WebTouchEventBuilder::Build(event, 1.f / dpi_scale()));
1080 float ContentViewCoreImpl::GetDpiScale() const {
1084 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
1089 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1093 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
1094 WebInputEvent::MouseMove,
1095 blink::WebMouseEvent::ButtonNone,
1096 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
1098 rwhv->SendMouseEvent(event);
1102 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
1107 jfloat vertical_axis) {
1108 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1112 WebMouseWheelEventBuilder::Direction direction;
1113 if (vertical_axis > 0) {
1114 direction = WebMouseWheelEventBuilder::DIRECTION_UP;
1115 } else if (vertical_axis < 0) {
1116 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
1120 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
1121 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1123 rwhv->SendMouseWheelEvent(event);
1127 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
1128 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
1129 return WebGestureEventBuilder::Build(
1130 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1133 void ContentViewCoreImpl::SendGestureEvent(
1134 const blink::WebGestureEvent& event) {
1135 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1137 rwhv->SendGestureEvent(event);
1140 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
1147 WebGestureEvent event = MakeGestureEvent(
1148 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1149 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1150 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1152 SendGestureEvent(event);
1155 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1156 WebGestureEvent event = MakeGestureEvent(
1157 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1158 SendGestureEvent(event);
1161 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1162 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1163 WebGestureEvent event = MakeGestureEvent(
1164 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1165 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1166 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1168 SendGestureEvent(event);
1171 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1172 jfloat x, jfloat y, jfloat vx, jfloat vy) {
1173 WebGestureEvent event = MakeGestureEvent(
1174 WebInputEvent::GestureFlingStart, time_ms, x, y);
1175 event.data.flingStart.velocityX = vx / dpi_scale();
1176 event.data.flingStart.velocityY = vy / dpi_scale();
1178 SendGestureEvent(event);
1181 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1182 WebGestureEvent event = MakeGestureEvent(
1183 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1184 SendGestureEvent(event);
1187 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1188 jfloat x, jfloat y) {
1189 WebGestureEvent event = MakeGestureEvent(
1190 WebInputEvent::GestureTap, time_ms, x, y);
1191 event.data.tap.tapCount = 1;
1193 SendGestureEvent(event);
1196 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1197 jfloat x, jfloat y) {
1198 WebGestureEvent event = MakeGestureEvent(
1199 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1200 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1201 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1202 event.data.tap.tapCount = 1;
1204 SendGestureEvent(event);
1207 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1208 jfloat x, jfloat y) {
1209 WebGestureEvent event = MakeGestureEvent(
1210 WebInputEvent::GestureLongPress, time_ms, x, y);
1212 SendGestureEvent(event);
1215 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1216 jfloat x, jfloat y) {
1217 WebGestureEvent event = MakeGestureEvent(
1218 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1219 SendGestureEvent(event);
1222 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1223 WebGestureEvent event = MakeGestureEvent(
1224 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1225 SendGestureEvent(event);
1228 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1229 jfloat anchor_x, jfloat anchor_y,
1231 WebGestureEvent event = MakeGestureEvent(
1232 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1233 event.data.pinchUpdate.scale = delta;
1235 SendGestureEvent(event);
1238 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1239 jfloat x1, jfloat y1,
1240 jfloat x2, jfloat y2) {
1241 if (!web_contents_ || !web_contents_->GetFocusedFrame())
1244 RenderFrameHostImpl* frame =
1245 static_cast<RenderFrameHostImpl*>(web_contents_->GetFocusedFrame());
1246 frame->SelectRange(gfx::Point(x1 / dpi_scale(), y1 / dpi_scale()),
1247 gfx::Point(x2 / dpi_scale(), y2 / dpi_scale()));
1250 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1251 jfloat x, jfloat y) {
1252 if (GetRenderWidgetHostViewAndroid()) {
1253 GetRenderWidgetHostViewAndroid()->MoveCaret(
1254 gfx::Point(x / dpi_scale(), y / dpi_scale()));
1258 void ContentViewCoreImpl::ResetGestureDetectors(JNIEnv* env, jobject obj) {
1259 gesture_provider_.ResetGestureDetectors();
1262 void ContentViewCoreImpl::IgnoreRemainingTouchEvents(JNIEnv* env, jobject obj) {
1263 CancelActiveTouchSequenceIfNecessary();
1266 void ContentViewCoreImpl::OnWindowFocusLost(JNIEnv* env, jobject obj) {
1267 CancelActiveTouchSequenceIfNecessary();
1270 void ContentViewCoreImpl::SetDoubleTapSupportForPageEnabled(JNIEnv* env,
1273 gesture_provider_.SetDoubleTapSupportForPageEnabled(enabled);
1276 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1279 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
1282 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1285 gesture_provider_.SetMultiTouchSupportEnabled(enabled);
1288 void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) {
1289 web_contents_->GetController().LoadIfNecessary();
1292 void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv* env, jobject obj) {
1293 web_contents_->GetController().SetNeedsReload();
1296 void ContentViewCoreImpl::StopLoading(JNIEnv* env, jobject obj) {
1297 web_contents_->Stop();
1300 void ContentViewCoreImpl::Reload(JNIEnv* env,
1302 jboolean check_for_repost) {
1303 if (web_contents_->GetController().NeedsReload())
1304 web_contents_->GetController().LoadIfNecessary();
1306 web_contents_->GetController().Reload(check_for_repost);
1309 void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv* env,
1311 jboolean check_for_repost) {
1312 web_contents_->GetController().ReloadIgnoringCache(check_for_repost);
1315 void ContentViewCoreImpl::CancelPendingReload(JNIEnv* env, jobject obj) {
1316 web_contents_->GetController().CancelPendingReload();
1319 void ContentViewCoreImpl::ContinuePendingReload(JNIEnv* env, jobject obj) {
1320 web_contents_->GetController().ContinuePendingReload();
1323 void ContentViewCoreImpl::ClearHistory(JNIEnv* env, jobject obj) {
1324 // TODO(creis): Do callers of this need to know if it fails?
1325 if (web_contents_->GetController().CanPruneAllButLastCommitted())
1326 web_contents_->GetController().PruneAllButLastCommitted();
1329 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1333 web_contents_->java_bridge_dispatcher_host_manager()
1334 ->SetAllowObjectContentsInspection(allow);
1337 void ContentViewCoreImpl::AddJavascriptInterface(
1342 jclass safe_annotation_clazz,
1343 jobject retained_object_set) {
1344 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1345 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1346 JavaObjectWeakGlobalRef weak_retained_object_set(env, retained_object_set);
1348 // JavaBoundObject creates the NPObject with a ref count of 1, and
1349 // JavaBridgeDispatcherHostManager takes its own ref.
1350 JavaBridgeDispatcherHostManager* java_bridge =
1351 web_contents_->java_bridge_dispatcher_host_manager();
1352 java_bridge->SetRetainedObjectSet(weak_retained_object_set);
1353 NPObject* bound_object =
1354 JavaBoundObject::Create(scoped_object,
1356 java_bridge->AsWeakPtr(),
1357 java_bridge->GetAllowObjectContentsInspection());
1358 java_bridge->AddNamedObject(ConvertJavaStringToUTF16(env, name),
1360 blink::WebBindings::releaseObject(bound_object);
1363 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1366 web_contents_->java_bridge_dispatcher_host_manager()->RemoveNamedObject(
1367 ConvertJavaStringToUTF16(env, name));
1370 void ContentViewCoreImpl::UpdateVSyncParameters(JNIEnv* env, jobject /* obj */,
1371 jlong timebase_micros,
1372 jlong interval_micros) {
1373 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1377 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1378 view->GetRenderWidgetHost());
1380 host->UpdateVSyncParameters(
1381 base::TimeTicks::FromInternalValue(timebase_micros),
1382 base::TimeDelta::FromMicroseconds(interval_micros));
1385 base::TimeDelta::FromMicroseconds(interval_micros);
1386 expected_browser_composite_time_ =
1387 vsync_interval_ * kDefaultBrowserCompositeVSyncFraction;
1390 void ContentViewCoreImpl::OnVSync(JNIEnv* env, jobject /* obj */,
1391 jlong frame_time_micros) {
1392 base::TimeTicks frame_time =
1393 base::TimeTicks::FromInternalValue(frame_time_micros);
1394 SendBeginFrame(frame_time);
1397 void ContentViewCoreImpl::SendBeginFrame(base::TimeTicks frame_time) {
1398 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1402 base::TimeTicks display_time = frame_time + vsync_interval_;
1403 base::TimeTicks deadline = display_time - expected_browser_composite_time_;
1405 view->SendBeginFrame(
1406 cc::BeginFrameArgs::Create(frame_time, deadline, vsync_interval_));
1409 jboolean ContentViewCoreImpl::OnAnimate(JNIEnv* env, jobject /* obj */,
1410 jlong frame_time_micros) {
1411 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1415 return view->Animate(base::TimeTicks::FromInternalValue(frame_time_micros));
1418 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1419 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1421 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1422 view->GetRenderWidgetHost());
1423 host->SendScreenRects();
1428 void ContentViewCoreImpl::ShowInterstitialPage(
1429 JNIEnv* env, jobject obj, jstring jurl, jint delegate_ptr) {
1430 GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
1431 InterstitialPageDelegateAndroid* delegate =
1432 reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
1433 InterstitialPage* interstitial = InterstitialPage::Create(
1434 web_contents_, false, url, delegate);
1435 delegate->set_interstitial_page(interstitial);
1436 interstitial->Show();
1439 jboolean ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv* env,
1441 return web_contents_->ShowingInterstitialPage();
1444 jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
1446 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1447 return view && view->HasValidFrame();
1450 void ContentViewCoreImpl::ExitFullscreen(JNIEnv* env, jobject obj) {
1451 RenderViewHost* host = web_contents_->GetRenderViewHost();
1454 host->ExitFullscreen();
1457 void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv* env,
1460 bool enable_showing,
1462 RenderViewHost* host = web_contents_->GetRenderViewHost();
1465 host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
1471 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
1472 RenderViewHost* host = web_contents_->GetRenderViewHost();
1473 host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
1476 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv* env,
1478 RenderViewHost* host = web_contents_->GetRenderViewHost();
1479 host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
1480 host->GetRoutingID(), gfx::Rect()));
1485 static void AddNavigationEntryToHistory(JNIEnv* env, jobject obj,
1487 NavigationEntry* entry,
1489 // Get the details of the current entry
1490 ScopedJavaLocalRef<jstring> j_url(
1491 ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
1492 ScopedJavaLocalRef<jstring> j_virtual_url(
1493 ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
1494 ScopedJavaLocalRef<jstring> j_original_url(
1495 ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
1496 ScopedJavaLocalRef<jstring> j_title(
1497 ConvertUTF16ToJavaString(env, entry->GetTitle()));
1498 ScopedJavaLocalRef<jobject> j_bitmap;
1499 const FaviconStatus& status = entry->GetFavicon();
1500 if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
1501 j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
1503 // Add the item to the list
1504 Java_ContentViewCore_addToNavigationHistory(
1505 env, obj, history, index, j_url.obj(), j_virtual_url.obj(),
1506 j_original_url.obj(), j_title.obj(), j_bitmap.obj());
1511 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env,
1514 // Iterate through navigation entries to populate the list
1515 const NavigationController& controller = web_contents_->GetController();
1516 int count = controller.GetEntryCount();
1517 for (int i = 0; i < count; ++i) {
1518 AddNavigationEntryToHistory(
1519 env, obj, history, controller.GetEntryAtIndex(i), i);
1522 return controller.GetCurrentEntryIndex();
1525 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv* env,
1528 jboolean is_forward,
1530 // Iterate through navigation entries to populate the list
1531 const NavigationController& controller = web_contents_->GetController();
1532 int count = controller.GetEntryCount();
1534 int increment_value = is_forward ? 1 : -1;
1535 for (int i = controller.GetCurrentEntryIndex() + increment_value;
1536 i >= 0 && i < count;
1537 i += increment_value) {
1538 if (num_added >= max_entries)
1541 AddNavigationEntryToHistory(
1542 env, obj, history, controller.GetEntryAtIndex(i), i);
1547 ScopedJavaLocalRef<jstring>
1548 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv* env,
1550 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1552 return ScopedJavaLocalRef<jstring>(env, NULL);
1553 return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
1556 int ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1557 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1560 return rwhva->GetNativeImeAdapter();
1564 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
1565 const base::Value* result) {
1566 JNIEnv* env = base::android::AttachCurrentThread();
1568 base::JSONWriter::Write(result, &json);
1569 ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
1570 Java_ContentViewCore_onEvaluateJavaScriptResult(env,
1576 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env,
1580 jboolean start_renderer) {
1581 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
1584 if (start_renderer && !rvh->IsRenderViewLive()) {
1585 if (!web_contents_->CreateRenderViewForInitialEmptyDocument()) {
1586 LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
1592 // No callback requested.
1593 web_contents_->GetMainFrame()->ExecuteJavaScript(
1594 ConvertJavaStringToUTF16(env, script));
1598 // Secure the Java callback in a scoped object and give ownership of it to the
1600 ScopedJavaGlobalRef<jobject> j_callback;
1601 j_callback.Reset(env, callback);
1602 content::RenderFrameHost::JavaScriptResultCallback c_callback =
1603 base::Bind(&JavaScriptResultCallback, j_callback);
1605 web_contents_->GetMainFrame()->ExecuteJavaScript(
1606 ConvertJavaStringToUTF16(env, script),
1610 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
1611 JNIEnv* env, jobject obj) {
1612 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1613 return entry && entry->GetIsOverridingUserAgent();
1616 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1617 int text_input_type,
1618 const std::string& text,
1619 int selection_start,
1621 int composition_start,
1622 int composition_end,
1623 bool show_ime_if_needed,
1625 JNIEnv* env = AttachCurrentThread();
1626 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1630 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1631 Java_ContentViewCore_updateImeAdapter(env, obj.obj(),
1632 native_ime_adapter, text_input_type,
1634 selection_start, selection_end,
1635 composition_start, composition_end,
1636 show_ime_if_needed, require_ack);
1639 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv* env, jobject obj) {
1640 SSLHostState* state = SSLHostState::GetFor(
1641 web_contents_->GetController().GetBrowserContext());
1645 void ContentViewCoreImpl::SetUseDesktopUserAgent(
1649 jboolean reload_on_state_change) {
1650 if (GetUseDesktopUserAgent(env, obj) == enabled)
1653 // Make sure the navigation entry actually exists.
1654 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1658 // Set the flag in the NavigationEntry.
1659 entry->SetIsOverridingUserAgent(enabled);
1661 // Send the override to the renderer.
1662 if (reload_on_state_change) {
1663 // Reloading the page will send the override down as part of the
1664 // navigation IPC message.
1665 NavigationControllerImpl& controller =
1666 static_cast<NavigationControllerImpl&>(web_contents_->GetController());
1667 controller.ReloadOriginalRequestURL(false);
1671 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1673 RenderWidgetHostViewAndroid* host_view = GetRenderWidgetHostViewAndroid();
1676 RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(
1677 host_view->GetRenderWidgetHost());
1678 BrowserAccessibilityState* accessibility_state =
1679 BrowserAccessibilityState::GetInstance();
1681 // This enables accessibility globally unless it was explicitly disallowed
1682 // by a command-line flag.
1683 accessibility_state->OnScreenReaderDetected();
1684 // If it was actually enabled globally, enable it for this RenderWidget now.
1685 if (accessibility_state->IsAccessibleBrowser() && host_impl)
1686 host_impl->AddAccessibilityMode(AccessibilityModeComplete);
1688 accessibility_state->ResetAccessibilityMode();
1690 host_impl->ResetAccessibilityMode();
1694 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1695 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1697 rwhv->UpdateScreenInfo(GetViewAndroid());
1699 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1700 web_contents_->GetRenderViewHost());
1701 rvhi->SendOrientationChangeEvent(device_orientation_);
1703 // TODO(mlamouri): temporary plumbing for Screen Orientation, this will change
1704 // in the future. It might leave ContentViewCoreImpl or simply replace the
1705 // SendOrientationChangeEvent call above.
1706 blink::WebScreenOrientation orientation =
1707 blink::WebScreenOrientationPortraitPrimary;
1709 switch (device_orientation_) {
1711 orientation = blink::WebScreenOrientationPortraitPrimary;
1714 orientation = blink::WebScreenOrientationLandscapePrimary;
1717 orientation = blink::WebScreenOrientationLandscapeSecondary;
1720 orientation = blink::WebScreenOrientationPortraitSecondary;
1726 ScreenOrientationDispatcherHost* sodh =
1727 static_cast<RenderProcessHostImpl*>(web_contents_->
1728 GetRenderProcessHost())->screen_orientation_dispatcher_host();
1730 // sodh can be null if the RenderProcessHost is in the process of being
1731 // destroyed or not yet initialized.
1733 sodh->OnOrientationChange(orientation);
1736 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1743 static_cast<int>(x / dpi_scale()),
1744 static_cast<int>(y / dpi_scale()),
1745 static_cast<int>((width > 0 && width < dpi_scale()) ?
1746 1 : (int)(width / dpi_scale())),
1747 static_cast<int>((height > 0 && height < dpi_scale()) ?
1748 1 : (int)(height / dpi_scale())));
1749 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1750 GetWebContents()->GetRoutingID(), rect));
1753 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1754 return GetRenderProcessIdFromRenderViewHost(
1755 web_contents_->GetRenderViewHost());
1758 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1759 const base::string16& result) {
1760 JNIEnv* env = AttachCurrentThread();
1761 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1764 ScopedJavaLocalRef<jstring> jresult = ConvertUTF16ToJavaString(env, result);
1765 Java_ContentViewCore_onSmartClipDataExtracted(
1766 env, obj.obj(), jresult.obj());
1769 void ContentViewCoreImpl::WebContentsDestroyed(WebContents* web_contents) {
1770 WebContentsViewAndroid* wcva =
1771 static_cast<WebContentsViewAndroid*>(web_contents->GetView());
1773 wcva->SetContentViewCore(NULL);
1776 // This is called for each ContentView.
1777 jlong Init(JNIEnv* env,
1779 jlong native_web_contents,
1781 jlong window_android) {
1782 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1784 reinterpret_cast<WebContents*>(native_web_contents),
1785 reinterpret_cast<ui::ViewAndroid*>(view_android),
1786 reinterpret_cast<ui::WindowAndroid*>(window_android));
1787 return reinterpret_cast<intptr_t>(view);
1790 bool RegisterContentViewCore(JNIEnv* env) {
1791 return RegisterNativesImpl(env);
1794 } // namespace content