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