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