1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/content_view_core_impl.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/command_line.h"
12 #include "base/json/json_writer.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/values.h"
17 #include "cc/layers/layer.h"
18 #include "cc/layers/solid_color_layer.h"
19 #include "cc/output/begin_frame_args.h"
20 #include "content/browser/android/gesture_event_type.h"
21 #include "content/browser/android/interstitial_page_delegate_android.h"
22 #include "content/browser/android/load_url_params.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/motion_event_android.h"
29 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
30 #include "content/browser/renderer_host/input/web_input_event_util.h"
31 #include "content/browser/renderer_host/java/java_bound_object.h"
32 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
33 #include "content/browser/renderer_host/render_view_host_impl.h"
34 #include "content/browser/renderer_host/render_widget_host_impl.h"
35 #include "content/browser/renderer_host/render_widget_host_view_android.h"
36 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
37 #include "content/browser/ssl/ssl_host_state.h"
38 #include "content/browser/web_contents/web_contents_view_android.h"
39 #include "content/common/input/web_input_event_traits.h"
40 #include "content/common/input_messages.h"
41 #include "content/common/view_messages.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/gfx/android/java_bitmap.h"
62 #include "ui/gfx/screen.h"
63 #include "ui/gfx/size_conversions.h"
64 #include "ui/gfx/size_f.h"
66 using base::android::AttachCurrentThread;
67 using base::android::ConvertJavaStringToUTF16;
68 using base::android::ConvertJavaStringToUTF8;
69 using base::android::ConvertUTF16ToJavaString;
70 using base::android::ConvertUTF8ToJavaString;
71 using base::android::ScopedJavaGlobalRef;
72 using base::android::ScopedJavaLocalRef;
73 using blink::WebGestureEvent;
74 using blink::WebInputEvent;
76 // Describes the type and enabled state of a select popup item.
80 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
81 #include "content/browser/android/popup_item_type_list.h"
82 #undef DEFINE_POPUP_ITEM_TYPE
91 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
93 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
95 RenderProcessHost* render_process = host->GetProcess();
96 DCHECK(render_process);
97 if (render_process->HasConnection())
98 return render_process->GetHandle();
103 ScopedJavaLocalRef<jobject> CreateJavaRect(
105 const gfx::Rect& rect) {
106 return ScopedJavaLocalRef<jobject>(
107 Java_ContentViewCore_createRect(env,
108 static_cast<int>(rect.x()),
109 static_cast<int>(rect.y()),
110 static_cast<int>(rect.right()),
111 static_cast<int>(rect.bottom())));
114 int ToGestureEventType(WebInputEvent::Type type) {
116 case WebInputEvent::GestureScrollBegin:
118 case WebInputEvent::GestureScrollEnd:
120 case WebInputEvent::GestureScrollUpdate:
122 case WebInputEvent::GestureFlingStart:
124 case WebInputEvent::GestureFlingCancel:
126 case WebInputEvent::GestureShowPress:
128 case WebInputEvent::GestureTap:
129 return SINGLE_TAP_CONFIRMED;
130 case WebInputEvent::GestureTapUnconfirmed:
131 return SINGLE_TAP_UNCONFIRMED;
132 case WebInputEvent::GestureTapDown:
134 case WebInputEvent::GestureTapCancel:
136 case WebInputEvent::GestureDoubleTap:
138 case WebInputEvent::GestureLongPress:
140 case WebInputEvent::GestureLongTap:
142 case WebInputEvent::GesturePinchBegin:
144 case WebInputEvent::GesturePinchEnd:
146 case WebInputEvent::GesturePinchUpdate:
148 case WebInputEvent::GestureTwoFingerTap:
149 case WebInputEvent::GestureScrollUpdateWithoutPropagation:
151 NOTREACHED() << "Invalid source gesture type: "
152 << WebInputEventTraits::GetName(type);
157 float GetPrimaryDisplayDeviceScaleFactor() {
158 const gfx::Display& display =
159 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
160 return display.device_scale_factor();
165 // Enables a callback when the underlying WebContents is destroyed, to enable
166 // nulling the back-pointer.
167 class ContentViewCoreImpl::ContentViewUserData
168 : public base::SupportsUserData::Data {
170 explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
171 : content_view_core_(content_view_core) {
174 virtual ~ContentViewUserData() {
175 // TODO(joth): When chrome has finished removing the TabContents class (see
176 // crbug.com/107201) consider inverting relationship, so ContentViewCore
177 // would own WebContents. That effectively implies making the WebContents
178 // destructor private on Android.
179 delete content_view_core_;
182 ContentViewCoreImpl* get() const { return content_view_core_; }
185 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
186 ContentViewCoreImpl* content_view_core_;
188 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
192 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
193 content::WebContents* web_contents) {
194 ContentViewCoreImpl::ContentViewUserData* data =
195 reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
196 web_contents->GetUserData(kContentViewUserDataKey));
197 return data ? data->get() : NULL;
201 ContentViewCore* ContentViewCore::FromWebContents(
202 content::WebContents* web_contents) {
203 return ContentViewCoreImpl::FromWebContents(web_contents);
207 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
209 return reinterpret_cast<ContentViewCore*>(
210 Java_ContentViewCore_getNativeContentViewCore(env, obj));
213 ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env,
215 WebContents* web_contents,
216 ui::ViewAndroid* view_android,
217 ui::WindowAndroid* window_android)
218 : WebContentsObserver(web_contents),
220 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
221 root_layer_(cc::SolidColorLayer::Create()),
222 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
223 view_android_(view_android),
224 window_android_(window_android),
225 device_orientation_(0),
226 geolocation_needs_pause_(false),
227 accessibility_enabled_(false) {
228 CHECK(web_contents) <<
229 "A ContentViewCoreImpl should be created with a valid WebContents.";
231 root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj));
232 gfx::Size physical_size(
233 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
234 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
235 root_layer_->SetBounds(physical_size);
236 root_layer_->SetIsDrawable(true);
238 // Currently, the only use case we have for overriding a user agent involves
239 // spoofing a desktop Linux user agent for "Request desktop site".
240 // Automatically set it for all WebContents so that it is available when a
241 // NavigationEntry requires the user agent to be overridden.
242 const char kLinuxInfoStr[] = "X11; Linux x86_64";
243 std::string product = content::GetContentClient()->GetProduct();
244 std::string spoofed_ua =
245 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
246 web_contents->SetUserAgentOverride(spoofed_ua);
251 ContentViewCoreImpl::~ContentViewCoreImpl() {
252 JNIEnv* env = base::android::AttachCurrentThread();
253 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
255 if (!j_obj.is_null()) {
256 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
257 env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
259 // Make sure nobody calls back into this object while we are tearing things
261 notification_registrar_.RemoveAll();
264 base::android::ScopedJavaLocalRef<jobject>
265 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
266 return web_contents_->GetJavaWebContents();
269 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
271 DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
275 void ContentViewCoreImpl::InitWebContents() {
276 DCHECK(web_contents_);
277 notification_registrar_.Add(
278 this, NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
279 Source<WebContents>(web_contents_));
280 notification_registrar_.Add(
281 this, NOTIFICATION_RENDERER_PROCESS_CREATED,
282 content::NotificationService::AllBrowserContextsAndSources());
283 notification_registrar_.Add(
284 this, NOTIFICATION_WEB_CONTENTS_CONNECTED,
285 Source<WebContents>(web_contents_));
287 static_cast<WebContentsViewAndroid*>(
288 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
289 SetContentViewCore(this);
290 DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
291 web_contents_->SetUserData(kContentViewUserDataKey,
292 new ContentViewUserData(this));
295 void ContentViewCoreImpl::Observe(int type,
296 const NotificationSource& source,
297 const NotificationDetails& details) {
299 case NOTIFICATION_RENDER_VIEW_HOST_CHANGED: {
300 std::pair<RenderViewHost*, RenderViewHost*>* switched_details =
301 Details<std::pair<RenderViewHost*, RenderViewHost*> >(details).ptr();
303 if (switched_details->first) {
304 old_pid = GetRenderProcessIdFromRenderViewHost(
305 switched_details->first);
307 RenderWidgetHostViewAndroid* view =
308 static_cast<RenderWidgetHostViewAndroid*>(
309 switched_details->first->GetView());
311 view->SetContentViewCore(NULL);
313 view = static_cast<RenderWidgetHostViewAndroid*>(
314 switched_details->second->GetView());
317 view->SetContentViewCore(this);
319 int new_pid = GetRenderProcessIdFromRenderViewHost(
320 web_contents_->GetRenderViewHost());
321 if (new_pid != old_pid) {
322 // Notify the Java side of the change of the current renderer process.
323 JNIEnv* env = AttachCurrentThread();
324 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
325 if (!obj.is_null()) {
326 Java_ContentViewCore_onRenderProcessSwap(env, obj.obj());
329 SetFocusInternal(HasFocus());
330 if (geolocation_needs_pause_)
331 PauseOrResumeGeolocation(true);
333 SetAccessibilityEnabledInternal(accessibility_enabled_);
336 case NOTIFICATION_RENDERER_PROCESS_CREATED: {
337 // Notify the Java side of the current renderer process.
338 RenderProcessHost* source_process_host =
339 Source<RenderProcessHost>(source).ptr();
340 RenderProcessHost* current_process_host =
341 web_contents_->GetRenderViewHost()->GetProcess();
343 if (source_process_host == current_process_host) {
344 JNIEnv* env = AttachCurrentThread();
345 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
346 if (!obj.is_null()) {
347 Java_ContentViewCore_onRenderProcessSwap(env, obj.obj());
352 case NOTIFICATION_WEB_CONTENTS_CONNECTED: {
353 JNIEnv* env = AttachCurrentThread();
354 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
355 if (!obj.is_null()) {
356 Java_ContentViewCore_onWebContentsConnected(env, obj.obj());
363 void ContentViewCoreImpl::RenderViewReady() {
364 if (device_orientation_ != 0)
365 SendOrientationChangeEventInternal();
368 RenderWidgetHostViewAndroid*
369 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
370 RenderWidgetHostView* rwhv = NULL;
372 rwhv = web_contents_->GetRenderWidgetHostView();
373 if (web_contents_->ShowingInterstitialPage()) {
374 rwhv = static_cast<InterstitialPageImpl*>(
375 web_contents_->GetInterstitialPage())->
376 GetRenderViewHost()->GetView();
379 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
382 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
383 JNIEnv* env = AttachCurrentThread();
384 return java_ref_.get(env);
387 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
388 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
390 return SK_ColorWHITE;
391 return rwhva->GetCachedBackgroundColor();
394 void ContentViewCoreImpl::OnHide(JNIEnv* env, jobject obj) {
398 void ContentViewCoreImpl::OnShow(JNIEnv* env, jobject obj) {
402 void ContentViewCoreImpl::Show() {
403 GetWebContents()->WasShown();
406 void ContentViewCoreImpl::Hide() {
407 GetWebContents()->WasHidden();
411 void ContentViewCoreImpl::PauseVideo() {
412 RenderViewHost* host = web_contents_->GetRenderViewHost();
414 host->Send(new ViewMsg_PauseVideo(host->GetRoutingID()));
417 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
418 geolocation_needs_pause_ = should_pause;
419 RenderViewHostImpl* rvh =
420 static_cast<RenderViewHostImpl*>(web_contents_->GetRenderViewHost());
422 scoped_refptr<GeolocationDispatcherHost> geolocation_dispatcher =
423 static_cast<RenderProcessHostImpl*>(
424 web_contents_->GetRenderProcessHost())->
425 geolocation_dispatcher_host();
426 if (geolocation_dispatcher.get()) {
427 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
428 base::Bind(&GeolocationDispatcherHost::PauseOrResume,
429 geolocation_dispatcher,
432 geolocation_needs_pause_ = false;
437 // All positions and sizes are in CSS pixels.
438 // Note that viewport_width/height is a best effort based.
439 // ContentViewCore has the actual information about the physical viewport size.
440 void ContentViewCoreImpl::UpdateFrameInfo(
441 const gfx::Vector2dF& scroll_offset,
442 float page_scale_factor,
443 const gfx::Vector2dF& page_scale_factor_limits,
444 const gfx::SizeF& content_size,
445 const gfx::SizeF& viewport_size,
446 const gfx::Vector2dF& controls_offset,
447 const gfx::Vector2dF& content_offset,
448 float overdraw_bottom_height) {
449 JNIEnv* env = AttachCurrentThread();
450 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
454 if (window_android_) {
455 gfx::Vector2dF window_offset(
456 Java_ContentViewCore_getLocationInWindowX(env, obj.obj()),
457 Java_ContentViewCore_getLocationInWindowY(env, obj.obj()));
458 window_android_->set_content_offset(
459 gfx::ScaleVector2d(content_offset, dpi_scale_) + window_offset);
462 Java_ContentViewCore_updateFrameInfo(
467 page_scale_factor_limits.x(),
468 page_scale_factor_limits.y(),
469 content_size.width(),
470 content_size.height(),
471 viewport_size.width(),
472 viewport_size.height(),
475 overdraw_bottom_height);
478 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
479 JNIEnv* env = AttachCurrentThread();
480 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
483 ScopedJavaLocalRef<jstring> jtitle =
484 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
485 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
488 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
489 root_layer_->SetBackgroundColor(color);
491 JNIEnv* env = AttachCurrentThread();
492 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
495 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
498 void ContentViewCoreImpl::ShowSelectPopupMenu(const gfx::Rect& bounds,
499 const std::vector<MenuItem>& items, int selected_item, bool multiple) {
500 JNIEnv* env = AttachCurrentThread();
501 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
505 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
507 // For multi-select list popups we find the list of previous selections by
508 // iterating through the items. But for single selection popups we take the
509 // given |selected_item| as is.
510 ScopedJavaLocalRef<jintArray> selected_array;
512 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
513 size_t selected_count = 0;
514 for (size_t i = 0; i < items.size(); ++i) {
515 if (items[i].checked)
516 native_selected_array[selected_count++] = i;
519 selected_array = ScopedJavaLocalRef<jintArray>(
520 env, env->NewIntArray(selected_count));
521 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
522 native_selected_array.get());
524 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
525 jint value = selected_item;
526 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
529 ScopedJavaLocalRef<jintArray> enabled_array(env,
530 env->NewIntArray(items.size()));
531 std::vector<base::string16> labels;
532 labels.reserve(items.size());
533 for (size_t i = 0; i < items.size(); ++i) {
534 labels.push_back(items[i].label);
536 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
537 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
538 POPUP_ITEM_TYPE_DISABLED));
539 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
541 ScopedJavaLocalRef<jobjectArray> items_array(
542 base::android::ToJavaArrayOfStrings(env, labels));
543 Java_ContentViewCore_showSelectPopup(env, j_obj.obj(),
548 selected_array.obj());
551 void ContentViewCoreImpl::HideSelectPopupMenu() {
552 JNIEnv* env = AttachCurrentThread();
553 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
554 if (!j_obj.is_null())
555 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
558 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
559 InputEventAckState ack_result) {
560 JNIEnv* env = AttachCurrentThread();
561 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
565 switch (event.type) {
566 case WebInputEvent::GestureFlingStart:
567 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
568 // The view expects the fling velocity in pixels/s.
569 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
570 event.data.flingStart.velocityX * dpi_scale(),
571 event.data.flingStart.velocityY * dpi_scale());
573 // If a scroll ends with a fling, a SCROLL_END event is never sent.
574 // However, if that fling went unconsumed, we still need to let the
575 // listeners know that scrolling has ended.
576 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
579 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
580 // The view expects the fling velocity in pixels/s.
581 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
582 event.data.flingStart.velocityX * dpi_scale(),
583 event.data.flingStart.velocityY * dpi_scale());
586 case WebInputEvent::GestureFlingCancel:
587 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
589 case WebInputEvent::GestureScrollBegin:
590 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
592 case WebInputEvent::GestureScrollUpdate:
593 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
594 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
596 case WebInputEvent::GestureScrollEnd:
597 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
599 case WebInputEvent::GesturePinchBegin:
600 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
602 case WebInputEvent::GesturePinchEnd:
603 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
605 case WebInputEvent::GestureTap:
606 if (ack_result != INPUT_EVENT_ACK_STATE_CONSUMED) {
607 Java_ContentViewCore_onTapEventNotConsumed(
608 env, j_obj.obj(), event.x * dpi_scale(), event.y * dpi_scale());
611 case WebInputEvent::GestureDoubleTap:
612 Java_ContentViewCore_onDoubleTapEventAck(env, j_obj.obj());
619 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
620 if (event.type != WebInputEvent::GestureTap &&
621 event.type != WebInputEvent::GestureDoubleTap &&
622 event.type != WebInputEvent::GestureLongTap &&
623 event.type != WebInputEvent::GestureLongPress)
626 JNIEnv* env = AttachCurrentThread();
627 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
631 const blink::WebGestureEvent& gesture =
632 static_cast<const blink::WebGestureEvent&>(event);
633 int gesture_type = ToGestureEventType(event.type);
634 return Java_ContentViewCore_filterTapOrPressEvent(env,
637 gesture.x * dpi_scale(),
638 gesture.y * dpi_scale());
640 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
643 bool ContentViewCoreImpl::HasFocus() {
644 JNIEnv* env = AttachCurrentThread();
645 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
648 return Java_ContentViewCore_hasFocus(env, obj.obj());
651 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
652 JNIEnv* env = AttachCurrentThread();
653 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
656 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
657 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
660 void ContentViewCoreImpl::OnSelectionBoundsChanged(
661 const ViewHostMsg_SelectionBounds_Params& params) {
662 JNIEnv* env = AttachCurrentThread();
663 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
666 ScopedJavaLocalRef<jobject> anchor_rect_dip(
667 CreateJavaRect(env, params.anchor_rect));
668 ScopedJavaLocalRef<jobject> focus_rect_dip(
669 CreateJavaRect(env, params.focus_rect));
670 Java_ContentViewCore_onSelectionBoundsChanged(env, obj.obj(),
671 anchor_rect_dip.obj(),
673 focus_rect_dip.obj(),
675 params.is_anchor_first);
678 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
679 JNIEnv* env = AttachCurrentThread();
680 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
683 Java_ContentViewCore_showPastePopup(env, obj.obj(),
684 static_cast<jint>(x_dip),
685 static_cast<jint>(y_dip));
688 void ContentViewCoreImpl::GetScaledContentBitmap(
690 jobject jbitmap_config,
691 gfx::Rect src_subrect,
692 const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
693 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
695 result_callback.Run(false, SkBitmap());
698 SkBitmap::Config skbitmap_format = gfx::ConvertToSkiaConfig(jbitmap_config);
699 view->GetScaledContentBitmap(scale, skbitmap_format, src_subrect,
703 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
704 JNIEnv* env = AttachCurrentThread();
705 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
708 ScopedJavaLocalRef<jstring> jcontent_url =
709 ConvertUTF8ToJavaString(env, content_url.spec());
710 Java_ContentViewCore_startContentIntent(env,
715 void ContentViewCoreImpl::ShowDisambiguationPopup(
716 const gfx::Rect& target_rect,
717 const SkBitmap& zoomed_bitmap) {
718 JNIEnv* env = AttachCurrentThread();
720 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
724 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, target_rect));
726 ScopedJavaLocalRef<jobject> java_bitmap =
727 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
728 DCHECK(!java_bitmap.is_null());
730 Java_ContentViewCore_showDisambiguationPopup(env,
736 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
737 JNIEnv* env = AttachCurrentThread();
739 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
741 return ScopedJavaLocalRef<jobject>();
742 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
745 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
746 JNIEnv* env = AttachCurrentThread();
748 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
750 return ScopedJavaLocalRef<jobject>();
752 return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
755 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
756 JNIEnv* env = AttachCurrentThread();
758 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
760 return ScopedJavaLocalRef<jobject>();
762 return Java_ContentViewCore_getContext(env, obj.obj());
765 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
766 JNIEnv* env = AttachCurrentThread();
768 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
771 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
772 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
776 void ContentViewCoreImpl::DidStopFlinging() {
777 JNIEnv* env = AttachCurrentThread();
779 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
781 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
784 gfx::Size ContentViewCoreImpl::GetViewSize() const {
785 gfx::Size size = GetViewportSizeDip();
786 gfx::Size offset = GetViewportSizeOffsetDip();
787 size.Enlarge(-offset.width(), -offset.height());
791 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
792 JNIEnv* env = AttachCurrentThread();
793 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
797 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
798 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
801 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
802 JNIEnv* env = AttachCurrentThread();
803 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
807 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
808 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
811 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
812 JNIEnv* env = AttachCurrentThread();
813 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
817 Java_ContentViewCore_getViewportSizeOffsetWidthPix(env, j_obj.obj()),
818 Java_ContentViewCore_getViewportSizeOffsetHeightPix(env, j_obj.obj()));
821 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
822 return gfx::ToCeiledSize(
823 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
826 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
827 return gfx::ToCeiledSize(
828 gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f / dpi_scale()));
831 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
832 JNIEnv* env = AttachCurrentThread();
833 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
836 return Java_ContentViewCore_getOverdrawBottomHeightPix(env, j_obj.obj())
840 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
841 root_layer_->AddChild(layer);
842 root_layer_->SetIsDrawable(false);
845 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
846 layer->RemoveFromParent();
848 if (!root_layer_->children().size())
849 root_layer_->SetIsDrawable(true);
852 void ContentViewCoreImpl::LoadUrl(
853 NavigationController::LoadURLParams& params) {
854 GetWebContents()->GetController().LoadURLWithParams(params);
857 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
858 // view_android_ should never be null for Chrome.
859 DCHECK(view_android_);
860 return view_android_;
863 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
864 // This should never be NULL for Chrome, but will be NULL for WebView.
865 DCHECK(window_android_);
866 return window_android_;
869 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
870 return root_layer_.get();
873 // ----------------------------------------------------------------------------
874 // Methods called from Java via JNI
875 // ----------------------------------------------------------------------------
877 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env, jobject obj,
879 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
880 web_contents_->GetRenderViewHost());
882 if (indices == NULL) {
883 rvhi->DidCancelPopupMenu();
887 int selected_count = env->GetArrayLength(indices);
888 std::vector<int> selected_indices;
889 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
890 for (int i = 0; i < selected_count; ++i)
891 selected_indices.push_back(indices_ptr[i]);
892 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
893 rvhi->DidSelectPopupMenuItems(selected_indices);
896 void ContentViewCoreImpl::LoadUrl(
897 JNIEnv* env, jobject obj,
900 jint transition_type,
901 jstring j_referrer_url,
902 jint referrer_policy,
903 jint ua_override_option,
904 jstring extra_headers,
905 jbyteArray post_data,
906 jstring base_url_for_data_url,
907 jstring virtual_url_for_data_url,
908 jboolean can_load_local_resources) {
910 NavigationController::LoadURLParams params(
911 GURL(ConvertJavaStringToUTF8(env, url)));
913 params.load_type = static_cast<NavigationController::LoadURLType>(
915 params.transition_type = PageTransitionFromInt(transition_type);
916 params.override_user_agent =
917 static_cast<NavigationController::UserAgentOverrideOption>(
921 params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
924 std::vector<uint8> http_body_vector;
925 base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
926 params.browser_initiated_post_data =
927 base::RefCountedBytes::TakeVector(&http_body_vector);
930 if (base_url_for_data_url) {
931 params.base_url_for_data_url =
932 GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
935 if (virtual_url_for_data_url) {
936 params.virtual_url_for_data_url =
937 GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
940 params.can_load_local_resources = can_load_local_resources;
941 if (j_referrer_url) {
942 params.referrer = content::Referrer(
943 GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
944 static_cast<blink::WebReferrerPolicy>(referrer_policy));
950 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetURL(
951 JNIEnv* env, jobject) const {
952 return ConvertUTF8ToJavaString(env, GetWebContents()->GetURL().spec());
955 jboolean ContentViewCoreImpl::IsIncognito(JNIEnv* env, jobject obj) {
956 return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
959 WebContents* ContentViewCoreImpl::GetWebContents() const {
960 return web_contents_;
963 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
964 SetFocusInternal(focused);
967 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
968 if (!GetRenderWidgetHostViewAndroid())
972 GetRenderWidgetHostViewAndroid()->Focus();
974 GetRenderWidgetHostViewAndroid()->Blur();
977 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
980 if (device_orientation_ != orientation) {
981 device_orientation_ = orientation;
982 SendOrientationChangeEventInternal();
986 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
988 jobject motion_event,
1000 jfloat touch_major_0,
1001 jfloat touch_major_1) {
1002 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1003 // Avoid synthesizing a touch event if it cannot be forwarded.
1007 MotionEventAndroid event(1.f / dpi_scale(),
1024 return rwhv->OnTouchEvent(event);
1027 float ContentViewCoreImpl::GetDpiScale() const {
1031 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
1036 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1040 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
1041 WebInputEvent::MouseMove,
1042 blink::WebMouseEvent::ButtonNone,
1043 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
1045 rwhv->SendMouseEvent(event);
1049 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
1054 jfloat vertical_axis) {
1055 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1059 WebMouseWheelEventBuilder::Direction direction;
1060 if (vertical_axis > 0) {
1061 direction = WebMouseWheelEventBuilder::DIRECTION_UP;
1062 } else if (vertical_axis < 0) {
1063 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
1067 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
1068 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1070 rwhv->SendMouseWheelEvent(event);
1074 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
1075 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
1076 return WebGestureEventBuilder::Build(
1077 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1080 void ContentViewCoreImpl::SendGestureEvent(
1081 const blink::WebGestureEvent& event) {
1082 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1084 rwhv->SendGestureEvent(event);
1087 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
1094 WebGestureEvent event = MakeGestureEvent(
1095 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1096 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1097 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1099 SendGestureEvent(event);
1102 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1103 WebGestureEvent event = MakeGestureEvent(
1104 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1105 SendGestureEvent(event);
1108 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1109 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1110 WebGestureEvent event = MakeGestureEvent(
1111 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1112 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1113 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1115 SendGestureEvent(event);
1118 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1119 jfloat x, jfloat y, jfloat vx, jfloat vy) {
1120 WebGestureEvent event = MakeGestureEvent(
1121 WebInputEvent::GestureFlingStart, time_ms, x, y);
1122 event.data.flingStart.velocityX = vx / dpi_scale();
1123 event.data.flingStart.velocityY = vy / dpi_scale();
1125 SendGestureEvent(event);
1128 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1129 WebGestureEvent event = MakeGestureEvent(
1130 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1131 SendGestureEvent(event);
1134 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1135 jfloat x, jfloat y) {
1136 WebGestureEvent event = MakeGestureEvent(
1137 WebInputEvent::GestureTap, time_ms, x, y);
1138 event.data.tap.tapCount = 1;
1140 SendGestureEvent(event);
1143 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1144 jfloat x, jfloat y) {
1145 WebGestureEvent event = MakeGestureEvent(
1146 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1147 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1148 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1149 event.data.tap.tapCount = 1;
1151 SendGestureEvent(event);
1154 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1155 jfloat x, jfloat y) {
1156 WebGestureEvent event = MakeGestureEvent(
1157 WebInputEvent::GestureLongPress, time_ms, x, y);
1159 SendGestureEvent(event);
1162 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1163 jfloat x, jfloat y) {
1164 WebGestureEvent event = MakeGestureEvent(
1165 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1166 SendGestureEvent(event);
1169 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1170 WebGestureEvent event = MakeGestureEvent(
1171 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1172 SendGestureEvent(event);
1175 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1176 jfloat anchor_x, jfloat anchor_y,
1178 WebGestureEvent event = MakeGestureEvent(
1179 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1180 event.data.pinchUpdate.scale = delta;
1182 SendGestureEvent(event);
1185 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1186 jfloat x1, jfloat y1,
1187 jfloat x2, jfloat y2) {
1191 web_contents_->SelectRange(
1192 gfx::Point(x1 / dpi_scale(), y1 / dpi_scale()),
1193 gfx::Point(x2 / dpi_scale(), y2 / dpi_scale()));
1196 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1197 jfloat x, jfloat y) {
1198 if (GetRenderWidgetHostViewAndroid()) {
1199 GetRenderWidgetHostViewAndroid()->MoveCaret(
1200 gfx::Point(x / dpi_scale(), y / dpi_scale()));
1204 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1205 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1207 rwhv->ResetGestureDetection();
1210 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1213 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1215 rwhv->SetDoubleTapSupportEnabled(enabled);
1218 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1221 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1223 rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1226 void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) {
1227 web_contents_->GetController().LoadIfNecessary();
1230 void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv* env, jobject obj) {
1231 web_contents_->GetController().SetNeedsReload();
1234 void ContentViewCoreImpl::Reload(JNIEnv* env,
1236 jboolean check_for_repost) {
1237 if (web_contents_->GetController().NeedsReload())
1238 web_contents_->GetController().LoadIfNecessary();
1240 web_contents_->GetController().Reload(check_for_repost);
1243 void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv* env,
1245 jboolean check_for_repost) {
1246 web_contents_->GetController().ReloadIgnoringCache(check_for_repost);
1249 void ContentViewCoreImpl::CancelPendingReload(JNIEnv* env, jobject obj) {
1250 web_contents_->GetController().CancelPendingReload();
1253 void ContentViewCoreImpl::ContinuePendingReload(JNIEnv* env, jobject obj) {
1254 web_contents_->GetController().ContinuePendingReload();
1257 void ContentViewCoreImpl::ClearHistory(JNIEnv* env, jobject obj) {
1258 // TODO(creis): Do callers of this need to know if it fails?
1259 if (web_contents_->GetController().CanPruneAllButLastCommitted())
1260 web_contents_->GetController().PruneAllButLastCommitted();
1263 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
1267 web_contents_->java_bridge_dispatcher_host_manager()
1268 ->SetAllowObjectContentsInspection(allow);
1271 void ContentViewCoreImpl::AddJavascriptInterface(
1276 jclass safe_annotation_clazz,
1277 jobject retained_object_set) {
1278 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1279 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1280 JavaObjectWeakGlobalRef weak_retained_object_set(env, retained_object_set);
1282 // JavaBoundObject creates the NPObject with a ref count of 1, and
1283 // JavaBridgeDispatcherHostManager takes its own ref.
1284 JavaBridgeDispatcherHostManager* java_bridge =
1285 web_contents_->java_bridge_dispatcher_host_manager();
1286 java_bridge->SetRetainedObjectSet(weak_retained_object_set);
1287 NPObject* bound_object =
1288 JavaBoundObject::Create(scoped_object,
1290 java_bridge->AsWeakPtr(),
1291 java_bridge->GetAllowObjectContentsInspection());
1292 java_bridge->AddNamedObject(ConvertJavaStringToUTF16(env, name),
1294 blink::WebBindings::releaseObject(bound_object);
1297 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1300 web_contents_->java_bridge_dispatcher_host_manager()->RemoveNamedObject(
1301 ConvertJavaStringToUTF16(env, name));
1304 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1305 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1306 gfx::Size physical_size(
1307 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1308 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1309 root_layer_->SetBounds(physical_size);
1312 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1313 view->GetRenderWidgetHost());
1314 host->SendScreenRects();
1319 void ContentViewCoreImpl::ShowInterstitialPage(
1320 JNIEnv* env, jobject obj, jstring jurl, jlong delegate_ptr) {
1321 GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
1322 InterstitialPageDelegateAndroid* delegate =
1323 reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
1324 InterstitialPage* interstitial = InterstitialPage::Create(
1325 web_contents_, false, url, delegate);
1326 delegate->set_interstitial_page(interstitial);
1327 interstitial->Show();
1330 jboolean ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv* env,
1332 return web_contents_->ShowingInterstitialPage();
1335 jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
1337 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1338 return view && view->HasValidFrame();
1341 void ContentViewCoreImpl::ExitFullscreen(JNIEnv* env, jobject obj) {
1342 RenderViewHost* host = web_contents_->GetRenderViewHost();
1345 host->ExitFullscreen();
1348 void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv* env,
1351 bool enable_showing,
1353 RenderViewHost* host = web_contents_->GetRenderViewHost();
1356 host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
1362 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
1363 RenderViewHost* host = web_contents_->GetRenderViewHost();
1364 host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
1367 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv* env,
1369 RenderViewHost* host = web_contents_->GetRenderViewHost();
1370 host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
1371 host->GetRoutingID(), gfx::Rect()));
1376 static void AddNavigationEntryToHistory(JNIEnv* env, jobject obj,
1378 NavigationEntry* entry,
1380 // Get the details of the current entry
1381 ScopedJavaLocalRef<jstring> j_url(
1382 ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
1383 ScopedJavaLocalRef<jstring> j_virtual_url(
1384 ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
1385 ScopedJavaLocalRef<jstring> j_original_url(
1386 ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
1387 ScopedJavaLocalRef<jstring> j_title(
1388 ConvertUTF16ToJavaString(env, entry->GetTitle()));
1389 ScopedJavaLocalRef<jobject> j_bitmap;
1390 const FaviconStatus& status = entry->GetFavicon();
1391 if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
1392 j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
1394 // Add the item to the list
1395 Java_ContentViewCore_addToNavigationHistory(
1396 env, obj, history, index, j_url.obj(), j_virtual_url.obj(),
1397 j_original_url.obj(), j_title.obj(), j_bitmap.obj());
1402 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env,
1405 // Iterate through navigation entries to populate the list
1406 const NavigationController& controller = web_contents_->GetController();
1407 int count = controller.GetEntryCount();
1408 for (int i = 0; i < count; ++i) {
1409 AddNavigationEntryToHistory(
1410 env, obj, history, controller.GetEntryAtIndex(i), i);
1413 return controller.GetCurrentEntryIndex();
1416 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv* env,
1419 jboolean is_forward,
1421 // Iterate through navigation entries to populate the list
1422 const NavigationController& controller = web_contents_->GetController();
1423 int count = controller.GetEntryCount();
1425 int increment_value = is_forward ? 1 : -1;
1426 for (int i = controller.GetCurrentEntryIndex() + increment_value;
1427 i >= 0 && i < count;
1428 i += increment_value) {
1429 if (num_added >= max_entries)
1432 AddNavigationEntryToHistory(
1433 env, obj, history, controller.GetEntryAtIndex(i), i);
1438 ScopedJavaLocalRef<jstring>
1439 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv* env,
1441 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1443 return ScopedJavaLocalRef<jstring>(env, NULL);
1444 return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
1447 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1448 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1451 return rwhva->GetNativeImeAdapter();
1455 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
1456 const base::Value* result) {
1457 JNIEnv* env = base::android::AttachCurrentThread();
1459 base::JSONWriter::Write(result, &json);
1460 ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
1461 Java_ContentViewCore_onEvaluateJavaScriptResult(env,
1467 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env,
1471 jboolean start_renderer) {
1472 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
1475 if (start_renderer && !rvh->IsRenderViewLive()) {
1476 if (!web_contents_->CreateRenderViewForInitialEmptyDocument()) {
1477 LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
1483 // No callback requested.
1484 web_contents_->GetMainFrame()->ExecuteJavaScript(
1485 ConvertJavaStringToUTF16(env, script));
1489 // Secure the Java callback in a scoped object and give ownership of it to the
1491 ScopedJavaGlobalRef<jobject> j_callback;
1492 j_callback.Reset(env, callback);
1493 content::RenderFrameHost::JavaScriptResultCallback c_callback =
1494 base::Bind(&JavaScriptResultCallback, j_callback);
1496 web_contents_->GetMainFrame()->ExecuteJavaScript(
1497 ConvertJavaStringToUTF16(env, script),
1501 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
1502 JNIEnv* env, jobject obj) {
1503 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1504 return entry && entry->GetIsOverridingUserAgent();
1507 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1508 int text_input_type,
1509 const std::string& text,
1510 int selection_start,
1512 int composition_start,
1513 int composition_end,
1514 bool show_ime_if_needed,
1515 bool is_non_ime_change) {
1516 JNIEnv* env = AttachCurrentThread();
1517 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1521 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1522 Java_ContentViewCore_updateImeAdapter(env, obj.obj(),
1523 native_ime_adapter, text_input_type,
1525 selection_start, selection_end,
1526 composition_start, composition_end,
1527 show_ime_if_needed, is_non_ime_change);
1530 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv* env, jobject obj) {
1531 SSLHostState* state = SSLHostState::GetFor(
1532 web_contents_->GetController().GetBrowserContext());
1536 void ContentViewCoreImpl::SetUseDesktopUserAgent(
1540 jboolean reload_on_state_change) {
1541 if (GetUseDesktopUserAgent(env, obj) == enabled)
1544 // Make sure the navigation entry actually exists.
1545 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1549 // Set the flag in the NavigationEntry.
1550 entry->SetIsOverridingUserAgent(enabled);
1552 // Send the override to the renderer.
1553 if (reload_on_state_change) {
1554 // Reloading the page will send the override down as part of the
1555 // navigation IPC message.
1556 NavigationControllerImpl& controller =
1557 static_cast<NavigationControllerImpl&>(web_contents_->GetController());
1558 controller.ReloadOriginalRequestURL(false);
1562 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1564 SetAccessibilityEnabledInternal(enabled);
1567 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1568 accessibility_enabled_ = enabled;
1569 RenderWidgetHostViewAndroid* host_view = GetRenderWidgetHostViewAndroid();
1572 RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(
1573 host_view->GetRenderWidgetHost());
1574 BrowserAccessibilityState* accessibility_state =
1575 BrowserAccessibilityState::GetInstance();
1577 // This enables accessibility globally unless it was explicitly disallowed
1578 // by a command-line flag.
1579 accessibility_state->OnScreenReaderDetected();
1580 // If it was actually enabled globally, enable it for this RenderWidget now.
1581 if (accessibility_state->IsAccessibleBrowser() && host_impl)
1582 host_impl->AddAccessibilityMode(AccessibilityModeComplete);
1584 accessibility_state->ResetAccessibilityMode();
1586 host_impl->ResetAccessibilityMode();
1590 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1591 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1593 rwhv->UpdateScreenInfo(GetViewAndroid());
1595 // TODO(mlamouri): temporary plumbing for Screen Orientation, this will change
1596 // in the future. The OnResize IPC message sent from UpdateScreenInfo() will
1597 // propagate the information.
1598 blink::WebScreenOrientationType orientation =
1599 blink::WebScreenOrientationPortraitPrimary;
1601 switch (device_orientation_) {
1603 orientation = blink::WebScreenOrientationPortraitPrimary;
1606 orientation = blink::WebScreenOrientationLandscapePrimary;
1609 orientation = blink::WebScreenOrientationLandscapeSecondary;
1612 orientation = blink::WebScreenOrientationPortraitSecondary;
1618 ScreenOrientationDispatcherHost* sodh =
1619 static_cast<RenderProcessHostImpl*>(web_contents_->
1620 GetRenderProcessHost())->screen_orientation_dispatcher_host();
1622 // sodh can be null if the RenderProcessHost is in the process of being
1623 // destroyed or not yet initialized.
1625 sodh->OnOrientationChange(orientation);
1628 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1635 static_cast<int>(x / dpi_scale()),
1636 static_cast<int>(y / dpi_scale()),
1637 static_cast<int>((width > 0 && width < dpi_scale()) ?
1638 1 : (int)(width / dpi_scale())),
1639 static_cast<int>((height > 0 && height < dpi_scale()) ?
1640 1 : (int)(height / dpi_scale())));
1641 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1642 GetWebContents()->GetRoutingID(), rect));
1645 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1646 return GetRenderProcessIdFromRenderViewHost(
1647 web_contents_->GetRenderViewHost());
1650 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1651 const base::string16& result) {
1652 JNIEnv* env = AttachCurrentThread();
1653 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1656 ScopedJavaLocalRef<jstring> jresult = ConvertUTF16ToJavaString(env, result);
1657 Java_ContentViewCore_onSmartClipDataExtracted(
1658 env, obj.obj(), jresult.obj());
1661 void ContentViewCoreImpl::WebContentsDestroyed() {
1662 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1663 static_cast<WebContentsImpl*>(web_contents())->GetView());
1665 wcva->SetContentViewCore(NULL);
1668 // This is called for each ContentView.
1669 jlong Init(JNIEnv* env,
1671 jlong native_web_contents,
1673 jlong window_android) {
1674 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1676 reinterpret_cast<WebContents*>(native_web_contents),
1677 reinterpret_cast<ui::ViewAndroid*>(view_android),
1678 reinterpret_cast<ui::WindowAndroid*>(window_android));
1679 return reinterpret_cast<intptr_t>(view);
1682 bool RegisterContentViewCore(JNIEnv* env) {
1683 return RegisterNativesImpl(env);
1686 } // namespace content