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/logging.h" 13 #include "base/metrics/histogram.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/values.h" 16 #include "cc/layers/layer.h" 17 #include "cc/layers/solid_color_layer.h" 18 #include "cc/output/begin_frame_args.h" 19 #include "content/browser/accessibility/browser_accessibility_state_impl.h" 20 #include "content/browser/android/gesture_event_type.h" 21 #include "content/browser/android/interstitial_page_delegate_android.h" 22 #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h" 23 #include "content/browser/android/load_url_params.h" 24 #include "content/browser/android/popup_touch_handle_drawable.h" 25 #include "content/browser/frame_host/interstitial_page_impl.h" 26 #include "content/browser/geolocation/geolocation_dispatcher_host.h" 27 #include "content/browser/media/media_web_contents_observer.h" 28 #include "content/browser/renderer_host/compositor_impl_android.h" 29 #include "content/browser/renderer_host/input/motion_event_android.h" 30 #include "content/browser/renderer_host/input/web_input_event_builders_android.h" 31 #include "content/browser/renderer_host/input/web_input_event_util.h" 32 #include "content/browser/renderer_host/render_view_host_impl.h" 33 #include "content/browser/renderer_host/render_widget_host_impl.h" 34 #include "content/browser/renderer_host/render_widget_host_view_android.h" 35 #include "content/browser/transition_request_manager.h" 36 #include "content/browser/web_contents/web_contents_view_android.h" 37 #include "content/common/frame_messages.h" 38 #include "content/common/input/web_input_event_traits.h" 39 #include "content/common/input_messages.h" 40 #include "content/common/view_messages.h" 41 #include "content/public/browser/browser_context.h" 42 #include "content/public/browser/browser_thread.h" 43 #include "content/public/browser/favicon_status.h" 44 #include "content/public/browser/render_frame_host.h" 45 #include "content/public/browser/screen_orientation_dispatcher_host.h" 46 #include "content/public/browser/ssl_host_state_delegate.h" 47 #include "content/public/browser/web_contents.h" 48 #include "content/public/common/content_client.h" 49 #include "content/public/common/content_switches.h" 50 #include "content/public/common/menu_item.h" 51 #include "content/public/common/user_agent.h" 52 #include "jni/ContentViewCore_jni.h" 53 #include "third_party/WebKit/public/web/WebInputEvent.h" 54 #include "ui/base/android/view_android.h" 55 #include "ui/base/android/window_android.h" 56 #include "ui/gfx/android/java_bitmap.h" 57 #include "ui/gfx/screen.h" 58 #include "ui/gfx/size_conversions.h" 59 #include "ui/gfx/size_f.h" 60 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::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 void* kContentViewUserDataKey = &kContentViewUserDataKey; 86 87 int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) { 88 DCHECK(host); 89 RenderProcessHost* render_process = host->GetProcess(); 90 DCHECK(render_process); 91 if (render_process->HasConnection()) 92 return render_process->GetHandle(); 93 else 94 return 0; 95 } 96 97 ScopedJavaLocalRef<jobject> CreateJavaRect( 98 JNIEnv* env, 99 const gfx::Rect& rect) { 100 return ScopedJavaLocalRef<jobject>( 101 Java_ContentViewCore_createRect(env, 102 static_cast<int>(rect.x()), 103 static_cast<int>(rect.y()), 104 static_cast<int>(rect.right()), 105 static_cast<int>(rect.bottom()))); 106 } 107 108 int ToGestureEventType(WebInputEvent::Type type) { 109 switch (type) { 110 case WebInputEvent::GestureScrollBegin: 111 return SCROLL_START; 112 case WebInputEvent::GestureScrollEnd: 113 return SCROLL_END; 114 case WebInputEvent::GestureScrollUpdate: 115 return SCROLL_BY; 116 case WebInputEvent::GestureFlingStart: 117 return FLING_START; 118 case WebInputEvent::GestureFlingCancel: 119 return FLING_CANCEL; 120 case WebInputEvent::GestureShowPress: 121 return SHOW_PRESS; 122 case WebInputEvent::GestureTap: 123 return SINGLE_TAP_CONFIRMED; 124 case WebInputEvent::GestureTapUnconfirmed: 125 return SINGLE_TAP_UNCONFIRMED; 126 case WebInputEvent::GestureTapDown: 127 return TAP_DOWN; 128 case WebInputEvent::GestureTapCancel: 129 return TAP_CANCEL; 130 case WebInputEvent::GestureDoubleTap: 131 return DOUBLE_TAP; 132 case WebInputEvent::GestureLongPress: 133 return LONG_PRESS; 134 case WebInputEvent::GestureLongTap: 135 return LONG_TAP; 136 case WebInputEvent::GesturePinchBegin: 137 return PINCH_BEGIN; 138 case WebInputEvent::GesturePinchEnd: 139 return PINCH_END; 140 case WebInputEvent::GesturePinchUpdate: 141 return PINCH_BY; 142 case WebInputEvent::GestureTwoFingerTap: 143 case WebInputEvent::GestureScrollUpdateWithoutPropagation: 144 default: 145 NOTREACHED() << "Invalid source gesture type: " 146 << WebInputEventTraits::GetName(type); 147 return -1; 148 }; 149 } 150 151 float GetPrimaryDisplayDeviceScaleFactor() { 152 const gfx::Display& display = 153 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); 154 return display.device_scale_factor(); 155 } 156 157 } // namespace 158 159 // Enables a callback when the underlying WebContents is destroyed, to enable 160 // nulling the back-pointer. 161 class ContentViewCoreImpl::ContentViewUserData 162 : public base::SupportsUserData::Data { 163 public: 164 explicit ContentViewUserData(ContentViewCoreImpl* content_view_core) 165 : content_view_core_(content_view_core) { 166 } 167 168 virtual ~ContentViewUserData() { 169 // TODO(joth): When chrome has finished removing the TabContents class (see 170 // crbug.com/107201) consider inverting relationship, so ContentViewCore 171 // would own WebContents. That effectively implies making the WebContents 172 // destructor private on Android. 173 delete content_view_core_; 174 } 175 176 ContentViewCoreImpl* get() const { return content_view_core_; } 177 178 private: 179 // Not using scoped_ptr as ContentViewCoreImpl destructor is private. 180 ContentViewCoreImpl* content_view_core_; 181 182 DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData); 183 }; 184 185 // static 186 ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents( 187 content::WebContents* web_contents) { 188 ContentViewCoreImpl::ContentViewUserData* data = 189 reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>( 190 web_contents->GetUserData(kContentViewUserDataKey)); 191 return data ? data->get() : NULL; 192 } 193 194 // static 195 ContentViewCore* ContentViewCore::FromWebContents( 196 content::WebContents* web_contents) { 197 return ContentViewCoreImpl::FromWebContents(web_contents); 198 } 199 200 // static 201 ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env, 202 jobject obj) { 203 return reinterpret_cast<ContentViewCore*>( 204 Java_ContentViewCore_getNativeContentViewCore(env, obj)); 205 } 206 207 ContentViewCoreImpl::ContentViewCoreImpl( 208 JNIEnv* env, 209 jobject obj, 210 WebContents* web_contents, 211 ui::ViewAndroid* view_android, 212 ui::WindowAndroid* window_android, 213 jobject java_bridge_retained_object_set) 214 : WebContentsObserver(web_contents), 215 java_ref_(env, obj), 216 web_contents_(static_cast<WebContentsImpl*>(web_contents)), 217 root_layer_(cc::SolidColorLayer::Create()), 218 dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()), 219 view_android_(view_android), 220 window_android_(window_android), 221 device_orientation_(0), 222 accessibility_enabled_(false) { 223 CHECK(web_contents) << 224 "A ContentViewCoreImpl should be created with a valid WebContents."; 225 DCHECK(view_android_); 226 DCHECK(window_android_); 227 228 root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj)); 229 gfx::Size physical_size( 230 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj), 231 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj)); 232 root_layer_->SetBounds(physical_size); 233 root_layer_->SetIsDrawable(true); 234 235 // Currently, the only use case we have for overriding a user agent involves 236 // spoofing a desktop Linux user agent for "Request desktop site". 237 // Automatically set it for all WebContents so that it is available when a 238 // NavigationEntry requires the user agent to be overridden. 239 const char kLinuxInfoStr[] = "X11; Linux x86_64"; 240 std::string product = content::GetContentClient()->GetProduct(); 241 std::string spoofed_ua = 242 BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product); 243 web_contents->SetUserAgentOverride(spoofed_ua); 244 245 java_bridge_dispatcher_host_ = 246 new GinJavaBridgeDispatcherHost(web_contents, 247 java_bridge_retained_object_set); 248 249 InitWebContents(); 250 } 251 252 ContentViewCoreImpl::~ContentViewCoreImpl() { 253 JNIEnv* env = base::android::AttachCurrentThread(); 254 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 255 java_ref_.reset(); 256 if (!j_obj.is_null()) { 257 Java_ContentViewCore_onNativeContentViewCoreDestroyed( 258 env, j_obj.obj(), reinterpret_cast<intptr_t>(this)); 259 } 260 } 261 262 base::android::ScopedJavaLocalRef<jobject> 263 ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) { 264 return web_contents_->GetJavaWebContents(); 265 } 266 267 void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env, 268 jobject obj) { 269 DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj)); 270 java_ref_.reset(); 271 // Java peer has gone, ContentViewCore is not functional and waits to 272 // be destroyed with WebContents. 273 // We need to reset WebContentsViewAndroid's reference, otherwise, there 274 // could have call in when swapping the WebContents, 275 // see http://crbug.com/383939 . 276 DCHECK(web_contents_); 277 static_cast<WebContentsViewAndroid*>( 278 static_cast<WebContentsImpl*>(web_contents_)->GetView())-> 279 SetContentViewCore(NULL); 280 } 281 282 void ContentViewCoreImpl::InitWebContents() { 283 DCHECK(web_contents_); 284 static_cast<WebContentsViewAndroid*>( 285 static_cast<WebContentsImpl*>(web_contents_)->GetView())-> 286 SetContentViewCore(this); 287 DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey)); 288 web_contents_->SetUserData(kContentViewUserDataKey, 289 new ContentViewUserData(this)); 290 } 291 292 void ContentViewCoreImpl::RenderViewReady() { 293 JNIEnv* env = AttachCurrentThread(); 294 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 295 if (!obj.is_null()) 296 Java_ContentViewCore_onRenderProcessChange(env, obj.obj()); 297 298 if (device_orientation_ != 0) 299 SendOrientationChangeEventInternal(); 300 } 301 302 void ContentViewCoreImpl::RenderViewHostChanged(RenderViewHost* old_host, 303 RenderViewHost* new_host) { 304 int old_pid = 0; 305 if (old_host) { 306 old_pid = GetRenderProcessIdFromRenderViewHost(old_host); 307 308 RenderWidgetHostViewAndroid* view = 309 static_cast<RenderWidgetHostViewAndroid*>(old_host->GetView()); 310 if (view) 311 view->SetContentViewCore(NULL); 312 313 view = static_cast<RenderWidgetHostViewAndroid*>(new_host->GetView()); 314 if (view) 315 view->SetContentViewCore(this); 316 } 317 int new_pid = GetRenderProcessIdFromRenderViewHost( 318 web_contents_->GetRenderViewHost()); 319 if (new_pid != old_pid) { 320 // Notify the Java side that the renderer process changed. 321 JNIEnv* env = AttachCurrentThread(); 322 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 323 if (!obj.is_null()) { 324 Java_ContentViewCore_onRenderProcessChange(env, obj.obj()); 325 } 326 } 327 328 SetFocusInternal(HasFocus()); 329 SetAccessibilityEnabledInternal(accessibility_enabled_); 330 } 331 332 RenderWidgetHostViewAndroid* 333 ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() { 334 RenderWidgetHostView* rwhv = NULL; 335 if (web_contents_) { 336 rwhv = web_contents_->GetRenderWidgetHostView(); 337 if (web_contents_->ShowingInterstitialPage()) { 338 rwhv = static_cast<InterstitialPageImpl*>( 339 web_contents_->GetInterstitialPage())-> 340 GetRenderViewHost()->GetView(); 341 } 342 } 343 return static_cast<RenderWidgetHostViewAndroid*>(rwhv); 344 } 345 346 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() { 347 JNIEnv* env = AttachCurrentThread(); 348 return java_ref_.get(env); 349 } 350 351 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) { 352 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid(); 353 if (!rwhva) 354 return SK_ColorWHITE; 355 return rwhva->GetCachedBackgroundColor(); 356 } 357 358 void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) { 359 web_contents_->geolocation_dispatcher_host()->PauseOrResume(should_pause); 360 } 361 362 // All positions and sizes are in CSS pixels. 363 // Note that viewport_width/height is a best effort based. 364 // ContentViewCore has the actual information about the physical viewport size. 365 void ContentViewCoreImpl::UpdateFrameInfo( 366 const gfx::Vector2dF& scroll_offset, 367 float page_scale_factor, 368 const gfx::Vector2dF& page_scale_factor_limits, 369 const gfx::SizeF& content_size, 370 const gfx::SizeF& viewport_size, 371 const gfx::Vector2dF& controls_offset, 372 const gfx::Vector2dF& content_offset) { 373 JNIEnv* env = AttachCurrentThread(); 374 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 375 if (obj.is_null()) 376 return; 377 378 window_android_->set_content_offset( 379 gfx::ScaleVector2d(content_offset, dpi_scale_)); 380 381 Java_ContentViewCore_updateFrameInfo( 382 env, obj.obj(), 383 scroll_offset.x(), 384 scroll_offset.y(), 385 page_scale_factor, 386 page_scale_factor_limits.x(), 387 page_scale_factor_limits.y(), 388 content_size.width(), 389 content_size.height(), 390 viewport_size.width(), 391 viewport_size.height(), 392 controls_offset.y(), 393 content_offset.y()); 394 } 395 396 void ContentViewCoreImpl::SetTitle(const base::string16& title) { 397 JNIEnv* env = AttachCurrentThread(); 398 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 399 if (obj.is_null()) 400 return; 401 ScopedJavaLocalRef<jstring> jtitle = 402 ConvertUTF8ToJavaString(env, base::UTF16ToUTF8(title)); 403 Java_ContentViewCore_setTitle(env, obj.obj(), jtitle.obj()); 404 } 405 406 void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) { 407 root_layer_->SetBackgroundColor(color); 408 409 JNIEnv* env = AttachCurrentThread(); 410 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 411 if (obj.is_null()) 412 return; 413 Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color); 414 } 415 416 void ContentViewCoreImpl::ShowSelectPopupMenu( 417 RenderFrameHost* frame, 418 const gfx::Rect& bounds, 419 const std::vector<MenuItem>& items, 420 int selected_item, 421 bool multiple) { 422 JNIEnv* env = AttachCurrentThread(); 423 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 424 if (j_obj.is_null()) 425 return; 426 427 ScopedJavaLocalRef<jobject> bounds_rect(CreateJavaRect(env, bounds)); 428 429 // For multi-select list popups we find the list of previous selections by 430 // iterating through the items. But for single selection popups we take the 431 // given |selected_item| as is. 432 ScopedJavaLocalRef<jintArray> selected_array; 433 if (multiple) { 434 scoped_ptr<jint[]> native_selected_array(new jint[items.size()]); 435 size_t selected_count = 0; 436 for (size_t i = 0; i < items.size(); ++i) { 437 if (items[i].checked) 438 native_selected_array[selected_count++] = i; 439 } 440 441 selected_array = ScopedJavaLocalRef<jintArray>( 442 env, env->NewIntArray(selected_count)); 443 env->SetIntArrayRegion(selected_array.obj(), 0, selected_count, 444 native_selected_array.get()); 445 } else { 446 selected_array = ScopedJavaLocalRef<jintArray>(env, env->NewIntArray(1)); 447 jint value = selected_item; 448 env->SetIntArrayRegion(selected_array.obj(), 0, 1, &value); 449 } 450 451 ScopedJavaLocalRef<jintArray> enabled_array(env, 452 env->NewIntArray(items.size())); 453 std::vector<base::string16> labels; 454 labels.reserve(items.size()); 455 for (size_t i = 0; i < items.size(); ++i) { 456 labels.push_back(items[i].label); 457 jint enabled = 458 (items[i].type == MenuItem::GROUP ? POPUP_ITEM_TYPE_GROUP : 459 (items[i].enabled ? POPUP_ITEM_TYPE_ENABLED : 460 POPUP_ITEM_TYPE_DISABLED)); 461 env->SetIntArrayRegion(enabled_array.obj(), i, 1, &enabled); 462 } 463 ScopedJavaLocalRef<jobjectArray> items_array( 464 base::android::ToJavaArrayOfStrings(env, labels)); 465 Java_ContentViewCore_showSelectPopup(env, 466 j_obj.obj(), 467 reinterpret_cast<intptr_t>(frame), 468 bounds_rect.obj(), 469 items_array.obj(), 470 enabled_array.obj(), 471 multiple, 472 selected_array.obj()); 473 } 474 475 void ContentViewCoreImpl::HideSelectPopupMenu() { 476 JNIEnv* env = AttachCurrentThread(); 477 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 478 if (!j_obj.is_null()) 479 Java_ContentViewCore_hideSelectPopup(env, j_obj.obj()); 480 } 481 482 void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event, 483 InputEventAckState ack_result) { 484 JNIEnv* env = AttachCurrentThread(); 485 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 486 if (j_obj.is_null()) 487 return; 488 489 switch (event.type) { 490 case WebInputEvent::GestureFlingStart: 491 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) { 492 // The view expects the fling velocity in pixels/s. 493 Java_ContentViewCore_onFlingStartEventConsumed(env, j_obj.obj(), 494 event.data.flingStart.velocityX * dpi_scale(), 495 event.data.flingStart.velocityY * dpi_scale()); 496 } else { 497 // If a scroll ends with a fling, a SCROLL_END event is never sent. 498 // However, if that fling went unconsumed, we still need to let the 499 // listeners know that scrolling has ended. 500 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj()); 501 } 502 503 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) { 504 // The view expects the fling velocity in pixels/s. 505 Java_ContentViewCore_onFlingStartEventHadNoConsumer(env, j_obj.obj(), 506 event.data.flingStart.velocityX * dpi_scale(), 507 event.data.flingStart.velocityY * dpi_scale()); 508 } 509 break; 510 case WebInputEvent::GestureFlingCancel: 511 Java_ContentViewCore_onFlingCancelEventAck(env, j_obj.obj()); 512 break; 513 case WebInputEvent::GestureScrollBegin: 514 Java_ContentViewCore_onScrollBeginEventAck(env, j_obj.obj()); 515 break; 516 case WebInputEvent::GestureScrollUpdate: 517 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) 518 Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj()); 519 break; 520 case WebInputEvent::GestureScrollEnd: 521 Java_ContentViewCore_onScrollEndEventAck(env, j_obj.obj()); 522 break; 523 case WebInputEvent::GesturePinchBegin: 524 Java_ContentViewCore_onPinchBeginEventAck(env, j_obj.obj()); 525 break; 526 case WebInputEvent::GesturePinchEnd: 527 Java_ContentViewCore_onPinchEndEventAck(env, j_obj.obj()); 528 break; 529 case WebInputEvent::GestureTap: 530 Java_ContentViewCore_onSingleTapEventAck( 531 env, 532 j_obj.obj(), 533 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED, 534 event.x * dpi_scale(), 535 event.y * dpi_scale()); 536 break; 537 default: 538 break; 539 } 540 } 541 542 bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) { 543 if (event.type != WebInputEvent::GestureTap && 544 event.type != WebInputEvent::GestureDoubleTap && 545 event.type != WebInputEvent::GestureLongTap && 546 event.type != WebInputEvent::GestureLongPress) 547 return false; 548 549 JNIEnv* env = AttachCurrentThread(); 550 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 551 if (j_obj.is_null()) 552 return false; 553 554 const blink::WebGestureEvent& gesture = 555 static_cast<const blink::WebGestureEvent&>(event); 556 int gesture_type = ToGestureEventType(event.type); 557 return Java_ContentViewCore_filterTapOrPressEvent(env, 558 j_obj.obj(), 559 gesture_type, 560 gesture.x * dpi_scale(), 561 gesture.y * dpi_scale()); 562 563 // TODO(jdduke): Also report double-tap UMA, crbug/347568. 564 } 565 566 bool ContentViewCoreImpl::HasFocus() { 567 JNIEnv* env = AttachCurrentThread(); 568 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 569 if (obj.is_null()) 570 return false; 571 return Java_ContentViewCore_hasFocus(env, obj.obj()); 572 } 573 574 void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) { 575 JNIEnv* env = AttachCurrentThread(); 576 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 577 if (obj.is_null()) 578 return; 579 ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text); 580 Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj()); 581 } 582 583 void ContentViewCoreImpl::OnSelectionEvent(SelectionEventType event, 584 const gfx::PointF& position) { 585 JNIEnv* env = AttachCurrentThread(); 586 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 587 if (j_obj.is_null()) 588 return; 589 Java_ContentViewCore_onSelectionEvent( 590 env, j_obj.obj(), event, position.x(), position.y()); 591 } 592 593 scoped_ptr<TouchHandleDrawable> 594 ContentViewCoreImpl::CreatePopupTouchHandleDrawable() { 595 JNIEnv* env = AttachCurrentThread(); 596 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 597 if (obj.is_null()) { 598 NOTREACHED(); 599 return scoped_ptr<TouchHandleDrawable>(); 600 } 601 return scoped_ptr<TouchHandleDrawable>(new PopupTouchHandleDrawable( 602 Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()), 603 dpi_scale_)); 604 } 605 606 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) { 607 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid(); 608 if (!view) 609 return; 610 611 view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip)); 612 613 JNIEnv* env = AttachCurrentThread(); 614 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 615 if (obj.is_null()) 616 return; 617 Java_ContentViewCore_showPastePopupWithFeedback(env, obj.obj(), 618 static_cast<jint>(x_dip), 619 static_cast<jint>(y_dip)); 620 } 621 622 void ContentViewCoreImpl::GetScaledContentBitmap( 623 float scale, 624 SkColorType color_type, 625 gfx::Rect src_subrect, 626 const base::Callback<void(bool, const SkBitmap&)>& result_callback) { 627 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid(); 628 if (!view) { 629 result_callback.Run(false, SkBitmap()); 630 return; 631 } 632 633 view->GetScaledContentBitmap(scale, color_type, src_subrect, 634 result_callback); 635 } 636 637 void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) { 638 JNIEnv* env = AttachCurrentThread(); 639 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 640 if (j_obj.is_null()) 641 return; 642 ScopedJavaLocalRef<jstring> jcontent_url = 643 ConvertUTF8ToJavaString(env, content_url.spec()); 644 Java_ContentViewCore_startContentIntent(env, 645 j_obj.obj(), 646 jcontent_url.obj()); 647 } 648 649 void ContentViewCoreImpl::ShowDisambiguationPopup( 650 const gfx::Rect& rect_pixels, 651 const SkBitmap& zoomed_bitmap) { 652 JNIEnv* env = AttachCurrentThread(); 653 654 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 655 if (obj.is_null()) 656 return; 657 658 ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels)); 659 660 ScopedJavaLocalRef<jobject> java_bitmap = 661 gfx::ConvertToJavaBitmap(&zoomed_bitmap); 662 DCHECK(!java_bitmap.is_null()); 663 664 Java_ContentViewCore_showDisambiguationPopup(env, 665 obj.obj(), 666 rect_object.obj(), 667 java_bitmap.obj()); 668 } 669 670 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() { 671 JNIEnv* env = AttachCurrentThread(); 672 673 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 674 if (obj.is_null()) 675 return ScopedJavaLocalRef<jobject>(); 676 return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj()); 677 } 678 679 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() { 680 JNIEnv* env = AttachCurrentThread(); 681 682 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 683 if (obj.is_null()) 684 return ScopedJavaLocalRef<jobject>(); 685 686 return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj()); 687 } 688 689 ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() { 690 JNIEnv* env = AttachCurrentThread(); 691 692 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 693 if (obj.is_null()) 694 return ScopedJavaLocalRef<jobject>(); 695 696 return Java_ContentViewCore_getContext(env, obj.obj()); 697 } 698 699 bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) { 700 JNIEnv* env = AttachCurrentThread(); 701 702 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 703 if (obj.is_null()) 704 return true; 705 ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec()); 706 return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(), 707 j_url.obj()); 708 } 709 710 void ContentViewCoreImpl::DidStopFlinging() { 711 JNIEnv* env = AttachCurrentThread(); 712 713 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 714 if (!obj.is_null()) 715 Java_ContentViewCore_onNativeFlingStopped(env, obj.obj()); 716 } 717 718 gfx::Size ContentViewCoreImpl::GetViewSize() const { 719 gfx::Size size = GetViewportSizeDip(); 720 size.Enlarge(0, -GetTopControlsLayoutHeightDip()); 721 return size; 722 } 723 724 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const { 725 JNIEnv* env = AttachCurrentThread(); 726 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 727 if (j_obj.is_null()) 728 return gfx::Size(); 729 return gfx::Size( 730 Java_ContentViewCore_getPhysicalBackingWidthPix(env, j_obj.obj()), 731 Java_ContentViewCore_getPhysicalBackingHeightPix(env, j_obj.obj())); 732 } 733 734 gfx::Size ContentViewCoreImpl::GetViewportSizePix() const { 735 JNIEnv* env = AttachCurrentThread(); 736 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 737 if (j_obj.is_null()) 738 return gfx::Size(); 739 return gfx::Size( 740 Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()), 741 Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj())); 742 } 743 744 int ContentViewCoreImpl::GetTopControlsLayoutHeightPix() const { 745 JNIEnv* env = AttachCurrentThread(); 746 ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); 747 if (j_obj.is_null()) 748 return 0; 749 return Java_ContentViewCore_getTopControlsLayoutHeightPix(env, j_obj.obj()); 750 } 751 752 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const { 753 return gfx::ToCeiledSize( 754 gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale())); 755 } 756 757 float ContentViewCoreImpl::GetTopControlsLayoutHeightDip() const { 758 return GetTopControlsLayoutHeightPix() / dpi_scale(); 759 } 760 761 void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) { 762 root_layer_->InsertChild(layer, 0); 763 root_layer_->SetIsDrawable(false); 764 } 765 766 void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) { 767 layer->RemoveFromParent(); 768 769 if (!root_layer_->children().size()) 770 root_layer_->SetIsDrawable(true); 771 } 772 773 void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& start, 774 const gfx::PointF& end) { 775 if (!web_contents_) 776 return; 777 778 gfx::Point start_point = gfx::Point(start.x(), start.y()); 779 gfx::Point end_point = gfx::Point(end.x(), end.y()); 780 if (start_point == end_point) 781 return; 782 783 web_contents_->SelectRange(start_point, end_point); 784 } 785 786 ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const { 787 return view_android_; 788 } 789 790 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const { 791 return window_android_; 792 } 793 794 scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const { 795 return root_layer_.get(); 796 } 797 798 // ---------------------------------------------------------------------------- 799 // Methods called from Java via JNI 800 // ---------------------------------------------------------------------------- 801 802 void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env, 803 jobject obj, 804 jlong selectPopupSourceFrame, 805 jintArray indices) { 806 RenderFrameHostImpl* rfhi = 807 reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame); 808 DCHECK(rfhi); 809 if (indices == NULL) { 810 rfhi->DidCancelPopupMenu(); 811 return; 812 } 813 814 int selected_count = env->GetArrayLength(indices); 815 std::vector<int> selected_indices; 816 jint* indices_ptr = env->GetIntArrayElements(indices, NULL); 817 for (int i = 0; i < selected_count; ++i) 818 selected_indices.push_back(indices_ptr[i]); 819 env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT); 820 rfhi->DidSelectPopupMenuItems(selected_indices); 821 } 822 823 WebContents* ContentViewCoreImpl::GetWebContents() const { 824 return web_contents_; 825 } 826 827 void ContentViewCoreImpl::SetFocus(JNIEnv* env, jobject obj, jboolean focused) { 828 SetFocusInternal(focused); 829 } 830 831 void ContentViewCoreImpl::SetFocusInternal(bool focused) { 832 if (!GetRenderWidgetHostViewAndroid()) 833 return; 834 835 if (focused) 836 GetRenderWidgetHostViewAndroid()->Focus(); 837 else 838 GetRenderWidgetHostViewAndroid()->Blur(); 839 } 840 841 void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env, 842 jobject obj, 843 jint orientation) { 844 if (device_orientation_ != orientation) { 845 device_orientation_ = orientation; 846 SendOrientationChangeEventInternal(); 847 } 848 } 849 850 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env, 851 jobject obj, 852 jobject motion_event, 853 jlong time_ms, 854 jint android_action, 855 jint pointer_count, 856 jint history_size, 857 jint action_index, 858 jfloat pos_x_0, 859 jfloat pos_y_0, 860 jfloat pos_x_1, 861 jfloat pos_y_1, 862 jint pointer_id_0, 863 jint pointer_id_1, 864 jfloat touch_major_0, 865 jfloat touch_major_1, 866 jfloat touch_minor_0, 867 jfloat touch_minor_1, 868 jfloat orientation_0, 869 jfloat orientation_1, 870 jfloat raw_pos_x, 871 jfloat raw_pos_y, 872 jint android_tool_type_0, 873 jint android_tool_type_1, 874 jint android_button_state, 875 jint android_meta_state, 876 jboolean is_touch_handle_event) { 877 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 878 // Avoid synthesizing a touch event if it cannot be forwarded. 879 if (!rwhv) 880 return false; 881 882 MotionEventAndroid event(1.f / dpi_scale(), 883 env, 884 motion_event, 885 time_ms, 886 android_action, 887 pointer_count, 888 history_size, 889 action_index, 890 pos_x_0, 891 pos_y_0, 892 pos_x_1, 893 pos_y_1, 894 pointer_id_0, 895 pointer_id_1, 896 touch_major_0, 897 touch_major_1, 898 touch_minor_0, 899 touch_minor_1, 900 orientation_0, 901 orientation_1, 902 raw_pos_x, 903 raw_pos_y, 904 android_tool_type_0, 905 android_tool_type_1, 906 android_button_state, 907 android_meta_state); 908 909 return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event) 910 : rwhv->OnTouchEvent(event); 911 } 912 913 float ContentViewCoreImpl::GetDpiScale() const { 914 return dpi_scale_; 915 } 916 917 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env, 918 jobject obj, 919 jlong time_ms, 920 jfloat x, 921 jfloat y) { 922 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 923 if (!rwhv) 924 return false; 925 926 blink::WebMouseEvent event = WebMouseEventBuilder::Build( 927 WebInputEvent::MouseMove, 928 blink::WebMouseEvent::ButtonNone, 929 time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1); 930 931 rwhv->SendMouseEvent(event); 932 return true; 933 } 934 935 jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env, 936 jobject obj, 937 jlong time_ms, 938 jfloat x, 939 jfloat y, 940 jfloat vertical_axis) { 941 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 942 if (!rwhv) 943 return false; 944 945 WebMouseWheelEventBuilder::Direction direction; 946 if (vertical_axis > 0) { 947 direction = WebMouseWheelEventBuilder::DIRECTION_UP; 948 } else if (vertical_axis < 0) { 949 direction = WebMouseWheelEventBuilder::DIRECTION_DOWN; 950 } else { 951 return false; 952 } 953 blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build( 954 direction, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale()); 955 956 rwhv->SendMouseWheelEvent(event); 957 return true; 958 } 959 960 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent( 961 WebInputEvent::Type type, int64 time_ms, float x, float y) const { 962 return WebGestureEventBuilder::Build( 963 type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale()); 964 } 965 966 void ContentViewCoreImpl::SendGestureEvent( 967 const blink::WebGestureEvent& event) { 968 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 969 if (rwhv) 970 rwhv->SendGestureEvent(event); 971 } 972 973 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env, 974 jobject obj, 975 jlong time_ms, 976 jfloat x, 977 jfloat y, 978 jfloat hintx, 979 jfloat hinty) { 980 WebGestureEvent event = MakeGestureEvent( 981 WebInputEvent::GestureScrollBegin, time_ms, x, y); 982 event.data.scrollBegin.deltaXHint = hintx / dpi_scale(); 983 event.data.scrollBegin.deltaYHint = hinty / dpi_scale(); 984 985 SendGestureEvent(event); 986 } 987 988 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) { 989 WebGestureEvent event = MakeGestureEvent( 990 WebInputEvent::GestureScrollEnd, time_ms, 0, 0); 991 SendGestureEvent(event); 992 } 993 994 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms, 995 jfloat x, jfloat y, jfloat dx, jfloat dy) { 996 WebGestureEvent event = MakeGestureEvent( 997 WebInputEvent::GestureScrollUpdate, time_ms, x, y); 998 event.data.scrollUpdate.deltaX = -dx / dpi_scale(); 999 event.data.scrollUpdate.deltaY = -dy / dpi_scale(); 1000 1001 SendGestureEvent(event); 1002 } 1003 1004 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms, 1005 jfloat x, jfloat y, jfloat vx, jfloat vy) { 1006 WebGestureEvent event = MakeGestureEvent( 1007 WebInputEvent::GestureFlingStart, time_ms, x, y); 1008 event.data.flingStart.velocityX = vx / dpi_scale(); 1009 event.data.flingStart.velocityY = vy / dpi_scale(); 1010 1011 SendGestureEvent(event); 1012 } 1013 1014 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) { 1015 WebGestureEvent event = MakeGestureEvent( 1016 WebInputEvent::GestureFlingCancel, time_ms, 0, 0); 1017 SendGestureEvent(event); 1018 } 1019 1020 void ContentViewCoreImpl::SingleTap(JNIEnv* env, jobject obj, jlong time_ms, 1021 jfloat x, jfloat y) { 1022 WebGestureEvent event = MakeGestureEvent( 1023 WebInputEvent::GestureTap, time_ms, x, y); 1024 event.data.tap.tapCount = 1; 1025 1026 SendGestureEvent(event); 1027 } 1028 1029 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms, 1030 jfloat x, jfloat y) { 1031 WebGestureEvent event = MakeGestureEvent( 1032 WebInputEvent::GestureDoubleTap, time_ms, x, y); 1033 // Set the tap count to 1 even for DoubleTap, in order to be consistent with 1034 // double tap behavior on a mobile viewport. See crbug.com/234986 for context. 1035 event.data.tap.tapCount = 1; 1036 1037 SendGestureEvent(event); 1038 } 1039 1040 void ContentViewCoreImpl::LongPress(JNIEnv* env, jobject obj, jlong time_ms, 1041 jfloat x, jfloat y) { 1042 WebGestureEvent event = MakeGestureEvent( 1043 WebInputEvent::GestureLongPress, time_ms, x, y); 1044 1045 SendGestureEvent(event); 1046 } 1047 1048 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms, 1049 jfloat x, jfloat y) { 1050 WebGestureEvent event = MakeGestureEvent( 1051 WebInputEvent::GesturePinchBegin, time_ms, x, y); 1052 SendGestureEvent(event); 1053 } 1054 1055 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) { 1056 WebGestureEvent event = MakeGestureEvent( 1057 WebInputEvent::GesturePinchEnd, time_ms, 0, 0); 1058 SendGestureEvent(event); 1059 } 1060 1061 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms, 1062 jfloat anchor_x, jfloat anchor_y, 1063 jfloat delta) { 1064 WebGestureEvent event = MakeGestureEvent( 1065 WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y); 1066 event.data.pinchUpdate.scale = delta; 1067 1068 SendGestureEvent(event); 1069 } 1070 1071 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj, 1072 jfloat x1, jfloat y1, 1073 jfloat x2, jfloat y2) { 1074 SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()), 1075 gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale())); 1076 } 1077 1078 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj, 1079 jfloat x, jfloat y) { 1080 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 1081 if (rwhv) 1082 rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_)); 1083 } 1084 1085 void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) { 1086 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 1087 if (rwhv) 1088 rwhv->DismissTextHandles(); 1089 } 1090 1091 void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env, 1092 jobject obj, 1093 jboolean hidden) { 1094 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 1095 if (rwhv) 1096 rwhv->SetTextHandlesTemporarilyHidden(hidden); 1097 } 1098 1099 void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) { 1100 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 1101 if (rwhv) 1102 rwhv->ResetGestureDetection(); 1103 } 1104 1105 void ContentViewCoreImpl::SetDoubleTapSupportEnabled(JNIEnv* env, 1106 jobject obj, 1107 jboolean enabled) { 1108 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 1109 if (rwhv) 1110 rwhv->SetDoubleTapSupportEnabled(enabled); 1111 } 1112 1113 void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env, 1114 jobject obj, 1115 jboolean enabled) { 1116 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 1117 if (rwhv) 1118 rwhv->SetMultiTouchZoomSupportEnabled(enabled); 1119 } 1120 1121 void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection( 1122 JNIEnv* env, 1123 jobject obj, 1124 jboolean allow) { 1125 java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow); 1126 } 1127 1128 void ContentViewCoreImpl::AddJavascriptInterface( 1129 JNIEnv* env, 1130 jobject /* obj */, 1131 jobject object, 1132 jstring name, 1133 jclass safe_annotation_clazz) { 1134 ScopedJavaLocalRef<jobject> scoped_object(env, object); 1135 ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz); 1136 java_bridge_dispatcher_host_->AddNamedObject( 1137 ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz); 1138 } 1139 1140 void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env, 1141 jobject /* obj */, 1142 jstring name) { 1143 java_bridge_dispatcher_host_->RemoveNamedObject( 1144 ConvertJavaStringToUTF8(env, name)); 1145 } 1146 1147 void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) { 1148 RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid(); 1149 gfx::Size physical_size( 1150 Java_ContentViewCore_getPhysicalBackingWidthPix(env, obj), 1151 Java_ContentViewCore_getPhysicalBackingHeightPix(env, obj)); 1152 root_layer_->SetBounds(physical_size); 1153 1154 if (view) { 1155 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From( 1156 view->GetRenderWidgetHost()); 1157 host->SendScreenRects(); 1158 view->WasResized(); 1159 } 1160 } 1161 1162 long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) { 1163 RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid(); 1164 if (!rwhva) 1165 return 0; 1166 return rwhva->GetNativeImeAdapter(); 1167 } 1168 1169 // TODO(sgurun) add support for posting a frame whose name is known (only 1170 // main frame is supported at this time, see crbug.com/389721) 1171 // TODO(sgurun) add support for passing message ports 1172 void ContentViewCoreImpl::PostMessageToFrame(JNIEnv* env, jobject obj, 1173 jstring frame_name, jstring message, jstring source_origin, 1174 jstring target_origin) { 1175 1176 RenderViewHost* host = web_contents_->GetRenderViewHost(); 1177 if (!host) 1178 return; 1179 ViewMsg_PostMessage_Params params; 1180 params.source_origin = ConvertJavaStringToUTF16(env, source_origin); 1181 params.target_origin = ConvertJavaStringToUTF16(env, target_origin); 1182 params.data = ConvertJavaStringToUTF16(env, message); 1183 params.is_data_raw_string = true; 1184 params.source_routing_id = MSG_ROUTING_NONE; 1185 host->Send(new ViewMsg_PostMessageEvent(host->GetRoutingID(), params)); 1186 } 1187 1188 void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter, 1189 int text_input_type, 1190 int text_input_flags, 1191 const std::string& text, 1192 int selection_start, 1193 int selection_end, 1194 int composition_start, 1195 int composition_end, 1196 bool show_ime_if_needed, 1197 bool is_non_ime_change) { 1198 JNIEnv* env = AttachCurrentThread(); 1199 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1200 if (obj.is_null()) 1201 return; 1202 1203 ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text); 1204 Java_ContentViewCore_updateImeAdapter(env, 1205 obj.obj(), 1206 native_ime_adapter, 1207 text_input_type, 1208 text_input_flags, 1209 jstring_text.obj(), 1210 selection_start, 1211 selection_end, 1212 composition_start, 1213 composition_end, 1214 show_ime_if_needed, 1215 is_non_ime_change); 1216 } 1217 1218 void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj, 1219 bool enabled) { 1220 SetAccessibilityEnabledInternal(enabled); 1221 } 1222 1223 bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const { 1224 JNIEnv* env = AttachCurrentThread(); 1225 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1226 if (obj.is_null()) 1227 return true; 1228 return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env, 1229 obj.obj()); 1230 } 1231 1232 void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) { 1233 accessibility_enabled_ = enabled; 1234 BrowserAccessibilityStateImpl* accessibility_state = 1235 BrowserAccessibilityStateImpl::GetInstance(); 1236 if (enabled) { 1237 // This enables accessibility globally unless it was explicitly disallowed 1238 // by a command-line flag. 1239 accessibility_state->OnScreenReaderDetected(); 1240 // If it was actually enabled globally, enable it for this RenderWidget now. 1241 if (accessibility_state->IsAccessibleBrowser() && web_contents_) 1242 web_contents_->AddAccessibilityMode(AccessibilityModeComplete); 1243 } else { 1244 accessibility_state->ResetAccessibilityMode(); 1245 if (web_contents_) { 1246 web_contents_->SetAccessibilityMode( 1247 accessibility_state->accessibility_mode()); 1248 } 1249 } 1250 } 1251 1252 void ContentViewCoreImpl::SendOrientationChangeEventInternal() { 1253 RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid(); 1254 if (rwhv) 1255 rwhv->UpdateScreenInfo(GetViewAndroid()); 1256 1257 static_cast<WebContentsImpl*>(web_contents())-> 1258 screen_orientation_dispatcher_host()->OnOrientationChange(); 1259 } 1260 1261 void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env, 1262 jobject obj, 1263 jint x, 1264 jint y, 1265 jint width, 1266 jint height) { 1267 gfx::Rect rect( 1268 static_cast<int>(x / dpi_scale()), 1269 static_cast<int>(y / dpi_scale()), 1270 static_cast<int>((width > 0 && width < dpi_scale()) ? 1271 1 : (int)(width / dpi_scale())), 1272 static_cast<int>((height > 0 && height < dpi_scale()) ? 1273 1 : (int)(height / dpi_scale()))); 1274 GetWebContents()->Send(new ViewMsg_ExtractSmartClipData( 1275 GetWebContents()->GetRoutingID(), rect)); 1276 } 1277 1278 jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) { 1279 return GetRenderProcessIdFromRenderViewHost( 1280 web_contents_->GetRenderViewHost()); 1281 } 1282 1283 void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj, 1284 jboolean opaque) { 1285 if (GetRenderWidgetHostViewAndroid()) 1286 GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque); 1287 } 1288 1289 void ContentViewCoreImpl::RequestTextSurroundingSelection( 1290 int max_length, 1291 const base::Callback< 1292 void(const base::string16& content, int start_offset, int end_offset)>& 1293 callback) { 1294 DCHECK(!callback.is_null()); 1295 RenderFrameHost* focused_frame = web_contents_->GetFocusedFrame(); 1296 if (!focused_frame) 1297 return; 1298 if (GetRenderWidgetHostViewAndroid()) { 1299 GetRenderWidgetHostViewAndroid()->SetTextSurroundingSelectionCallback( 1300 callback); 1301 focused_frame->Send(new FrameMsg_TextSurroundingSelectionRequest( 1302 focused_frame->GetRoutingID(), max_length)); 1303 } 1304 } 1305 1306 void ContentViewCoreImpl::OnSmartClipDataExtracted( 1307 const base::string16& text, 1308 const base::string16& html, 1309 const gfx::Rect& clip_rect) { 1310 JNIEnv* env = AttachCurrentThread(); 1311 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 1312 if (obj.is_null()) 1313 return; 1314 ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text); 1315 ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html); 1316 ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect)); 1317 Java_ContentViewCore_onSmartClipDataExtracted( 1318 env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj()); 1319 } 1320 1321 void ContentViewCoreImpl::WebContentsDestroyed() { 1322 WebContentsViewAndroid* wcva = static_cast<WebContentsViewAndroid*>( 1323 static_cast<WebContentsImpl*>(web_contents())->GetView()); 1324 DCHECK(wcva); 1325 wcva->SetContentViewCore(NULL); 1326 } 1327 1328 // This is called for each ContentView. 1329 jlong Init(JNIEnv* env, 1330 jobject obj, 1331 jlong native_web_contents, 1332 jlong view_android, 1333 jlong window_android, 1334 jobject retained_objects_set) { 1335 ContentViewCoreImpl* view = new ContentViewCoreImpl( 1336 env, obj, 1337 reinterpret_cast<WebContents*>(native_web_contents), 1338 reinterpret_cast<ui::ViewAndroid*>(view_android), 1339 reinterpret_cast<ui::WindowAndroid*>(window_android), 1340 retained_objects_set); 1341 return reinterpret_cast<intptr_t>(view); 1342 } 1343 1344 bool RegisterContentViewCore(JNIEnv* env) { 1345 return RegisterNativesImpl(env); 1346 } 1347 1348 } // namespace content 1349