When enabling new profile management programmatically, make sure to set the
[chromium-blink-merge.git] / content / browser / android / content_view_core_impl.cc
blob4bb56aae1985baf38f5de2f903477838ca0ecdc2
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/geolocation/geolocation_dispatcher_host.h"
27 #include "content/browser/media/media_web_contents_observer.h"
28 #include "content/browser/renderer_host/compositor_impl_android.h"
29 #include "content/browser/renderer_host/input/motion_event_android.h"
30 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
31 #include "content/browser/renderer_host/input/web_input_event_util.h"
32 #include "content/browser/renderer_host/java/java_bound_object.h"
33 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
34 #include "content/browser/renderer_host/render_view_host_impl.h"
35 #include "content/browser/renderer_host/render_widget_host_impl.h"
36 #include "content/browser/renderer_host/render_widget_host_view_android.h"
37 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
38 #include "content/browser/ssl/ssl_host_state.h"
39 #include "content/browser/web_contents/web_contents_view_android.h"
40 #include "content/common/frame_messages.h"
41 #include "content/common/input/web_input_event_traits.h"
42 #include "content/common/input_messages.h"
43 #include "content/common/view_messages.h"
44 #include "content/public/browser/browser_accessibility_state.h"
45 #include "content/public/browser/browser_context.h"
46 #include "content/public/browser/favicon_status.h"
47 #include "content/public/browser/render_frame_host.h"
48 #include "content/public/browser/web_contents.h"
49 #include "content/public/common/content_client.h"
50 #include "content/public/common/content_switches.h"
51 #include "content/public/common/menu_item.h"
52 #include "content/public/common/page_transition_types.h"
53 #include "content/public/common/user_agent.h"
54 #include "jni/ContentViewCore_jni.h"
55 #include "third_party/WebKit/public/web/WebBindings.h"
56 #include "third_party/WebKit/public/web/WebInputEvent.h"
57 #include "ui/base/android/view_android.h"
58 #include "ui/base/android/window_android.h"
59 #include "ui/gfx/android/java_bitmap.h"
60 #include "ui/gfx/screen.h"
61 #include "ui/gfx/size_conversions.h"
62 #include "ui/gfx/size_f.h"
64 using base::android::AttachCurrentThread;
65 using base::android::ConvertJavaStringToUTF16;
66 using base::android::ConvertJavaStringToUTF8;
67 using base::android::ConvertUTF16ToJavaString;
68 using base::android::ConvertUTF8ToJavaString;
69 using base::android::ScopedJavaGlobalRef;
70 using base::android::ScopedJavaLocalRef;
71 using blink::WebGestureEvent;
72 using blink::WebInputEvent;
74 // Describes the type and enabled state of a select popup item.
75 namespace {
77 enum {
78 #define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
79 #include "content/browser/android/popup_item_type_list.h"
80 #undef DEFINE_POPUP_ITEM_TYPE
83 } //namespace
85 namespace content {
87 namespace {
89 const void* kContentViewUserDataKey = &kContentViewUserDataKey;
91 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
92 DCHECK(host);
93 RenderProcessHost* render_process = host->GetProcess();
94 DCHECK(render_process);
95 if (render_process->HasConnection())
96 return render_process->GetHandle();
97 else
98 return 0;
101 ScopedJavaLocalRef<jobject> CreateJavaRect(
102 JNIEnv* env,
103 const gfx::Rect& rect) {
104 return ScopedJavaLocalRef<jobject>(
105 Java_ContentViewCore_createRect(env,
106 static_cast<int>(rect.x()),
107 static_cast<int>(rect.y()),
108 static_cast<int>(rect.right()),
109 static_cast<int>(rect.bottom())));
112 int ToGestureEventType(WebInputEvent::Type type) {
113 switch (type) {
114 case WebInputEvent::GestureScrollBegin:
115 return SCROLL_START;
116 case WebInputEvent::GestureScrollEnd:
117 return SCROLL_END;
118 case WebInputEvent::GestureScrollUpdate:
119 return SCROLL_BY;
120 case WebInputEvent::GestureFlingStart:
121 return FLING_START;
122 case WebInputEvent::GestureFlingCancel:
123 return FLING_CANCEL;
124 case WebInputEvent::GestureShowPress:
125 return SHOW_PRESS;
126 case WebInputEvent::GestureTap:
127 return SINGLE_TAP_CONFIRMED;
128 case WebInputEvent::GestureTapUnconfirmed:
129 return SINGLE_TAP_UNCONFIRMED;
130 case WebInputEvent::GestureTapDown:
131 return TAP_DOWN;
132 case WebInputEvent::GestureTapCancel:
133 return TAP_CANCEL;
134 case WebInputEvent::GestureDoubleTap:
135 return DOUBLE_TAP;
136 case WebInputEvent::GestureLongPress:
137 return LONG_PRESS;
138 case WebInputEvent::GestureLongTap:
139 return LONG_TAP;
140 case WebInputEvent::GesturePinchBegin:
141 return PINCH_BEGIN;
142 case WebInputEvent::GesturePinchEnd:
143 return PINCH_END;
144 case WebInputEvent::GesturePinchUpdate:
145 return PINCH_BY;
146 case WebInputEvent::GestureTwoFingerTap:
147 case WebInputEvent::GestureScrollUpdateWithoutPropagation:
148 default:
149 NOTREACHED() << "Invalid source gesture type: "
150 << WebInputEventTraits::GetName(type);
151 return -1;
155 float GetPrimaryDisplayDeviceScaleFactor() {
156 const gfx::Display& display =
157 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
158 return display.device_scale_factor();
161 } // namespace
163 // Enables a callback when the underlying WebContents is destroyed, to enable
164 // nulling the back-pointer.
165 class ContentViewCoreImpl::ContentViewUserData
166 : public base::SupportsUserData::Data {
167 public:
168 explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
169 : content_view_core_(content_view_core) {
172 virtual ~ContentViewUserData() {
173 // TODO(joth): When chrome has finished removing the TabContents class (see
174 // crbug.com/107201) consider inverting relationship, so ContentViewCore
175 // would own WebContents. That effectively implies making the WebContents
176 // destructor private on Android.
177 delete content_view_core_;
180 ContentViewCoreImpl* get() const { return content_view_core_; }
182 private:
183 // Not using scoped_ptr as ContentViewCoreImpl destructor is private.
184 ContentViewCoreImpl* content_view_core_;
186 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
189 // static
190 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
191 content::WebContents* web_contents) {
192 ContentViewCoreImpl::ContentViewUserData* data =
193 reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
194 web_contents->GetUserData(kContentViewUserDataKey));
195 return data ? data->get() : NULL;
198 // static
199 ContentViewCore* ContentViewCore::FromWebContents(
200 content::WebContents* web_contents) {
201 return ContentViewCoreImpl::FromWebContents(web_contents);
204 // static
205 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
206 jobject obj) {
207 return reinterpret_cast<ContentViewCore*>(
208 Java_ContentViewCore_getNativeContentViewCore(env, obj));
211 ContentViewCoreImpl::ContentViewCoreImpl(
212 JNIEnv* env,
213 jobject obj,
214 WebContents* web_contents,
215 ui::ViewAndroid* view_android,
216 ui::WindowAndroid* window_android,
217 jobject java_bridge_retained_object_set)
218 : WebContentsObserver(web_contents),
219 java_ref_(env, obj),
220 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
221 root_layer_(cc::SolidColorLayer::Create()),
222 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()),
223 view_android_(view_android),
224 window_android_(window_android),
225 device_orientation_(0),
226 accessibility_enabled_(false) {
227 CHECK(web_contents) <<
228 "A ContentViewCoreImpl should be created with a valid WebContents.";
230 root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj));
231 gfx::Size physical_size(
232 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
233 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
234 root_layer_->SetBounds(physical_size);
235 root_layer_->SetIsDrawable(true);
237 // Currently, the only use case we have for overriding a user agent involves
238 // spoofing a desktop Linux user agent for "Request desktop site".
239 // Automatically set it for all WebContents so that it is available when a
240 // NavigationEntry requires the user agent to be overridden.
241 const char kLinuxInfoStr[] = "X11; Linux x86_64";
242 std::string product = content::GetContentClient()->GetProduct();
243 std::string spoofed_ua =
244 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
245 web_contents->SetUserAgentOverride(spoofed_ua);
247 java_bridge_dispatcher_host_manager_.reset(
248 new JavaBridgeDispatcherHostManager(web_contents,
249 java_bridge_retained_object_set));
251 InitWebContents();
254 ContentViewCoreImpl::~ContentViewCoreImpl() {
255 JNIEnv* env = base::android::AttachCurrentThread();
256 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
257 java_ref_.reset();
258 if (!j_obj.is_null()) {
259 Java_ContentViewCore_onNativeContentViewCoreDestroyed(
260 env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
264 base::android::ScopedJavaLocalRef<jobject>
265 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
266 return web_contents_->GetJavaWebContents();
269 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
270 jobject obj) {
271 DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
272 java_ref_.reset();
275 void ContentViewCoreImpl::InitWebContents() {
276 DCHECK(web_contents_);
277 static_cast<WebContentsViewAndroid*>(
278 static_cast<WebContentsImpl*>(web_contents_)->GetView())->
279 SetContentViewCore(this);
280 DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
281 web_contents_->SetUserData(kContentViewUserDataKey,
282 new ContentViewUserData(this));
285 void ContentViewCoreImpl::RenderViewReady() {
286 JNIEnv* env = AttachCurrentThread();
287 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
288 if (!obj.is_null())
289 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
291 if (device_orientation_ != 0)
292 SendOrientationChangeEventInternal();
295 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host,
296 RenderViewHost* new_host) {
297 int old_pid = 0;
298 if (old_host) {
299 old_pid = GetRenderProcessIdFromRenderViewHost(old_host);
301 RenderWidgetHostViewAndroid* view =
302 static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView());
303 if (view)
304 view->SetContentViewCore(NULL);
306 view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView());
307 if (view)
308 view->SetContentViewCore(this);
310 int new_pid = GetRenderProcessIdFromRenderViewHost(
311 web_contents_->GetRenderViewHost());
312 if (new_pid != old_pid) {
313 // Notify the Java side that the renderer process changed.
314 JNIEnv* env = AttachCurrentThread();
315 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
316 if (!obj.is_null()) {
317 Java_ContentViewCore_onRenderProcessChange(env, obj.obj());
321 SetFocusInternal(HasFocus());
322 SetAccessibilityEnabledInternal(accessibility_enabled_);
325 RenderWidgetHostViewAndroid*
326 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
327 RenderWidgetHostView* rwhv = NULL;
328 if (web_contents_) {
329 rwhv = web_contents_->GetRenderWidgetHostView();
330 if (web_contents_->ShowingInterstitialPage()) {
331 rwhv = static_cast<InterstitialPageImpl*>(
332 web_contents_->GetInterstitialPage())->
333 GetRenderViewHost()->GetView();
336 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
339 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
340 JNIEnv* env = AttachCurrentThread();
341 return java_ref_.get(env);
344 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
345 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
346 if (!rwhva)
347 return SK_ColorWHITE;
348 return rwhva->GetCachedBackgroundColor();
351 void ContentViewCoreImpl::OnHide(JNIEnv* env, jobject obj) {
352 Hide();
355 void ContentViewCoreImpl::OnShow(JNIEnv* env, jobject obj) {
356 Show();
359 void ContentViewCoreImpl::Show() {
360 GetWebContents()->WasShown();
363 void ContentViewCoreImpl::Hide() {
364 GetWebContents()->WasHidden();
365 PauseVideo();
368 void ContentViewCoreImpl::PauseVideo() {
369 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
370 web_contents_->GetRenderViewHost());
371 if (rvhi)
372 rvhi->media_web_contents_observer()->PauseVideo();
375 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
376 web_contents_->geolocation_dispatcher_host()->PauseOrResume(should_pause);
379 // All positions and sizes are in CSS pixels.
380 // Note that viewport_width/height is a best effort based.
381 // ContentViewCore has the actual information about the physical viewport size.
382 void ContentViewCoreImpl::UpdateFrameInfo(
383 const gfx::Vector2dF& scroll_offset,
384 float page_scale_factor,
385 const gfx::Vector2dF& page_scale_factor_limits,
386 const gfx::SizeF& content_size,
387 const gfx::SizeF& viewport_size,
388 const gfx::Vector2dF& controls_offset,
389 const gfx::Vector2dF& content_offset,
390 float overdraw_bottom_height) {
391 JNIEnv* env = AttachCurrentThread();
392 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
393 if (obj.is_null())
394 return;
396 if (window_android_) {
397 gfx::Vector2dF window_offset(
398 Java_ContentViewCore_getLocationInWindowX(env, obj.obj()),
399 Java_ContentViewCore_getLocationInWindowY(env, obj.obj()));
400 window_android_->set_content_offset(
401 gfx::ScaleVector2d(content_offset, dpi_scale_) + window_offset);
404 Java_ContentViewCore_updateFrameInfo(
405 env, obj.obj(),
406 scroll_offset.x(),
407 scroll_offset.y(),
408 page_scale_factor,
409 page_scale_factor_limits.x(),
410 page_scale_factor_limits.y(),
411 content_size.width(),
412 content_size.height(),
413 viewport_size.width(),
414 viewport_size.height(),
415 controls_offset.y(),
416 content_offset.y(),
417 overdraw_bottom_height);
420 void ContentViewCoreImpl::SetTitle(const base::string16& title) {
421 JNIEnv* env = AttachCurrentThread();
422 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
423 if (obj.is_null())
424 return;
425 ScopedJavaLocalRef<jstring> jtitle =
426 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title));
427 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj());
430 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
431 root_layer_->SetBackgroundColor(color);
433 JNIEnv* env = AttachCurrentThread();
434 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
435 if (obj.is_null())
436 return;
437 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
440 void ContentViewCoreImpl::ShowSelectPopupMenu(const gfx::Rect& bounds,
441 const std::vector<MenuItem>& items, int selected_item, bool multiple) {
442 JNIEnv* env = AttachCurrentThread();
443 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
444 if (j_obj.is_null())
445 return;
447 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds));
449 // For multi-select list popups we find the list of previous selections by
450 // iterating through the items. But for single selection popups we take the
451 // given |selected_item| as is.
452 ScopedJavaLocalRef<jintArray> selected_array;
453 if (multiple) {
454 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
455 size_t selected_count = 0;
456 for (size_t i = 0; i < items.size(); ++i) {
457 if (items[i].checked)
458 native_selected_array[selected_count++] = i;
461 selected_array = ScopedJavaLocalRef<jintArray>(
462 env, env->NewIntArray(selected_count));
463 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count,
464 native_selected_array.get());
465 } else {
466 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1));
467 jint value = selected_item;
468 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value);
471 ScopedJavaLocalRef<jintArray> enabled_array(env,
472 env->NewIntArray(items.size()));
473 std::vector<base::string16> labels;
474 labels.reserve(items.size());
475 for (size_t i = 0; i < items.size(); ++i) {
476 labels.push_back(items[i].label);
477 jint enabled =
478 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP :
479 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED :
480 POPUP_ITEM_TYPE_DISABLED));
481 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled);
483 ScopedJavaLocalRef<jobjectArray> items_array(
484 base::android::ToJavaArrayOfStrings(env, labels));
485 Java_ContentViewCore_showSelectPopup(env, j_obj.obj(),
486 bounds_rect.obj(),
487 items_array.obj(),
488 enabled_array.obj(),
489 multiple,
490 selected_array.obj());
493 void ContentViewCoreImpl::HideSelectPopupMenu() {
494 JNIEnv* env = AttachCurrentThread();
495 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
496 if (!j_obj.is_null())
497 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj());
500 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
501 InputEventAckState ack_result) {
502 JNIEnv* env = AttachCurrentThread();
503 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
504 if (j_obj.is_null())
505 return;
507 switch (event.type) {
508 case WebInputEvent::GestureFlingStart:
509 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
510 // The view expects the fling velocity in pixels/s.
511 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(),
512 event.data.flingStart.velocityX * dpi_scale(),
513 event.data.flingStart.velocityY * dpi_scale());
514 } else {
515 // If a scroll ends with a fling, a SCROLL_END event is never sent.
516 // However, if that fling went unconsumed, we still need to let the
517 // listeners know that scrolling has ended.
518 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
521 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
522 // The view expects the fling velocity in pixels/s.
523 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(),
524 event.data.flingStart.velocityX * dpi_scale(),
525 event.data.flingStart.velocityY * dpi_scale());
527 break;
528 case WebInputEvent::GestureFlingCancel:
529 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj());
530 break;
531 case WebInputEvent::GestureScrollBegin:
532 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj());
533 break;
534 case WebInputEvent::GestureScrollUpdate:
535 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
536 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
537 break;
538 case WebInputEvent::GestureScrollEnd:
539 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj());
540 break;
541 case WebInputEvent::GesturePinchBegin:
542 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj());
543 break;
544 case WebInputEvent::GesturePinchEnd:
545 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj());
546 break;
547 case WebInputEvent::GestureTap:
548 Java_ContentViewCore_onSingleTapEventAck(
549 env,
550 j_obj.obj(),
551 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED,
552 event.x * dpi_scale(),
553 event.y * dpi_scale());
554 break;
555 case WebInputEvent::GestureDoubleTap:
556 Java_ContentViewCore_onDoubleTapEventAck(env, j_obj.obj());
557 break;
558 default:
559 break;
563 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) {
564 if (event.type != WebInputEvent::GestureTap &&
565 event.type != WebInputEvent::GestureDoubleTap &&
566 event.type != WebInputEvent::GestureLongTap &&
567 event.type != WebInputEvent::GestureLongPress)
568 return false;
570 JNIEnv* env = AttachCurrentThread();
571 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
572 if (j_obj.is_null())
573 return false;
575 const blink::WebGestureEvent& gesture =
576 static_cast<const blink::WebGestureEvent&>(event);
577 int gesture_type = ToGestureEventType(event.type);
578 return Java_ContentViewCore_filterTapOrPressEvent(env,
579 j_obj.obj(),
580 gesture_type,
581 gesture.x * dpi_scale(),
582 gesture.y * dpi_scale());
584 // TODO(jdduke): Also report double-tap UMA, crbug/347568.
587 bool ContentViewCoreImpl::HasFocus() {
588 JNIEnv* env = AttachCurrentThread();
589 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
590 if (obj.is_null())
591 return false;
592 return Java_ContentViewCore_hasFocus(env, obj.obj());
595 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
596 JNIEnv* env = AttachCurrentThread();
597 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
598 if (obj.is_null())
599 return;
600 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
601 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
604 void ContentViewCoreImpl::OnSelectionBoundsChanged(
605 const ViewHostMsg_SelectionBounds_Params& params) {
606 JNIEnv* env = AttachCurrentThread();
607 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
608 if (obj.is_null())
609 return;
610 ScopedJavaLocalRef<jobject> anchor_rect_dip(
611 CreateJavaRect(env, params.anchor_rect));
612 ScopedJavaLocalRef<jobject> focus_rect_dip(
613 CreateJavaRect(env, params.focus_rect));
614 Java_ContentViewCore_onSelectionBoundsChanged(env, obj.obj(),
615 anchor_rect_dip.obj(),
616 params.anchor_dir,
617 focus_rect_dip.obj(),
618 params.focus_dir,
619 params.is_anchor_first);
622 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
623 JNIEnv* env = AttachCurrentThread();
624 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
625 if (obj.is_null())
626 return;
627 Java_ContentViewCore_showPastePopup(env, obj.obj(),
628 static_cast<jint>(x_dip),
629 static_cast<jint>(y_dip));
632 void ContentViewCoreImpl::GetScaledContentBitmap(
633 float scale,
634 jobject jbitmap_config,
635 gfx::Rect src_subrect,
636 const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
637 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
638 if (!view) {
639 result_callback.Run(false, SkBitmap());
640 return;
642 SkBitmap::Config skbitmap_format = gfx::ConvertToSkiaConfig(jbitmap_config);
643 view->GetScaledContentBitmap(scale, skbitmap_format, src_subrect,
644 result_callback);
647 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
648 JNIEnv* env = AttachCurrentThread();
649 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
650 if (j_obj.is_null())
651 return;
652 ScopedJavaLocalRef<jstring> jcontent_url =
653 ConvertUTF8ToJavaString(env, content_url.spec());
654 Java_ContentViewCore_startContentIntent(env,
655 j_obj.obj(),
656 jcontent_url.obj());
659 void ContentViewCoreImpl::ShowDisambiguationPopup(
660 const gfx::Rect& target_rect,
661 const SkBitmap& zoomed_bitmap) {
662 JNIEnv* env = AttachCurrentThread();
664 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
665 if (obj.is_null())
666 return;
668 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, target_rect));
670 ScopedJavaLocalRef<jobject> java_bitmap =
671 gfx::ConvertToJavaBitmap(&zoomed_bitmap);
672 DCHECK(!java_bitmap.is_null());
674 Java_ContentViewCore_showDisambiguationPopup(env,
675 obj.obj(),
676 rect_object.obj(),
677 java_bitmap.obj());
680 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
681 JNIEnv* env = AttachCurrentThread();
683 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
684 if (obj.is_null())
685 return ScopedJavaLocalRef<jobject>();
686 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
689 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
690 JNIEnv* env = AttachCurrentThread();
692 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
693 if (obj.is_null())
694 return ScopedJavaLocalRef<jobject>();
696 return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
699 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
700 JNIEnv* env = AttachCurrentThread();
702 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
703 if (obj.is_null())
704 return ScopedJavaLocalRef<jobject>();
706 return Java_ContentViewCore_getContext(env, obj.obj());
709 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
710 JNIEnv* env = AttachCurrentThread();
712 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
713 if (obj.is_null())
714 return true;
715 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
716 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
717 j_url.obj());
720 void ContentViewCoreImpl::DidStopFlinging() {
721 JNIEnv* env = AttachCurrentThread();
723 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
724 if (!obj.is_null())
725 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
728 gfx::Size ContentViewCoreImpl::GetViewSize() const {
729 gfx::Size size = GetViewportSizeDip();
730 gfx::Size offset = GetViewportSizeOffsetDip();
731 size.Enlarge(-offset.width(), -offset.height());
732 return size;
735 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
736 JNIEnv* env = AttachCurrentThread();
737 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
738 if (j_obj.is_null())
739 return gfx::Size();
740 return gfx::Size(
741 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()),
742 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj()));
745 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
746 JNIEnv* env = AttachCurrentThread();
747 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
748 if (j_obj.is_null())
749 return gfx::Size();
750 return gfx::Size(
751 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
752 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
755 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
756 JNIEnv* env = AttachCurrentThread();
757 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
758 if (j_obj.is_null())
759 return gfx::Size();
760 return gfx::Size(
761 Java_ContentViewCore_getViewportSizeOffsetWidthPix(env, j_obj.obj()),
762 Java_ContentViewCore_getViewportSizeOffsetHeightPix(env, j_obj.obj()));
765 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
766 return gfx::ToCeiledSize(
767 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
770 gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
771 return gfx::ToCeiledSize(
772 gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f / dpi_scale()));
775 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
776 JNIEnv* env = AttachCurrentThread();
777 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
778 if (j_obj.is_null())
779 return 0.f;
780 return Java_ContentViewCore_getOverdrawBottomHeightPix(env, j_obj.obj())
781 / dpi_scale();
784 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
785 root_layer_->AddChild(layer);
786 root_layer_->SetIsDrawable(false);
789 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
790 layer->RemoveFromParent();
792 if (!root_layer_->children().size())
793 root_layer_->SetIsDrawable(true);
796 void ContentViewCoreImpl::LoadUrl(
797 NavigationController::LoadURLParams& params) {
798 GetWebContents()->GetController().LoadURLWithParams(params);
801 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
802 // view_android_ should never be null for Chrome.
803 DCHECK(view_android_);
804 return view_android_;
807 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
808 // This should never be NULL for Chrome, but will be NULL for WebView.
809 DCHECK(window_android_);
810 return window_android_;
813 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
814 return root_layer_.get();
817 // ----------------------------------------------------------------------------
818 // Methods called from Java via JNI
819 // ----------------------------------------------------------------------------
821 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env, jobject obj,
822 jintArray indices) {
823 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
824 web_contents_->GetRenderViewHost());
825 DCHECK(rvhi);
826 if (indices == NULL) {
827 rvhi->DidCancelPopupMenu();
828 return;
831 int selected_count = env->GetArrayLength(indices);
832 std::vector<int> selected_indices;
833 jint* indices_ptr = env->GetIntArrayElements(indices, NULL);
834 for (int i = 0; i < selected_count; ++i)
835 selected_indices.push_back(indices_ptr[i]);
836 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
837 rvhi->DidSelectPopupMenuItems(selected_indices);
840 void ContentViewCoreImpl::LoadUrl(
841 JNIEnv* env, jobject obj,
842 jstring url,
843 jint load_url_type,
844 jint transition_type,
845 jstring j_referrer_url,
846 jint referrer_policy,
847 jint ua_override_option,
848 jstring extra_headers,
849 jbyteArray post_data,
850 jstring base_url_for_data_url,
851 jstring virtual_url_for_data_url,
852 jboolean can_load_local_resources,
853 jboolean is_renderer_initiated) {
854 DCHECK(url);
855 NavigationController::LoadURLParams params(
856 GURL(ConvertJavaStringToUTF8(env, url)));
858 params.load_type = static_cast<NavigationController::LoadURLType>(
859 load_url_type);
860 params.transition_type = PageTransitionFromInt(transition_type);
861 params.override_user_agent =
862 static_cast<NavigationController::UserAgentOverrideOption>(
863 ua_override_option);
865 if (extra_headers)
866 params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
868 if (post_data) {
869 std::vector<uint8> http_body_vector;
870 base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
871 params.browser_initiated_post_data =
872 base::RefCountedBytes::TakeVector(&http_body_vector);
875 if (base_url_for_data_url) {
876 params.base_url_for_data_url =
877 GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
880 if (virtual_url_for_data_url) {
881 params.virtual_url_for_data_url =
882 GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
885 params.can_load_local_resources = can_load_local_resources;
886 if (j_referrer_url) {
887 params.referrer = content::Referrer(
888 GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
889 static_cast<blink::WebReferrerPolicy>(referrer_policy));
892 params.is_renderer_initiated = is_renderer_initiated;
894 LoadUrl(params);
897 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetURL(
898 JNIEnv* env, jobject) const {
899 return ConvertUTF8ToJavaString(env, GetWebContents()->GetURL().spec());
902 jboolean ContentViewCoreImpl::IsIncognito(JNIEnv* env, jobject obj) {
903 return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
906 WebContents* ContentViewCoreImpl::GetWebContents() const {
907 return web_contents_;
910 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) {
911 SetFocusInternal(focused);
914 void ContentViewCoreImpl::SetFocusInternal(bool focused) {
915 if (!GetRenderWidgetHostViewAndroid())
916 return;
918 if (focused)
919 GetRenderWidgetHostViewAndroid()->Focus();
920 else
921 GetRenderWidgetHostViewAndroid()->Blur();
924 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
925 jobject obj,
926 jint orientation) {
927 if (device_orientation_ != orientation) {
928 device_orientation_ = orientation;
929 SendOrientationChangeEventInternal();
933 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
934 jobject obj,
935 jobject motion_event,
936 jlong time_ms,
937 jint android_action,
938 jint pointer_count,
939 jint history_size,
940 jint action_index,
941 jfloat pos_x_0,
942 jfloat pos_y_0,
943 jfloat pos_x_1,
944 jfloat pos_y_1,
945 jint pointer_id_0,
946 jint pointer_id_1,
947 jfloat touch_major_0,
948 jfloat touch_major_1,
949 jfloat raw_pos_x,
950 jfloat raw_pos_y) {
951 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
952 // Avoid synthesizing a touch event if it cannot be forwarded.
953 if (!rwhv)
954 return false;
956 MotionEventAndroid event(1.f / dpi_scale(),
957 env,
958 motion_event,
959 time_ms,
960 android_action,
961 pointer_count,
962 history_size,
963 action_index,
964 pos_x_0,
965 pos_y_0,
966 pos_x_1,
967 pos_y_1,
968 pointer_id_0,
969 pointer_id_1,
970 touch_major_0,
971 touch_major_1,
972 raw_pos_x,
973 raw_pos_y);
975 return rwhv->OnTouchEvent(event);
978 float ContentViewCoreImpl::GetDpiScale() const {
979 return dpi_scale_;
982 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
983 jobject obj,
984 jlong time_ms,
985 jfloat x,
986 jfloat y) {
987 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
988 if (!rwhv)
989 return false;
991 blink::WebMouseEvent event = WebMouseEventBuilder::Build(
992 WebInputEvent::MouseMove,
993 blink::WebMouseEvent::ButtonNone,
994 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
996 rwhv->SendMouseEvent(event);
997 return true;
1000 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
1001 jobject obj,
1002 jlong time_ms,
1003 jfloat x,
1004 jfloat y,
1005 jfloat vertical_axis) {
1006 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1007 if (!rwhv)
1008 return false;
1010 WebMouseWheelEventBuilder::Direction direction;
1011 if (vertical_axis > 0) {
1012 direction = WebMouseWheelEventBuilder::DIRECTION_UP;
1013 } else if (vertical_axis < 0) {
1014 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN;
1015 } else {
1016 return false;
1018 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
1019 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1021 rwhv->SendMouseWheelEvent(event);
1022 return true;
1025 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
1026 WebInputEvent::Type type, int64 time_ms, float x, float y) const {
1027 return WebGestureEventBuilder::Build(
1028 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
1031 void ContentViewCoreImpl::SendGestureEvent(
1032 const blink::WebGestureEvent& event) {
1033 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1034 if (rwhv)
1035 rwhv->SendGestureEvent(event);
1038 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env,
1039 jobject obj,
1040 jlong time_ms,
1041 jfloat x,
1042 jfloat y,
1043 jfloat hintx,
1044 jfloat hinty) {
1045 WebGestureEvent event = MakeGestureEvent(
1046 WebInputEvent::GestureScrollBegin, time_ms, x, y);
1047 event.data.scrollBegin.deltaXHint = hintx / dpi_scale();
1048 event.data.scrollBegin.deltaYHint = hinty / dpi_scale();
1050 SendGestureEvent(event);
1053 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1054 WebGestureEvent event = MakeGestureEvent(
1055 WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
1056 SendGestureEvent(event);
1059 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
1060 jfloat x, jfloat y, jfloat dx, jfloat dy) {
1061 WebGestureEvent event = MakeGestureEvent(
1062 WebInputEvent::GestureScrollUpdate, time_ms, x, y);
1063 event.data.scrollUpdate.deltaX = -dx / dpi_scale();
1064 event.data.scrollUpdate.deltaY = -dy / dpi_scale();
1066 SendGestureEvent(event);
1069 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
1070 jfloat x, jfloat y, jfloat vx, jfloat vy) {
1071 WebGestureEvent event = MakeGestureEvent(
1072 WebInputEvent::GestureFlingStart, time_ms, x, y);
1073 event.data.flingStart.velocityX = vx / dpi_scale();
1074 event.data.flingStart.velocityY = vy / dpi_scale();
1076 SendGestureEvent(event);
1079 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
1080 WebGestureEvent event = MakeGestureEvent(
1081 WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
1082 SendGestureEvent(event);
1085 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms,
1086 jfloat x, jfloat y) {
1087 WebGestureEvent event = MakeGestureEvent(
1088 WebInputEvent::GestureTap, time_ms, x, y);
1089 event.data.tap.tapCount = 1;
1091 SendGestureEvent(event);
1094 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
1095 jfloat x, jfloat y) {
1096 WebGestureEvent event = MakeGestureEvent(
1097 WebInputEvent::GestureDoubleTap, time_ms, x, y);
1098 // Set the tap count to 1 even for DoubleTap, in order to be consistent with
1099 // double tap behavior on a mobile viewport. See crbug.com/234986 for context.
1100 event.data.tap.tapCount = 1;
1102 SendGestureEvent(event);
1105 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms,
1106 jfloat x, jfloat y) {
1107 WebGestureEvent event = MakeGestureEvent(
1108 WebInputEvent::GestureLongPress, time_ms, x, y);
1110 SendGestureEvent(event);
1113 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
1114 jfloat x, jfloat y) {
1115 WebGestureEvent event = MakeGestureEvent(
1116 WebInputEvent::GesturePinchBegin, time_ms, x, y);
1117 SendGestureEvent(event);
1120 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
1121 WebGestureEvent event = MakeGestureEvent(
1122 WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
1123 SendGestureEvent(event);
1126 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
1127 jfloat anchor_x, jfloat anchor_y,
1128 jfloat delta) {
1129 WebGestureEvent event = MakeGestureEvent(
1130 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
1131 event.data.pinchUpdate.scale = delta;
1133 SendGestureEvent(event);
1136 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
1137 jfloat x1, jfloat y1,
1138 jfloat x2, jfloat y2) {
1139 if (!web_contents_)
1140 return;
1142 web_contents_->SelectRange(
1143 gfx::Point(x1 / dpi_scale(), y1 / dpi_scale()),
1144 gfx::Point(x2 / dpi_scale(), y2 / dpi_scale()));
1147 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
1148 jfloat x, jfloat y) {
1149 if (GetRenderWidgetHostViewAndroid()) {
1150 GetRenderWidgetHostViewAndroid()->MoveCaret(
1151 gfx::Point(x / dpi_scale(), y / dpi_scale()));
1155 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
1156 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1157 if (rwhv)
1158 rwhv->ResetGestureDetection();
1161 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env,
1162 jobject obj,
1163 jboolean enabled) {
1164 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1165 if (rwhv)
1166 rwhv->SetDoubleTapSupportEnabled(enabled);
1169 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
1170 jobject obj,
1171 jboolean enabled) {
1172 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1173 if (rwhv)
1174 rwhv->SetMultiTouchZoomSupportEnabled(enabled);
1177 void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) {
1178 web_contents_->GetController().LoadIfNecessary();
1181 void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv* env, jobject obj) {
1182 web_contents_->GetController().SetNeedsReload();
1185 void ContentViewCoreImpl::Reload(JNIEnv* env,
1186 jobject obj,
1187 jboolean check_for_repost) {
1188 if (web_contents_->GetController().NeedsReload())
1189 web_contents_->GetController().LoadIfNecessary();
1190 else
1191 web_contents_->GetController().Reload(check_for_repost);
1194 void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv* env,
1195 jobject obj,
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::SetAllowJavascriptInterfacesInspection(
1215 JNIEnv* env,
1216 jobject obj,
1217 jboolean allow) {
1218 java_bridge_dispatcher_host_manager_->SetAllowObjectContentsInspection(allow);
1221 void ContentViewCoreImpl::AddJavascriptInterface(
1222 JNIEnv* env,
1223 jobject /* obj */,
1224 jobject object,
1225 jstring name,
1226 jclass safe_annotation_clazz) {
1227 ScopedJavaLocalRef<jobject> scoped_object(env, object);
1228 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
1230 // JavaBoundObject creates the NPObject with a ref count of 1, and
1231 // JavaBridgeDispatcherHostManager takes its own ref.
1232 NPObject* bound_object = JavaBoundObject::Create(
1233 scoped_object,
1234 scoped_clazz,
1235 java_bridge_dispatcher_host_manager_->AsWeakPtr(),
1236 java_bridge_dispatcher_host_manager_->GetAllowObjectContentsInspection());
1237 java_bridge_dispatcher_host_manager_->AddNamedObject(
1238 ConvertJavaStringToUTF16(env, name), bound_object);
1239 blink::WebBindings::releaseObject(bound_object);
1242 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
1243 jobject /* obj */,
1244 jstring name) {
1245 java_bridge_dispatcher_host_manager_->RemoveNamedObject(
1246 ConvertJavaStringToUTF16(env, name));
1249 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
1250 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1251 gfx::Size physical_size(
1252 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj),
1253 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj));
1254 root_layer_->SetBounds(physical_size);
1256 if (view) {
1257 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
1258 view->GetRenderWidgetHost());
1259 host->SendScreenRects();
1260 view->WasResized();
1264 void ContentViewCoreImpl::ShowInterstitialPage(
1265 JNIEnv* env, jobject obj, jstring jurl, jlong delegate_ptr) {
1266 GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
1267 InterstitialPageDelegateAndroid* delegate =
1268 reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
1269 InterstitialPage* interstitial = InterstitialPage::Create(
1270 web_contents_, false, url, delegate);
1271 delegate->set_interstitial_page(interstitial);
1272 interstitial->Show();
1275 jboolean ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv* env,
1276 jobject obj) {
1277 return web_contents_->ShowingInterstitialPage();
1280 jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
1281 jobject obj) {
1282 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
1283 return view && view->HasValidFrame();
1286 void ContentViewCoreImpl::ExitFullscreen(JNIEnv* env, jobject obj) {
1287 RenderViewHost* host = web_contents_->GetRenderViewHost();
1288 if (!host)
1289 return;
1290 host->ExitFullscreen();
1293 void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv* env,
1294 jobject obj,
1295 bool enable_hiding,
1296 bool enable_showing,
1297 bool animate) {
1298 RenderViewHost* host = web_contents_->GetRenderViewHost();
1299 if (!host)
1300 return;
1301 host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
1302 enable_hiding,
1303 enable_showing,
1304 animate));
1307 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
1308 RenderViewHost* host = web_contents_->GetRenderViewHost();
1309 host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
1312 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv* env,
1313 jobject obj) {
1314 RenderViewHost* host = web_contents_->GetRenderViewHost();
1315 host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
1316 host->GetRoutingID(), gfx::Rect()));
1319 void ContentViewCoreImpl::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
1320 RenderViewHost* host = web_contents_->GetRenderViewHost();
1321 if (!host)
1322 return;
1323 host->SelectWordAroundCaret();
1326 namespace {
1328 static void AddNavigationEntryToHistory(JNIEnv* env, jobject obj,
1329 jobject history,
1330 NavigationEntry* entry,
1331 int index) {
1332 // Get the details of the current entry
1333 ScopedJavaLocalRef<jstring> j_url(
1334 ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
1335 ScopedJavaLocalRef<jstring> j_virtual_url(
1336 ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
1337 ScopedJavaLocalRef<jstring> j_original_url(
1338 ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
1339 ScopedJavaLocalRef<jstring> j_title(
1340 ConvertUTF16ToJavaString(env, entry->GetTitle()));
1341 ScopedJavaLocalRef<jobject> j_bitmap;
1342 const FaviconStatus& status = entry->GetFavicon();
1343 if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
1344 j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
1346 // Add the item to the list
1347 Java_ContentViewCore_addToNavigationHistory(
1348 env, obj, history, index, j_url.obj(), j_virtual_url.obj(),
1349 j_original_url.obj(), j_title.obj(), j_bitmap.obj());
1352 } // namespace
1354 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env,
1355 jobject obj,
1356 jobject history) {
1357 // Iterate through navigation entries to populate the list
1358 const NavigationController& controller = web_contents_->GetController();
1359 int count = controller.GetEntryCount();
1360 for (int i = 0; i < count; ++i) {
1361 AddNavigationEntryToHistory(
1362 env, obj, history, controller.GetEntryAtIndex(i), i);
1365 return controller.GetCurrentEntryIndex();
1368 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv* env,
1369 jobject obj,
1370 jobject history,
1371 jboolean is_forward,
1372 jint max_entries) {
1373 // Iterate through navigation entries to populate the list
1374 const NavigationController& controller = web_contents_->GetController();
1375 int count = controller.GetEntryCount();
1376 int num_added = 0;
1377 int increment_value = is_forward ? 1 : -1;
1378 for (int i = controller.GetCurrentEntryIndex() + increment_value;
1379 i >= 0 && i < count;
1380 i += increment_value) {
1381 if (num_added >= max_entries)
1382 break;
1384 AddNavigationEntryToHistory(
1385 env, obj, history, controller.GetEntryAtIndex(i), i);
1386 num_added++;
1390 ScopedJavaLocalRef<jstring>
1391 ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv* env,
1392 jobject obj) {
1393 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1394 if (entry == NULL)
1395 return ScopedJavaLocalRef<jstring>(env, NULL);
1396 return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
1399 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
1400 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
1401 if (!rwhva)
1402 return 0;
1403 return rwhva->GetNativeImeAdapter();
1406 namespace {
1407 void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
1408 const base::Value* result) {
1409 JNIEnv* env = base::android::AttachCurrentThread();
1410 std::string json;
1411 base::JSONWriter::Write(result, &json);
1412 ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
1413 Java_ContentViewCore_onEvaluateJavaScriptResult(env,
1414 j_json.obj(),
1415 callback.obj());
1417 } // namespace
1419 void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env,
1420 jobject obj,
1421 jstring script,
1422 jobject callback,
1423 jboolean start_renderer) {
1424 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
1425 DCHECK(rvh);
1427 if (start_renderer && !rvh->IsRenderViewLive()) {
1428 if (!web_contents_->CreateRenderViewForInitialEmptyDocument()) {
1429 LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
1430 return;
1434 if (!callback) {
1435 // No callback requested.
1436 web_contents_->GetMainFrame()->ExecuteJavaScript(
1437 ConvertJavaStringToUTF16(env, script));
1438 return;
1441 // Secure the Java callback in a scoped object and give ownership of it to the
1442 // base::Callback.
1443 ScopedJavaGlobalRef<jobject> j_callback;
1444 j_callback.Reset(env, callback);
1445 content::RenderFrameHost::JavaScriptResultCallback c_callback =
1446 base::Bind(&JavaScriptResultCallback, j_callback);
1448 web_contents_->GetMainFrame()->ExecuteJavaScript(
1449 ConvertJavaStringToUTF16(env, script),
1450 c_callback);
1453 bool ContentViewCoreImpl::GetUseDesktopUserAgent(
1454 JNIEnv* env, jobject obj) {
1455 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1456 return entry && entry->GetIsOverridingUserAgent();
1459 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
1460 int text_input_type,
1461 const std::string& text,
1462 int selection_start,
1463 int selection_end,
1464 int composition_start,
1465 int composition_end,
1466 bool show_ime_if_needed,
1467 bool is_non_ime_change) {
1468 JNIEnv* env = AttachCurrentThread();
1469 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1470 if (obj.is_null())
1471 return;
1473 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
1474 Java_ContentViewCore_updateImeAdapter(env, obj.obj(),
1475 native_ime_adapter, text_input_type,
1476 jstring_text.obj(),
1477 selection_start, selection_end,
1478 composition_start, composition_end,
1479 show_ime_if_needed, is_non_ime_change);
1482 void ContentViewCoreImpl::ClearSslPreferences(JNIEnv* env, jobject obj) {
1483 SSLHostState* state = SSLHostState::GetFor(
1484 web_contents_->GetController().GetBrowserContext());
1485 state->Clear();
1488 void ContentViewCoreImpl::SetUseDesktopUserAgent(
1489 JNIEnv* env,
1490 jobject obj,
1491 jboolean enabled,
1492 jboolean reload_on_state_change) {
1493 if (GetUseDesktopUserAgent(env, obj) == enabled)
1494 return;
1496 // Make sure the navigation entry actually exists.
1497 NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
1498 if (!entry)
1499 return;
1501 // Set the flag in the NavigationEntry.
1502 entry->SetIsOverridingUserAgent(enabled);
1504 // Send the override to the renderer.
1505 if (reload_on_state_change) {
1506 // Reloading the page will send the override down as part of the
1507 // navigation IPC message.
1508 NavigationControllerImpl& controller =
1509 static_cast<NavigationControllerImpl&>(web_contents_->GetController());
1510 controller.ReloadOriginalRequestURL(false);
1514 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
1515 bool enabled) {
1516 SetAccessibilityEnabledInternal(enabled);
1519 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
1520 accessibility_enabled_ = enabled;
1521 RenderWidgetHostViewAndroid* host_view = GetRenderWidgetHostViewAndroid();
1522 if (!host_view)
1523 return;
1524 RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(
1525 host_view->GetRenderWidgetHost());
1526 BrowserAccessibilityState* accessibility_state =
1527 BrowserAccessibilityState::GetInstance();
1528 if (enabled) {
1529 // This enables accessibility globally unless it was explicitly disallowed
1530 // by a command-line flag.
1531 accessibility_state->OnScreenReaderDetected();
1532 // If it was actually enabled globally, enable it for this RenderWidget now.
1533 if (accessibility_state->IsAccessibleBrowser() && host_impl)
1534 host_impl->AddAccessibilityMode(AccessibilityModeComplete);
1535 } else {
1536 accessibility_state->ResetAccessibilityMode();
1537 if (host_impl)
1538 host_impl->ResetAccessibilityMode();
1542 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
1543 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
1544 if (rwhv)
1545 rwhv->UpdateScreenInfo(GetViewAndroid());
1548 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
1549 jobject obj,
1550 jint x,
1551 jint y,
1552 jint width,
1553 jint height) {
1554 gfx::Rect rect(
1555 static_cast<int>(x / dpi_scale()),
1556 static_cast<int>(y / dpi_scale()),
1557 static_cast<int>((width > 0 && width < dpi_scale()) ?
1558 1 : (int)(width / dpi_scale())),
1559 static_cast<int>((height > 0 && height < dpi_scale()) ?
1560 1 : (int)(height / dpi_scale())));
1561 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
1562 GetWebContents()->GetRoutingID(), rect));
1565 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
1566 return GetRenderProcessIdFromRenderViewHost(
1567 web_contents_->GetRenderViewHost());
1570 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
1571 jboolean opaque) {
1572 if (GetRenderWidgetHostViewAndroid())
1573 GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque);
1576 void ContentViewCoreImpl::RequestTextSurroundingSelection(
1577 int max_length,
1578 const base::Callback<
1579 void(const base::string16& content, int start_offset, int end_offset)>&
1580 callback) {
1581 DCHECK(!callback.is_null());
1582 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame();
1583 if (!focused_frame)
1584 return;
1585 if (GetRenderWidgetHostViewAndroid()) {
1586 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback(
1587 callback);
1588 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest(
1589 focused_frame->GetRoutingID(), max_length));
1593 void ContentViewCoreImpl::OnSmartClipDataExtracted(
1594 const base::string16& result) {
1595 JNIEnv* env = AttachCurrentThread();
1596 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
1597 if (obj.is_null())
1598 return;
1599 ScopedJavaLocalRef<jstring> jresult = ConvertUTF16ToJavaString(env, result);
1600 Java_ContentViewCore_onSmartClipDataExtracted(
1601 env, obj.obj(), jresult.obj());
1604 void ContentViewCoreImpl::WebContentsDestroyed() {
1605 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>(
1606 static_cast<WebContentsImpl*>(web_contents())->GetView());
1607 DCHECK(wcva);
1608 wcva->SetContentViewCore(NULL);
1611 // This is called for each ContentView.
1612 jlong Init(JNIEnv* env,
1613 jobject obj,
1614 jlong native_web_contents,
1615 jlong view_android,
1616 jlong window_android,
1617 jobject retained_objects_set) {
1618 ContentViewCoreImpl* view = new ContentViewCoreImpl(
1619 env, obj,
1620 reinterpret_cast<WebContents*>(native_web_contents),
1621 reinterpret_cast<ui::ViewAndroid*>(view_android),
1622 reinterpret_cast<ui::WindowAndroid*>(window_android),
1623 retained_objects_set);
1624 return reinterpret_cast<intptr_t>(view);
1627 bool RegisterContentViewCore(JNIEnv* env) {
1628 return RegisterNativesImpl(env);
1631 } // namespace content