IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / browser_plugin / browser_plugin_guest.cc
blob716c2b7cfeb12e6fb5e0284b92101d433176a33c
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.
5 #include "content/browser/browser_plugin/browser_plugin_guest.h"
7 #include <algorithm>
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"
52 #if defined(OS_MACOSX)
53 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
54 #endif
56 namespace content {
58 // static
59 BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
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;
70 protected:
71 PermissionRequest() {
72 RecordAction(UserMetricsAction("BrowserPlugin.Guest.PermissionRequest"));
74 virtual ~PermissionRequest() {}
75 // Friend RefCounted so that the dtor can be non-public.
76 friend class base::RefCounted<BrowserPluginGuest::PermissionRequest>;
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"));
86 virtual void Respond(bool should_allow,
87 const std::string& user_input) OVERRIDE {
88 callback_.Run(should_allow);
91 private:
92 virtual ~DownloadRequest() {}
93 base::Callback<void(bool)> callback_;
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"));
108 virtual void Respond(bool should_allow,
109 const std::string& user_input) OVERRIDE {
110 base::WeakPtr<BrowserPluginGuest> guest(weak_ptr_factory_->GetWeakPtr());
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;
140 guest->SetGeolocationPermission(callback_, bridge_id_, false);
143 private:
144 virtual ~GeolocationRequest() {}
145 base::Callback<void(bool)> callback_;
146 int bridge_id_;
147 base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory_;
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"));
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>());
175 private:
176 virtual ~MediaRequest() {}
177 MediaStreamRequest request_;
178 MediaResponseCallback callback_;
179 BrowserPluginGuest* guest_;
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"));
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;
203 // If we do not destroy the guest then we allow the new window.
204 if (!should_allow)
205 guest->Destroy();
208 private:
209 virtual ~NewWindowRequest() {}
210 int instance_id_;
211 BrowserPluginGuest* guest_;
214 class BrowserPluginGuest::JavaScriptDialogRequest : public PermissionRequest {
215 public:
216 JavaScriptDialogRequest(const DialogClosedCallback& callback)
217 : callback_(callback) {
218 RecordAction(
219 UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.JSDialog"));
222 virtual void Respond(bool should_allow,
223 const std::string& user_input) OVERRIDE {
224 callback_.Run(should_allow, base::UTF8ToUTF16(user_input));
227 private:
228 virtual ~JavaScriptDialogRequest() {}
229 DialogClosedCallback callback_;
232 class BrowserPluginGuest::PointerLockRequest : public PermissionRequest {
233 public:
234 PointerLockRequest(BrowserPluginGuest* guest)
235 : guest_(guest) {
236 RecordAction(
237 UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.PointerLock"));
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));
246 private:
247 virtual ~PointerLockRequest() {}
248 BrowserPluginGuest* guest_;
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";
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";
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));
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 "";
304 } // namespace
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) {
314 virtual ~EmbedderWebContentsObserver() {
317 // WebContentsObserver:
318 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
319 browser_plugin_guest_->EmbedderDestroyed();
322 virtual void WasShown() OVERRIDE {
323 browser_plugin_guest_->EmbedderVisibilityChanged(true);
326 virtual void WasHidden() OVERRIDE {
327 browser_plugin_guest_->EmbedderVisibilityChanged(false);
330 private:
331 BrowserPluginGuest* browser_plugin_guest_;
333 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
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());
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;
376 delegate_->AddMessageToConsole(level, message, line_no, source_id);
377 return true;
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();
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());
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;
407 web_contents->GetController().LoadURLWithParams(load_url_params);
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;
419 request_itr->second->Respond(should_allow, user_input);
420 permission_request_map_.erase(request_itr);
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;
432 int request_id = ++next_permission_request_id_;
433 permission_request_map_[request_id] = request;
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;
447 return request_id;
450 BrowserPluginGuest* BrowserPluginGuest::CreateNewGuestWindow(
451 const OpenURLParams& params) {
452 BrowserPluginGuestManager* guest_manager =
453 GetWebContents()->GetBrowserPluginGuestManager();
455 // Allocate a new instance ID for the new guest.
456 int instance_id = guest_manager->get_next_instance_id();
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;
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();
477 // Take ownership of |new_guest|.
478 pending_new_windows_.insert(
479 std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
481 // Request permission to show the new window.
482 RequestNewWindowPermission(params.disposition, gfx::Rect(),
483 params.user_gesture, new_guest->GetWebContents());
485 return new_guest;
488 void BrowserPluginGuest::EmbedderDestroyed() {
489 embedder_web_contents_ = NULL;
490 if (delegate_)
491 delegate_->EmbedderDestroyed();
492 Destroy();
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();
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_CompositorFrameSwappedACK,
511 OnCompositorFrameSwappedACK)
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;
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;
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;
562 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
563 // be attached.
564 embedder_web_contents_ = embedder_web_contents;
566 WebContentsViewGuest* new_view =
567 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
568 new_view->OnGuestInitialized(embedder_web_contents->GetView());
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.
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;
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;
592 embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
594 OnSetSize(instance_id_, params.auto_size_params, params.resize_guest_params);
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));
605 if (!params.src.empty()) {
606 // params.src will be validated in BrowserPluginGuest::OnNavigateGuest.
607 OnNavigateGuest(instance_id_, params.src);
610 has_render_view_ = true;
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);
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);
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));
639 if (delegate_)
640 delegate_->DidAttach();
643 BrowserPluginGuest::~BrowserPluginGuest() {
644 while (!pending_messages_.empty()) {
645 delete pending_messages_.front();
646 pending_messages_.pop();
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);
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;
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;
691 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
692 return embedder_web_contents_->GetRenderWidgetHostView();
695 void BrowserPluginGuest::UpdateVisibility() {
696 OnSetVisibility(instance_id_, visible());
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));
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;
716 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
717 embedder_visible_ = visible;
718 UpdateVisibility();
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));
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));
748 void BrowserPluginGuest::LoadProgressChanged(WebContents* contents,
749 double progress) {
750 if (delegate_)
751 delegate_->LoadProgressed(progress);
754 void BrowserPluginGuest::CloseContents(WebContents* source) {
755 if (!delegate_)
756 return;
758 delegate_->Close();
761 JavaScriptDialogManager* BrowserPluginGuest::GetJavaScriptDialogManager() {
762 return this;
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.
772 void BrowserPluginGuest::HandleKeyboardEvent(
773 WebContents* source,
774 const NativeWebKeyboardEvent& event) {
775 if (!attached())
776 return;
778 if (UnlockMouseIfNecessary(event))
779 return;
781 if (delegate_ && delegate_->HandleKeyboardEvent(event))
782 return;
784 if (!embedder_web_contents_->GetDelegate())
785 return;
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);
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;
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;
820 return CreateNewGuestWindow(params)->GetWebContents();
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 = base::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)));
841 void BrowserPluginGuest::RendererUnresponsive(WebContents* source) {
842 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Hung"));
843 if (!delegate_)
844 return;
845 delegate_->RendererUnresponsive();
848 void BrowserPluginGuest::RendererResponsive(WebContents* source) {
849 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Responsive"));
850 if (!delegate_)
851 return;
852 delegate_->RendererResponsive();
855 void BrowserPluginGuest::RunFileChooser(WebContents* web_contents,
856 const FileChooserParams& params) {
857 if (!attached())
858 return;
860 if (!embedder_web_contents_->GetDelegate())
861 return;
863 embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params);
866 bool BrowserPluginGuest::ShouldFocusPageAfterCrash() {
867 // Rather than managing focus in WebContentsImpl::RenderViewReady, we will
868 // manage the focus ourselves.
869 return false;
872 WebContentsImpl* BrowserPluginGuest::GetWebContents() {
873 return static_cast<WebContentsImpl*>(web_contents());
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;
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;
895 return shared_buf.release();
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;
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;
918 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
919 return size.width() <= max_auto_size_.width() &&
920 size.height() <= max_auto_size_.height();
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;
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)));
949 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW,
950 new NewWindowRequest(guest->instance_id(), this),
951 request_info);
954 bool BrowserPluginGuest::UnlockMouseIfNecessary(
955 const NativeWebKeyboardEvent& event) {
956 if (!mouse_locked_)
957 return false;
959 embedder_web_contents()->GotResponseToLockMouseRequest(false);
960 return true;
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;
973 msg->set_routing_id(embedder_web_contents_->GetRoutingID());
974 embedder_web_contents_->Send(msg);
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);
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);
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);
1000 void BrowserPluginGuest::SetDelegate(BrowserPluginGuestDelegate* delegate) {
1001 DCHECK(!delegate_);
1002 delegate_.reset(delegate);
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()));
1013 int request_id =
1014 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION,
1015 new GeolocationRequest(
1016 callback, bridge_id, &weak_ptr_factory_),
1017 request_info);
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;
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;
1030 int request_id = bridge_itr->second;
1031 bridge_id_to_request_id_map_.erase(bridge_itr);
1032 return request_id;
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);
1043 void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback,
1044 int bridge_id,
1045 bool allowed) {
1046 callback.Run(allowed);
1047 RemoveBridgeID(bridge_id);
1050 void BrowserPluginGuest::SendQueuedMessages() {
1051 if (!attached())
1052 return;
1054 while (!pending_messages_.empty()) {
1055 IPC::Message* message = pending_messages_.front();
1056 pending_messages_.pop();
1057 SendMessageToEmbedder(message);
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"));
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 base::ASCIIToUTF16(script));
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_);
1098 Send(new ViewMsg_SetName(routing_id(), name_));
1099 OnSetContentsOpaque(instance_id_, guest_opaque_);
1101 RenderWidgetHostImpl::From(rvh)->
1102 set_hung_renderer_delay_ms(guest_hang_timeout_);
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;
1120 // TODO(fsamuel): Consider whether we should be clearing
1121 // |permission_request_map_| here.
1122 if (delegate_)
1123 delegate_->GuestProcessGone(status);
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);
1140 // static
1141 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
1142 const IPC::Message& message) {
1143 switch (message.type()) {
1144 case BrowserPluginHostMsg_BuffersSwappedACK::ID:
1145 case BrowserPluginHostMsg_CompositorFrameSwappedACK::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;
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;
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;
1211 extra_attach_params_.reset(extra_params.DeepCopy());
1213 // Clear parameters that get inherited from the opener.
1214 params.storage_partition_id.clear();
1215 params.persist_storage = false;
1216 params.src.clear();
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());
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();
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);
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();
1252 Initialize(params, embedder_web_contents);
1254 SendQueuedMessages();
1256 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Attached"));
1259 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
1260 int instance_id,
1261 const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
1262 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
1263 params.output_surface_id,
1264 params.producing_host_id,
1265 params.ack);
1268 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
1269 blink::WebDragStatus drag_status,
1270 const DropData& drop_data,
1271 blink::WebDragOperationsMask mask,
1272 const gfx::Point& location) {
1273 RenderViewHost* host = GetWebContents()->GetRenderViewHost();
1274 switch (drag_status) {
1275 case blink::WebDragStatusEnter:
1276 embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
1277 this);
1278 host->DragTargetDragEnter(drop_data, location, location, mask, 0);
1279 break;
1280 case blink::WebDragStatusOver:
1281 host->DragTargetDragOver(location, location, mask, 0);
1282 break;
1283 case blink::WebDragStatusLeave:
1284 embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
1285 host->DragTargetDragLeave();
1286 break;
1287 case blink::WebDragStatusDrop:
1288 host->DragTargetDrop(location, location, 0);
1289 EndSystemDrag();
1290 break;
1291 case blink::WebDragStatusUnknown:
1292 NOTREACHED();
1296 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
1297 const std::string& name) {
1298 Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
1301 void BrowserPluginGuest::OnImeSetComposition(
1302 int instance_id,
1303 const std::string& text,
1304 const std::vector<blink::WebCompositionUnderline>& underlines,
1305 int selection_start,
1306 int selection_end) {
1307 Send(new ViewMsg_ImeSetComposition(routing_id(),
1308 base::UTF8ToUTF16(text), underlines,
1309 selection_start, selection_end));
1312 void BrowserPluginGuest::OnImeConfirmComposition(
1313 int instance_id,
1314 const std::string& text,
1315 bool keep_selection) {
1316 Send(new ViewMsg_ImeConfirmComposition(routing_id(),
1317 base::UTF8ToUTF16(text),
1318 gfx::Range::InvalidRange(),
1319 keep_selection));
1322 void BrowserPluginGuest::OnExtendSelectionAndDelete(
1323 int instance_id,
1324 int before,
1325 int after) {
1326 Send(new ViewMsg_ExtendSelectionAndDelete(routing_id(), before, after));
1329 void BrowserPluginGuest::OnReclaimCompositorResources(
1330 int instance_id,
1331 int route_id,
1332 uint32 output_surface_id,
1333 int renderer_host_id,
1334 const cc::CompositorFrameAck& ack) {
1335 RenderWidgetHostImpl::SendReclaimCompositorResources(route_id,
1336 output_surface_id,
1337 renderer_host_id,
1338 ack);
1341 void BrowserPluginGuest::OnHandleInputEvent(
1342 int instance_id,
1343 const gfx::Rect& guest_window_rect,
1344 const blink::WebInputEvent* event) {
1345 guest_window_rect_ = guest_window_rect;
1346 // If the embedder's RWHV is destroyed then that means that the embedder's
1347 // window has been closed but the embedder's WebContents has not yet been
1348 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
1349 // if there is a visible embedder.
1350 if (embedder_web_contents_->GetRenderWidgetHostView()) {
1351 guest_screen_rect_ = guest_window_rect;
1352 guest_screen_rect_.Offset(
1353 embedder_web_contents_->GetRenderWidgetHostView()->
1354 GetViewBounds().OffsetFromOrigin());
1356 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
1357 GetWebContents()->GetRenderViewHost());
1359 if (blink::WebInputEvent::isMouseEventType(event->type)) {
1360 guest_rvh->ForwardMouseEvent(
1361 *static_cast<const blink::WebMouseEvent*>(event));
1362 return;
1365 if (event->type == blink::WebInputEvent::MouseWheel) {
1366 guest_rvh->ForwardWheelEvent(
1367 *static_cast<const blink::WebMouseWheelEvent*>(event));
1368 return;
1371 if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
1372 RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
1373 embedder_web_contents_->GetRenderViewHost());
1374 if (!embedder_rvh->GetLastKeyboardEvent())
1375 return;
1376 NativeWebKeyboardEvent keyboard_event(
1377 *embedder_rvh->GetLastKeyboardEvent());
1378 guest_rvh->ForwardKeyboardEvent(keyboard_event);
1379 return;
1382 if (blink::WebInputEvent::isTouchEventType(event->type)) {
1383 guest_rvh->ForwardTouchEventWithLatencyInfo(
1384 *static_cast<const blink::WebTouchEvent*>(event),
1385 ui::LatencyInfo());
1386 return;
1389 if (blink::WebInputEvent::isGestureEventType(event->type)) {
1390 guest_rvh->ForwardGestureEvent(
1391 *static_cast<const blink::WebGestureEvent*>(event));
1392 return;
1396 void BrowserPluginGuest::OnLockMouse(bool user_gesture,
1397 bool last_unlocked_by_target,
1398 bool privileged) {
1399 if (pending_lock_request_) {
1400 // Immediately reject the lock because only one pointerLock may be active
1401 // at a time.
1402 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
1403 return;
1405 pending_lock_request_ = true;
1406 base::DictionaryValue request_info;
1407 request_info.Set(browser_plugin::kUserGesture,
1408 base::Value::CreateBooleanValue(user_gesture));
1409 request_info.Set(browser_plugin::kLastUnlockedBySelf,
1410 base::Value::CreateBooleanValue(last_unlocked_by_target));
1411 request_info.Set(browser_plugin::kURL,
1412 base::Value::CreateStringValue(
1413 web_contents()->GetLastCommittedURL().spec()));
1415 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK,
1416 new PointerLockRequest(this),
1417 request_info);
1420 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
1421 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
1422 pending_lock_request_ = false;
1423 if (succeeded)
1424 mouse_locked_ = true;
1427 void BrowserPluginGuest::OnNavigateGuest(
1428 int instance_id,
1429 const std::string& src) {
1430 GURL url = delegate_ ? delegate_->ResolveURL(src) : GURL(src);
1432 // Do not allow navigating a guest to schemes other than known safe schemes.
1433 // This will block the embedder trying to load unwanted schemes, e.g.
1434 // chrome://settings.
1435 bool scheme_is_blocked =
1436 (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme(
1437 url.scheme()) &&
1438 !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme(
1439 url.scheme())) ||
1440 url.SchemeIs(kJavaScriptScheme);
1441 if (scheme_is_blocked || !url.is_valid()) {
1442 if (delegate_) {
1443 std::string error_type;
1444 base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::",
1445 &error_type);
1446 delegate_->LoadAbort(true /* is_top_level */, url, error_type);
1448 return;
1451 GURL validated_url(url);
1452 GetWebContents()->GetRenderProcessHost()->FilterURL(false, &validated_url);
1453 // As guests do not swap processes on navigation, only navigations to
1454 // normal web URLs are supported. No protocol handlers are installed for
1455 // other schemes (e.g., WebUI or extensions), and no permissions or bindings
1456 // can be granted to the guest process.
1457 LoadURLWithParams(validated_url, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL,
1458 GetWebContents());
1461 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
1462 Destroy();
1465 void BrowserPluginGuest::OnResizeGuest(
1466 int instance_id,
1467 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
1468 if (!params.size_changed)
1469 return;
1470 // BrowserPlugin manages resize flow control itself and does not depend
1471 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
1472 // here. If we are setting the size for the first time before navigating then
1473 // BrowserPluginGuest does not yet have a RenderViewHost.
1474 if (GetWebContents()->GetRenderViewHost()) {
1475 RenderWidgetHostImpl* render_widget_host =
1476 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
1477 render_widget_host->ResetSizeAndRepaintPendingFlags();
1479 if (guest_device_scale_factor_ != params.scale_factor) {
1480 guest_device_scale_factor_ = params.scale_factor;
1481 render_widget_host->NotifyScreenInfoChanged();
1484 // When autosize is turned off and as a result there is a layout change, we
1485 // send a sizechanged event.
1486 if (!auto_size_enabled_ && last_seen_auto_size_enabled_ &&
1487 !params.view_rect.size().IsEmpty() && delegate_) {
1488 delegate_->SizeChanged(last_seen_view_size_, params.view_rect.size());
1489 last_seen_auto_size_enabled_ = false;
1491 // Invalid damage buffer means we are in HW compositing mode,
1492 // so just resize the WebContents and repaint if needed.
1493 if (base::SharedMemory::IsHandleValid(params.damage_buffer_handle))
1494 SetDamageBuffer(params);
1495 if (!params.view_rect.size().IsEmpty())
1496 GetWebContents()->GetView()->SizeContents(params.view_rect.size());
1497 if (params.repaint)
1498 Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size()));
1501 void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
1502 if (focused_ == focused)
1503 return;
1504 focused_ = focused;
1505 Send(new InputMsg_SetFocus(routing_id(), focused));
1506 if (!focused && mouse_locked_)
1507 OnUnlockMouse();
1510 void BrowserPluginGuest::OnSetName(int instance_id, const std::string& name) {
1511 if (name == name_)
1512 return;
1513 name_ = name;
1514 Send(new ViewMsg_SetName(routing_id(), name));
1517 void BrowserPluginGuest::OnSetSize(
1518 int instance_id,
1519 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
1520 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
1521 bool old_auto_size_enabled = auto_size_enabled_;
1522 gfx::Size old_max_size = max_auto_size_;
1523 gfx::Size old_min_size = min_auto_size_;
1524 auto_size_enabled_ = auto_size_params.enable;
1525 max_auto_size_ = auto_size_params.max_size;
1526 min_auto_size_ = auto_size_params.min_size;
1527 if (auto_size_enabled_ && (!old_auto_size_enabled ||
1528 (old_max_size != max_auto_size_) ||
1529 (old_min_size != min_auto_size_))) {
1530 RecordAction(UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
1531 GetWebContents()->GetRenderViewHost()->EnableAutoResize(
1532 min_auto_size_, max_auto_size_);
1533 // TODO(fsamuel): If we're changing autosize parameters, then we force
1534 // the guest to completely repaint itself, because BrowserPlugin has
1535 // allocated a new damage buffer and expects a full frame of pixels.
1536 // Ideally, we shouldn't need to do this because we shouldn't need to
1537 // allocate a new damage buffer unless |max_auto_size_| has changed.
1538 // However, even in that case, layout may not change and so we may
1539 // not get a full frame worth of pixels.
1540 Send(new ViewMsg_Repaint(routing_id(), max_auto_size_));
1541 } else if (!auto_size_enabled_ && old_auto_size_enabled) {
1542 GetWebContents()->GetRenderViewHost()->DisableAutoResize(
1543 resize_guest_params.view_rect.size());
1545 OnResizeGuest(instance_id_, resize_guest_params);
1548 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
1549 int instance_id,
1550 const std::vector<EditCommand>& edit_commands) {
1551 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
1552 edit_commands));
1555 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) {
1556 guest_opaque_ = opaque;
1558 SkBitmap background;
1559 if (!guest_opaque_) {
1560 background.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
1561 unsigned int color = 0;
1562 background.setPixels(&color);
1564 Send(new ViewMsg_SetBackground(routing_id(), background));
1567 void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
1568 guest_visible_ = visible;
1569 if (embedder_visible_ && guest_visible_)
1570 GetWebContents()->WasShown();
1571 else
1572 GetWebContents()->WasHidden();
1575 void BrowserPluginGuest::OnSwapBuffersACK(
1576 int instance_id,
1577 const FrameHostMsg_BuffersSwappedACK_Params& params) {
1578 AcknowledgeBufferPresent(params.gpu_route_id, params.gpu_host_id,
1579 params.mailbox_name, params.sync_point);
1581 // This is only relevant on MACOSX and WIN when threaded compositing
1582 // is not enabled. In threaded mode, above ACK is sufficient.
1583 #if defined(OS_MACOSX) || defined(OS_WIN)
1584 RenderWidgetHostImpl* render_widget_host =
1585 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
1586 render_widget_host->AcknowledgeSwapBuffersToRenderer();
1587 #endif // defined(OS_MACOSX) || defined(OS_WIN)
1590 void BrowserPluginGuest::OnUnlockMouse() {
1591 SendMessageToEmbedder(
1592 new BrowserPluginMsg_SetMouseLock(instance_id(), false));
1595 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
1596 // mouse_locked_ could be false here if the lock attempt was cancelled due
1597 // to window focus, or for various other reasons before the guest was informed
1598 // of the lock's success.
1599 if (mouse_locked_)
1600 Send(new ViewMsg_MouseLockLost(routing_id()));
1601 mouse_locked_ = false;
1604 void BrowserPluginGuest::OnUpdateRectACK(
1605 int instance_id,
1606 bool needs_ack,
1607 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
1608 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
1609 // Only the software path expects an ACK.
1610 if (needs_ack)
1611 Send(new ViewMsg_UpdateRect_ACK(routing_id()));
1612 OnSetSize(instance_id_, auto_size_params, resize_guest_params);
1615 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
1616 int instance_id,
1617 int request_id,
1618 const SkBitmap& bitmap) {
1619 CHECK(copy_request_callbacks_.count(request_id));
1620 if (!copy_request_callbacks_.count(request_id))
1621 return;
1622 const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
1623 callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
1624 copy_request_callbacks_.erase(request_id);
1627 void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
1628 const gfx::Rect& view_rect) {
1629 // The plugin has moved within the embedder without resizing or the
1630 // embedder/container's view rect changing.
1631 guest_window_rect_ = view_rect;
1632 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
1633 GetWebContents()->GetRenderViewHost());
1634 if (rvh)
1635 rvh->SendScreenRects();
1638 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
1639 SendMessageToEmbedder(
1640 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
1643 void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
1644 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
1647 #if defined(OS_MACOSX)
1648 void BrowserPluginGuest::OnShowPopup(
1649 const ViewHostMsg_ShowPopup_Params& params) {
1650 gfx::Rect translated_bounds(params.bounds);
1651 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
1652 BrowserPluginPopupMenuHelper popup_menu_helper(
1653 embedder_web_contents_->GetRenderViewHost(),
1654 GetWebContents()->GetRenderViewHost());
1655 popup_menu_helper.ShowPopupMenu(translated_bounds,
1656 params.item_height,
1657 params.item_font_size,
1658 params.selected_item,
1659 params.popup_items,
1660 params.right_aligned,
1661 params.allow_multiple_selection);
1663 #endif
1665 void BrowserPluginGuest::OnShowWidget(int route_id,
1666 const gfx::Rect& initial_pos) {
1667 GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
1670 void BrowserPluginGuest::OnTakeFocus(bool reverse) {
1671 SendMessageToEmbedder(
1672 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
1675 void BrowserPluginGuest::OnUpdateFrameName(int frame_id,
1676 bool is_top_level,
1677 const std::string& name) {
1678 if (!is_top_level)
1679 return;
1681 name_ = name;
1682 SendMessageToEmbedder(new BrowserPluginMsg_UpdatedName(instance_id_, name));
1685 void BrowserPluginGuest::RequestMediaAccessPermission(
1686 WebContents* web_contents,
1687 const MediaStreamRequest& request,
1688 const MediaResponseCallback& callback) {
1689 base::DictionaryValue request_info;
1690 request_info.Set(
1691 browser_plugin::kURL,
1692 base::Value::CreateStringValue(request.security_origin.spec()));
1694 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA,
1695 new MediaRequest(request, callback, this),
1696 request_info);
1699 void BrowserPluginGuest::RunJavaScriptDialog(
1700 WebContents* web_contents,
1701 const GURL& origin_url,
1702 const std::string& accept_lang,
1703 JavaScriptMessageType javascript_message_type,
1704 const base::string16& message_text,
1705 const base::string16& default_prompt_text,
1706 const DialogClosedCallback& callback,
1707 bool* did_suppress_message) {
1708 base::DictionaryValue request_info;
1709 request_info.Set(
1710 browser_plugin::kDefaultPromptText,
1711 base::Value::CreateStringValue(base::UTF16ToUTF8(default_prompt_text)));
1712 request_info.Set(
1713 browser_plugin::kMessageText,
1714 base::Value::CreateStringValue(base::UTF16ToUTF8(message_text)));
1715 request_info.Set(
1716 browser_plugin::kMessageType,
1717 base::Value::CreateStringValue(
1718 JavaScriptMessageTypeToString(javascript_message_type)));
1719 request_info.Set(
1720 browser_plugin::kURL,
1721 base::Value::CreateStringValue(origin_url.spec()));
1723 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG,
1724 new JavaScriptDialogRequest(callback),
1725 request_info);
1728 void BrowserPluginGuest::RunBeforeUnloadDialog(
1729 WebContents* web_contents,
1730 const base::string16& message_text,
1731 bool is_reload,
1732 const DialogClosedCallback& callback) {
1733 // This is called if the guest has a beforeunload event handler.
1734 // This callback allows navigation to proceed.
1735 callback.Run(true, base::string16());
1738 bool BrowserPluginGuest::HandleJavaScriptDialog(
1739 WebContents* web_contents,
1740 bool accept,
1741 const base::string16* prompt_override) {
1742 return false;
1745 void BrowserPluginGuest::CancelActiveAndPendingDialogs(
1746 WebContents* web_contents) {
1749 void BrowserPluginGuest::WebContentsDestroyed(WebContents* web_contents) {
1752 void BrowserPluginGuest::OnUpdateRect(
1753 const ViewHostMsg_UpdateRect_Params& params) {
1754 BrowserPluginMsg_UpdateRect_Params relay_params;
1755 relay_params.view_size = params.view_size;
1756 relay_params.scale_factor = params.scale_factor;
1757 relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
1758 params.flags);
1759 relay_params.needs_ack = params.needs_ack;
1761 bool size_changed = last_seen_view_size_ != params.view_size;
1762 gfx::Size old_size = last_seen_view_size_;
1763 last_seen_view_size_ = params.view_size;
1765 if ((auto_size_enabled_ || last_seen_auto_size_enabled_) &&
1766 size_changed && delegate_) {
1767 delegate_->SizeChanged(old_size, last_seen_view_size_);
1769 last_seen_auto_size_enabled_ = auto_size_enabled_;
1771 // HW accelerated case, acknowledge resize only
1772 if (!params.needs_ack || !damage_buffer_) {
1773 relay_params.damage_buffer_sequence_id = 0;
1774 SendMessageToEmbedder(
1775 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
1776 return;
1779 // Only copy damage if the guest is in autosize mode and the guest's view size
1780 // is less than the maximum size or the guest's view size is equal to the
1781 // damage buffer's size and the guest's scale factor is equal to the damage
1782 // buffer's scale factor.
1783 // The scaling change can happen due to asynchronous updates of the DPI on a
1784 // resolution change.
1785 if (((auto_size_enabled_ && InAutoSizeBounds(params.view_size)) ||
1786 (params.view_size == damage_view_size())) &&
1787 params.scale_factor == damage_buffer_scale_factor()) {
1788 TransportDIB* dib = GetWebContents()->GetRenderProcessHost()->
1789 GetTransportDIB(params.bitmap);
1790 if (dib) {
1791 size_t guest_damage_buffer_size =
1792 #if defined(OS_WIN)
1793 params.bitmap_rect.width() *
1794 params.bitmap_rect.height() * 4;
1795 #else
1796 dib->size();
1797 #endif
1798 size_t embedder_damage_buffer_size = damage_buffer_size_;
1799 void* guest_memory = dib->memory();
1800 void* embedder_memory = damage_buffer_->memory();
1801 size_t size = std::min(guest_damage_buffer_size,
1802 embedder_damage_buffer_size);
1803 memcpy(embedder_memory, guest_memory, size);
1806 relay_params.damage_buffer_sequence_id = damage_buffer_sequence_id_;
1807 relay_params.bitmap_rect = params.bitmap_rect;
1808 relay_params.scroll_delta = params.scroll_delta;
1809 relay_params.scroll_rect = params.scroll_rect;
1810 relay_params.copy_rects = params.copy_rects;
1812 SendMessageToEmbedder(
1813 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
1816 void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type,
1817 ui::TextInputMode input_mode,
1818 bool can_compose_inline) {
1819 RenderWidgetHostViewPort::FromRWHV(
1820 web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged(
1821 type, input_mode, can_compose_inline);
1824 void BrowserPluginGuest::OnImeCancelComposition() {
1825 RenderWidgetHostViewPort::FromRWHV(
1826 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
1829 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
1830 void BrowserPluginGuest::OnImeCompositionRangeChanged(
1831 const gfx::Range& range,
1832 const std::vector<gfx::Rect>& character_bounds) {
1833 RenderWidgetHostViewPort::FromRWHV(
1834 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
1835 range, character_bounds);
1837 #endif
1839 void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
1840 const std::string& request_method,
1841 const base::Callback<void(bool)>& callback,
1842 const std::string& url) {
1843 if (url.empty()) {
1844 callback.Run(false);
1845 return;
1848 base::DictionaryValue request_info;
1849 request_info.Set(browser_plugin::kRequestMethod,
1850 base::Value::CreateStringValue(request_method));
1851 request_info.Set(browser_plugin::kURL, base::Value::CreateStringValue(url));
1853 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD,
1854 new DownloadRequest(callback),
1855 request_info);
1858 } // namespace content