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/content_video_view.h"
20 #include "content/browser/android/interstitial_page_delegate_android.h"
21 #include "content/browser/android/load_url_params.h"
22 #include "content/browser/android/touch_point.h"
23 #include "content/browser/frame_host/interstitial_page_impl.h"
24 #include "content/browser/frame_host/navigation_controller_impl.h"
25 #include "content/browser/frame_host/navigation_entry_impl.h"
26 #include "content/browser/media/android/browser_media_player_manager.h"
27 #include "content/browser/renderer_host/compositor_impl_android.h"
28 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
29 #include "content/browser/renderer_host/java/java_bound_object.h"
30 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
31 #include "content/browser/renderer_host/render_view_host_impl.h"
32 #include "content/browser/renderer_host/render_widget_host_impl.h"
33 #include "content/browser/renderer_host/render_widget_host_view_android.h"
34 #include "content/browser/ssl/ssl_host_state.h"
35 #include "content/browser/web_contents/web_contents_view_android.h"
36 #include "content/common/input_messages.h"
37 #include "content/common/view_messages.h"
38 #include "content/public/browser/browser_accessibility_state.h"
39 #include "content/public/browser/browser_context.h"
40 #include "content/public/browser/favicon_status.h"
41 #include "content/public/browser/notification_details.h"
42 #include "content/public/browser/notification_service.h"
43 #include "content/public/browser/notification_source.h"
44 #include "content/public/browser/notification_types.h"
45 #include "content/public/browser/web_contents.h"
46 #include "content/public/common/content_client.h"
47 #include "content/public/common/content_switches.h"
48 #include "content/public/common/menu_item.h"
49 #include "content/public/common/page_transition_types.h"
50 #include "jni/ContentViewCore_jni.h"
51 #include "third_party/WebKit/public/web/WebBindings.h"
52 #include "third_party/WebKit/public/web/WebInputEvent.h"
53 #include "ui/base/android/view_android.h"
54 #include "ui/base/android/window_android.h"
55 #include "ui/gfx/android/java_bitmap.h"
56 #include "ui/gfx/screen.h"
57 #include "ui/gfx/size_conversions.h"
58 #include "ui/gfx/size_f.h"
59 #include "webkit/common/user_agent/user_agent_util.h"
61 using base::android::AttachCurrentThread
;
62 using base::android::ConvertJavaStringToUTF16
;
63 using base::android::ConvertJavaStringToUTF8
;
64 using base::android::ConvertUTF16ToJavaString
;
65 using base::android::ConvertUTF8ToJavaString
;
66 using base::android::ScopedJavaGlobalRef
;
67 using base::android::ScopedJavaLocalRef
;
68 using blink::WebGestureEvent
;
69 using blink::WebInputEvent
;
71 // Describes the type and enabled state of a select popup item.
75 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
76 #include "content/browser/android/popup_item_type_list.h"
77 #undef DEFINE_POPUP_ITEM_TYPE
86 const unsigned int kDefaultVSyncIntervalMicros
= 16666u;
87 // TODO(brianderson): Use adaptive draw-time estimation.
88 const float kDefaultBrowserCompositeVSyncFraction
= 1.0f
/ 3;
90 const void* kContentViewUserDataKey
= &kContentViewUserDataKey
;
92 int GetRenderProcessIdFromRenderViewHost(RenderViewHost
* host
) {
94 RenderProcessHost
* render_process
= host
->GetProcess();
95 DCHECK(render_process
);
96 if (render_process
->HasConnection())
97 return render_process
->GetHandle();
102 ScopedJavaLocalRef
<jobject
> CreateJavaRect(
104 const gfx::Rect
& rect
) {
105 return ScopedJavaLocalRef
<jobject
>(
106 Java_ContentViewCore_createRect(env
,
107 static_cast<int>(rect
.x()),
108 static_cast<int>(rect
.y()),
109 static_cast<int>(rect
.right()),
110 static_cast<int>(rect
.bottom())));
115 // Enables a callback when the underlying WebContents is destroyed, to enable
116 // nulling the back-pointer.
117 class ContentViewCoreImpl::ContentViewUserData
118 : public base::SupportsUserData::Data
{
120 explicit ContentViewUserData(ContentViewCoreImpl
* content_view_core
)
121 : content_view_core_(content_view_core
) {
124 virtual ~ContentViewUserData() {
125 // TODO(joth): When chrome has finished removing the TabContents class (see
126 // crbug.com/107201) consider inverting relationship, so ContentViewCore
127 // would own WebContents. That effectively implies making the WebContents
128 // destructor private on Android.
129 delete content_view_core_
;
132 ContentViewCoreImpl
* get() const { return content_view_core_
; }
135 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
136 ContentViewCoreImpl
* content_view_core_
;
138 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData
);
142 ContentViewCoreImpl
* ContentViewCoreImpl::FromWebContents(
143 content::WebContents
* web_contents
) {
144 ContentViewCoreImpl::ContentViewUserData
* data
=
145 reinterpret_cast<ContentViewCoreImpl::ContentViewUserData
*>(
146 web_contents
->GetUserData(kContentViewUserDataKey
));
147 return data
? data
->get() : NULL
;
151 ContentViewCore
* ContentViewCore::FromWebContents(
152 content::WebContents
* web_contents
) {
153 return ContentViewCoreImpl::FromWebContents(web_contents
);
157 ContentViewCore
* ContentViewCore::GetNativeContentViewCore(JNIEnv
* env
,
159 return reinterpret_cast<ContentViewCore
*>(
160 Java_ContentViewCore_getNativeContentViewCore(env
, obj
));
163 ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv
* env
, jobject obj
,
164 bool hardware_accelerated
,
165 WebContents
* web_contents
,
166 ui::ViewAndroid
* view_android
,
167 ui::WindowAndroid
* window_android
)
168 : WebContentsObserver(web_contents
),
170 web_contents_(static_cast<WebContentsImpl
*>(web_contents
)),
171 root_layer_(cc::Layer::Create()),
172 vsync_interval_(base::TimeDelta::FromMicroseconds(
173 kDefaultVSyncIntervalMicros
)),
174 expected_browser_composite_time_(base::TimeDelta::FromMicroseconds(
175 kDefaultVSyncIntervalMicros
* kDefaultBrowserCompositeVSyncFraction
)),
176 view_android_(view_android
),
177 window_android_(window_android
),
178 device_orientation_(0),
179 geolocation_needs_pause_(false) {
180 CHECK(web_contents
) <<
181 "A ContentViewCoreImpl should be created with a valid WebContents.";
183 // TODO(leandrogracia): make use of the hardware_accelerated argument.
185 const gfx::Display
& display
=
186 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
187 dpi_scale_
= display
.device_scale_factor();
189 // Currently, the only use case we have for overriding a user agent involves
190 // spoofing a desktop Linux user agent for "Request desktop site".
191 // Automatically set it for all WebContents so that it is available when a
192 // NavigationEntry requires the user agent to be overridden.
193 const char kLinuxInfoStr
[] = "X11; Linux x86_64";
194 std::string product
= content::GetContentClient()->GetProduct();
195 std::string spoofed_ua
=
196 webkit_glue::BuildUserAgentFromOSAndProduct(kLinuxInfoStr
, product
);
197 web_contents
->SetUserAgentOverride(spoofed_ua
);
202 ContentViewCoreImpl::~ContentViewCoreImpl() {
203 JNIEnv
* env
= base::android::AttachCurrentThread();
204 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
206 if (!j_obj
.is_null()) {
207 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
208 env
, j_obj
.obj(), reinterpret_cast<intptr_t>(this));
210 // Make sure nobody calls back into this object while we are tearing things
212 notification_registrar_
.RemoveAll();
215 base::android::ScopedJavaLocalRef
<jobject
>
216 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv
* env
, jobject obj
) {
217 return web_contents_
->GetJavaWebContents();
220 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv
* env
,
222 DCHECK(env
->IsSameObject(java_ref_
.get(env
).obj(), obj
));
226 void ContentViewCoreImpl::InitWebContents() {
227 DCHECK(web_contents_
);
228 notification_registrar_
.Add(
229 this, NOTIFICATION_RENDER_VIEW_HOST_CHANGED
,
230 Source
<WebContents
>(web_contents_
));
231 notification_registrar_
.Add(
232 this, NOTIFICATION_RENDERER_PROCESS_CREATED
,
233 content::NotificationService::AllBrowserContextsAndSources());
234 notification_registrar_
.Add(
235 this, NOTIFICATION_WEB_CONTENTS_CONNECTED
,
236 Source
<WebContents
>(web_contents_
));
238 static_cast<WebContentsViewAndroid
*>(web_contents_
->GetView())->
239 SetContentViewCore(this);
240 DCHECK(!web_contents_
->GetUserData(kContentViewUserDataKey
));
241 web_contents_
->SetUserData(kContentViewUserDataKey
,
242 new ContentViewUserData(this));
245 void ContentViewCoreImpl::Observe(int type
,
246 const NotificationSource
& source
,
247 const NotificationDetails
& details
) {
249 case NOTIFICATION_RENDER_VIEW_HOST_CHANGED
: {
250 std::pair
<RenderViewHost
*, RenderViewHost
*>* switched_details
=
251 Details
<std::pair
<RenderViewHost
*, RenderViewHost
*> >(details
).ptr();
253 if (switched_details
->first
) {
254 old_pid
= GetRenderProcessIdFromRenderViewHost(
255 switched_details
->first
);
257 int new_pid
= GetRenderProcessIdFromRenderViewHost(
258 web_contents_
->GetRenderViewHost());
259 if (new_pid
!= old_pid
) {
260 // Notify the Java side of the change of the current renderer process.
261 JNIEnv
* env
= AttachCurrentThread();
262 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
263 if (!obj
.is_null()) {
264 Java_ContentViewCore_onRenderProcessSwap(
265 env
, obj
.obj(), old_pid
, new_pid
);
268 SetFocusInternal(HasFocus());
269 if (geolocation_needs_pause_
)
270 PauseOrResumeGeolocation(true);
273 case NOTIFICATION_RENDERER_PROCESS_CREATED
: {
274 // Notify the Java side of the current renderer process.
275 RenderProcessHost
* source_process_host
=
276 Source
<RenderProcessHost
>(source
).ptr();
277 RenderProcessHost
* current_process_host
=
278 web_contents_
->GetRenderViewHost()->GetProcess();
280 if (source_process_host
== current_process_host
) {
281 int pid
= GetRenderProcessIdFromRenderViewHost(
282 web_contents_
->GetRenderViewHost());
283 JNIEnv
* env
= AttachCurrentThread();
284 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
285 if (!obj
.is_null()) {
286 Java_ContentViewCore_onRenderProcessSwap(env
, obj
.obj(), 0, pid
);
291 case NOTIFICATION_WEB_CONTENTS_CONNECTED
: {
292 JNIEnv
* env
= AttachCurrentThread();
293 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
294 if (!obj
.is_null()) {
295 Java_ContentViewCore_onWebContentsConnected(env
, obj
.obj());
302 void ContentViewCoreImpl::RenderViewReady() {
303 if (device_orientation_
!= 0)
304 SendOrientationChangeEventInternal();
307 RenderWidgetHostViewAndroid
*
308 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
309 RenderWidgetHostView
* rwhv
= NULL
;
311 rwhv
= web_contents_
->GetRenderWidgetHostView();
312 if (web_contents_
->ShowingInterstitialPage()) {
313 rwhv
= static_cast<InterstitialPageImpl
*>(
314 web_contents_
->GetInterstitialPage())->
315 GetRenderViewHost()->GetView();
318 return static_cast<RenderWidgetHostViewAndroid
*>(rwhv
);
321 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetJavaObject() {
322 JNIEnv
* env
= AttachCurrentThread();
323 return java_ref_
.get(env
);
326 jint
ContentViewCoreImpl::GetBackgroundColor(JNIEnv
* env
, jobject obj
) {
327 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
329 return SK_ColorWHITE
;
330 return rwhva
->GetCachedBackgroundColor();
333 void ContentViewCoreImpl::OnHide(JNIEnv
* env
, jobject obj
) {
337 void ContentViewCoreImpl::OnShow(JNIEnv
* env
, jobject obj
) {
341 void ContentViewCoreImpl::Show() {
342 GetWebContents()->WasShown();
346 void ContentViewCoreImpl::Hide() {
347 GetWebContents()->WasHidden();
351 void ContentViewCoreImpl::PauseVideo() {
352 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
354 host
->Send(new ViewMsg_PauseVideo(host
->GetRoutingID()));
355 if (ContentVideoView::GetInstance())
356 ContentVideoView::GetInstance()->SuspendFullscreen();
359 void ContentViewCoreImpl::ResumeVideo() {
360 if (ContentVideoView::GetInstance())
361 ContentVideoView::GetInstance()->ResumeFullscreenIfSuspended();
364 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause
) {
365 geolocation_needs_pause_
= should_pause
;
366 RenderViewHostImpl
* rvh
=
367 static_cast<RenderViewHostImpl
*>(web_contents_
->GetRenderViewHost());
369 scoped_refptr
<GeolocationDispatcherHost
> geolocation_dispatcher
=
370 static_cast<RenderProcessHostImpl
*>(
371 web_contents_
->GetRenderProcessHost())->
372 geolocation_dispatcher_host();
373 if (geolocation_dispatcher
.get()) {
374 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
375 base::Bind(&GeolocationDispatcherHost::PauseOrResume
,
376 geolocation_dispatcher
,
379 geolocation_needs_pause_
= false;
384 void ContentViewCoreImpl::OnTabCrashed() {
385 JNIEnv
* env
= AttachCurrentThread();
386 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
389 Java_ContentViewCore_resetVSyncNotification(env
, obj
.obj());
392 // All positions and sizes are in CSS pixels.
393 // Note that viewport_width/height is a best effort based.
394 // ContentViewCore has the actual information about the physical viewport size.
395 void ContentViewCoreImpl::UpdateFrameInfo(
396 const gfx::Vector2dF
& scroll_offset
,
397 float page_scale_factor
,
398 const gfx::Vector2dF
& page_scale_factor_limits
,
399 const gfx::SizeF
& content_size
,
400 const gfx::SizeF
& viewport_size
,
401 const gfx::Vector2dF
& controls_offset
,
402 const gfx::Vector2dF
& content_offset
,
403 float overdraw_bottom_height
) {
404 JNIEnv
* env
= AttachCurrentThread();
405 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
409 if (window_android_
) {
410 gfx::Vector2dF
window_offset(
411 Java_ContentViewCore_getLocationInWindowX(env
, obj
.obj()),
412 Java_ContentViewCore_getLocationInWindowY(env
, obj
.obj()));
413 window_android_
->set_content_offset(
414 gfx::ScaleVector2d(content_offset
, dpi_scale_
) + window_offset
);
417 Java_ContentViewCore_updateFrameInfo(
422 page_scale_factor_limits
.x(),
423 page_scale_factor_limits
.y(),
424 content_size
.width(),
425 content_size
.height(),
426 viewport_size
.width(),
427 viewport_size
.height(),
430 overdraw_bottom_height
);
433 void ContentViewCoreImpl::SetTitle(const base::string16
& title
) {
434 JNIEnv
* env
= AttachCurrentThread();
435 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
438 ScopedJavaLocalRef
<jstring
> jtitle
=
439 ConvertUTF8ToJavaString(env
, base::UTF16ToUTF8(title
));
440 Java_ContentViewCore_setTitle(env
, obj
.obj(), jtitle
.obj());
443 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color
) {
444 JNIEnv
* env
= AttachCurrentThread();
445 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
448 Java_ContentViewCore_onBackgroundColorChanged(env
, obj
.obj(), color
);
451 void ContentViewCoreImpl::ShowSelectPopupMenu(
452 const std::vector
<MenuItem
>& items
, int selected_item
, bool multiple
) {
453 JNIEnv
* env
= AttachCurrentThread();
454 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
458 // For multi-select list popups we find the list of previous selections by
459 // iterating through the items. But for single selection popups we take the
460 // given |selected_item| as is.
461 ScopedJavaLocalRef
<jintArray
> selected_array
;
463 scoped_ptr
<jint
[]> native_selected_array(new jint
[items
.size()]);
464 size_t selected_count
= 0;
465 for (size_t i
= 0; i
< items
.size(); ++i
) {
466 if (items
[i
].checked
)
467 native_selected_array
[selected_count
++] = i
;
470 selected_array
= ScopedJavaLocalRef
<jintArray
>(
471 env
, env
->NewIntArray(selected_count
));
472 env
->SetIntArrayRegion(selected_array
.obj(), 0, selected_count
,
473 native_selected_array
.get());
475 selected_array
= ScopedJavaLocalRef
<jintArray
>(env
, env
->NewIntArray(1));
476 jint value
= selected_item
;
477 env
->SetIntArrayRegion(selected_array
.obj(), 0, 1, &value
);
480 ScopedJavaLocalRef
<jintArray
> enabled_array(env
,
481 env
->NewIntArray(items
.size()));
482 std::vector
<base::string16
> labels
;
483 labels
.reserve(items
.size());
484 for (size_t i
= 0; i
< items
.size(); ++i
) {
485 labels
.push_back(items
[i
].label
);
487 (items
[i
].type
== MenuItem::GROUP
? POPUP_ITEM_TYPE_GROUP
:
488 (items
[i
].enabled
? POPUP_ITEM_TYPE_ENABLED
:
489 POPUP_ITEM_TYPE_DISABLED
));
490 env
->SetIntArrayRegion(enabled_array
.obj(), i
, 1, &enabled
);
492 ScopedJavaLocalRef
<jobjectArray
> items_array(
493 base::android::ToJavaArrayOfStrings(env
, labels
));
494 Java_ContentViewCore_showSelectPopup(env
, j_obj
.obj(),
495 items_array
.obj(), enabled_array
.obj(),
496 multiple
, selected_array
.obj());
499 void ContentViewCoreImpl::ConfirmTouchEvent(InputEventAckState ack_result
) {
500 JNIEnv
* env
= AttachCurrentThread();
501 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
504 Java_ContentViewCore_confirmTouchEvent(env
, j_obj
.obj(),
505 static_cast<jint
>(ack_result
));
508 void ContentViewCoreImpl::UnhandledFlingStartEvent() {
509 JNIEnv
* env
= AttachCurrentThread();
510 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
513 Java_ContentViewCore_unhandledFlingStartEvent(env
, j_obj
.obj());
516 void ContentViewCoreImpl::OnScrollUpdateGestureConsumed() {
517 JNIEnv
* env
= AttachCurrentThread();
518 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
521 Java_ContentViewCore_onScrollUpdateGestureConsumed(env
, j_obj
.obj());
524 void ContentViewCoreImpl::HasTouchEventHandlers(bool need_touch_events
) {
525 JNIEnv
* env
= AttachCurrentThread();
526 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
529 Java_ContentViewCore_hasTouchEventHandlers(env
,
534 bool ContentViewCoreImpl::HasFocus() {
535 JNIEnv
* env
= AttachCurrentThread();
536 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
539 return Java_ContentViewCore_hasFocus(env
, obj
.obj());
542 void ContentViewCoreImpl::OnSelectionChanged(const std::string
& text
) {
543 JNIEnv
* env
= AttachCurrentThread();
544 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
547 ScopedJavaLocalRef
<jstring
> jtext
= ConvertUTF8ToJavaString(env
, text
);
548 Java_ContentViewCore_onSelectionChanged(env
, obj
.obj(), jtext
.obj());
551 void ContentViewCoreImpl::OnSelectionBoundsChanged(
552 const ViewHostMsg_SelectionBounds_Params
& params
) {
553 JNIEnv
* env
= AttachCurrentThread();
554 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
557 ScopedJavaLocalRef
<jobject
> anchor_rect_dip(
558 CreateJavaRect(env
, params
.anchor_rect
));
559 ScopedJavaLocalRef
<jobject
> focus_rect_dip(
560 CreateJavaRect(env
, params
.focus_rect
));
561 Java_ContentViewCore_onSelectionBoundsChanged(env
, obj
.obj(),
562 anchor_rect_dip
.obj(),
564 focus_rect_dip
.obj(),
566 params
.is_anchor_first
);
569 void ContentViewCoreImpl::ShowPastePopup(int x_dip
, int y_dip
) {
570 JNIEnv
* env
= AttachCurrentThread();
571 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
574 Java_ContentViewCore_showPastePopup(env
, obj
.obj(),
575 static_cast<jint
>(x_dip
),
576 static_cast<jint
>(y_dip
));
579 unsigned int ContentViewCoreImpl::GetScaledContentTexture(
581 gfx::Size
* out_size
) {
582 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
586 return view
->GetScaledContentTexture(scale
, out_size
);
589 void ContentViewCoreImpl::StartContentIntent(const GURL
& content_url
) {
590 JNIEnv
* env
= AttachCurrentThread();
591 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
594 ScopedJavaLocalRef
<jstring
> jcontent_url
=
595 ConvertUTF8ToJavaString(env
, content_url
.spec());
596 Java_ContentViewCore_startContentIntent(env
,
601 void ContentViewCoreImpl::ShowDisambiguationPopup(
602 const gfx::Rect
& target_rect
,
603 const SkBitmap
& zoomed_bitmap
) {
604 JNIEnv
* env
= AttachCurrentThread();
606 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
610 ScopedJavaLocalRef
<jobject
> rect_object(CreateJavaRect(env
, target_rect
));
612 ScopedJavaLocalRef
<jobject
> java_bitmap
=
613 gfx::ConvertToJavaBitmap(&zoomed_bitmap
);
614 DCHECK(!java_bitmap
.is_null());
616 Java_ContentViewCore_showDisambiguationPopup(env
,
622 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
623 JNIEnv
* env
= AttachCurrentThread();
625 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
627 return ScopedJavaLocalRef
<jobject
>();
628 return Java_ContentViewCore_createTouchEventSynthesizer(env
, obj
.obj());
631 void ContentViewCoreImpl::NotifyExternalSurface(
632 int player_id
, bool is_request
, const gfx::RectF
& rect
) {
633 JNIEnv
* env
= AttachCurrentThread();
635 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
639 Java_ContentViewCore_notifyExternalSurface(
642 static_cast<jint
>(player_id
),
643 static_cast<jboolean
>(is_request
),
644 static_cast<jfloat
>(rect
.x()),
645 static_cast<jfloat
>(rect
.y()),
646 static_cast<jfloat
>(rect
.width()),
647 static_cast<jfloat
>(rect
.height()));
650 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetContentVideoViewClient() {
651 JNIEnv
* env
= AttachCurrentThread();
653 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
655 return ScopedJavaLocalRef
<jobject
>();
657 return Java_ContentViewCore_getContentVideoViewClient(env
, obj
.obj());
660 ScopedJavaLocalRef
<jobject
> ContentViewCoreImpl::GetContext() {
661 JNIEnv
* env
= AttachCurrentThread();
663 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
665 return ScopedJavaLocalRef
<jobject
>();
667 return Java_ContentViewCore_getContext(env
, obj
.obj());
670 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL
& url
) {
671 JNIEnv
* env
= AttachCurrentThread();
673 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
676 ScopedJavaLocalRef
<jstring
> j_url
= ConvertUTF8ToJavaString(env
, url
.spec());
677 return Java_ContentViewCore_shouldBlockMediaRequest(env
, obj
.obj(),
681 gfx::Size
ContentViewCoreImpl::GetPhysicalBackingSize() const {
682 JNIEnv
* env
= AttachCurrentThread();
683 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
687 Java_ContentViewCore_getPhysicalBackingWidthPix(env
, j_obj
.obj()),
688 Java_ContentViewCore_getPhysicalBackingHeightPix(env
, j_obj
.obj()));
691 gfx::Size
ContentViewCoreImpl::GetViewportSizePix() const {
692 JNIEnv
* env
= AttachCurrentThread();
693 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
697 Java_ContentViewCore_getViewportWidthPix(env
, j_obj
.obj()),
698 Java_ContentViewCore_getViewportHeightPix(env
, j_obj
.obj()));
701 gfx::Size
ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
702 JNIEnv
* env
= AttachCurrentThread();
703 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
707 Java_ContentViewCore_getViewportSizeOffsetWidthPix(env
, j_obj
.obj()),
708 Java_ContentViewCore_getViewportSizeOffsetHeightPix(env
, j_obj
.obj()));
711 gfx::Size
ContentViewCoreImpl::GetViewportSizeDip() const {
712 return gfx::ToCeiledSize(
713 gfx::ScaleSize(GetViewportSizePix(), 1.0f
/ GetDpiScale()));
716 gfx::Size
ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
717 return gfx::ToCeiledSize(
718 gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f
/ GetDpiScale()));
721 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
722 JNIEnv
* env
= AttachCurrentThread();
723 ScopedJavaLocalRef
<jobject
> j_obj
= java_ref_
.get(env
);
726 return Java_ContentViewCore_getOverdrawBottomHeightPix(env
, j_obj
.obj())
730 void ContentViewCoreImpl::AttachLayer(scoped_refptr
<cc::Layer
> layer
) {
731 root_layer_
->AddChild(layer
);
734 void ContentViewCoreImpl::RemoveLayer(scoped_refptr
<cc::Layer
> layer
) {
735 layer
->RemoveFromParent();
738 void ContentViewCoreImpl::LoadUrl(
739 NavigationController::LoadURLParams
& params
) {
740 GetWebContents()->GetController().LoadURLWithParams(params
);
743 void ContentViewCoreImpl::AddBeginFrameSubscriber() {
744 JNIEnv
* env
= AttachCurrentThread();
745 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
748 Java_ContentViewCore_addVSyncSubscriber(env
, obj
.obj());
751 void ContentViewCoreImpl::RemoveBeginFrameSubscriber() {
752 JNIEnv
* env
= AttachCurrentThread();
753 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
756 Java_ContentViewCore_removeVSyncSubscriber(env
, obj
.obj());
759 void ContentViewCoreImpl::SetNeedsAnimate() {
760 JNIEnv
* env
= AttachCurrentThread();
761 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
764 Java_ContentViewCore_setNeedsAnimate(env
, obj
.obj());
767 ui::ViewAndroid
* ContentViewCoreImpl::GetViewAndroid() const {
768 // view_android_ should never be null for Chrome.
769 DCHECK(view_android_
);
770 return view_android_
;
773 ui::WindowAndroid
* ContentViewCoreImpl::GetWindowAndroid() const {
774 // This should never be NULL for Chrome, but will be NULL for WebView.
775 DCHECK(window_android_
);
776 return window_android_
;
779 scoped_refptr
<cc::Layer
> ContentViewCoreImpl::GetLayer() const {
780 return root_layer_
.get();
783 // ----------------------------------------------------------------------------
784 // Methods called from Java via JNI
785 // ----------------------------------------------------------------------------
787 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv
* env
, jobject obj
,
789 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
790 web_contents_
->GetRenderViewHost());
792 if (indices
== NULL
) {
793 rvhi
->DidCancelPopupMenu();
797 int selected_count
= env
->GetArrayLength(indices
);
798 std::vector
<int> selected_indices
;
799 jint
* indices_ptr
= env
->GetIntArrayElements(indices
, NULL
);
800 for (int i
= 0; i
< selected_count
; ++i
)
801 selected_indices
.push_back(indices_ptr
[i
]);
802 env
->ReleaseIntArrayElements(indices
, indices_ptr
, JNI_ABORT
);
803 rvhi
->DidSelectPopupMenuItems(selected_indices
);
806 void ContentViewCoreImpl::LoadUrl(
807 JNIEnv
* env
, jobject obj
,
810 jint transition_type
,
811 jint ua_override_option
,
812 jstring extra_headers
,
813 jbyteArray post_data
,
814 jstring base_url_for_data_url
,
815 jstring virtual_url_for_data_url
,
816 jboolean can_load_local_resources
) {
818 NavigationController::LoadURLParams
params(
819 GURL(ConvertJavaStringToUTF8(env
, url
)));
821 params
.load_type
= static_cast<NavigationController::LoadURLType
>(
823 params
.transition_type
= PageTransitionFromInt(transition_type
);
824 params
.override_user_agent
=
825 static_cast<NavigationController::UserAgentOverrideOption
>(
829 params
.extra_headers
= ConvertJavaStringToUTF8(env
, extra_headers
);
832 std::vector
<uint8
> http_body_vector
;
833 base::android::JavaByteArrayToByteVector(env
, post_data
, &http_body_vector
);
834 params
.browser_initiated_post_data
=
835 base::RefCountedBytes::TakeVector(&http_body_vector
);
838 if (base_url_for_data_url
) {
839 params
.base_url_for_data_url
=
840 GURL(ConvertJavaStringToUTF8(env
, base_url_for_data_url
));
843 if (virtual_url_for_data_url
) {
844 params
.virtual_url_for_data_url
=
845 GURL(ConvertJavaStringToUTF8(env
, virtual_url_for_data_url
));
848 params
.can_load_local_resources
= can_load_local_resources
;
853 jint
ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv
* env
, jobject obj
) {
854 return GetRenderProcessIdFromRenderViewHost(
855 web_contents_
->GetRenderViewHost());
858 ScopedJavaLocalRef
<jstring
> ContentViewCoreImpl::GetURL(
859 JNIEnv
* env
, jobject
) const {
860 return ConvertUTF8ToJavaString(env
, GetWebContents()->GetURL().spec());
863 ScopedJavaLocalRef
<jstring
> ContentViewCoreImpl::GetTitle(
864 JNIEnv
* env
, jobject obj
) const {
865 return ConvertUTF16ToJavaString(env
, GetWebContents()->GetTitle());
868 jboolean
ContentViewCoreImpl::IsIncognito(JNIEnv
* env
, jobject obj
) {
869 return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
872 WebContents
* ContentViewCoreImpl::GetWebContents() const {
873 return web_contents_
;
876 void ContentViewCoreImpl::SetFocus(JNIEnv
* env
, jobject obj
, jboolean focused
) {
877 SetFocusInternal(focused
);
880 void ContentViewCoreImpl::SetFocusInternal(bool focused
) {
881 if (!GetRenderWidgetHostViewAndroid())
885 GetRenderWidgetHostViewAndroid()->Focus();
887 GetRenderWidgetHostViewAndroid()->Blur();
890 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv
* env
,
893 if (device_orientation_
!= orientation
) {
894 device_orientation_
= orientation
;
895 SendOrientationChangeEventInternal();
899 jboolean
ContentViewCoreImpl::SendTouchEvent(JNIEnv
* env
,
904 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
906 using blink::WebTouchEvent
;
907 blink::WebTouchEvent event
;
908 TouchPoint::BuildWebTouchEvent(env
, type
, time_ms
, GetDpiScale(), pts
,
910 rwhv
->SendTouchEvent(event
);
916 float ContentViewCoreImpl::GetTouchPaddingDip() {
917 return 48.0f
/ GetDpiScale();
920 float ContentViewCoreImpl::GetDpiScale() const {
924 void ContentViewCoreImpl::RequestContentClipping(
925 const gfx::Rect
& clipping
,
926 const gfx::Size
& content_size
) {
927 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
929 rwhv
->RequestContentClipping(clipping
, content_size
);
932 jboolean
ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv
* env
,
937 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
941 blink::WebMouseEvent event
= WebMouseEventBuilder::Build(
942 WebInputEvent::MouseMove
,
943 blink::WebMouseEvent::ButtonNone
,
944 time_ms
/ 1000.0, x
/ GetDpiScale(), y
/ GetDpiScale(), 0, 1);
946 rwhv
->SendMouseEvent(event
);
950 jboolean
ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv
* env
,
955 jfloat vertical_axis
) {
956 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
960 WebMouseWheelEventBuilder::Direction direction
;
961 if (vertical_axis
> 0) {
962 direction
= WebMouseWheelEventBuilder::DIRECTION_UP
;
963 } else if (vertical_axis
< 0) {
964 direction
= WebMouseWheelEventBuilder::DIRECTION_DOWN
;
968 blink::WebMouseWheelEvent event
= WebMouseWheelEventBuilder::Build(
969 direction
, time_ms
/ 1000.0, x
/ GetDpiScale(), y
/ GetDpiScale());
971 rwhv
->SendMouseWheelEvent(event
);
975 WebGestureEvent
ContentViewCoreImpl::MakeGestureEvent(
976 WebInputEvent::Type type
, int64 time_ms
, float x
, float y
) const {
977 return WebGestureEventBuilder::Build(
978 type
, time_ms
/ 1000.0, x
/ GetDpiScale(), y
/ GetDpiScale());
981 void ContentViewCoreImpl::SendGestureEvent(
982 const blink::WebGestureEvent
& event
) {
983 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
985 rwhv
->SendGestureEvent(event
);
988 void ContentViewCoreImpl::ScrollBegin(JNIEnv
* env
,
995 WebGestureEvent event
= MakeGestureEvent(
996 WebInputEvent::GestureScrollBegin
, time_ms
, x
, y
);
997 event
.data
.scrollBegin
.deltaXHint
= hintx
/ GetDpiScale();
998 event
.data
.scrollBegin
.deltaYHint
= hinty
/ GetDpiScale();
1000 SendGestureEvent(event
);
1003 void ContentViewCoreImpl::ScrollEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1004 WebGestureEvent event
= MakeGestureEvent(
1005 WebInputEvent::GestureScrollEnd
, time_ms
, 0, 0);
1006 SendGestureEvent(event
);
1009 void ContentViewCoreImpl::ScrollBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1010 jfloat x
, jfloat y
, jfloat dx
, jfloat dy
) {
1011 WebGestureEvent event
= MakeGestureEvent(
1012 WebInputEvent::GestureScrollUpdate
, time_ms
, x
, y
);
1013 event
.data
.scrollUpdate
.deltaX
= -dx
/ GetDpiScale();
1014 event
.data
.scrollUpdate
.deltaY
= -dy
/ GetDpiScale();
1016 SendGestureEvent(event
);
1019 void ContentViewCoreImpl::FlingStart(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1020 jfloat x
, jfloat y
, jfloat vx
, jfloat vy
) {
1021 WebGestureEvent event
= MakeGestureEvent(
1022 WebInputEvent::GestureFlingStart
, time_ms
, x
, y
);
1024 // Velocity should not be scaled by DIP since that interacts poorly with the
1025 // deceleration constants. The DIP scaling is done on the renderer.
1026 event
.data
.flingStart
.velocityX
= vx
;
1027 event
.data
.flingStart
.velocityY
= vy
;
1029 SendGestureEvent(event
);
1032 void ContentViewCoreImpl::FlingCancel(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1033 WebGestureEvent event
= MakeGestureEvent(
1034 WebInputEvent::GestureFlingCancel
, time_ms
, 0, 0);
1035 SendGestureEvent(event
);
1038 void ContentViewCoreImpl::SingleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1040 jboolean disambiguation_popup_tap
) {
1041 WebGestureEvent event
= MakeGestureEvent(
1042 WebInputEvent::GestureTap
, time_ms
, x
, y
);
1044 event
.data
.tap
.tapCount
= 1;
1045 if (!disambiguation_popup_tap
) {
1046 const float touch_padding_dip
= GetTouchPaddingDip();
1047 event
.data
.tap
.width
= touch_padding_dip
;
1048 event
.data
.tap
.height
= touch_padding_dip
;
1051 SendGestureEvent(event
);
1054 void ContentViewCoreImpl::SingleTapUnconfirmed(JNIEnv
* env
, jobject obj
,
1056 jfloat x
, jfloat y
) {
1057 WebGestureEvent event
= MakeGestureEvent(
1058 WebInputEvent::GestureTapUnconfirmed
, time_ms
, x
, y
);
1060 event
.data
.tap
.tapCount
= 1;
1062 const float touch_padding_dip
= GetTouchPaddingDip();
1063 event
.data
.tap
.width
= touch_padding_dip
;
1064 event
.data
.tap
.height
= touch_padding_dip
;
1066 SendGestureEvent(event
);
1069 void ContentViewCoreImpl::ShowPressState(JNIEnv
* env
, jobject obj
,
1071 jfloat x
, jfloat y
) {
1072 WebGestureEvent event
= MakeGestureEvent(
1073 WebInputEvent::GestureShowPress
, time_ms
, x
, y
);
1074 SendGestureEvent(event
);
1077 void ContentViewCoreImpl::TapCancel(JNIEnv
* env
,
1082 WebGestureEvent event
= MakeGestureEvent(
1083 WebInputEvent::GestureTapCancel
, time_ms
, x
, y
);
1084 SendGestureEvent(event
);
1087 void ContentViewCoreImpl::TapDown(JNIEnv
* env
, jobject obj
,
1089 jfloat x
, jfloat y
) {
1090 WebGestureEvent event
= MakeGestureEvent(
1091 WebInputEvent::GestureTapDown
, time_ms
, x
, y
);
1092 SendGestureEvent(event
);
1095 void ContentViewCoreImpl::DoubleTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1096 jfloat x
, jfloat y
) {
1097 WebGestureEvent event
= MakeGestureEvent(
1098 WebInputEvent::GestureDoubleTap
, time_ms
, x
, y
);
1099 SendGestureEvent(event
);
1102 void ContentViewCoreImpl::LongPress(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1104 jboolean disambiguation_popup_tap
) {
1105 WebGestureEvent event
= MakeGestureEvent(
1106 WebInputEvent::GestureLongPress
, time_ms
, x
, y
);
1108 if (!disambiguation_popup_tap
) {
1109 const float touch_padding_dip
= GetTouchPaddingDip();
1110 event
.data
.longPress
.width
= touch_padding_dip
;
1111 event
.data
.longPress
.height
= touch_padding_dip
;
1114 SendGestureEvent(event
);
1117 void ContentViewCoreImpl::LongTap(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1119 jboolean disambiguation_popup_tap
) {
1120 WebGestureEvent event
= MakeGestureEvent(
1121 WebInputEvent::GestureLongTap
, time_ms
, x
, y
);
1123 if (!disambiguation_popup_tap
) {
1124 const float touch_padding_dip
= GetTouchPaddingDip();
1125 event
.data
.longPress
.width
= touch_padding_dip
;
1126 event
.data
.longPress
.height
= touch_padding_dip
;
1129 SendGestureEvent(event
);
1132 void ContentViewCoreImpl::PinchBegin(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1133 jfloat x
, jfloat y
) {
1134 WebGestureEvent event
= MakeGestureEvent(
1135 WebInputEvent::GesturePinchBegin
, time_ms
, x
, y
);
1136 SendGestureEvent(event
);
1139 void ContentViewCoreImpl::PinchEnd(JNIEnv
* env
, jobject obj
, jlong time_ms
) {
1140 WebGestureEvent event
= MakeGestureEvent(
1141 WebInputEvent::GesturePinchEnd
, time_ms
, 0, 0);
1142 SendGestureEvent(event
);
1145 void ContentViewCoreImpl::PinchBy(JNIEnv
* env
, jobject obj
, jlong time_ms
,
1146 jfloat anchor_x
, jfloat anchor_y
,
1148 WebGestureEvent event
= MakeGestureEvent(
1149 WebInputEvent::GesturePinchUpdate
, time_ms
, anchor_x
, anchor_y
);
1150 event
.data
.pinchUpdate
.scale
= delta
;
1152 SendGestureEvent(event
);
1155 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv
* env
, jobject obj
,
1156 jfloat x1
, jfloat y1
,
1157 jfloat x2
, jfloat y2
) {
1158 if (GetRenderWidgetHostViewAndroid()) {
1159 GetRenderWidgetHostViewAndroid()->SelectRange(
1160 gfx::Point(x1
/ GetDpiScale(), y1
/ GetDpiScale()),
1161 gfx::Point(x2
/ GetDpiScale(), y2
/ GetDpiScale()));
1165 void ContentViewCoreImpl::MoveCaret(JNIEnv
* env
, jobject obj
,
1166 jfloat x
, jfloat y
) {
1167 if (GetRenderWidgetHostViewAndroid()) {
1168 GetRenderWidgetHostViewAndroid()->MoveCaret(
1169 gfx::Point(x
/ GetDpiScale(), y
/ GetDpiScale()));
1173 void ContentViewCoreImpl::LoadIfNecessary(JNIEnv
* env
, jobject obj
) {
1174 web_contents_
->GetController().LoadIfNecessary();
1177 void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv
* env
, jobject obj
) {
1178 web_contents_
->GetController().SetNeedsReload();
1181 void ContentViewCoreImpl::StopLoading(JNIEnv
* env
, jobject obj
) {
1182 web_contents_
->Stop();
1185 void ContentViewCoreImpl::Reload(JNIEnv
* env
,
1187 jboolean check_for_repost
) {
1188 if (web_contents_
->GetController().NeedsReload())
1189 web_contents_
->GetController().LoadIfNecessary();
1191 web_contents_
->GetController().Reload(check_for_repost
);
1194 void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv
* env
,
1196 jboolean check_for_repost
) {
1197 web_contents_
->GetController().ReloadIgnoringCache(check_for_repost
);
1200 void ContentViewCoreImpl::CancelPendingReload(JNIEnv
* env
, jobject obj
) {
1201 web_contents_
->GetController().CancelPendingReload();
1204 void ContentViewCoreImpl::ContinuePendingReload(JNIEnv
* env
, jobject obj
) {
1205 web_contents_
->GetController().ContinuePendingReload();
1208 void ContentViewCoreImpl::ClearHistory(JNIEnv
* env
, jobject obj
) {
1209 // TODO(creis): Do callers of this need to know if it fails?
1210 if (web_contents_
->GetController().CanPruneAllButLastCommitted())
1211 web_contents_
->GetController().PruneAllButLastCommitted();
1214 void ContentViewCoreImpl::AddJavascriptInterface(
1219 jclass safe_annotation_clazz
,
1220 jobject retained_object_set
) {
1221 ScopedJavaLocalRef
<jobject
> scoped_object(env
, object
);
1222 ScopedJavaLocalRef
<jclass
> scoped_clazz(env
, safe_annotation_clazz
);
1223 JavaObjectWeakGlobalRef
weak_retained_object_set(env
, retained_object_set
);
1225 // JavaBoundObject creates the NPObject with a ref count of 1, and
1226 // JavaBridgeDispatcherHostManager takes its own ref.
1227 JavaBridgeDispatcherHostManager
* java_bridge
=
1228 web_contents_
->java_bridge_dispatcher_host_manager();
1229 java_bridge
->SetRetainedObjectSet(weak_retained_object_set
);
1230 NPObject
* bound_object
= JavaBoundObject::Create(scoped_object
, scoped_clazz
,
1231 java_bridge
->AsWeakPtr());
1232 java_bridge
->AddNamedObject(ConvertJavaStringToUTF16(env
, name
),
1234 blink::WebBindings::releaseObject(bound_object
);
1237 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv
* env
,
1240 web_contents_
->java_bridge_dispatcher_host_manager()->RemoveNamedObject(
1241 ConvertJavaStringToUTF16(env
, name
));
1244 void ContentViewCoreImpl::UpdateVSyncParameters(JNIEnv
* env
, jobject
/* obj */,
1245 jlong timebase_micros
,
1246 jlong interval_micros
) {
1247 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1251 RenderWidgetHostImpl
* host
= RenderWidgetHostImpl::From(
1252 view
->GetRenderWidgetHost());
1254 host
->UpdateVSyncParameters(
1255 base::TimeTicks::FromInternalValue(timebase_micros
),
1256 base::TimeDelta::FromMicroseconds(interval_micros
));
1259 base::TimeDelta::FromMicroseconds(interval_micros
);
1260 expected_browser_composite_time_
=
1261 vsync_interval_
* kDefaultBrowserCompositeVSyncFraction
;
1264 void ContentViewCoreImpl::OnVSync(JNIEnv
* env
, jobject
/* obj */,
1265 jlong frame_time_micros
) {
1266 base::TimeTicks frame_time
=
1267 base::TimeTicks::FromInternalValue(frame_time_micros
);
1268 SendBeginFrame(frame_time
);
1271 void ContentViewCoreImpl::SendBeginFrame(base::TimeTicks frame_time
) {
1272 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1276 base::TimeTicks display_time
= frame_time
+ vsync_interval_
;
1277 base::TimeTicks deadline
= display_time
- expected_browser_composite_time_
;
1279 view
->SendBeginFrame(
1280 cc::BeginFrameArgs::Create(frame_time
, deadline
, vsync_interval_
));
1283 jboolean
ContentViewCoreImpl::OnAnimate(JNIEnv
* env
, jobject
/* obj */,
1284 jlong frame_time_micros
) {
1285 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1289 return view
->Animate(base::TimeTicks::FromInternalValue(frame_time_micros
));
1292 jboolean
ContentViewCoreImpl::PopulateBitmapFromCompositor(JNIEnv
* env
,
1295 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1299 return view
->PopulateBitmapWithContents(jbitmap
);
1302 void ContentViewCoreImpl::WasResized(JNIEnv
* env
, jobject obj
) {
1303 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1308 void ContentViewCoreImpl::ShowInterstitialPage(
1309 JNIEnv
* env
, jobject obj
, jstring jurl
, jint delegate_ptr
) {
1310 GURL
url(base::android::ConvertJavaStringToUTF8(env
, jurl
));
1311 InterstitialPageDelegateAndroid
* delegate
=
1312 reinterpret_cast<InterstitialPageDelegateAndroid
*>(delegate_ptr
);
1313 InterstitialPage
* interstitial
= InterstitialPage::Create(
1314 web_contents_
, false, url
, delegate
);
1315 delegate
->set_interstitial_page(interstitial
);
1316 interstitial
->Show();
1319 jboolean
ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv
* env
,
1321 return web_contents_
->ShowingInterstitialPage();
1324 void ContentViewCoreImpl::AttachExternalVideoSurface(JNIEnv
* env
,
1328 #if defined(VIDEO_HOLE)
1329 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
1330 web_contents_
->GetRenderViewHost());
1331 if (rvhi
&& rvhi
->media_player_manager()) {
1332 rvhi
->media_player_manager()->AttachExternalVideoSurface(
1333 static_cast<int>(player_id
), jsurface
);
1335 #endif // defined(VIDEO_HOLE)
1338 void ContentViewCoreImpl::DetachExternalVideoSurface(JNIEnv
* env
,
1341 #if defined(VIDEO_HOLE)
1342 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
1343 web_contents_
->GetRenderViewHost());
1344 if (rvhi
&& rvhi
->media_player_manager()) {
1345 rvhi
->media_player_manager()->DetachExternalVideoSurface(
1346 static_cast<int>(player_id
));
1348 #endif // defined(VIDEO_HOLE)
1351 jboolean
ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv
* env
,
1353 RenderWidgetHostViewAndroid
* view
= GetRenderWidgetHostViewAndroid();
1354 return view
&& view
->HasValidFrame();
1357 void ContentViewCoreImpl::ExitFullscreen(JNIEnv
* env
, jobject obj
) {
1358 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1361 host
->ExitFullscreen();
1364 void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv
* env
,
1367 bool enable_showing
,
1369 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1372 host
->Send(new ViewMsg_UpdateTopControlsState(host
->GetRoutingID(),
1378 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv
* env
, jobject obj
) {
1379 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1380 host
->Send(new ViewMsg_ShowImeIfNeeded(host
->GetRoutingID()));
1383 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv
* env
,
1385 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1386 host
->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
1387 host
->GetRoutingID(), gfx::Rect()));
1392 static void AddNavigationEntryToHistory(JNIEnv
* env
, jobject obj
,
1394 NavigationEntry
* entry
,
1396 // Get the details of the current entry
1397 ScopedJavaLocalRef
<jstring
> j_url(
1398 ConvertUTF8ToJavaString(env
, entry
->GetURL().spec()));
1399 ScopedJavaLocalRef
<jstring
> j_virtual_url(
1400 ConvertUTF8ToJavaString(env
, entry
->GetVirtualURL().spec()));
1401 ScopedJavaLocalRef
<jstring
> j_original_url(
1402 ConvertUTF8ToJavaString(env
, entry
->GetOriginalRequestURL().spec()));
1403 ScopedJavaLocalRef
<jstring
> j_title(
1404 ConvertUTF16ToJavaString(env
, entry
->GetTitle()));
1405 ScopedJavaLocalRef
<jobject
> j_bitmap
;
1406 const FaviconStatus
& status
= entry
->GetFavicon();
1407 if (status
.valid
&& status
.image
.ToSkBitmap()->getSize() > 0)
1408 j_bitmap
= gfx::ConvertToJavaBitmap(status
.image
.ToSkBitmap());
1410 // Add the item to the list
1411 Java_ContentViewCore_addToNavigationHistory(
1412 env
, obj
, history
, index
, j_url
.obj(), j_virtual_url
.obj(),
1413 j_original_url
.obj(), j_title
.obj(), j_bitmap
.obj());
1418 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv
* env
,
1421 // Iterate through navigation entries to populate the list
1422 const NavigationController
& controller
= web_contents_
->GetController();
1423 int count
= controller
.GetEntryCount();
1424 for (int i
= 0; i
< count
; ++i
) {
1425 AddNavigationEntryToHistory(
1426 env
, obj
, history
, controller
.GetEntryAtIndex(i
), i
);
1429 return controller
.GetCurrentEntryIndex();
1432 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv
* env
,
1435 jboolean is_forward
,
1437 // Iterate through navigation entries to populate the list
1438 const NavigationController
& controller
= web_contents_
->GetController();
1439 int count
= controller
.GetEntryCount();
1441 int increment_value
= is_forward
? 1 : -1;
1442 for (int i
= controller
.GetCurrentEntryIndex() + increment_value
;
1443 i
>= 0 && i
< count
;
1444 i
+= increment_value
) {
1445 if (num_added
>= max_entries
)
1448 AddNavigationEntryToHistory(
1449 env
, obj
, history
, controller
.GetEntryAtIndex(i
), i
);
1454 ScopedJavaLocalRef
<jstring
>
1455 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv
* env
,
1457 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1459 return ScopedJavaLocalRef
<jstring
>(env
, NULL
);
1460 return ConvertUTF8ToJavaString(env
, entry
->GetOriginalRequestURL().spec());
1463 int ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv
* env
, jobject obj
) {
1464 RenderWidgetHostViewAndroid
* rwhva
= GetRenderWidgetHostViewAndroid();
1467 return rwhva
->GetNativeImeAdapter();
1470 void ContentViewCoreImpl::UndoScrollFocusedEditableNodeIntoView(
1473 RenderViewHost
* host
= web_contents_
->GetRenderViewHost();
1475 new ViewMsg_UndoScrollFocusedEditableNodeIntoView(host
->GetRoutingID()));
1479 void JavaScriptResultCallback(const ScopedJavaGlobalRef
<jobject
>& callback
,
1480 const base::Value
* result
) {
1481 JNIEnv
* env
= base::android::AttachCurrentThread();
1483 base::JSONWriter::Write(result
, &json
);
1484 ScopedJavaLocalRef
<jstring
> j_json
= ConvertUTF8ToJavaString(env
, json
);
1485 Java_ContentViewCore_onEvaluateJavaScriptResult(env
,
1491 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv
* env
,
1495 jboolean start_renderer
) {
1496 RenderViewHost
* rvh
= web_contents_
->GetRenderViewHost();
1499 if (start_renderer
&& !rvh
->IsRenderViewLive()) {
1500 if (!web_contents_
->CreateRenderViewForInitialEmptyDocument()) {
1501 LOG(ERROR
) << "Failed to create RenderView in EvaluateJavaScript";
1507 // No callback requested.
1508 rvh
->ExecuteJavascriptInWebFrame(base::string16(), // frame_xpath
1509 ConvertJavaStringToUTF16(env
, script
));
1513 // Secure the Java callback in a scoped object and give ownership of it to the
1515 ScopedJavaGlobalRef
<jobject
> j_callback
;
1516 j_callback
.Reset(env
, callback
);
1517 content::RenderViewHost::JavascriptResultCallback c_callback
=
1518 base::Bind(&JavaScriptResultCallback
, j_callback
);
1520 rvh
->ExecuteJavascriptInWebFrameCallbackResult(
1521 base::string16(), // frame_xpath
1522 ConvertJavaStringToUTF16(env
, script
),
1526 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
1527 JNIEnv
* env
, jobject obj
) {
1528 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1529 return entry
&& entry
->GetIsOverridingUserAgent();
1532 void ContentViewCoreImpl::UpdateImeAdapter(int native_ime_adapter
,
1533 int text_input_type
,
1534 const std::string
& text
,
1535 int selection_start
,
1537 int composition_start
,
1538 int composition_end
,
1539 bool show_ime_if_needed
,
1541 JNIEnv
* env
= AttachCurrentThread();
1542 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1546 ScopedJavaLocalRef
<jstring
> jstring_text
= ConvertUTF8ToJavaString(env
, text
);
1547 Java_ContentViewCore_updateImeAdapter(env
, obj
.obj(),
1548 native_ime_adapter
, text_input_type
,
1550 selection_start
, selection_end
,
1551 composition_start
, composition_end
,
1552 show_ime_if_needed
, require_ack
);
1555 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv
* env
, jobject obj
) {
1556 SSLHostState
* state
= SSLHostState::GetFor(
1557 web_contents_
->GetController().GetBrowserContext());
1561 void ContentViewCoreImpl::SetUseDesktopUserAgent(
1565 jboolean reload_on_state_change
) {
1566 if (GetUseDesktopUserAgent(env
, obj
) == enabled
)
1569 // Make sure the navigation entry actually exists.
1570 NavigationEntry
* entry
= web_contents_
->GetController().GetVisibleEntry();
1574 // Set the flag in the NavigationEntry.
1575 entry
->SetIsOverridingUserAgent(enabled
);
1577 // Send the override to the renderer.
1578 if (reload_on_state_change
) {
1579 // Reloading the page will send the override down as part of the
1580 // navigation IPC message.
1581 NavigationControllerImpl
& controller
=
1582 static_cast<NavigationControllerImpl
&>(web_contents_
->GetController());
1583 controller
.ReloadOriginalRequestURL(false);
1587 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv
* env
, jobject obj
,
1589 RenderWidgetHostViewAndroid
* host_view
= GetRenderWidgetHostViewAndroid();
1592 RenderWidgetHostImpl
* host_impl
= RenderWidgetHostImpl::From(
1593 host_view
->GetRenderWidgetHost());
1594 BrowserAccessibilityState
* accessibility_state
=
1595 BrowserAccessibilityState::GetInstance();
1597 // This enables accessibility globally unless it was explicitly disallowed
1598 // by a command-line flag.
1599 accessibility_state
->OnScreenReaderDetected();
1600 // If it was actually enabled globally, enable it for this RenderWidget now.
1601 if (accessibility_state
->IsAccessibleBrowser() && host_impl
)
1602 host_impl
->SetAccessibilityMode(AccessibilityModeComplete
);
1604 accessibility_state
->DisableAccessibility();
1606 host_impl
->SetAccessibilityMode(AccessibilityModeOff
);
1610 void ContentViewCoreImpl::SendSingleTapUma(JNIEnv
* env
,
1614 UMA_HISTOGRAM_ENUMERATION("Event.SingleTapType", type
, count
);
1617 void ContentViewCoreImpl::SendActionAfterDoubleTapUma(JNIEnv
* env
,
1622 // This UMA stat tracks a user's action after a double tap within
1623 // k seconds (where k == 5 currently). This UMA will tell us if
1624 // removing the tap gesture delay will lead to significantly more
1625 // accidental navigations after a double tap.
1627 UMA_HISTOGRAM_ENUMERATION("Event.ActionAfterDoubleTapWithDelay", type
,
1630 UMA_HISTOGRAM_ENUMERATION("Event.ActionAfterDoubleTapNoDelay", type
,
1635 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1636 RenderWidgetHostViewAndroid
* rwhv
= GetRenderWidgetHostViewAndroid();
1638 rwhv
->UpdateScreenInfo(rwhv
->GetNativeView());
1640 RenderViewHostImpl
* rvhi
= static_cast<RenderViewHostImpl
*>(
1641 web_contents_
->GetRenderViewHost());
1642 rvhi
->SendOrientationChangeEvent(device_orientation_
);
1645 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv
* env
,
1652 static_cast<int>(x
/ GetDpiScale()),
1653 static_cast<int>(y
/ GetDpiScale()),
1654 static_cast<int>((width
> 0 && width
< GetDpiScale()) ?
1655 1 : (int)(width
/ GetDpiScale())),
1656 static_cast<int>((height
> 0 && height
< GetDpiScale()) ?
1657 1 : (int)(height
/ GetDpiScale())));
1658 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1659 GetWebContents()->GetRoutingID(), rect
));
1662 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1663 const base::string16
& result
) {
1664 JNIEnv
* env
= AttachCurrentThread();
1665 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
1668 ScopedJavaLocalRef
<jstring
> jresult
= ConvertUTF16ToJavaString(env
, result
);
1669 Java_ContentViewCore_onSmartClipDataExtracted(
1670 env
, obj
.obj(), jresult
.obj());
1673 // This is called for each ContentView.
1674 jlong
Init(JNIEnv
* env
, jobject obj
,
1675 jboolean hardware_accelerated
,
1676 jlong native_web_contents
,
1678 jlong window_android
) {
1679 ContentViewCoreImpl
* view
= new ContentViewCoreImpl(
1680 env
, obj
, hardware_accelerated
,
1681 reinterpret_cast<WebContents
*>(native_web_contents
),
1682 reinterpret_cast<ui::ViewAndroid
*>(view_android
),
1683 reinterpret_cast<ui::WindowAndroid
*>(window_android
));
1684 return reinterpret_cast<intptr_t>(view
);
1687 bool RegisterContentViewCore(JNIEnv
* env
) {
1688 return RegisterNativesImpl(env
);
1691 } // namespace content