1 // Copyright (c) 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/browser_plugin/browser_plugin_guest.h" 6 7 #include <algorithm> 8 9 #include "base/message_loop/message_loop.h" 10 #include "base/pickle.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "content/browser/browser_plugin/browser_plugin_embedder.h" 13 #include "content/browser/browser_thread_impl.h" 14 #include "content/browser/child_process_security_policy_impl.h" 15 #include "content/browser/frame_host/render_frame_host_impl.h" 16 #include "content/browser/frame_host/render_widget_host_view_guest.h" 17 #include "content/browser/loader/resource_dispatcher_host_impl.h" 18 #include "content/browser/renderer_host/render_view_host_impl.h" 19 #include "content/browser/renderer_host/render_widget_host_impl.h" 20 #include "content/browser/renderer_host/render_widget_host_view_base.h" 21 #include "content/browser/web_contents/web_contents_impl.h" 22 #include "content/browser/web_contents/web_contents_view_guest.h" 23 #include "content/common/browser_plugin/browser_plugin_constants.h" 24 #include "content/common/browser_plugin/browser_plugin_messages.h" 25 #include "content/common/content_constants_internal.h" 26 #include "content/common/drag_messages.h" 27 #include "content/common/frame_messages.h" 28 #include "content/common/host_shared_bitmap_manager.h" 29 #include "content/common/input_messages.h" 30 #include "content/common/view_messages.h" 31 #include "content/public/browser/browser_context.h" 32 #include "content/public/browser/browser_plugin_guest_manager.h" 33 #include "content/public/browser/content_browser_client.h" 34 #include "content/public/browser/render_widget_host_view.h" 35 #include "content/public/browser/user_metrics.h" 36 #include "content/public/browser/web_contents_observer.h" 37 #include "content/public/common/drop_data.h" 38 #include "ui/gfx/geometry/size_conversions.h" 39 40 #if defined(OS_MACOSX) 41 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h" 42 #endif 43 44 namespace content { 45 46 class BrowserPluginGuest::EmbedderWebContentsObserver 47 : public WebContentsObserver { 48 public: 49 explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest) 50 : WebContentsObserver(guest->embedder_web_contents()), 51 browser_plugin_guest_(guest) { 52 } 53 54 virtual ~EmbedderWebContentsObserver() { 55 } 56 57 // WebContentsObserver implementation. 58 virtual void WasShown() OVERRIDE { 59 browser_plugin_guest_->EmbedderVisibilityChanged(true); 60 } 61 62 virtual void WasHidden() OVERRIDE { 63 browser_plugin_guest_->EmbedderVisibilityChanged(false); 64 } 65 66 private: 67 BrowserPluginGuest* browser_plugin_guest_; 68 69 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver); 70 }; 71 72 BrowserPluginGuest::BrowserPluginGuest(bool has_render_view, 73 WebContentsImpl* web_contents, 74 BrowserPluginGuestDelegate* delegate) 75 : WebContentsObserver(web_contents), 76 embedder_web_contents_(NULL), 77 browser_plugin_instance_id_(browser_plugin::kInstanceIDNone), 78 guest_device_scale_factor_(1.0f), 79 focused_(false), 80 mouse_locked_(false), 81 pending_lock_request_(false), 82 guest_visible_(false), 83 embedder_visible_(true), 84 copy_request_id_(0), 85 has_render_view_(has_render_view), 86 is_in_destruction_(false), 87 last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE), 88 last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT), 89 last_can_compose_inline_(true), 90 delegate_(delegate), 91 weak_ptr_factory_(this) { 92 DCHECK(web_contents); 93 DCHECK(delegate); 94 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create")); 95 web_contents->SetBrowserPluginGuest(this); 96 delegate->RegisterDestructionCallback( 97 base::Bind(&BrowserPluginGuest::WillDestroy, AsWeakPtr())); 98 } 99 100 void BrowserPluginGuest::WillDestroy() { 101 is_in_destruction_ = true; 102 embedder_web_contents_ = NULL; 103 } 104 105 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() { 106 return weak_ptr_factory_.GetWeakPtr(); 107 } 108 109 void BrowserPluginGuest::SetFocus(RenderWidgetHost* rwh, bool focused) { 110 focused_ = focused; 111 if (!rwh) 112 return; 113 114 rwh->Send(new InputMsg_SetFocus(rwh->GetRoutingID(), focused)); 115 if (!focused && mouse_locked_) 116 OnUnlockMouse(); 117 118 // Restore the last seen state of text input to the view. 119 RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>( 120 rwh->GetView()); 121 if (rwhv) { 122 rwhv->TextInputTypeChanged(last_text_input_type_, last_input_mode_, 123 last_can_compose_inline_); 124 } 125 } 126 127 bool BrowserPluginGuest::LockMouse(bool allowed) { 128 if (!attached() || (mouse_locked_ == allowed)) 129 return false; 130 131 return embedder_web_contents()->GotResponseToLockMouseRequest(allowed); 132 } 133 134 void BrowserPluginGuest::Destroy() { 135 delegate_->Destroy(); 136 } 137 138 WebContentsImpl* BrowserPluginGuest::CreateNewGuestWindow( 139 const WebContents::CreateParams& params) { 140 WebContentsImpl* new_contents = 141 static_cast<WebContentsImpl*>(delegate_->CreateNewGuestWindow(params)); 142 DCHECK(new_contents); 143 return new_contents; 144 } 145 146 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder( 147 const IPC::Message& message) { 148 RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>( 149 web_contents()->GetRenderWidgetHostView()); 150 if (rwhv && 151 rwhv->OnMessageReceivedFromEmbedder( 152 message, 153 static_cast<RenderViewHostImpl*>( 154 embedder_web_contents()->GetRenderViewHost()))) { 155 return true; 156 } 157 158 bool handled = true; 159 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message) 160 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK, 161 OnCompositorFrameSwappedACK) 162 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck, 163 OnCopyFromCompositingSurfaceAck) 164 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate, 165 OnDragStatusUpdate) 166 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand, 167 OnExecuteEditCommand) 168 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete, 169 OnExtendSelectionAndDelete) 170 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition, 171 OnImeConfirmComposition) 172 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition, 173 OnImeSetComposition) 174 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck) 175 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed) 176 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources, 177 OnReclaimCompositorResources) 178 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest) 179 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent, 180 OnSetEditCommandsForNextKeyEvent) 181 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus) 182 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility) 183 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck) 184 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry) 185 IPC_MESSAGE_UNHANDLED(handled = false) 186 IPC_END_MESSAGE_MAP() 187 return handled; 188 } 189 190 void BrowserPluginGuest::Initialize( 191 int browser_plugin_instance_id, 192 const BrowserPluginHostMsg_Attach_Params& params, 193 WebContentsImpl* embedder_web_contents) { 194 browser_plugin_instance_id_ = browser_plugin_instance_id; 195 focused_ = params.focused; 196 guest_visible_ = params.visible; 197 guest_window_rect_ = gfx::Rect(params.origin, 198 params.resize_guest_params.view_size); 199 200 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to 201 // be attached. 202 embedder_web_contents_ = embedder_web_contents; 203 204 WebContentsViewGuest* new_view = 205 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView()); 206 new_view->OnGuestInitialized(embedder_web_contents->GetView()); 207 208 RendererPreferences* renderer_prefs = 209 GetWebContents()->GetMutableRendererPrefs(); 210 std::string guest_user_agent_override = renderer_prefs->user_agent_override; 211 // Copy renderer preferences (and nothing else) from the embedder's 212 // WebContents to the guest. 213 // 214 // For GTK and Aura this is necessary to get proper renderer configuration 215 // values for caret blinking interval, colors related to selection and 216 // focus. 217 *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs(); 218 renderer_prefs->user_agent_override = guest_user_agent_override; 219 220 // We would like the guest to report changes to frame names so that we can 221 // update the BrowserPlugin's corresponding 'name' attribute. 222 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed. 223 renderer_prefs->report_frame_name_changes = true; 224 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated 225 // navigations still continue to function inside the app. 226 renderer_prefs->browser_handles_all_top_level_requests = false; 227 // Disable "client blocked" error page for browser plugin. 228 renderer_prefs->disable_client_blocked_error_page = true; 229 230 embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this)); 231 232 OnResizeGuest(browser_plugin_instance_id_, params.resize_guest_params); 233 234 // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will 235 // be reset again the next time preferences are updated. 236 WebPreferences prefs = 237 GetWebContents()->GetRenderViewHost()->GetWebkitPreferences(); 238 prefs.navigate_on_drag_drop = false; 239 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs); 240 241 // Enable input method for guest if it's enabled for the embedder. 242 if (static_cast<RenderViewHostImpl*>( 243 embedder_web_contents_->GetRenderViewHost())->input_method_active()) { 244 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( 245 GetWebContents()->GetRenderViewHost()); 246 guest_rvh->SetInputMethodActive(true); 247 } 248 249 // Inform the embedder of the guest's attachment. 250 SendMessageToEmbedder( 251 new BrowserPluginMsg_Attach_ACK(browser_plugin_instance_id_)); 252 } 253 254 BrowserPluginGuest::~BrowserPluginGuest() { 255 } 256 257 // static 258 BrowserPluginGuest* BrowserPluginGuest::Create( 259 WebContentsImpl* web_contents, 260 BrowserPluginGuestDelegate* delegate) { 261 return new BrowserPluginGuest( 262 web_contents->opener() != NULL, web_contents, delegate); 263 } 264 265 // static 266 bool BrowserPluginGuest::IsGuest(WebContentsImpl* web_contents) { 267 return web_contents && web_contents->GetBrowserPluginGuest(); 268 } 269 270 // static 271 bool BrowserPluginGuest::IsGuest(RenderViewHostImpl* render_view_host) { 272 return render_view_host && IsGuest( 273 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost( 274 render_view_host))); 275 } 276 277 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() { 278 if (!attached()) 279 return NULL; 280 return embedder_web_contents_->GetRenderWidgetHostView(); 281 } 282 283 void BrowserPluginGuest::UpdateVisibility() { 284 OnSetVisibility(browser_plugin_instance_id(), visible()); 285 } 286 287 void BrowserPluginGuest::CopyFromCompositingSurface( 288 gfx::Rect src_subrect, 289 gfx::Size dst_size, 290 const base::Callback<void(bool, const SkBitmap&)>& callback) { 291 copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback)); 292 SendMessageToEmbedder( 293 new BrowserPluginMsg_CopyFromCompositingSurface( 294 browser_plugin_instance_id(), 295 copy_request_id_, 296 src_subrect, 297 dst_size)); 298 } 299 300 BrowserPluginGuestManager* 301 BrowserPluginGuest::GetBrowserPluginGuestManager() const { 302 return GetWebContents()->GetBrowserContext()->GetGuestManager(); 303 } 304 305 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) { 306 embedder_visible_ = visible; 307 UpdateVisibility(); 308 } 309 310 void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) { 311 SendMessageToEmbedder( 312 new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), allow)); 313 } 314 315 void BrowserPluginGuest::SwapCompositorFrame( 316 uint32 output_surface_id, 317 int host_process_id, 318 int host_routing_id, 319 scoped_ptr<cc::CompositorFrame> frame) { 320 cc::RenderPass* root_pass = 321 frame->delegated_frame_data->render_pass_list.back(); 322 gfx::Size view_size(gfx::ToFlooredSize(gfx::ScaleSize( 323 root_pass->output_rect.size(), 324 1.0f / frame->metadata.device_scale_factor))); 325 326 if (last_seen_view_size_ != view_size) { 327 delegate_->GuestSizeChanged(last_seen_view_size_, view_size); 328 last_seen_view_size_ = view_size; 329 } 330 331 FrameMsg_CompositorFrameSwapped_Params guest_params; 332 frame->AssignTo(&guest_params.frame); 333 guest_params.output_surface_id = output_surface_id; 334 guest_params.producing_route_id = host_routing_id; 335 guest_params.producing_host_id = host_process_id; 336 337 SendMessageToEmbedder( 338 new BrowserPluginMsg_CompositorFrameSwapped( 339 browser_plugin_instance_id(), guest_params)); 340 } 341 342 void BrowserPluginGuest::SetContentsOpaque(bool opaque) { 343 SendMessageToEmbedder( 344 new BrowserPluginMsg_SetContentsOpaque( 345 browser_plugin_instance_id(), opaque)); 346 } 347 348 WebContentsImpl* BrowserPluginGuest::GetWebContents() const { 349 return static_cast<WebContentsImpl*>(web_contents()); 350 } 351 352 gfx::Point BrowserPluginGuest::GetScreenCoordinates( 353 const gfx::Point& relative_position) const { 354 if (!attached()) 355 return relative_position; 356 357 gfx::Point screen_pos(relative_position); 358 screen_pos += guest_window_rect_.OffsetFromOrigin(); 359 if (embedder_web_contents()->GetBrowserPluginGuest()) { 360 BrowserPluginGuest* embedder_guest = 361 embedder_web_contents()->GetBrowserPluginGuest(); 362 screen_pos += embedder_guest->guest_window_rect_.OffsetFromOrigin(); 363 } 364 return screen_pos; 365 } 366 367 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) { 368 if (!attached()) { 369 // Some pages such as data URLs, javascript URLs, and about:blank 370 // do not load external resources and so they load prior to attachment. 371 // As a result, we must save all these IPCs until attachment and then 372 // forward them so that the embedder gets a chance to see and process 373 // the load events. 374 pending_messages_.push_back(linked_ptr<IPC::Message>(msg)); 375 return; 376 } 377 msg->set_routing_id(embedder_web_contents_->GetRoutingID()); 378 embedder_web_contents_->Send(msg); 379 } 380 381 void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y, 382 int screen_x, int screen_y, blink::WebDragOperation operation) { 383 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y, 384 screen_x, screen_y, operation); 385 } 386 387 void BrowserPluginGuest::EndSystemDrag() { 388 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( 389 GetWebContents()->GetRenderViewHost()); 390 guest_rvh->DragSourceSystemDragEnded(); 391 } 392 393 void BrowserPluginGuest::SendQueuedMessages() { 394 if (!attached()) 395 return; 396 397 while (!pending_messages_.empty()) { 398 linked_ptr<IPC::Message> message_ptr = pending_messages_.front(); 399 pending_messages_.pop_front(); 400 SendMessageToEmbedder(message_ptr.release()); 401 } 402 } 403 404 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame( 405 RenderFrameHost* render_frame_host, 406 const GURL& url, 407 ui::PageTransition transition_type) { 408 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate")); 409 } 410 411 void BrowserPluginGuest::RenderViewReady() { 412 RenderViewHost* rvh = GetWebContents()->GetRenderViewHost(); 413 // TODO(fsamuel): Investigate whether it's possible to update state earlier 414 // here (see http://crbug.com/158151). 415 Send(new InputMsg_SetFocus(routing_id(), focused_)); 416 UpdateVisibility(); 417 418 RenderWidgetHostImpl::From(rvh)->set_hung_renderer_delay_ms( 419 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)); 420 } 421 422 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) { 423 SendMessageToEmbedder( 424 new BrowserPluginMsg_GuestGone(browser_plugin_instance_id())); 425 switch (status) { 426 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: 427 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed")); 428 break; 429 case base::TERMINATION_STATUS_PROCESS_CRASHED: 430 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed")); 431 break; 432 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: 433 RecordAction( 434 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath")); 435 break; 436 default: 437 break; 438 } 439 } 440 441 // static 442 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest( 443 const IPC::Message& message) { 444 switch (message.type()) { 445 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID: 446 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID: 447 case BrowserPluginHostMsg_DragStatusUpdate::ID: 448 case BrowserPluginHostMsg_ExecuteEditCommand::ID: 449 case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID: 450 case BrowserPluginHostMsg_HandleInputEvent::ID: 451 case BrowserPluginHostMsg_ImeConfirmComposition::ID: 452 case BrowserPluginHostMsg_ImeSetComposition::ID: 453 case BrowserPluginHostMsg_LockMouse_ACK::ID: 454 case BrowserPluginHostMsg_PluginDestroyed::ID: 455 case BrowserPluginHostMsg_ReclaimCompositorResources::ID: 456 case BrowserPluginHostMsg_ResizeGuest::ID: 457 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID: 458 case BrowserPluginHostMsg_SetFocus::ID: 459 case BrowserPluginHostMsg_SetVisibility::ID: 460 case BrowserPluginHostMsg_UnlockMouse_ACK::ID: 461 case BrowserPluginHostMsg_UpdateGeometry::ID: 462 return true; 463 default: 464 return false; 465 } 466 } 467 468 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) { 469 bool handled = true; 470 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message) 471 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition, 472 OnImeCancelComposition) 473 #if defined(OS_MACOSX) || defined(USE_AURA) 474 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged, 475 OnImeCompositionRangeChanged) 476 #endif 477 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, 478 OnHasTouchEventHandlers) 479 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse) 480 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget) 481 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus) 482 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged, 483 OnTextInputTypeChanged) 484 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse) 485 IPC_MESSAGE_UNHANDLED(handled = false) 486 IPC_END_MESSAGE_MAP() 487 return handled; 488 } 489 490 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message, 491 RenderFrameHost* render_frame_host) { 492 // This will eventually be the home for more IPC handlers that depend on 493 // RenderFrameHost. Until more are moved here, though, the IPC_* macros won't 494 // compile if there are no handlers for a platform. So we have both #if guards 495 // around the whole thing (unfortunate but temporary), and #if guards where 496 // they belong, only around the one IPC handler. TODO(avi): Move more of the 497 // frame-based handlers to this function and remove the outer #if layer. 498 #if defined(OS_MACOSX) 499 bool handled = true; 500 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserPluginGuest, message, 501 render_frame_host) 502 #if defined(OS_MACOSX) 503 // MacOS X creates and populates platform-specific select drop-down menus 504 // whereas other platforms merely create a popup window that the guest 505 // renderer process paints inside. 506 IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup) 507 #endif 508 IPC_MESSAGE_UNHANDLED(handled = false) 509 IPC_END_MESSAGE_MAP() 510 return handled; 511 #else 512 return false; 513 #endif 514 } 515 516 void BrowserPluginGuest::Attach( 517 int browser_plugin_instance_id, 518 WebContentsImpl* embedder_web_contents, 519 const BrowserPluginHostMsg_Attach_Params& params) { 520 if (attached()) 521 return; 522 523 delegate_->WillAttach(embedder_web_contents, browser_plugin_instance_id); 524 525 // If a RenderView has already been created for this new window, then we need 526 // to initialize the browser-side state now so that the RenderFrameHostManager 527 // does not create a new RenderView on navigation. 528 if (has_render_view_) { 529 static_cast<RenderViewHostImpl*>( 530 GetWebContents()->GetRenderViewHost())->Init(); 531 WebContentsViewGuest* new_view = 532 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView()); 533 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost()); 534 } 535 536 Initialize(browser_plugin_instance_id, params, embedder_web_contents); 537 538 SendQueuedMessages(); 539 540 // Create a swapped out RenderView for the guest in the embedder render 541 // process, so that the embedder can access the guest's window object. 542 int guest_routing_id = 543 GetWebContents()->CreateSwappedOutRenderView( 544 embedder_web_contents_->GetSiteInstance()); 545 546 delegate_->DidAttach(guest_routing_id); 547 548 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached")); 549 } 550 551 void BrowserPluginGuest::OnCompositorFrameSwappedACK( 552 int browser_plugin_instance_id, 553 const FrameHostMsg_CompositorFrameSwappedACK_Params& params) { 554 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id, 555 params.output_surface_id, 556 params.producing_host_id, 557 params.ack); 558 } 559 560 void BrowserPluginGuest::OnDragStatusUpdate(int browser_plugin_instance_id, 561 blink::WebDragStatus drag_status, 562 const DropData& drop_data, 563 blink::WebDragOperationsMask mask, 564 const gfx::Point& location) { 565 RenderViewHost* host = GetWebContents()->GetRenderViewHost(); 566 switch (drag_status) { 567 case blink::WebDragStatusEnter: 568 embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest( 569 this); 570 host->DragTargetDragEnter(drop_data, location, location, mask, 0); 571 break; 572 case blink::WebDragStatusOver: 573 host->DragTargetDragOver(location, location, mask, 0); 574 break; 575 case blink::WebDragStatusLeave: 576 embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this); 577 host->DragTargetDragLeave(); 578 break; 579 case blink::WebDragStatusDrop: 580 host->DragTargetDrop(location, location, 0); 581 EndSystemDrag(); 582 break; 583 case blink::WebDragStatusUnknown: 584 NOTREACHED(); 585 } 586 } 587 588 void BrowserPluginGuest::OnExecuteEditCommand(int browser_plugin_instance_id, 589 const std::string& name) { 590 Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string())); 591 } 592 593 void BrowserPluginGuest::OnImeSetComposition( 594 int browser_plugin_instance_id, 595 const std::string& text, 596 const std::vector<blink::WebCompositionUnderline>& underlines, 597 int selection_start, 598 int selection_end) { 599 Send(new InputMsg_ImeSetComposition(routing_id(), 600 base::UTF8ToUTF16(text), underlines, 601 selection_start, selection_end)); 602 } 603 604 void BrowserPluginGuest::OnImeConfirmComposition( 605 int browser_plugin_instance_id, 606 const std::string& text, 607 bool keep_selection) { 608 Send(new InputMsg_ImeConfirmComposition(routing_id(), 609 base::UTF8ToUTF16(text), 610 gfx::Range::InvalidRange(), 611 keep_selection)); 612 } 613 614 void BrowserPluginGuest::OnExtendSelectionAndDelete( 615 int browser_plugin_instance_id, 616 int before, 617 int after) { 618 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>( 619 web_contents()->GetFocusedFrame()); 620 if (rfh) 621 rfh->ExtendSelectionAndDelete(before, after); 622 } 623 624 void BrowserPluginGuest::OnReclaimCompositorResources( 625 int browser_plugin_instance_id, 626 const FrameHostMsg_ReclaimCompositorResources_Params& params) { 627 RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id, 628 params.output_surface_id, 629 params.renderer_host_id, 630 params.ack); 631 } 632 633 void BrowserPluginGuest::OnLockMouse(bool user_gesture, 634 bool last_unlocked_by_target, 635 bool privileged) { 636 if (pending_lock_request_) { 637 // Immediately reject the lock because only one pointerLock may be active 638 // at a time. 639 Send(new ViewMsg_LockMouse_ACK(routing_id(), false)); 640 return; 641 } 642 643 pending_lock_request_ = true; 644 645 delegate_->RequestPointerLockPermission( 646 user_gesture, 647 last_unlocked_by_target, 648 base::Bind(&BrowserPluginGuest::PointerLockPermissionResponse, 649 weak_ptr_factory_.GetWeakPtr())); 650 } 651 652 void BrowserPluginGuest::OnLockMouseAck(int browser_plugin_instance_id, 653 bool succeeded) { 654 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded)); 655 pending_lock_request_ = false; 656 if (succeeded) 657 mouse_locked_ = true; 658 } 659 660 void BrowserPluginGuest::OnPluginDestroyed(int browser_plugin_instance_id) { 661 Destroy(); 662 } 663 664 void BrowserPluginGuest::OnResizeGuest( 665 int browser_plugin_instance_id, 666 const BrowserPluginHostMsg_ResizeGuest_Params& params) { 667 // If we are setting the size for the first time before navigating then 668 // BrowserPluginGuest does not yet have a RenderViewHost. 669 if (guest_device_scale_factor_ != params.scale_factor && 670 GetWebContents()->GetRenderViewHost()) { 671 RenderWidgetHostImpl* render_widget_host = 672 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost()); 673 guest_device_scale_factor_ = params.scale_factor; 674 render_widget_host->NotifyScreenInfoChanged(); 675 } 676 677 if (last_seen_browser_plugin_size_ != params.view_size) { 678 delegate_->ElementSizeChanged(last_seen_browser_plugin_size_, 679 params.view_size); 680 last_seen_browser_plugin_size_ = params.view_size; 681 } 682 683 // Just resize the WebContents and repaint if needed. 684 if (!params.view_size.IsEmpty()) 685 GetWebContents()->GetView()->SizeContents(params.view_size); 686 if (params.repaint) 687 Send(new ViewMsg_Repaint(routing_id(), params.view_size)); 688 } 689 690 void BrowserPluginGuest::OnSetFocus(int browser_plugin_instance_id, 691 bool focused) { 692 RenderWidgetHostView* rwhv = web_contents()->GetRenderWidgetHostView(); 693 RenderWidgetHost* rwh = rwhv ? rwhv->GetRenderWidgetHost() : NULL; 694 SetFocus(rwh, focused); 695 } 696 697 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent( 698 int browser_plugin_instance_id, 699 const std::vector<EditCommand>& edit_commands) { 700 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(), 701 edit_commands)); 702 } 703 704 void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id, 705 bool visible) { 706 guest_visible_ = visible; 707 if (embedder_visible_ && guest_visible_) 708 GetWebContents()->WasShown(); 709 else 710 GetWebContents()->WasHidden(); 711 } 712 713 void BrowserPluginGuest::OnUnlockMouse() { 714 SendMessageToEmbedder( 715 new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), false)); 716 } 717 718 void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id) { 719 // mouse_locked_ could be false here if the lock attempt was cancelled due 720 // to window focus, or for various other reasons before the guest was informed 721 // of the lock's success. 722 if (mouse_locked_) 723 Send(new ViewMsg_MouseLockLost(routing_id())); 724 mouse_locked_ = false; 725 } 726 727 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck( 728 int browser_plugin_instance_id, 729 int request_id, 730 const SkBitmap& bitmap) { 731 CHECK(copy_request_callbacks_.count(request_id)); 732 if (!copy_request_callbacks_.count(request_id)) 733 return; 734 const CopyRequestCallback& callback = copy_request_callbacks_[request_id]; 735 callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap); 736 copy_request_callbacks_.erase(request_id); 737 } 738 739 void BrowserPluginGuest::OnUpdateGeometry(int browser_plugin_instance_id, 740 const gfx::Rect& view_rect) { 741 // The plugin has moved within the embedder without resizing or the 742 // embedder/container's view rect changing. 743 guest_window_rect_ = view_rect; 744 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( 745 GetWebContents()->GetRenderViewHost()); 746 if (rvh) 747 rvh->SendScreenRects(); 748 } 749 750 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) { 751 SendMessageToEmbedder( 752 new BrowserPluginMsg_ShouldAcceptTouchEvents( 753 browser_plugin_instance_id(), accept)); 754 } 755 756 #if defined(OS_MACOSX) 757 void BrowserPluginGuest::OnShowPopup( 758 RenderFrameHost* render_frame_host, 759 const FrameHostMsg_ShowPopup_Params& params) { 760 gfx::Rect translated_bounds(params.bounds); 761 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin()); 762 BrowserPluginPopupMenuHelper popup_menu_helper( 763 embedder_web_contents_->GetRenderViewHost(), render_frame_host); 764 popup_menu_helper.ShowPopupMenu(translated_bounds, 765 params.item_height, 766 params.item_font_size, 767 params.selected_item, 768 params.popup_items, 769 params.right_aligned, 770 params.allow_multiple_selection); 771 } 772 #endif 773 774 void BrowserPluginGuest::OnShowWidget(int route_id, 775 const gfx::Rect& initial_pos) { 776 GetWebContents()->ShowCreatedWidget(route_id, initial_pos); 777 } 778 779 void BrowserPluginGuest::OnTakeFocus(bool reverse) { 780 SendMessageToEmbedder( 781 new BrowserPluginMsg_AdvanceFocus(browser_plugin_instance_id(), reverse)); 782 } 783 784 void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type, 785 ui::TextInputMode input_mode, 786 bool can_compose_inline) { 787 // Save the state of text input so we can restore it on focus. 788 last_text_input_type_ = type; 789 last_input_mode_ = input_mode; 790 last_can_compose_inline_ = can_compose_inline; 791 792 static_cast<RenderWidgetHostViewBase*>( 793 web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged( 794 type, input_mode, can_compose_inline); 795 } 796 797 void BrowserPluginGuest::OnImeCancelComposition() { 798 static_cast<RenderWidgetHostViewBase*>( 799 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition(); 800 } 801 802 #if defined(OS_MACOSX) || defined(USE_AURA) 803 void BrowserPluginGuest::OnImeCompositionRangeChanged( 804 const gfx::Range& range, 805 const std::vector<gfx::Rect>& character_bounds) { 806 static_cast<RenderWidgetHostViewBase*>( 807 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged( 808 range, character_bounds); 809 } 810 #endif 811 812 } // namespace content 813