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/strings/string_util.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "content/browser/browser_plugin/browser_plugin_embedder.h" 13 #include "content/browser/browser_plugin/browser_plugin_guest_manager.h" 14 #include "content/browser/browser_plugin/browser_plugin_host_factory.h" 15 #include "content/browser/browser_thread_impl.h" 16 #include "content/browser/child_process_security_policy_impl.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/web_contents/web_contents_impl.h" 21 #include "content/browser/web_contents/web_contents_view_guest.h" 22 #include "content/common/browser_plugin/browser_plugin_constants.h" 23 #include "content/common/browser_plugin/browser_plugin_messages.h" 24 #include "content/common/content_constants_internal.h" 25 #include "content/common/drag_messages.h" 26 #include "content/common/gpu/gpu_messages.h" 27 #include "content/common/input_messages.h" 28 #include "content/common/view_messages.h" 29 #include "content/port/browser/render_view_host_delegate_view.h" 30 #include "content/port/browser/render_widget_host_view_port.h" 31 #include "content/public/browser/browser_context.h" 32 #include "content/public/browser/content_browser_client.h" 33 #include "content/public/browser/geolocation_permission_context.h" 34 #include "content/public/browser/navigation_controller.h" 35 #include "content/public/browser/render_process_host.h" 36 #include "content/public/browser/render_widget_host_view.h" 37 #include "content/public/browser/resource_request_details.h" 38 #include "content/public/browser/user_metrics.h" 39 #include "content/public/browser/web_contents_observer.h" 40 #include "content/public/browser/web_contents_view.h" 41 #include "content/public/common/drop_data.h" 42 #include "content/public/common/media_stream_request.h" 43 #include "content/public/common/result_codes.h" 44 #include "content/public/common/url_constants.h" 45 #include "content/public/common/url_utils.h" 46 #include "net/url_request/url_request.h" 47 #include "third_party/WebKit/public/platform/WebCursorInfo.h" 48 #include "ui/events/keycodes/keyboard_codes.h" 49 #include "ui/surface/transport_dib.h" 50 #include "webkit/common/resource_type.h" 51 52 #if defined(OS_MACOSX) 53 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h" 54 #endif 55 56 namespace content { 57 58 // static 59 BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL; 60 61 // Parent class for the various types of permission requests, each of which 62 // should be able to handle the response to their permission request. 63 class BrowserPluginGuest::PermissionRequest : 64 public base::RefCounted<BrowserPluginGuest::PermissionRequest> { 65 public: 66 virtual void Respond(bool should_allow, const std::string& user_input) = 0; 67 virtual bool AllowedByDefault() const { 68 return false; 69 } 70 protected: 71 PermissionRequest() { 72 RecordAction(UserMetricsAction("BrowserPlugin.Guest.PermissionRequest")); 73 } 74 virtual ~PermissionRequest() {} 75 // Friend RefCounted so that the dtor can be non-public. 76 friend class base::RefCounted<BrowserPluginGuest::PermissionRequest>; 77 }; 78 79 class BrowserPluginGuest::DownloadRequest : public PermissionRequest { 80 public: 81 explicit DownloadRequest(base::Callback<void(bool)> callback) 82 : callback_(callback) { 83 RecordAction( 84 UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Download")); 85 } 86 virtual void Respond(bool should_allow, 87 const std::string& user_input) OVERRIDE { 88 callback_.Run(should_allow); 89 } 90 91 private: 92 virtual ~DownloadRequest() {} 93 base::Callback<void(bool)> callback_; 94 }; 95 96 class BrowserPluginGuest::GeolocationRequest : public PermissionRequest { 97 public: 98 GeolocationRequest(GeolocationCallback callback, 99 int bridge_id, 100 base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory) 101 : callback_(callback), 102 bridge_id_(bridge_id), 103 weak_ptr_factory_(weak_ptr_factory) { 104 RecordAction( 105 UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Geolocation")); 106 } 107 108 virtual void Respond(bool should_allow, 109 const std::string& user_input) OVERRIDE { 110 base::WeakPtr<BrowserPluginGuest> guest(weak_ptr_factory_->GetWeakPtr()); 111 112 WebContents* web_contents = guest->embedder_web_contents(); 113 if (should_allow && web_contents) { 114 // If renderer side embedder decides to allow gelocation, we need to check 115 // if the app/embedder itself has geolocation access. 116 BrowserContext* browser_context = web_contents->GetBrowserContext(); 117 if (browser_context) { 118 GeolocationPermissionContext* geolocation_context = 119 browser_context->GetGeolocationPermissionContext(); 120 if (geolocation_context) { 121 base::Callback<void(bool)> geolocation_callback = base::Bind( 122 &BrowserPluginGuest::SetGeolocationPermission, 123 guest, 124 callback_, 125 bridge_id_); 126 geolocation_context->RequestGeolocationPermission( 127 web_contents->GetRenderProcessHost()->GetID(), 128 web_contents->GetRoutingID(), 129 // The geolocation permission request here is not initiated 130 // through WebGeolocationPermissionRequest. We are only interested 131 // in the fact whether the embedder/app has geolocation 132 // permission. Therefore we use an invalid |bridge_id|. 133 -1 /* bridge_id */, 134 web_contents->GetLastCommittedURL(), 135 geolocation_callback); 136 return; 137 } 138 } 139 } 140 guest->SetGeolocationPermission(callback_, bridge_id_, false); 141 } 142 143 private: 144 virtual ~GeolocationRequest() {} 145 base::Callback<void(bool)> callback_; 146 int bridge_id_; 147 base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory_; 148 }; 149 150 class BrowserPluginGuest::MediaRequest : public PermissionRequest { 151 public: 152 MediaRequest(const MediaStreamRequest& request, 153 const MediaResponseCallback& callback, 154 BrowserPluginGuest* guest) 155 : request_(request), 156 callback_(callback), 157 guest_(guest) { 158 RecordAction( 159 UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Media")); 160 } 161 162 virtual void Respond(bool should_allow, 163 const std::string& user_input) OVERRIDE { 164 WebContentsImpl* web_contents = guest_->embedder_web_contents(); 165 if (should_allow && web_contents) { 166 // Re-route the request to the embedder's WebContents; the guest gets the 167 // permission this way. 168 web_contents->RequestMediaAccessPermission(request_, callback_); 169 } else { 170 // Deny the request. 171 callback_.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>()); 172 } 173 } 174 175 private: 176 virtual ~MediaRequest() {} 177 MediaStreamRequest request_; 178 MediaResponseCallback callback_; 179 BrowserPluginGuest* guest_; 180 }; 181 182 class BrowserPluginGuest::NewWindowRequest : public PermissionRequest { 183 public: 184 NewWindowRequest(int instance_id, BrowserPluginGuest* guest) 185 : instance_id_(instance_id), 186 guest_(guest) { 187 RecordAction( 188 UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.NewWindow")); 189 } 190 191 virtual void Respond(bool should_allow, 192 const std::string& user_input) OVERRIDE { 193 int embedder_render_process_id = 194 guest_->embedder_web_contents()->GetRenderProcessHost()->GetID(); 195 BrowserPluginGuest* guest = 196 guest_->GetWebContents()->GetBrowserPluginGuestManager()-> 197 GetGuestByInstanceID(instance_id_, embedder_render_process_id); 198 if (!guest) { 199 VLOG(0) << "Guest not found. Instance ID: " << instance_id_; 200 return; 201 } 202 203 // If we do not destroy the guest then we allow the new window. 204 if (!should_allow) 205 guest->Destroy(); 206 } 207 208 private: 209 virtual ~NewWindowRequest() {} 210 int instance_id_; 211 BrowserPluginGuest* guest_; 212 }; 213 214 class BrowserPluginGuest::JavaScriptDialogRequest : public PermissionRequest { 215 public: 216 JavaScriptDialogRequest(const DialogClosedCallback& callback) 217 : callback_(callback) { 218 RecordAction( 219 UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.JSDialog")); 220 } 221 222 virtual void Respond(bool should_allow, 223 const std::string& user_input) OVERRIDE { 224 callback_.Run(should_allow, UTF8ToUTF16(user_input)); 225 } 226 227 private: 228 virtual ~JavaScriptDialogRequest() {} 229 DialogClosedCallback callback_; 230 }; 231 232 class BrowserPluginGuest::PointerLockRequest : public PermissionRequest { 233 public: 234 PointerLockRequest(BrowserPluginGuest* guest) 235 : guest_(guest) { 236 RecordAction( 237 UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.PointerLock")); 238 } 239 240 virtual void Respond(bool should_allow, 241 const std::string& user_input) OVERRIDE { 242 guest_->SendMessageToEmbedder( 243 new BrowserPluginMsg_SetMouseLock(guest_->instance_id(), should_allow)); 244 } 245 246 private: 247 virtual ~PointerLockRequest() {} 248 BrowserPluginGuest* guest_; 249 }; 250 251 namespace { 252 std::string WindowOpenDispositionToString( 253 WindowOpenDisposition window_open_disposition) { 254 switch (window_open_disposition) { 255 case IGNORE_ACTION: 256 return "ignore"; 257 case SAVE_TO_DISK: 258 return "save_to_disk"; 259 case CURRENT_TAB: 260 return "current_tab"; 261 case NEW_BACKGROUND_TAB: 262 return "new_background_tab"; 263 case NEW_FOREGROUND_TAB: 264 return "new_foreground_tab"; 265 case NEW_WINDOW: 266 return "new_window"; 267 case NEW_POPUP: 268 return "new_popup"; 269 default: 270 NOTREACHED() << "Unknown Window Open Disposition"; 271 return "ignore"; 272 } 273 } 274 275 std::string JavaScriptMessageTypeToString(JavaScriptMessageType message_type) { 276 switch (message_type) { 277 case JAVASCRIPT_MESSAGE_TYPE_ALERT: 278 return "alert"; 279 case JAVASCRIPT_MESSAGE_TYPE_CONFIRM: 280 return "confirm"; 281 case JAVASCRIPT_MESSAGE_TYPE_PROMPT: 282 return "prompt"; 283 default: 284 NOTREACHED() << "Unknown JavaScript Message Type."; 285 return "unknown"; 286 } 287 } 288 289 // Called on IO thread. 290 static std::string RetrieveDownloadURLFromRequestId( 291 RenderViewHost* render_view_host, 292 int url_request_id) { 293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 294 295 int render_process_id = render_view_host->GetProcess()->GetID(); 296 GlobalRequestID global_id(render_process_id, url_request_id); 297 net::URLRequest* url_request = 298 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id); 299 if (url_request) 300 return url_request->url().possibly_invalid_spec(); 301 return ""; 302 } 303 304 } // namespace 305 306 class BrowserPluginGuest::EmbedderWebContentsObserver 307 : public WebContentsObserver { 308 public: 309 explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest) 310 : WebContentsObserver(guest->embedder_web_contents()), 311 browser_plugin_guest_(guest) { 312 } 313 314 virtual ~EmbedderWebContentsObserver() { 315 } 316 317 // WebContentsObserver: 318 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE { 319 browser_plugin_guest_->EmbedderDestroyed(); 320 } 321 322 virtual void WasShown() OVERRIDE { 323 browser_plugin_guest_->EmbedderVisibilityChanged(true); 324 } 325 326 virtual void WasHidden() OVERRIDE { 327 browser_plugin_guest_->EmbedderVisibilityChanged(false); 328 } 329 330 private: 331 BrowserPluginGuest* browser_plugin_guest_; 332 333 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver); 334 }; 335 336 BrowserPluginGuest::BrowserPluginGuest( 337 int instance_id, 338 bool has_render_view, 339 WebContentsImpl* web_contents, 340 BrowserPluginGuest* opener) 341 : WebContentsObserver(web_contents), 342 weak_ptr_factory_(this), 343 embedder_web_contents_(NULL), 344 instance_id_(instance_id), 345 damage_buffer_sequence_id_(0), 346 damage_buffer_size_(0), 347 damage_buffer_scale_factor_(1.0f), 348 guest_device_scale_factor_(1.0f), 349 guest_hang_timeout_( 350 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)), 351 focused_(false), 352 mouse_locked_(false), 353 pending_lock_request_(false), 354 embedder_visible_(true), 355 copy_request_id_(0), 356 next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID), 357 has_render_view_(has_render_view), 358 last_seen_auto_size_enabled_(false), 359 is_in_destruction_(false) { 360 DCHECK(web_contents); 361 web_contents->SetDelegate(this); 362 if (opener) 363 opener_ = opener->AsWeakPtr(); 364 GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_, 365 GetWebContents()); 366 } 367 368 bool BrowserPluginGuest::AddMessageToConsole(WebContents* source, 369 int32 level, 370 const base::string16& message, 371 int32 line_no, 372 const base::string16& source_id) { 373 if (!delegate_) 374 return false; 375 376 delegate_->AddMessageToConsole(level, message, line_no, source_id); 377 return true; 378 } 379 380 void BrowserPluginGuest::DestroyUnattachedWindows() { 381 // Destroy() reaches in and removes the BrowserPluginGuest from its opener's 382 // pending_new_windows_ set. To avoid mutating the set while iterating, we 383 // create a copy of the pending new windows set and iterate over the copy. 384 PendingWindowMap pending_new_windows(pending_new_windows_); 385 // Clean up unattached new windows opened by this guest. 386 for (PendingWindowMap::const_iterator it = pending_new_windows.begin(); 387 it != pending_new_windows.end(); ++it) { 388 it->first->Destroy(); 389 } 390 // All pending windows should be removed from the set after Destroy() is 391 // called on all of them. 392 DCHECK(pending_new_windows_.empty()); 393 } 394 395 void BrowserPluginGuest::LoadURLWithParams(const GURL& url, 396 const Referrer& referrer, 397 PageTransition transition_type, 398 WebContents* web_contents) { 399 NavigationController::LoadURLParams load_url_params(url); 400 load_url_params.referrer = referrer; 401 load_url_params.transition_type = transition_type; 402 load_url_params.extra_headers = std::string(); 403 if (delegate_ && delegate_->IsOverridingUserAgent()) { 404 load_url_params.override_user_agent = 405 NavigationController::UA_OVERRIDE_TRUE; 406 } 407 web_contents->GetController().LoadURLWithParams(load_url_params); 408 } 409 410 void BrowserPluginGuest::RespondToPermissionRequest( 411 int request_id, 412 bool should_allow, 413 const std::string& user_input) { 414 RequestMap::iterator request_itr = permission_request_map_.find(request_id); 415 if (request_itr == permission_request_map_.end()) { 416 VLOG(0) << "Not a valid request ID."; 417 return; 418 } 419 request_itr->second->Respond(should_allow, user_input); 420 permission_request_map_.erase(request_itr); 421 } 422 423 int BrowserPluginGuest::RequestPermission( 424 BrowserPluginPermissionType permission_type, 425 scoped_refptr<BrowserPluginGuest::PermissionRequest> request, 426 const base::DictionaryValue& request_info) { 427 if (!delegate_) { 428 request->Respond(false, ""); 429 return browser_plugin::kInvalidPermissionRequestID; 430 } 431 432 int request_id = ++next_permission_request_id_; 433 permission_request_map_[request_id] = request; 434 435 BrowserPluginGuestDelegate::PermissionResponseCallback callback = 436 base::Bind(&BrowserPluginGuest::RespondToPermissionRequest, 437 AsWeakPtr(), 438 request_id); 439 // If BrowserPluginGuestDelegate hasn't handled the permission then we simply 440 // perform the default action (which is one of allow or reject) immediately. 441 if (!delegate_->RequestPermission( 442 permission_type, request_info, callback, request->AllowedByDefault())) { 443 callback.Run(request->AllowedByDefault(), ""); 444 return browser_plugin::kInvalidPermissionRequestID; 445 } 446 447 return request_id; 448 } 449 450 BrowserPluginGuest* BrowserPluginGuest::CreateNewGuestWindow( 451 const OpenURLParams& params) { 452 BrowserPluginGuestManager* guest_manager = 453 GetWebContents()->GetBrowserPluginGuestManager(); 454 455 // Allocate a new instance ID for the new guest. 456 int instance_id = guest_manager->get_next_instance_id(); 457 458 // Set the attach params to use the same partition as the opener. 459 // We pull the partition information from the site's URL, which is of the form 460 // guest://site/{persist}?{partition_name}. 461 const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL(); 462 BrowserPluginHostMsg_Attach_Params attach_params; 463 attach_params.storage_partition_id = site_url.query(); 464 attach_params.persist_storage = 465 site_url.path().find("persist") != std::string::npos; 466 467 // The new guest gets a copy of this guest's extra params so that the content 468 // embedder exposes the same API for this guest as its opener. 469 scoped_ptr<base::DictionaryValue> extra_params( 470 extra_attach_params_->DeepCopy()); 471 BrowserPluginGuest* new_guest = 472 GetWebContents()->GetBrowserPluginGuestManager()->CreateGuest( 473 GetWebContents()->GetSiteInstance(), instance_id, 474 attach_params, extra_params.Pass()); 475 new_guest->opener_ = AsWeakPtr(); 476 477 // Take ownership of |new_guest|. 478 pending_new_windows_.insert( 479 std::make_pair(new_guest, NewWindowInfo(params.url, std::string()))); 480 481 // Request permission to show the new window. 482 RequestNewWindowPermission(params.disposition, gfx::Rect(), 483 params.user_gesture, new_guest->GetWebContents()); 484 485 return new_guest; 486 } 487 488 void BrowserPluginGuest::EmbedderDestroyed() { 489 embedder_web_contents_ = NULL; 490 if (delegate_) 491 delegate_->EmbedderDestroyed(); 492 Destroy(); 493 } 494 495 void BrowserPluginGuest::Destroy() { 496 is_in_destruction_ = true; 497 if (!attached() && opener()) 498 opener()->pending_new_windows_.erase(this); 499 DestroyUnattachedWindows(); 500 GetWebContents()->GetBrowserPluginGuestManager()->RemoveGuest(instance_id_); 501 delete GetWebContents(); 502 } 503 504 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder( 505 const IPC::Message& message) { 506 bool handled = true; 507 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message) 508 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK, 509 OnSwapBuffersACK) 510 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameACK, 511 OnCompositorFrameACK) 512 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck, 513 OnCopyFromCompositingSurfaceAck) 514 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate, 515 OnDragStatusUpdate) 516 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand, 517 OnExecuteEditCommand) 518 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete, 519 OnExtendSelectionAndDelete) 520 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent, 521 OnHandleInputEvent) 522 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition, 523 OnImeConfirmComposition) 524 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition, 525 OnImeSetComposition) 526 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck) 527 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest, OnNavigateGuest) 528 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed) 529 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources, 530 OnReclaimCompositorResources) 531 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest) 532 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetSize) 533 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent, 534 OnSetEditCommandsForNextKeyEvent) 535 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus) 536 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetName, OnSetName) 537 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque, 538 OnSetContentsOpaque) 539 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility) 540 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck) 541 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry) 542 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateRect_ACK, OnUpdateRectACK) 543 IPC_MESSAGE_UNHANDLED(handled = false) 544 IPC_END_MESSAGE_MAP() 545 return handled; 546 } 547 548 void BrowserPluginGuest::Initialize( 549 const BrowserPluginHostMsg_Attach_Params& params, 550 WebContentsImpl* embedder_web_contents) { 551 focused_ = params.focused; 552 guest_visible_ = params.visible; 553 guest_opaque_ = params.opaque; 554 guest_window_rect_ = params.resize_guest_params.view_rect; 555 556 if (!params.name.empty()) 557 name_ = params.name; 558 auto_size_enabled_ = params.auto_size_params.enable; 559 max_auto_size_ = params.auto_size_params.max_size; 560 min_auto_size_ = params.auto_size_params.min_size; 561 562 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to 563 // be attached. 564 embedder_web_contents_ = embedder_web_contents; 565 566 WebContentsViewGuest* new_view = 567 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView()); 568 new_view->OnGuestInitialized(embedder_web_contents->GetView()); 569 570 RendererPreferences* renderer_prefs = 571 GetWebContents()->GetMutableRendererPrefs(); 572 std::string guest_user_agent_override = renderer_prefs->user_agent_override; 573 // Copy renderer preferences (and nothing else) from the embedder's 574 // WebContents to the guest. 575 // 576 // For GTK and Aura this is necessary to get proper renderer configuration 577 // values for caret blinking interval, colors related to selection and 578 // focus. 579 *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs(); 580 renderer_prefs->user_agent_override = guest_user_agent_override; 581 582 // We would like the guest to report changes to frame names so that we can 583 // update the BrowserPlugin's corresponding 'name' attribute. 584 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed. 585 renderer_prefs->report_frame_name_changes = true; 586 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated 587 // navigations still continue to function inside the app. 588 renderer_prefs->browser_handles_all_top_level_requests = false; 589 // Disable "client blocked" error page for browser plugin. 590 renderer_prefs->disable_client_blocked_error_page = true; 591 592 embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this)); 593 594 OnSetSize(instance_id_, params.auto_size_params, params.resize_guest_params); 595 596 // Create a swapped out RenderView for the guest in the embedder render 597 // process, so that the embedder can access the guest's window object. 598 int guest_routing_id = 599 GetWebContents()->CreateSwappedOutRenderView( 600 embedder_web_contents_->GetSiteInstance()); 601 SendMessageToEmbedder( 602 new BrowserPluginMsg_GuestContentWindowReady(instance_id_, 603 guest_routing_id)); 604 605 if (!params.src.empty()) { 606 // params.src will be validated in BrowserPluginGuest::OnNavigateGuest. 607 OnNavigateGuest(instance_id_, params.src); 608 } 609 610 has_render_view_ = true; 611 612 if (!embedder_web_contents_-> 613 GetWebkitPrefs().accelerated_compositing_enabled) { 614 WebPreferences prefs = GetWebContents()->GetWebkitPrefs(); 615 prefs.accelerated_compositing_enabled = false; 616 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs); 617 } 618 619 // Enable input method for guest if it's enabled for the embedder. 620 if (static_cast<RenderViewHostImpl*>( 621 embedder_web_contents_->GetRenderViewHost())->input_method_active()) { 622 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( 623 GetWebContents()->GetRenderViewHost()); 624 guest_rvh->SetInputMethodActive(true); 625 } 626 627 // Inform the embedder of the guest's information. 628 // We pull the partition information from the site's URL, which is of the form 629 // guest://site/{persist}?{partition_name}. 630 const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL(); 631 BrowserPluginMsg_Attach_ACK_Params ack_params; 632 ack_params.storage_partition_id = site_url.query(); 633 ack_params.persist_storage = 634 site_url.path().find("persist") != std::string::npos; 635 ack_params.name = name_; 636 SendMessageToEmbedder( 637 new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params)); 638 639 if (delegate_) 640 delegate_->DidAttach(); 641 } 642 643 BrowserPluginGuest::~BrowserPluginGuest() { 644 while (!pending_messages_.empty()) { 645 delete pending_messages_.front(); 646 pending_messages_.pop(); 647 } 648 } 649 650 // static 651 BrowserPluginGuest* BrowserPluginGuest::Create( 652 int instance_id, 653 SiteInstance* guest_site_instance, 654 WebContentsImpl* web_contents, 655 scoped_ptr<base::DictionaryValue> extra_params) { 656 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create")); 657 BrowserPluginGuest* guest = NULL; 658 if (factory_) { 659 guest = factory_->CreateBrowserPluginGuest(instance_id, web_contents); 660 } else { 661 guest = new BrowserPluginGuest(instance_id, false, web_contents, NULL); 662 } 663 guest->extra_attach_params_.reset(extra_params->DeepCopy()); 664 web_contents->SetBrowserPluginGuest(guest); 665 BrowserPluginGuestDelegate* delegate = NULL; 666 GetContentClient()->browser()->GuestWebContentsCreated( 667 guest_site_instance, web_contents, NULL, &delegate, extra_params.Pass()); 668 guest->SetDelegate(delegate); 669 return guest; 670 } 671 672 // static 673 BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener( 674 int instance_id, 675 bool has_render_view, 676 WebContentsImpl* web_contents, 677 BrowserPluginGuest* opener) { 678 BrowserPluginGuest* guest = 679 new BrowserPluginGuest( 680 instance_id, has_render_view, web_contents, opener); 681 web_contents->SetBrowserPluginGuest(guest); 682 BrowserPluginGuestDelegate* delegate = NULL; 683 GetContentClient()->browser()->GuestWebContentsCreated( 684 opener->GetWebContents()->GetSiteInstance(), 685 web_contents, opener->GetWebContents(), &delegate, 686 scoped_ptr<base::DictionaryValue>()); 687 guest->SetDelegate(delegate); 688 return guest; 689 } 690 691 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() { 692 return embedder_web_contents_->GetRenderWidgetHostView(); 693 } 694 695 void BrowserPluginGuest::UpdateVisibility() { 696 OnSetVisibility(instance_id_, visible()); 697 } 698 699 void BrowserPluginGuest::CopyFromCompositingSurface( 700 gfx::Rect src_subrect, 701 gfx::Size dst_size, 702 const base::Callback<void(bool, const SkBitmap&)>& callback) { 703 copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback)); 704 SendMessageToEmbedder( 705 new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(), 706 copy_request_id_, src_subrect, dst_size)); 707 } 708 709 // screen. 710 gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) { 711 gfx::Rect guest_rect(bounds); 712 guest_rect.Offset(guest_window_rect_.OffsetFromOrigin()); 713 return guest_rect; 714 } 715 716 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) { 717 embedder_visible_ = visible; 718 UpdateVisibility(); 719 } 720 721 void BrowserPluginGuest::AddNewContents(WebContents* source, 722 WebContents* new_contents, 723 WindowOpenDisposition disposition, 724 const gfx::Rect& initial_pos, 725 bool user_gesture, 726 bool* was_blocked) { 727 if (was_blocked) 728 *was_blocked = false; 729 RequestNewWindowPermission(disposition, initial_pos, user_gesture, 730 static_cast<WebContentsImpl*>(new_contents)); 731 } 732 733 void BrowserPluginGuest::CanDownload( 734 RenderViewHost* render_view_host, 735 int request_id, 736 const std::string& request_method, 737 const base::Callback<void(bool)>& callback) { 738 BrowserThread::PostTaskAndReplyWithResult( 739 BrowserThread::IO, FROM_HERE, 740 base::Bind(&RetrieveDownloadURLFromRequestId, 741 render_view_host, request_id), 742 base::Bind(&BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId, 743 weak_ptr_factory_.GetWeakPtr(), 744 request_method, 745 callback)); 746 } 747 748 void BrowserPluginGuest::LoadProgressChanged(WebContents* contents, 749 double progress) { 750 if (delegate_) 751 delegate_->LoadProgressed(progress); 752 } 753 754 void BrowserPluginGuest::CloseContents(WebContents* source) { 755 if (!delegate_) 756 return; 757 758 delegate_->Close(); 759 } 760 761 JavaScriptDialogManager* BrowserPluginGuest::GetJavaScriptDialogManager() { 762 return this; 763 } 764 765 bool BrowserPluginGuest::HandleContextMenu(const ContextMenuParams& params) { 766 // TODO(fsamuel): We show the regular page context menu handler for now until 767 // we implement the Apps Context Menu API for Browser Plugin (see 768 // http://crbug.com/140315). 769 return false; // Will be handled by WebContentsViewGuest. 770 } 771 772 void BrowserPluginGuest::HandleKeyboardEvent( 773 WebContents* source, 774 const NativeWebKeyboardEvent& event) { 775 if (!attached()) 776 return; 777 778 if (UnlockMouseIfNecessary(event)) 779 return; 780 781 if (delegate_ && delegate_->HandleKeyboardEvent(event)) 782 return; 783 784 if (!embedder_web_contents_->GetDelegate()) 785 return; 786 787 // Send the unhandled keyboard events back to the embedder to reprocess them. 788 // TODO(fsamuel): This introduces the possibility of out-of-order keyboard 789 // events because the guest may be arbitrarily delayed when responding to 790 // keyboard events. In that time, the embedder may have received and processed 791 // additional key events. This needs to be fixed as soon as possible. 792 // See http://crbug.com/229882. 793 embedder_web_contents_->GetDelegate()->HandleKeyboardEvent( 794 web_contents(), event); 795 } 796 797 WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source, 798 const OpenURLParams& params) { 799 // If the guest wishes to navigate away prior to attachment then we save the 800 // navigation to perform upon attachment. Navigation initializes a lot of 801 // state that assumes an embedder exists, such as RenderWidgetHostViewGuest. 802 // Navigation also resumes resource loading which we don't want to allow 803 // until attachment. 804 if (!attached()) { 805 PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this); 806 if (it == opener()->pending_new_windows_.end()) 807 return NULL; 808 const NewWindowInfo& old_target_url = it->second; 809 NewWindowInfo new_window_info(params.url, old_target_url.name); 810 new_window_info.changed = new_window_info.url != old_target_url.url; 811 it->second = new_window_info; 812 return NULL; 813 } 814 if (params.disposition == CURRENT_TAB) { 815 // This can happen for cross-site redirects. 816 LoadURLWithParams(params.url, params.referrer, params.transition, source); 817 return source; 818 } 819 820 return CreateNewGuestWindow(params)->GetWebContents(); 821 } 822 823 void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents, 824 int64 source_frame_id, 825 const base::string16& frame_name, 826 const GURL& target_url, 827 WebContents* new_contents) { 828 WebContentsImpl* new_contents_impl = 829 static_cast<WebContentsImpl*>(new_contents); 830 BrowserPluginGuest* guest = new_contents_impl->GetBrowserPluginGuest(); 831 guest->opener_ = AsWeakPtr(); 832 std::string guest_name = UTF16ToUTF8(frame_name); 833 guest->name_ = guest_name; 834 // Take ownership of the new guest until it is attached to the embedder's DOM 835 // tree to avoid leaking a guest if this guest is destroyed before attaching 836 // the new guest. 837 pending_new_windows_.insert( 838 std::make_pair(guest, NewWindowInfo(target_url, guest_name))); 839 } 840 841 void BrowserPluginGuest::RendererUnresponsive(WebContents* source) { 842 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Hung")); 843 if (!delegate_) 844 return; 845 delegate_->RendererUnresponsive(); 846 } 847 848 void BrowserPluginGuest::RendererResponsive(WebContents* source) { 849 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Responsive")); 850 if (!delegate_) 851 return; 852 delegate_->RendererResponsive(); 853 } 854 855 void BrowserPluginGuest::RunFileChooser(WebContents* web_contents, 856 const FileChooserParams& params) { 857 if (!attached()) 858 return; 859 860 if (!embedder_web_contents_->GetDelegate()) 861 return; 862 863 embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params); 864 } 865 866 bool BrowserPluginGuest::ShouldFocusPageAfterCrash() { 867 // Rather than managing focus in WebContentsImpl::RenderViewReady, we will 868 // manage the focus ourselves. 869 return false; 870 } 871 872 WebContentsImpl* BrowserPluginGuest::GetWebContents() { 873 return static_cast<WebContentsImpl*>(web_contents()); 874 } 875 876 base::SharedMemory* BrowserPluginGuest::GetDamageBufferFromEmbedder( 877 const BrowserPluginHostMsg_ResizeGuest_Params& params) { 878 if (!attached()) { 879 LOG(WARNING) << "Attempting to map a damage buffer prior to attachment."; 880 return NULL; 881 } 882 #if defined(OS_WIN) 883 base::ProcessHandle handle = 884 embedder_web_contents_->GetRenderProcessHost()->GetHandle(); 885 scoped_ptr<base::SharedMemory> shared_buf( 886 new base::SharedMemory(params.damage_buffer_handle, false, handle)); 887 #elif defined(OS_POSIX) 888 scoped_ptr<base::SharedMemory> shared_buf( 889 new base::SharedMemory(params.damage_buffer_handle, false)); 890 #endif 891 if (!shared_buf->Map(params.damage_buffer_size)) { 892 LOG(WARNING) << "Unable to map the embedder's damage buffer."; 893 return NULL; 894 } 895 return shared_buf.release(); 896 } 897 898 void BrowserPluginGuest::SetDamageBuffer( 899 const BrowserPluginHostMsg_ResizeGuest_Params& params) { 900 damage_buffer_.reset(GetDamageBufferFromEmbedder(params)); 901 // Sanity check: Verify that we've correctly shared the damage buffer memory 902 // between the embedder and browser processes. 903 DCHECK(!damage_buffer_ || 904 *static_cast<unsigned int*>(damage_buffer_->memory()) == 0xdeadbeef); 905 damage_buffer_sequence_id_ = params.damage_buffer_sequence_id; 906 damage_buffer_size_ = params.damage_buffer_size; 907 damage_view_size_ = params.view_rect.size(); 908 damage_buffer_scale_factor_ = params.scale_factor; 909 } 910 911 gfx::Point BrowserPluginGuest::GetScreenCoordinates( 912 const gfx::Point& relative_position) const { 913 gfx::Point screen_pos(relative_position); 914 screen_pos += guest_window_rect_.OffsetFromOrigin(); 915 return screen_pos; 916 } 917 918 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const { 919 return size.width() <= max_auto_size_.width() && 920 size.height() <= max_auto_size_.height(); 921 } 922 923 void BrowserPluginGuest::RequestNewWindowPermission( 924 WindowOpenDisposition disposition, 925 const gfx::Rect& initial_bounds, 926 bool user_gesture, 927 WebContentsImpl* new_contents) { 928 BrowserPluginGuest* guest = new_contents->GetBrowserPluginGuest(); 929 PendingWindowMap::iterator it = pending_new_windows_.find(guest); 930 if (it == pending_new_windows_.end()) 931 return; 932 const NewWindowInfo& new_window_info = it->second; 933 934 base::DictionaryValue request_info; 935 request_info.Set(browser_plugin::kInitialHeight, 936 base::Value::CreateIntegerValue(initial_bounds.height())); 937 request_info.Set(browser_plugin::kInitialWidth, 938 base::Value::CreateIntegerValue(initial_bounds.width())); 939 request_info.Set(browser_plugin::kTargetURL, 940 base::Value::CreateStringValue(new_window_info.url.spec())); 941 request_info.Set(browser_plugin::kName, 942 base::Value::CreateStringValue(new_window_info.name)); 943 request_info.Set(browser_plugin::kWindowID, 944 base::Value::CreateIntegerValue(guest->instance_id())); 945 request_info.Set(browser_plugin::kWindowOpenDisposition, 946 base::Value::CreateStringValue( 947 WindowOpenDispositionToString(disposition))); 948 949 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW, 950 new NewWindowRequest(guest->instance_id(), this), 951 request_info); 952 } 953 954 bool BrowserPluginGuest::UnlockMouseIfNecessary( 955 const NativeWebKeyboardEvent& event) { 956 if (!mouse_locked_) 957 return false; 958 959 embedder_web_contents()->GotResponseToLockMouseRequest(false); 960 return true; 961 } 962 963 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) { 964 if (!attached()) { 965 // Some pages such as data URLs, javascript URLs, and about:blank 966 // do not load external resources and so they load prior to attachment. 967 // As a result, we must save all these IPCs until attachment and then 968 // forward them so that the embedder gets a chance to see and process 969 // the load events. 970 pending_messages_.push(msg); 971 return; 972 } 973 msg->set_routing_id(embedder_web_contents_->GetRoutingID()); 974 embedder_web_contents_->Send(msg); 975 } 976 977 void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y, 978 int screen_x, int screen_y, blink::WebDragOperation operation) { 979 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y, 980 screen_x, screen_y, operation); 981 } 982 983 void BrowserPluginGuest::DragSourceMovedTo(int client_x, int client_y, 984 int screen_x, int screen_y) { 985 web_contents()->GetRenderViewHost()->DragSourceMovedTo(client_x, client_y, 986 screen_x, screen_y); 987 } 988 989 void BrowserPluginGuest::EndSystemDrag() { 990 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( 991 GetWebContents()->GetRenderViewHost()); 992 guest_rvh->DragSourceSystemDragEnded(); 993 // Issue a MouseUp event to get out of a selection state. 994 blink::WebMouseEvent mouse_event; 995 mouse_event.type = blink::WebInputEvent::MouseUp; 996 mouse_event.button = blink::WebMouseEvent::ButtonLeft; 997 guest_rvh->ForwardMouseEvent(mouse_event); 998 } 999 1000 void BrowserPluginGuest::SetDelegate(BrowserPluginGuestDelegate* delegate) { 1001 DCHECK(!delegate_); 1002 delegate_.reset(delegate); 1003 } 1004 1005 void BrowserPluginGuest::AskEmbedderForGeolocationPermission( 1006 int bridge_id, 1007 const GURL& requesting_frame, 1008 const GeolocationCallback& callback) { 1009 base::DictionaryValue request_info; 1010 request_info.Set(browser_plugin::kURL, 1011 base::Value::CreateStringValue(requesting_frame.spec())); 1012 1013 int request_id = 1014 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION, 1015 new GeolocationRequest( 1016 callback, bridge_id, &weak_ptr_factory_), 1017 request_info); 1018 1019 DCHECK(bridge_id_to_request_id_map_.find(bridge_id) == 1020 bridge_id_to_request_id_map_.end()); 1021 bridge_id_to_request_id_map_[bridge_id] = request_id; 1022 } 1023 1024 int BrowserPluginGuest::RemoveBridgeID(int bridge_id) { 1025 std::map<int, int>::iterator bridge_itr = 1026 bridge_id_to_request_id_map_.find(bridge_id); 1027 if (bridge_itr == bridge_id_to_request_id_map_.end()) 1028 return browser_plugin::kInvalidPermissionRequestID; 1029 1030 int request_id = bridge_itr->second; 1031 bridge_id_to_request_id_map_.erase(bridge_itr); 1032 return request_id; 1033 } 1034 1035 void BrowserPluginGuest::CancelGeolocationRequest(int bridge_id) { 1036 int request_id = RemoveBridgeID(bridge_id); 1037 RequestMap::iterator request_itr = permission_request_map_.find(request_id); 1038 if (request_itr == permission_request_map_.end()) 1039 return; 1040 permission_request_map_.erase(request_itr); 1041 } 1042 1043 void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback, 1044 int bridge_id, 1045 bool allowed) { 1046 callback.Run(allowed); 1047 RemoveBridgeID(bridge_id); 1048 } 1049 1050 void BrowserPluginGuest::SendQueuedMessages() { 1051 if (!attached()) 1052 return; 1053 1054 while (!pending_messages_.empty()) { 1055 IPC::Message* message = pending_messages_.front(); 1056 pending_messages_.pop(); 1057 SendMessageToEmbedder(message); 1058 } 1059 } 1060 1061 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame( 1062 int64 frame_id, 1063 const base::string16& frame_unique_name, 1064 bool is_main_frame, 1065 const GURL& url, 1066 PageTransition transition_type, 1067 RenderViewHost* render_view_host) { 1068 RecordAction(UserMetricsAction("BrowserPlugin.Guest.DidNavigate")); 1069 } 1070 1071 void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) { 1072 bool enable_dragdrop = delegate_ && delegate_->IsDragAndDropEnabled(); 1073 if (!enable_dragdrop) { 1074 // Initiating a drag from inside a guest is currently not supported without 1075 // the kEnableBrowserPluginDragDrop flag on a linux platform. So inject some 1076 // JS to disable it. http://crbug.com/161112 1077 const char script[] = "window.addEventListener('dragstart', function() { " 1078 " window.event.preventDefault(); " 1079 "});"; 1080 render_view_host->ExecuteJavascriptInWebFrame(base::string16(), 1081 ASCIIToUTF16(script)); 1082 } 1083 } 1084 1085 void BrowserPluginGuest::RenderViewReady() { 1086 RenderViewHost* rvh = GetWebContents()->GetRenderViewHost(); 1087 // The guest RenderView should always live in a guest process. 1088 CHECK(rvh->GetProcess()->IsGuest()); 1089 // TODO(fsamuel): Investigate whether it's possible to update state earlier 1090 // here (see http://crbug.com/158151). 1091 Send(new InputMsg_SetFocus(routing_id(), focused_)); 1092 UpdateVisibility(); 1093 if (auto_size_enabled_) 1094 rvh->EnableAutoResize(min_auto_size_, max_auto_size_); 1095 else 1096 rvh->DisableAutoResize(damage_view_size_); 1097 1098 Send(new ViewMsg_SetName(routing_id(), name_)); 1099 OnSetContentsOpaque(instance_id_, guest_opaque_); 1100 1101 RenderWidgetHostImpl::From(rvh)-> 1102 set_hung_renderer_delay_ms(guest_hang_timeout_); 1103 } 1104 1105 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) { 1106 SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(instance_id())); 1107 switch (status) { 1108 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: 1109 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Killed")); 1110 break; 1111 case base::TERMINATION_STATUS_PROCESS_CRASHED: 1112 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Crashed")); 1113 break; 1114 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: 1115 RecordAction(UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath")); 1116 break; 1117 default: 1118 break; 1119 } 1120 // TODO(fsamuel): Consider whether we should be clearing 1121 // |permission_request_map_| here. 1122 if (delegate_) 1123 delegate_->GuestProcessGone(status); 1124 } 1125 1126 // static 1127 void BrowserPluginGuest::AcknowledgeBufferPresent( 1128 int route_id, 1129 int gpu_host_id, 1130 const std::string& mailbox_name, 1131 uint32 sync_point) { 1132 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; 1133 ack_params.mailbox_name = mailbox_name; 1134 ack_params.sync_point = sync_point; 1135 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, 1136 gpu_host_id, 1137 ack_params); 1138 } 1139 1140 // static 1141 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest( 1142 const IPC::Message& message) { 1143 switch (message.type()) { 1144 case BrowserPluginHostMsg_BuffersSwappedACK::ID: 1145 case BrowserPluginHostMsg_CompositorFrameACK::ID: 1146 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID: 1147 case BrowserPluginHostMsg_DragStatusUpdate::ID: 1148 case BrowserPluginHostMsg_ExecuteEditCommand::ID: 1149 case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID: 1150 case BrowserPluginHostMsg_HandleInputEvent::ID: 1151 case BrowserPluginHostMsg_ImeConfirmComposition::ID: 1152 case BrowserPluginHostMsg_ImeSetComposition::ID: 1153 case BrowserPluginHostMsg_LockMouse_ACK::ID: 1154 case BrowserPluginHostMsg_NavigateGuest::ID: 1155 case BrowserPluginHostMsg_PluginDestroyed::ID: 1156 case BrowserPluginHostMsg_ReclaimCompositorResources::ID: 1157 case BrowserPluginHostMsg_ResizeGuest::ID: 1158 case BrowserPluginHostMsg_SetAutoSize::ID: 1159 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID: 1160 case BrowserPluginHostMsg_SetFocus::ID: 1161 case BrowserPluginHostMsg_SetName::ID: 1162 case BrowserPluginHostMsg_SetContentsOpaque::ID: 1163 case BrowserPluginHostMsg_SetVisibility::ID: 1164 case BrowserPluginHostMsg_UnlockMouse_ACK::ID: 1165 case BrowserPluginHostMsg_UpdateGeometry::ID: 1166 case BrowserPluginHostMsg_UpdateRect_ACK::ID: 1167 return true; 1168 default: 1169 return false; 1170 } 1171 } 1172 1173 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) { 1174 bool handled = true; 1175 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message) 1176 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, 1177 OnHasTouchEventHandlers) 1178 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse) 1179 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor) 1180 #if defined(OS_MACOSX) 1181 // MacOSX creates and populates platform-specific select drop-down menus 1182 // whereas other platforms merely create a popup window that the guest 1183 // renderer process paints inside. 1184 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup) 1185 #endif 1186 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget) 1187 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus) 1188 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged, 1189 OnTextInputTypeChanged) 1190 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition, 1191 OnImeCancelComposition) 1192 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) 1193 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged, 1194 OnImeCompositionRangeChanged) 1195 #endif 1196 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse) 1197 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName, OnUpdateFrameName) 1198 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect) 1199 IPC_MESSAGE_UNHANDLED(handled = false) 1200 IPC_END_MESSAGE_MAP() 1201 return handled; 1202 } 1203 1204 void BrowserPluginGuest::Attach( 1205 WebContentsImpl* embedder_web_contents, 1206 BrowserPluginHostMsg_Attach_Params params, 1207 const base::DictionaryValue& extra_params) { 1208 if (attached()) 1209 return; 1210 1211 extra_attach_params_.reset(extra_params.DeepCopy()); 1212 1213 // Clear parameters that get inherited from the opener. 1214 params.storage_partition_id.clear(); 1215 params.persist_storage = false; 1216 params.src.clear(); 1217 1218 // If a RenderView has already been created for this new window, then we need 1219 // to initialize the browser-side state now so that the RenderFrameHostManager 1220 // does not create a new RenderView on navigation. 1221 if (has_render_view_) { 1222 static_cast<RenderViewHostImpl*>( 1223 GetWebContents()->GetRenderViewHost())->Init(); 1224 WebContentsViewGuest* new_view = 1225 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView()); 1226 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost()); 1227 } 1228 1229 // We need to do a navigation here if the target URL has changed between 1230 // the time the WebContents was created and the time it was attached. 1231 // We also need to do an initial navigation if a RenderView was never 1232 // created for the new window in cases where there is no referrer. 1233 PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this); 1234 if (it != opener()->pending_new_windows_.end()) { 1235 const NewWindowInfo& new_window_info = it->second; 1236 if (new_window_info.changed || !has_render_view_) 1237 params.src = it->second.url.spec(); 1238 } else { 1239 NOTREACHED(); 1240 } 1241 1242 // Once a new guest is attached to the DOM of the embedder page, then the 1243 // lifetime of the new guest is no longer managed by the opener guest. 1244 opener()->pending_new_windows_.erase(this); 1245 1246 // The guest's frame name takes precedence over the BrowserPlugin's name. 1247 // The guest's frame name is assigned in 1248 // BrowserPluginGuest::WebContentsCreated. 1249 if (!name_.empty()) 1250 params.name.clear(); 1251 1252 Initialize(params, embedder_web_contents); 1253 1254 SendQueuedMessages(); 1255 1256 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Attached")); 1257 } 1258 1259 void BrowserPluginGuest::OnCompositorFrameACK( 1260 int instance_id, 1261 int route_id, 1262 uint32 output_surface_id, 1263 int renderer_host_id, 1264 const cc::CompositorFrameAck& ack) { 1265 RenderWidgetHostImpl::SendSwapCompositorFrameAck(route_id, 1266 output_surface_id, 1267 renderer_host_id, 1268 ack); 1269 } 1270 1271 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id, 1272 blink::WebDragStatus drag_status, 1273 const DropData& drop_data, 1274 blink::WebDragOperationsMask mask, 1275 const gfx::Point& location) { 1276 RenderViewHost* host = GetWebContents()->GetRenderViewHost(); 1277 switch (drag_status) { 1278 case blink::WebDragStatusEnter: 1279 embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest( 1280 this); 1281 host->DragTargetDragEnter(drop_data, location, location, mask, 0); 1282 break; 1283 case blink::WebDragStatusOver: 1284 host->DragTargetDragOver(location, location, mask, 0); 1285 break; 1286 case blink::WebDragStatusLeave: 1287 embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this); 1288 host->DragTargetDragLeave(); 1289 break; 1290 case blink::WebDragStatusDrop: 1291 host->DragTargetDrop(location, location, 0); 1292 EndSystemDrag(); 1293 break; 1294 case blink::WebDragStatusUnknown: 1295 NOTREACHED(); 1296 } 1297 } 1298 1299 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id, 1300 const std::string& name) { 1301 Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string())); 1302 } 1303 1304 void BrowserPluginGuest::OnImeSetComposition( 1305 int instance_id, 1306 const std::string& text, 1307 const std::vector<blink::WebCompositionUnderline>& underlines, 1308 int selection_start, 1309 int selection_end) { 1310 Send(new ViewMsg_ImeSetComposition(routing_id(), 1311 UTF8ToUTF16(text), underlines, 1312 selection_start, selection_end)); 1313 } 1314 1315 void BrowserPluginGuest::OnImeConfirmComposition( 1316 int instance_id, 1317 const std::string& text, 1318 bool keep_selection) { 1319 Send(new ViewMsg_ImeConfirmComposition(routing_id(), 1320 UTF8ToUTF16(text), 1321 gfx::Range::InvalidRange(), 1322 keep_selection)); 1323 } 1324 1325 void BrowserPluginGuest::OnExtendSelectionAndDelete( 1326 int instance_id, 1327 int before, 1328 int after) { 1329 Send(new ViewMsg_ExtendSelectionAndDelete(routing_id(), before, after)); 1330 } 1331 1332 void BrowserPluginGuest::OnReclaimCompositorResources( 1333 int instance_id, 1334 int route_id, 1335 uint32 output_surface_id, 1336 int renderer_host_id, 1337 const cc::CompositorFrameAck& ack) { 1338 RenderWidgetHostImpl::SendReclaimCompositorResources(route_id, 1339 output_surface_id, 1340 renderer_host_id, 1341 ack); 1342 } 1343 1344 void BrowserPluginGuest::OnHandleInputEvent( 1345 int instance_id, 1346 const gfx::Rect& guest_window_rect, 1347 const blink::WebInputEvent* event) { 1348 guest_window_rect_ = guest_window_rect; 1349 // If the embedder's RWHV is destroyed then that means that the embedder's 1350 // window has been closed but the embedder's WebContents has not yet been 1351 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense 1352 // if there is a visible embedder. 1353 if (embedder_web_contents_->GetRenderWidgetHostView()) { 1354 guest_screen_rect_ = guest_window_rect; 1355 guest_screen_rect_.Offset( 1356 embedder_web_contents_->GetRenderWidgetHostView()-> 1357 GetViewBounds().OffsetFromOrigin()); 1358 } 1359 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( 1360 GetWebContents()->GetRenderViewHost()); 1361 1362 if (blink::WebInputEvent::isMouseEventType(event->type)) { 1363 guest_rvh->ForwardMouseEvent( 1364 *static_cast<const blink::WebMouseEvent*>(event)); 1365 return; 1366 } 1367 1368 if (event->type == blink::WebInputEvent::MouseWheel) { 1369 guest_rvh->ForwardWheelEvent( 1370 *static_cast<const blink::WebMouseWheelEvent*>(event)); 1371 return; 1372 } 1373 1374 if (blink::WebInputEvent::isKeyboardEventType(event->type)) { 1375 RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>( 1376 embedder_web_contents_->GetRenderViewHost()); 1377 if (!embedder_rvh->GetLastKeyboardEvent()) 1378 return; 1379 NativeWebKeyboardEvent keyboard_event( 1380 *embedder_rvh->GetLastKeyboardEvent()); 1381 guest_rvh->ForwardKeyboardEvent(keyboard_event); 1382 return; 1383 } 1384 1385 if (blink::WebInputEvent::isTouchEventType(event->type)) { 1386 guest_rvh->ForwardTouchEventWithLatencyInfo( 1387 *static_cast<const blink::WebTouchEvent*>(event), 1388 ui::LatencyInfo()); 1389 return; 1390 } 1391 1392 if (blink::WebInputEvent::isGestureEventType(event->type)) { 1393 guest_rvh->ForwardGestureEvent( 1394 *static_cast<const blink::WebGestureEvent*>(event)); 1395 return; 1396 } 1397 } 1398 1399 void BrowserPluginGuest::OnLockMouse(bool user_gesture, 1400 bool last_unlocked_by_target, 1401 bool privileged) { 1402 if (pending_lock_request_) { 1403 // Immediately reject the lock because only one pointerLock may be active 1404 // at a time. 1405 Send(new ViewMsg_LockMouse_ACK(routing_id(), false)); 1406 return; 1407 } 1408 pending_lock_request_ = true; 1409 base::DictionaryValue request_info; 1410 request_info.Set(browser_plugin::kUserGesture, 1411 base::Value::CreateBooleanValue(user_gesture)); 1412 request_info.Set(browser_plugin::kLastUnlockedBySelf, 1413 base::Value::CreateBooleanValue(last_unlocked_by_target)); 1414 request_info.Set(browser_plugin::kURL, 1415 base::Value::CreateStringValue( 1416 web_contents()->GetLastCommittedURL().spec())); 1417 1418 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK, 1419 new PointerLockRequest(this), 1420 request_info); 1421 } 1422 1423 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) { 1424 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded)); 1425 pending_lock_request_ = false; 1426 if (succeeded) 1427 mouse_locked_ = true; 1428 } 1429 1430 void BrowserPluginGuest::OnNavigateGuest( 1431 int instance_id, 1432 const std::string& src) { 1433 GURL url = delegate_ ? delegate_->ResolveURL(src) : GURL(src); 1434 // We do not load empty urls in web_contents. 1435 // If a guest sets empty src attribute after it has navigated to some 1436 // non-empty page, the action is considered no-op. This empty src navigation 1437 // should never be sent to BrowserPluginGuest (browser process). 1438 DCHECK(!src.empty()); 1439 if (src.empty()) 1440 return; 1441 1442 // Do not allow navigating a guest to schemes other than known safe schemes. 1443 // This will block the embedder trying to load unwanted schemes, e.g. 1444 // chrome://settings. 1445 bool scheme_is_blocked = 1446 (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme( 1447 url.scheme()) && 1448 !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme( 1449 url.scheme())) || 1450 url.SchemeIs(kJavaScriptScheme); 1451 if (scheme_is_blocked || !url.is_valid()) { 1452 if (delegate_) { 1453 std::string error_type; 1454 base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::", 1455 &error_type); 1456 delegate_->LoadAbort(true /* is_top_level */, url, error_type); 1457 } 1458 return; 1459 } 1460 1461 GURL validated_url(url); 1462 RenderViewHost::FilterURL( 1463 GetWebContents()->GetRenderProcessHost(), 1464 false, 1465 &validated_url); 1466 // As guests do not swap processes on navigation, only navigations to 1467 // normal web URLs are supported. No protocol handlers are installed for 1468 // other schemes (e.g., WebUI or extensions), and no permissions or bindings 1469 // can be granted to the guest process. 1470 LoadURLWithParams(validated_url, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL, 1471 GetWebContents()); 1472 } 1473 1474 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) { 1475 Destroy(); 1476 } 1477 1478 void BrowserPluginGuest::OnResizeGuest( 1479 int instance_id, 1480 const BrowserPluginHostMsg_ResizeGuest_Params& params) { 1481 if (!params.size_changed) 1482 return; 1483 // BrowserPlugin manages resize flow control itself and does not depend 1484 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags 1485 // here. If we are setting the size for the first time before navigating then 1486 // BrowserPluginGuest does not yet have a RenderViewHost. 1487 if (GetWebContents()->GetRenderViewHost()) { 1488 RenderWidgetHostImpl* render_widget_host = 1489 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost()); 1490 render_widget_host->ResetSizeAndRepaintPendingFlags(); 1491 1492 if (guest_device_scale_factor_ != params.scale_factor) { 1493 guest_device_scale_factor_ = params.scale_factor; 1494 render_widget_host->NotifyScreenInfoChanged(); 1495 } 1496 } 1497 // When autosize is turned off and as a result there is a layout change, we 1498 // send a sizechanged event. 1499 if (!auto_size_enabled_ && last_seen_auto_size_enabled_ && 1500 !params.view_rect.size().IsEmpty() && delegate_) { 1501 delegate_->SizeChanged(last_seen_view_size_, params.view_rect.size()); 1502 last_seen_auto_size_enabled_ = false; 1503 } 1504 // Invalid damage buffer means we are in HW compositing mode, 1505 // so just resize the WebContents and repaint if needed. 1506 if (base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) 1507 SetDamageBuffer(params); 1508 if (!params.view_rect.size().IsEmpty()) 1509 GetWebContents()->GetView()->SizeContents(params.view_rect.size()); 1510 if (params.repaint) 1511 Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size())); 1512 } 1513 1514 void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) { 1515 if (focused_ == focused) 1516 return; 1517 focused_ = focused; 1518 Send(new InputMsg_SetFocus(routing_id(), focused)); 1519 if (!focused && mouse_locked_) 1520 OnUnlockMouse(); 1521 } 1522 1523 void BrowserPluginGuest::OnSetName(int instance_id, const std::string& name) { 1524 if (name == name_) 1525 return; 1526 name_ = name; 1527 Send(new ViewMsg_SetName(routing_id(), name)); 1528 } 1529 1530 void BrowserPluginGuest::OnSetSize( 1531 int instance_id, 1532 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, 1533 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) { 1534 bool old_auto_size_enabled = auto_size_enabled_; 1535 gfx::Size old_max_size = max_auto_size_; 1536 gfx::Size old_min_size = min_auto_size_; 1537 auto_size_enabled_ = auto_size_params.enable; 1538 max_auto_size_ = auto_size_params.max_size; 1539 min_auto_size_ = auto_size_params.min_size; 1540 if (auto_size_enabled_ && (!old_auto_size_enabled || 1541 (old_max_size != max_auto_size_) || 1542 (old_min_size != min_auto_size_))) { 1543 RecordAction(UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize")); 1544 GetWebContents()->GetRenderViewHost()->EnableAutoResize( 1545 min_auto_size_, max_auto_size_); 1546 // TODO(fsamuel): If we're changing autosize parameters, then we force 1547 // the guest to completely repaint itself, because BrowserPlugin has 1548 // allocated a new damage buffer and expects a full frame of pixels. 1549 // Ideally, we shouldn't need to do this because we shouldn't need to 1550 // allocate a new damage buffer unless |max_auto_size_| has changed. 1551 // However, even in that case, layout may not change and so we may 1552 // not get a full frame worth of pixels. 1553 Send(new ViewMsg_Repaint(routing_id(), max_auto_size_)); 1554 } else if (!auto_size_enabled_ && old_auto_size_enabled) { 1555 GetWebContents()->GetRenderViewHost()->DisableAutoResize( 1556 resize_guest_params.view_rect.size()); 1557 } 1558 OnResizeGuest(instance_id_, resize_guest_params); 1559 } 1560 1561 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent( 1562 int instance_id, 1563 const std::vector<EditCommand>& edit_commands) { 1564 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(), 1565 edit_commands)); 1566 } 1567 1568 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) { 1569 guest_opaque_ = opaque; 1570 1571 SkBitmap background; 1572 if (!guest_opaque_) { 1573 background.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); 1574 unsigned int color = 0; 1575 background.setPixels(&color); 1576 } 1577 Send(new ViewMsg_SetBackground(routing_id(), background)); 1578 } 1579 1580 void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) { 1581 guest_visible_ = visible; 1582 if (embedder_visible_ && guest_visible_) 1583 GetWebContents()->WasShown(); 1584 else 1585 GetWebContents()->WasHidden(); 1586 } 1587 1588 void BrowserPluginGuest::OnSwapBuffersACK(int instance_id, 1589 int route_id, 1590 int gpu_host_id, 1591 const std::string& mailbox_name, 1592 uint32 sync_point) { 1593 AcknowledgeBufferPresent(route_id, gpu_host_id, mailbox_name, sync_point); 1594 1595 // This is only relevant on MACOSX and WIN when threaded compositing 1596 // is not enabled. In threaded mode, above ACK is sufficient. 1597 #if defined(OS_MACOSX) || defined(OS_WIN) 1598 RenderWidgetHostImpl* render_widget_host = 1599 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost()); 1600 render_widget_host->AcknowledgeSwapBuffersToRenderer(); 1601 #endif // defined(OS_MACOSX) || defined(OS_WIN) 1602 } 1603 1604 void BrowserPluginGuest::OnUnlockMouse() { 1605 SendMessageToEmbedder( 1606 new BrowserPluginMsg_SetMouseLock(instance_id(), false)); 1607 } 1608 1609 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) { 1610 // mouse_locked_ could be false here if the lock attempt was cancelled due 1611 // to window focus, or for various other reasons before the guest was informed 1612 // of the lock's success. 1613 if (mouse_locked_) 1614 Send(new ViewMsg_MouseLockLost(routing_id())); 1615 mouse_locked_ = false; 1616 } 1617 1618 void BrowserPluginGuest::OnUpdateRectACK( 1619 int instance_id, 1620 bool needs_ack, 1621 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, 1622 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) { 1623 // Only the software path expects an ACK. 1624 if (needs_ack) 1625 Send(new ViewMsg_UpdateRect_ACK(routing_id())); 1626 OnSetSize(instance_id_, auto_size_params, resize_guest_params); 1627 } 1628 1629 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck( 1630 int instance_id, 1631 int request_id, 1632 const SkBitmap& bitmap) { 1633 CHECK(copy_request_callbacks_.count(request_id)); 1634 if (!copy_request_callbacks_.count(request_id)) 1635 return; 1636 const CopyRequestCallback& callback = copy_request_callbacks_[request_id]; 1637 callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap); 1638 copy_request_callbacks_.erase(request_id); 1639 } 1640 1641 void BrowserPluginGuest::OnUpdateGeometry(int instance_id, 1642 const gfx::Rect& view_rect) { 1643 // The plugin has moved within the embedder without resizing or the 1644 // embedder/container's view rect changing. 1645 guest_window_rect_ = view_rect; 1646 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( 1647 GetWebContents()->GetRenderViewHost()); 1648 if (rvh) 1649 rvh->SendScreenRects(); 1650 } 1651 1652 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) { 1653 SendMessageToEmbedder( 1654 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept)); 1655 } 1656 1657 void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) { 1658 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor)); 1659 } 1660 1661 #if defined(OS_MACOSX) 1662 void BrowserPluginGuest::OnShowPopup( 1663 const ViewHostMsg_ShowPopup_Params& params) { 1664 gfx::Rect translated_bounds(params.bounds); 1665 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin()); 1666 BrowserPluginPopupMenuHelper popup_menu_helper( 1667 embedder_web_contents_->GetRenderViewHost(), 1668 GetWebContents()->GetRenderViewHost()); 1669 popup_menu_helper.ShowPopupMenu(translated_bounds, 1670 params.item_height, 1671 params.item_font_size, 1672 params.selected_item, 1673 params.popup_items, 1674 params.right_aligned, 1675 params.allow_multiple_selection); 1676 } 1677 #endif 1678 1679 void BrowserPluginGuest::OnShowWidget(int route_id, 1680 const gfx::Rect& initial_pos) { 1681 GetWebContents()->ShowCreatedWidget(route_id, initial_pos); 1682 } 1683 1684 void BrowserPluginGuest::OnTakeFocus(bool reverse) { 1685 SendMessageToEmbedder( 1686 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse)); 1687 } 1688 1689 void BrowserPluginGuest::OnUpdateFrameName(int frame_id, 1690 bool is_top_level, 1691 const std::string& name) { 1692 if (!is_top_level) 1693 return; 1694 1695 name_ = name; 1696 SendMessageToEmbedder(new BrowserPluginMsg_UpdatedName(instance_id_, name)); 1697 } 1698 1699 void BrowserPluginGuest::RequestMediaAccessPermission( 1700 WebContents* web_contents, 1701 const MediaStreamRequest& request, 1702 const MediaResponseCallback& callback) { 1703 base::DictionaryValue request_info; 1704 request_info.Set( 1705 browser_plugin::kURL, 1706 base::Value::CreateStringValue(request.security_origin.spec())); 1707 1708 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA, 1709 new MediaRequest(request, callback, this), 1710 request_info); 1711 } 1712 1713 void BrowserPluginGuest::RunJavaScriptDialog( 1714 WebContents* web_contents, 1715 const GURL& origin_url, 1716 const std::string& accept_lang, 1717 JavaScriptMessageType javascript_message_type, 1718 const base::string16& message_text, 1719 const base::string16& default_prompt_text, 1720 const DialogClosedCallback& callback, 1721 bool* did_suppress_message) { 1722 base::DictionaryValue request_info; 1723 request_info.Set( 1724 browser_plugin::kDefaultPromptText, 1725 base::Value::CreateStringValue(UTF16ToUTF8(default_prompt_text))); 1726 request_info.Set( 1727 browser_plugin::kMessageText, 1728 base::Value::CreateStringValue(UTF16ToUTF8(message_text))); 1729 request_info.Set( 1730 browser_plugin::kMessageType, 1731 base::Value::CreateStringValue( 1732 JavaScriptMessageTypeToString(javascript_message_type))); 1733 request_info.Set( 1734 browser_plugin::kURL, 1735 base::Value::CreateStringValue(origin_url.spec())); 1736 1737 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG, 1738 new JavaScriptDialogRequest(callback), 1739 request_info); 1740 } 1741 1742 void BrowserPluginGuest::RunBeforeUnloadDialog( 1743 WebContents* web_contents, 1744 const base::string16& message_text, 1745 bool is_reload, 1746 const DialogClosedCallback& callback) { 1747 // This is called if the guest has a beforeunload event handler. 1748 // This callback allows navigation to proceed. 1749 callback.Run(true, base::string16()); 1750 } 1751 1752 bool BrowserPluginGuest::HandleJavaScriptDialog( 1753 WebContents* web_contents, 1754 bool accept, 1755 const base::string16* prompt_override) { 1756 return false; 1757 } 1758 1759 void BrowserPluginGuest::CancelActiveAndPendingDialogs( 1760 WebContents* web_contents) { 1761 } 1762 1763 void BrowserPluginGuest::WebContentsDestroyed(WebContents* web_contents) { 1764 } 1765 1766 void BrowserPluginGuest::OnUpdateRect( 1767 const ViewHostMsg_UpdateRect_Params& params) { 1768 BrowserPluginMsg_UpdateRect_Params relay_params; 1769 relay_params.view_size = params.view_size; 1770 relay_params.scale_factor = params.scale_factor; 1771 relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack( 1772 params.flags); 1773 relay_params.needs_ack = params.needs_ack; 1774 1775 bool size_changed = last_seen_view_size_ != params.view_size; 1776 gfx::Size old_size = last_seen_view_size_; 1777 last_seen_view_size_ = params.view_size; 1778 1779 if ((auto_size_enabled_ || last_seen_auto_size_enabled_) && 1780 size_changed && delegate_) { 1781 delegate_->SizeChanged(old_size, last_seen_view_size_); 1782 } 1783 last_seen_auto_size_enabled_ = auto_size_enabled_; 1784 1785 // HW accelerated case, acknowledge resize only 1786 if (!params.needs_ack || !damage_buffer_) { 1787 relay_params.damage_buffer_sequence_id = 0; 1788 SendMessageToEmbedder( 1789 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params)); 1790 return; 1791 } 1792 1793 // Only copy damage if the guest is in autosize mode and the guest's view size 1794 // is less than the maximum size or the guest's view size is equal to the 1795 // damage buffer's size and the guest's scale factor is equal to the damage 1796 // buffer's scale factor. 1797 // The scaling change can happen due to asynchronous updates of the DPI on a 1798 // resolution change. 1799 if (((auto_size_enabled_ && InAutoSizeBounds(params.view_size)) || 1800 (params.view_size == damage_view_size())) && 1801 params.scale_factor == damage_buffer_scale_factor()) { 1802 TransportDIB* dib = GetWebContents()->GetRenderProcessHost()-> 1803 GetTransportDIB(params.bitmap); 1804 if (dib) { 1805 size_t guest_damage_buffer_size = 1806 #if defined(OS_WIN) 1807 params.bitmap_rect.width() * 1808 params.bitmap_rect.height() * 4; 1809 #else 1810 dib->size(); 1811 #endif 1812 size_t embedder_damage_buffer_size = damage_buffer_size_; 1813 void* guest_memory = dib->memory(); 1814 void* embedder_memory = damage_buffer_->memory(); 1815 size_t size = std::min(guest_damage_buffer_size, 1816 embedder_damage_buffer_size); 1817 memcpy(embedder_memory, guest_memory, size); 1818 } 1819 } 1820 relay_params.damage_buffer_sequence_id = damage_buffer_sequence_id_; 1821 relay_params.bitmap_rect = params.bitmap_rect; 1822 relay_params.scroll_delta = params.scroll_delta; 1823 relay_params.scroll_rect = params.scroll_rect; 1824 relay_params.copy_rects = params.copy_rects; 1825 1826 SendMessageToEmbedder( 1827 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params)); 1828 } 1829 1830 void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type, 1831 ui::TextInputMode input_mode, 1832 bool can_compose_inline) { 1833 RenderWidgetHostViewPort::FromRWHV( 1834 web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged( 1835 type, input_mode, can_compose_inline); 1836 } 1837 1838 void BrowserPluginGuest::OnImeCancelComposition() { 1839 RenderWidgetHostViewPort::FromRWHV( 1840 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition(); 1841 } 1842 1843 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) 1844 void BrowserPluginGuest::OnImeCompositionRangeChanged( 1845 const gfx::Range& range, 1846 const std::vector<gfx::Rect>& character_bounds) { 1847 RenderWidgetHostViewPort::FromRWHV( 1848 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged( 1849 range, character_bounds); 1850 } 1851 #endif 1852 1853 void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId( 1854 const std::string& request_method, 1855 const base::Callback<void(bool)>& callback, 1856 const std::string& url) { 1857 if (url.empty()) { 1858 callback.Run(false); 1859 return; 1860 } 1861 1862 base::DictionaryValue request_info; 1863 request_info.Set(browser_plugin::kRequestMethod, 1864 base::Value::CreateStringValue(request_method)); 1865 request_info.Set(browser_plugin::kURL, base::Value::CreateStringValue(url)); 1866 1867 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD, 1868 new DownloadRequest(callback), 1869 request_info); 1870 } 1871 1872 } // namespace content 1873