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"
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/frame_host/render_frame_host_impl.h"
18 #include "content/browser/frame_host/render_widget_host_view_guest.h"
19 #include "content/browser/loader/resource_dispatcher_host_impl.h"
20 #include "content/browser/renderer_host/render_view_host_impl.h"
21 #include "content/browser/renderer_host/render_widget_host_impl.h"
22 #include "content/browser/web_contents/web_contents_impl.h"
23 #include "content/browser/web_contents/web_contents_view_guest.h"
24 #include "content/common/browser_plugin/browser_plugin_constants.h"
25 #include "content/common/browser_plugin/browser_plugin_messages.h"
26 #include "content/common/content_constants_internal.h"
27 #include "content/common/drag_messages.h"
28 #include "content/common/gpu/gpu_messages.h"
29 #include "content/common/input_messages.h"
30 #include "content/common/view_messages.h"
31 #include "content/port/browser/render_view_host_delegate_view.h"
32 #include "content/port/browser/render_widget_host_view_port.h"
33 #include "content/public/browser/browser_context.h"
34 #include "content/public/browser/content_browser_client.h"
35 #include "content/public/browser/geolocation_permission_context.h"
36 #include "content/public/browser/navigation_controller.h"
37 #include "content/public/browser/render_process_host.h"
38 #include "content/public/browser/render_widget_host_view.h"
39 #include "content/public/browser/resource_request_details.h"
40 #include "content/public/browser/user_metrics.h"
41 #include "content/public/browser/web_contents_observer.h"
42 #include "content/public/browser/web_contents_view.h"
43 #include "content/public/common/drop_data.h"
44 #include "content/public/common/media_stream_request.h"
45 #include "content/public/common/result_codes.h"
46 #include "content/public/common/url_constants.h"
47 #include "content/public/common/url_utils.h"
48 #include "net/url_request/url_request.h"
49 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
50 #include "ui/events/keycodes/keyboard_codes.h"
51 #include "ui/surface/transport_dib.h"
52 #include "webkit/common/resource_type.h"
54 #if defined(OS_MACOSX)
55 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
61 BrowserPluginHostFactory
* BrowserPluginGuest::factory_
= NULL
;
63 // Parent class for the various types of permission requests, each of which
64 // should be able to handle the response to their permission request.
65 class BrowserPluginGuest::PermissionRequest
:
66 public base::RefCounted
<BrowserPluginGuest::PermissionRequest
> {
68 void Respond(bool should_allow
, const std::string
& user_input
) {
71 RespondImpl(should_allow
, user_input
);
73 virtual bool AllowedByDefault() const {
77 explicit PermissionRequest(const base::WeakPtr
<BrowserPluginGuest
>& guest
)
80 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest"));
82 virtual ~PermissionRequest() {}
84 virtual void RespondImpl(bool should_allow
,
85 const std::string
& user_input
) = 0;
86 // Friend RefCounted so that the dtor can be non-public.
87 friend class base::RefCounted
<BrowserPluginGuest::PermissionRequest
>;
89 base::WeakPtr
<BrowserPluginGuest
> guest_
;
92 class BrowserPluginGuest::DownloadRequest
: public PermissionRequest
{
94 DownloadRequest(const base::WeakPtr
<BrowserPluginGuest
>& guest
,
95 const base::Callback
<void(bool)>& callback
)
96 : PermissionRequest(guest
),
99 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Download"));
101 virtual void RespondImpl(bool should_allow
,
102 const std::string
& user_input
) OVERRIDE
{
103 callback_
.Run(should_allow
);
107 virtual ~DownloadRequest() {}
108 base::Callback
<void(bool)> callback_
;
111 class BrowserPluginGuest::GeolocationRequest
: public PermissionRequest
{
113 GeolocationRequest(const base::WeakPtr
<BrowserPluginGuest
>& guest
,
114 GeolocationCallback callback
,
116 : PermissionRequest(guest
),
118 bridge_id_(bridge_id
) {
120 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Geolocation"));
123 virtual void RespondImpl(bool should_allow
,
124 const std::string
& user_input
) OVERRIDE
{
125 WebContents
* web_contents
= guest_
->embedder_web_contents();
126 if (should_allow
&& web_contents
) {
127 // If renderer side embedder decides to allow gelocation, we need to check
128 // if the app/embedder itself has geolocation access.
129 BrowserContext
* browser_context
= web_contents
->GetBrowserContext();
130 if (browser_context
) {
131 GeolocationPermissionContext
* geolocation_context
=
132 browser_context
->GetGeolocationPermissionContext();
133 if (geolocation_context
) {
134 base::Callback
<void(bool)> geolocation_callback
= base::Bind(
135 &BrowserPluginGuest::SetGeolocationPermission
,
139 geolocation_context
->RequestGeolocationPermission(
140 web_contents
->GetRenderProcessHost()->GetID(),
141 web_contents
->GetRoutingID(),
142 // The geolocation permission request here is not initiated
143 // through WebGeolocationPermissionRequest. We are only interested
144 // in the fact whether the embedder/app has geolocation
145 // permission. Therefore we use an invalid |bridge_id|.
147 web_contents
->GetLastCommittedURL(),
148 geolocation_callback
);
153 guest_
->SetGeolocationPermission(callback_
, bridge_id_
, false);
157 virtual ~GeolocationRequest() {}
158 base::Callback
<void(bool)> callback_
;
162 class BrowserPluginGuest::MediaRequest
: public PermissionRequest
{
164 MediaRequest(const base::WeakPtr
<BrowserPluginGuest
>& guest
,
165 const MediaStreamRequest
& request
,
166 const MediaResponseCallback
& callback
)
167 : PermissionRequest(guest
),
169 callback_(callback
) {
171 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Media"));
174 virtual void RespondImpl(bool should_allow
,
175 const std::string
& user_input
) OVERRIDE
{
176 WebContentsImpl
* web_contents
= guest_
->embedder_web_contents();
177 if (should_allow
&& web_contents
) {
178 // Re-route the request to the embedder's WebContents; the guest gets the
179 // permission this way.
180 web_contents
->RequestMediaAccessPermission(request_
, callback_
);
183 callback_
.Run(MediaStreamDevices(),
184 MEDIA_DEVICE_INVALID_STATE
,
185 scoped_ptr
<MediaStreamUI
>());
190 virtual ~MediaRequest() {}
191 MediaStreamRequest request_
;
192 MediaResponseCallback callback_
;
195 class BrowserPluginGuest::NewWindowRequest
: public PermissionRequest
{
197 NewWindowRequest(const base::WeakPtr
<BrowserPluginGuest
>& guest
,
199 : PermissionRequest(guest
),
200 instance_id_(instance_id
) {
202 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.NewWindow"));
205 virtual void RespondImpl(bool should_allow
,
206 const std::string
& user_input
) OVERRIDE
{
207 int embedder_render_process_id
=
208 guest_
->embedder_web_contents()->GetRenderProcessHost()->GetID();
209 BrowserPluginGuest
* guest
=
210 guest_
->GetWebContents()->GetBrowserPluginGuestManager()->
211 GetGuestByInstanceID(instance_id_
, embedder_render_process_id
);
213 VLOG(0) << "Guest not found. Instance ID: " << instance_id_
;
217 // If we do not destroy the guest then we allow the new window.
223 virtual ~NewWindowRequest() {}
227 class BrowserPluginGuest::JavaScriptDialogRequest
: public PermissionRequest
{
229 JavaScriptDialogRequest(const base::WeakPtr
<BrowserPluginGuest
>& guest
,
230 const DialogClosedCallback
& callback
)
231 : PermissionRequest(guest
),
232 callback_(callback
) {
234 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.JSDialog"));
237 virtual void RespondImpl(bool should_allow
,
238 const std::string
& user_input
) OVERRIDE
{
239 callback_
.Run(should_allow
, base::UTF8ToUTF16(user_input
));
243 virtual ~JavaScriptDialogRequest() {}
244 DialogClosedCallback callback_
;
247 class BrowserPluginGuest::PointerLockRequest
: public PermissionRequest
{
249 explicit PointerLockRequest(const base::WeakPtr
<BrowserPluginGuest
>& guest
)
250 : PermissionRequest(guest
) {
252 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.PointerLock"));
255 virtual void RespondImpl(bool should_allow
,
256 const std::string
& user_input
) OVERRIDE
{
257 guest_
->SendMessageToEmbedder(
258 new BrowserPluginMsg_SetMouseLock(guest_
->instance_id(), should_allow
));
262 virtual ~PointerLockRequest() {}
266 std::string
WindowOpenDispositionToString(
267 WindowOpenDisposition window_open_disposition
) {
268 switch (window_open_disposition
) {
272 return "save_to_disk";
274 return "current_tab";
275 case NEW_BACKGROUND_TAB
:
276 return "new_background_tab";
277 case NEW_FOREGROUND_TAB
:
278 return "new_foreground_tab";
284 NOTREACHED() << "Unknown Window Open Disposition";
289 std::string
JavaScriptMessageTypeToString(JavaScriptMessageType message_type
) {
290 switch (message_type
) {
291 case JAVASCRIPT_MESSAGE_TYPE_ALERT
:
293 case JAVASCRIPT_MESSAGE_TYPE_CONFIRM
:
295 case JAVASCRIPT_MESSAGE_TYPE_PROMPT
:
298 NOTREACHED() << "Unknown JavaScript Message Type.";
303 // Called on IO thread.
304 static std::string
RetrieveDownloadURLFromRequestId(
305 RenderViewHost
* render_view_host
,
306 int url_request_id
) {
307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
309 int render_process_id
= render_view_host
->GetProcess()->GetID();
310 GlobalRequestID
global_id(render_process_id
, url_request_id
);
311 net::URLRequest
* url_request
=
312 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id
);
314 return url_request
->url().possibly_invalid_spec();
320 class BrowserPluginGuest::EmbedderWebContentsObserver
321 : public WebContentsObserver
{
323 explicit EmbedderWebContentsObserver(BrowserPluginGuest
* guest
)
324 : WebContentsObserver(guest
->embedder_web_contents()),
325 browser_plugin_guest_(guest
) {
328 virtual ~EmbedderWebContentsObserver() {
331 // WebContentsObserver:
332 virtual void WebContentsDestroyed(WebContents
* web_contents
) OVERRIDE
{
333 browser_plugin_guest_
->EmbedderDestroyed();
336 virtual void WasShown() OVERRIDE
{
337 browser_plugin_guest_
->EmbedderVisibilityChanged(true);
340 virtual void WasHidden() OVERRIDE
{
341 browser_plugin_guest_
->EmbedderVisibilityChanged(false);
345 BrowserPluginGuest
* browser_plugin_guest_
;
347 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver
);
350 BrowserPluginGuest::BrowserPluginGuest(
352 bool has_render_view
,
353 WebContentsImpl
* web_contents
,
354 BrowserPluginGuest
* opener
)
355 : WebContentsObserver(web_contents
),
356 embedder_web_contents_(NULL
),
357 instance_id_(instance_id
),
358 damage_buffer_sequence_id_(0),
359 damage_buffer_size_(0),
360 damage_buffer_scale_factor_(1.0f
),
361 guest_device_scale_factor_(1.0f
),
363 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs
)),
365 mouse_locked_(false),
366 pending_lock_request_(false),
367 embedder_visible_(true),
368 auto_size_enabled_(false),
370 next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID
),
371 has_render_view_(has_render_view
),
372 last_seen_auto_size_enabled_(false),
373 is_in_destruction_(false),
374 last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE
),
375 last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT
),
376 last_can_compose_inline_(true),
377 weak_ptr_factory_(this) {
378 DCHECK(web_contents
);
379 web_contents
->SetDelegate(this);
381 opener_
= opener
->AsWeakPtr();
382 GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_
,
386 bool BrowserPluginGuest::AddMessageToConsole(WebContents
* source
,
388 const base::string16
& message
,
390 const base::string16
& source_id
) {
394 delegate_
->AddMessageToConsole(level
, message
, line_no
, source_id
);
398 void BrowserPluginGuest::DestroyUnattachedWindows() {
399 // Destroy() reaches in and removes the BrowserPluginGuest from its opener's
400 // pending_new_windows_ set. To avoid mutating the set while iterating, we
401 // create a copy of the pending new windows set and iterate over the copy.
402 PendingWindowMap
pending_new_windows(pending_new_windows_
);
403 // Clean up unattached new windows opened by this guest.
404 for (PendingWindowMap::const_iterator it
= pending_new_windows
.begin();
405 it
!= pending_new_windows
.end(); ++it
) {
406 it
->first
->Destroy();
408 // All pending windows should be removed from the set after Destroy() is
409 // called on all of them.
410 DCHECK(pending_new_windows_
.empty());
413 void BrowserPluginGuest::LoadURLWithParams(const GURL
& url
,
414 const Referrer
& referrer
,
415 PageTransition transition_type
,
416 WebContents
* web_contents
) {
417 NavigationController::LoadURLParams
load_url_params(url
);
418 load_url_params
.referrer
= referrer
;
419 load_url_params
.transition_type
= transition_type
;
420 load_url_params
.extra_headers
= std::string();
421 if (delegate_
&& delegate_
->IsOverridingUserAgent()) {
422 load_url_params
.override_user_agent
=
423 NavigationController::UA_OVERRIDE_TRUE
;
425 web_contents
->GetController().LoadURLWithParams(load_url_params
);
428 void BrowserPluginGuest::RespondToPermissionRequest(
431 const std::string
& user_input
) {
432 RequestMap::iterator request_itr
= permission_request_map_
.find(request_id
);
433 if (request_itr
== permission_request_map_
.end()) {
434 VLOG(0) << "Not a valid request ID.";
437 request_itr
->second
->Respond(should_allow
, user_input
);
438 permission_request_map_
.erase(request_itr
);
441 int BrowserPluginGuest::RequestPermission(
442 BrowserPluginPermissionType permission_type
,
443 scoped_refptr
<BrowserPluginGuest::PermissionRequest
> request
,
444 const base::DictionaryValue
& request_info
) {
446 // Let the stack unwind before we deny the permission request so that
447 // objects held by the permission request are not destroyed immediately
448 // after creation. This is to allow those same objects to be accessed again
449 // in the same scope without fear of use after freeing.
450 base::MessageLoop::current()->PostTask(
452 base::Bind(&BrowserPluginGuest::PermissionRequest::Respond
,
453 request
, false, ""));
454 return browser_plugin::kInvalidPermissionRequestID
;
457 int request_id
= ++next_permission_request_id_
;
458 permission_request_map_
[request_id
] = request
;
460 BrowserPluginGuestDelegate::PermissionResponseCallback callback
=
461 base::Bind(&BrowserPluginGuest::RespondToPermissionRequest
,
464 // If BrowserPluginGuestDelegate hasn't handled the permission then we simply
465 // perform the default action (which is one of allow or reject) immediately.
466 if (!delegate_
->RequestPermission(
467 permission_type
, request_info
, callback
, request
->AllowedByDefault())) {
468 callback
.Run(request
->AllowedByDefault(), "");
469 return browser_plugin::kInvalidPermissionRequestID
;
475 BrowserPluginGuest
* BrowserPluginGuest::CreateNewGuestWindow(
476 const OpenURLParams
& params
) {
477 BrowserPluginGuestManager
* guest_manager
=
478 GetWebContents()->GetBrowserPluginGuestManager();
480 // Allocate a new instance ID for the new guest.
481 int instance_id
= guest_manager
->get_next_instance_id();
483 // Set the attach params to use the same partition as the opener.
484 // We pull the partition information from the site's URL, which is of the form
485 // guest://site/{persist}?{partition_name}.
486 const GURL
& site_url
= GetWebContents()->GetSiteInstance()->GetSiteURL();
487 BrowserPluginHostMsg_Attach_Params attach_params
;
488 attach_params
.storage_partition_id
= site_url
.query();
489 attach_params
.persist_storage
=
490 site_url
.path().find("persist") != std::string::npos
;
492 // The new guest gets a copy of this guest's extra params so that the content
493 // embedder exposes the same API for this guest as its opener.
494 scoped_ptr
<base::DictionaryValue
> extra_params(
495 extra_attach_params_
->DeepCopy());
496 BrowserPluginGuest
* new_guest
=
497 GetWebContents()->GetBrowserPluginGuestManager()->CreateGuest(
498 GetWebContents()->GetSiteInstance(), instance_id
,
499 attach_params
, extra_params
.Pass());
500 new_guest
->opener_
= AsWeakPtr();
502 // Take ownership of |new_guest|.
503 pending_new_windows_
.insert(
504 std::make_pair(new_guest
, NewWindowInfo(params
.url
, std::string())));
506 // Request permission to show the new window.
507 RequestNewWindowPermission(params
.disposition
, gfx::Rect(),
508 params
.user_gesture
, new_guest
->GetWebContents());
513 base::WeakPtr
<BrowserPluginGuest
> BrowserPluginGuest::AsWeakPtr() {
514 return weak_ptr_factory_
.GetWeakPtr();
517 void BrowserPluginGuest::EmbedderDestroyed() {
518 embedder_web_contents_
= NULL
;
520 delegate_
->EmbedderDestroyed();
524 void BrowserPluginGuest::Destroy() {
525 is_in_destruction_
= true;
526 if (!attached() && opener())
527 opener()->pending_new_windows_
.erase(this);
528 DestroyUnattachedWindows();
529 GetWebContents()->GetBrowserPluginGuestManager()->RemoveGuest(instance_id_
);
530 delete GetWebContents();
533 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
534 const IPC::Message
& message
) {
536 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest
, message
)
537 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK
,
539 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK
,
540 OnCompositorFrameSwappedACK
)
541 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck
,
542 OnCopyFromCompositingSurfaceAck
)
543 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate
,
545 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand
,
546 OnExecuteEditCommand
)
547 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete
,
548 OnExtendSelectionAndDelete
)
549 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent
,
551 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition
,
552 OnImeConfirmComposition
)
553 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition
,
555 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK
, OnLockMouseAck
)
556 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest
, OnNavigateGuest
)
557 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed
, OnPluginDestroyed
)
558 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources
,
559 OnReclaimCompositorResources
)
560 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest
, OnResizeGuest
)
561 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize
, OnSetSize
)
562 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent
,
563 OnSetEditCommandsForNextKeyEvent
)
564 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus
, OnSetFocus
)
565 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetName
, OnSetName
)
566 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque
,
568 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility
, OnSetVisibility
)
569 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK
, OnUnlockMouseAck
)
570 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry
, OnUpdateGeometry
)
571 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateRect_ACK
, OnUpdateRectACK
)
572 IPC_MESSAGE_UNHANDLED(handled
= false)
573 IPC_END_MESSAGE_MAP()
577 void BrowserPluginGuest::Initialize(
578 const BrowserPluginHostMsg_Attach_Params
& params
,
579 WebContentsImpl
* embedder_web_contents
) {
580 focused_
= params
.focused
;
581 guest_visible_
= params
.visible
;
582 guest_opaque_
= params
.opaque
;
583 guest_window_rect_
= params
.resize_guest_params
.view_rect
;
585 if (!params
.name
.empty())
587 auto_size_enabled_
= params
.auto_size_params
.enable
;
588 max_auto_size_
= params
.auto_size_params
.max_size
;
589 min_auto_size_
= params
.auto_size_params
.min_size
;
591 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
593 embedder_web_contents_
= embedder_web_contents
;
595 WebContentsViewGuest
* new_view
=
596 static_cast<WebContentsViewGuest
*>(GetWebContents()->GetView());
597 new_view
->OnGuestInitialized(embedder_web_contents
->GetView());
599 RendererPreferences
* renderer_prefs
=
600 GetWebContents()->GetMutableRendererPrefs();
601 std::string guest_user_agent_override
= renderer_prefs
->user_agent_override
;
602 // Copy renderer preferences (and nothing else) from the embedder's
603 // WebContents to the guest.
605 // For GTK and Aura this is necessary to get proper renderer configuration
606 // values for caret blinking interval, colors related to selection and
608 *renderer_prefs
= *embedder_web_contents_
->GetMutableRendererPrefs();
609 renderer_prefs
->user_agent_override
= guest_user_agent_override
;
611 // We would like the guest to report changes to frame names so that we can
612 // update the BrowserPlugin's corresponding 'name' attribute.
613 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
614 renderer_prefs
->report_frame_name_changes
= true;
615 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
616 // navigations still continue to function inside the app.
617 renderer_prefs
->browser_handles_all_top_level_requests
= false;
618 // Disable "client blocked" error page for browser plugin.
619 renderer_prefs
->disable_client_blocked_error_page
= true;
621 embedder_web_contents_observer_
.reset(new EmbedderWebContentsObserver(this));
623 OnSetSize(instance_id_
, params
.auto_size_params
, params
.resize_guest_params
);
625 // Create a swapped out RenderView for the guest in the embedder render
626 // process, so that the embedder can access the guest's window object.
627 int guest_routing_id
=
628 GetWebContents()->CreateSwappedOutRenderView(
629 embedder_web_contents_
->GetSiteInstance());
630 SendMessageToEmbedder(
631 new BrowserPluginMsg_GuestContentWindowReady(instance_id_
,
634 if (!params
.src
.empty()) {
635 // params.src will be validated in BrowserPluginGuest::OnNavigateGuest.
636 OnNavigateGuest(instance_id_
, params
.src
);
639 has_render_view_
= true;
641 WebPreferences prefs
= GetWebContents()->GetWebkitPrefs();
642 prefs
.navigate_on_drag_drop
= false;
643 if (!embedder_web_contents_
->
644 GetWebkitPrefs().accelerated_compositing_enabled
) {
645 prefs
.accelerated_compositing_enabled
= false;
647 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs
);
649 // Enable input method for guest if it's enabled for the embedder.
650 if (static_cast<RenderViewHostImpl
*>(
651 embedder_web_contents_
->GetRenderViewHost())->input_method_active()) {
652 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
653 GetWebContents()->GetRenderViewHost());
654 guest_rvh
->SetInputMethodActive(true);
657 // Inform the embedder of the guest's information.
658 // We pull the partition information from the site's URL, which is of the form
659 // guest://site/{persist}?{partition_name}.
660 const GURL
& site_url
= GetWebContents()->GetSiteInstance()->GetSiteURL();
661 BrowserPluginMsg_Attach_ACK_Params ack_params
;
662 ack_params
.storage_partition_id
= site_url
.query();
663 ack_params
.persist_storage
=
664 site_url
.path().find("persist") != std::string::npos
;
665 ack_params
.name
= name_
;
666 SendMessageToEmbedder(
667 new BrowserPluginMsg_Attach_ACK(instance_id_
, ack_params
));
670 delegate_
->DidAttach();
673 BrowserPluginGuest::~BrowserPluginGuest() {
674 while (!pending_messages_
.empty()) {
675 delete pending_messages_
.front();
676 pending_messages_
.pop();
681 BrowserPluginGuest
* BrowserPluginGuest::Create(
683 SiteInstance
* guest_site_instance
,
684 WebContentsImpl
* web_contents
,
685 scoped_ptr
<base::DictionaryValue
> extra_params
) {
686 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
687 BrowserPluginGuest
* guest
= NULL
;
689 guest
= factory_
->CreateBrowserPluginGuest(instance_id
, web_contents
);
691 guest
= new BrowserPluginGuest(instance_id
, false, web_contents
, NULL
);
693 guest
->extra_attach_params_
.reset(extra_params
->DeepCopy());
694 web_contents
->SetBrowserPluginGuest(guest
);
695 BrowserPluginGuestDelegate
* delegate
= NULL
;
696 GetContentClient()->browser()->GuestWebContentsCreated(
697 guest_site_instance
, web_contents
, NULL
, &delegate
, extra_params
.Pass());
698 guest
->SetDelegate(delegate
);
703 BrowserPluginGuest
* BrowserPluginGuest::CreateWithOpener(
705 bool has_render_view
,
706 WebContentsImpl
* web_contents
,
707 BrowserPluginGuest
* opener
) {
708 BrowserPluginGuest
* guest
=
709 new BrowserPluginGuest(
710 instance_id
, has_render_view
, web_contents
, opener
);
711 web_contents
->SetBrowserPluginGuest(guest
);
712 BrowserPluginGuestDelegate
* delegate
= NULL
;
713 GetContentClient()->browser()->GuestWebContentsCreated(
714 opener
->GetWebContents()->GetSiteInstance(),
715 web_contents
, opener
->GetWebContents(), &delegate
,
716 scoped_ptr
<base::DictionaryValue
>());
717 guest
->SetDelegate(delegate
);
721 RenderWidgetHostView
* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
724 return embedder_web_contents_
->GetRenderWidgetHostView();
727 void BrowserPluginGuest::UpdateVisibility() {
728 OnSetVisibility(instance_id_
, visible());
731 void BrowserPluginGuest::CopyFromCompositingSurface(
732 gfx::Rect src_subrect
,
734 const base::Callback
<void(bool, const SkBitmap
&)>& callback
) {
735 copy_request_callbacks_
.insert(std::make_pair(++copy_request_id_
, callback
));
736 SendMessageToEmbedder(
737 new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
738 copy_request_id_
, src_subrect
, dst_size
));
742 gfx::Rect
BrowserPluginGuest::ToGuestRect(const gfx::Rect
& bounds
) {
743 gfx::Rect
guest_rect(bounds
);
744 guest_rect
.Offset(guest_window_rect_
.OffsetFromOrigin());
748 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible
) {
749 embedder_visible_
= visible
;
753 void BrowserPluginGuest::AddNewContents(WebContents
* source
,
754 WebContents
* new_contents
,
755 WindowOpenDisposition disposition
,
756 const gfx::Rect
& initial_pos
,
760 *was_blocked
= false;
761 RequestNewWindowPermission(disposition
, initial_pos
, user_gesture
,
762 static_cast<WebContentsImpl
*>(new_contents
));
765 void BrowserPluginGuest::CanDownload(
766 RenderViewHost
* render_view_host
,
768 const std::string
& request_method
,
769 const base::Callback
<void(bool)>& callback
) {
770 BrowserThread::PostTaskAndReplyWithResult(
771 BrowserThread::IO
, FROM_HERE
,
772 base::Bind(&RetrieveDownloadURLFromRequestId
,
773 render_view_host
, request_id
),
774 base::Bind(&BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId
,
775 weak_ptr_factory_
.GetWeakPtr(),
780 void BrowserPluginGuest::LoadProgressChanged(WebContents
* contents
,
783 delegate_
->LoadProgressed(progress
);
786 void BrowserPluginGuest::CloseContents(WebContents
* source
) {
793 JavaScriptDialogManager
* BrowserPluginGuest::GetJavaScriptDialogManager() {
797 ColorChooser
* BrowserPluginGuest::OpenColorChooser(
798 WebContents
* web_contents
,
800 const std::vector
<ColorSuggestion
>& suggestions
) {
801 if (!embedder_web_contents_
|| !embedder_web_contents_
->GetDelegate())
803 return embedder_web_contents_
->GetDelegate()->OpenColorChooser(
804 web_contents
, color
, suggestions
);
807 bool BrowserPluginGuest::HandleContextMenu(const ContextMenuParams
& params
) {
808 // TODO(fsamuel): We show the regular page context menu handler for now until
809 // we implement the Apps Context Menu API for Browser Plugin (see
810 // http://crbug.com/140315).
811 return false; // Will be handled by WebContentsViewGuest.
814 void BrowserPluginGuest::HandleKeyboardEvent(
816 const NativeWebKeyboardEvent
& event
) {
820 if (UnlockMouseIfNecessary(event
))
823 if (delegate_
&& delegate_
->HandleKeyboardEvent(event
))
826 if (!embedder_web_contents_
->GetDelegate())
829 // Send the unhandled keyboard events back to the embedder to reprocess them.
830 // TODO(fsamuel): This introduces the possibility of out-of-order keyboard
831 // events because the guest may be arbitrarily delayed when responding to
832 // keyboard events. In that time, the embedder may have received and processed
833 // additional key events. This needs to be fixed as soon as possible.
834 // See http://crbug.com/229882.
835 embedder_web_contents_
->GetDelegate()->HandleKeyboardEvent(
836 web_contents(), event
);
839 void BrowserPluginGuest::SetZoom(double zoom_factor
) {
841 delegate_
->SetZoom(zoom_factor
);
844 void BrowserPluginGuest::FindReply(WebContents
* contents
,
846 int number_of_matches
,
847 const gfx::Rect
& selection_rect
,
848 int active_match_ordinal
,
853 // |selection_rect| is updated to incorporate embedder coordinates.
854 delegate_
->FindReply(request_id
, number_of_matches
,
855 ToGuestRect(selection_rect
),
856 active_match_ordinal
, final_update
);
859 WebContents
* BrowserPluginGuest::OpenURLFromTab(WebContents
* source
,
860 const OpenURLParams
& params
) {
861 // If the guest wishes to navigate away prior to attachment then we save the
862 // navigation to perform upon attachment. Navigation initializes a lot of
863 // state that assumes an embedder exists, such as RenderWidgetHostViewGuest.
864 // Navigation also resumes resource loading which we don't want to allow
867 PendingWindowMap::iterator it
= opener()->pending_new_windows_
.find(this);
868 if (it
== opener()->pending_new_windows_
.end())
870 const NewWindowInfo
& old_target_url
= it
->second
;
871 NewWindowInfo
new_window_info(params
.url
, old_target_url
.name
);
872 new_window_info
.changed
= new_window_info
.url
!= old_target_url
.url
;
873 it
->second
= new_window_info
;
876 if (params
.disposition
== CURRENT_TAB
) {
877 // This can happen for cross-site redirects.
878 LoadURLWithParams(params
.url
, params
.referrer
, params
.transition
, source
);
882 return CreateNewGuestWindow(params
)->GetWebContents();
885 void BrowserPluginGuest::WebContentsCreated(WebContents
* source_contents
,
886 int opener_render_frame_id
,
887 const base::string16
& frame_name
,
888 const GURL
& target_url
,
889 WebContents
* new_contents
) {
890 WebContentsImpl
* new_contents_impl
=
891 static_cast<WebContentsImpl
*>(new_contents
);
892 BrowserPluginGuest
* guest
= new_contents_impl
->GetBrowserPluginGuest();
893 guest
->opener_
= AsWeakPtr();
894 std::string guest_name
= base::UTF16ToUTF8(frame_name
);
895 guest
->name_
= guest_name
;
896 // Take ownership of the new guest until it is attached to the embedder's DOM
897 // tree to avoid leaking a guest if this guest is destroyed before attaching
899 pending_new_windows_
.insert(
900 std::make_pair(guest
, NewWindowInfo(target_url
, guest_name
)));
903 void BrowserPluginGuest::RendererUnresponsive(WebContents
* source
) {
904 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Hung"));
907 delegate_
->RendererUnresponsive();
910 void BrowserPluginGuest::RendererResponsive(WebContents
* source
) {
911 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Responsive"));
914 delegate_
->RendererResponsive();
917 void BrowserPluginGuest::RunFileChooser(WebContents
* web_contents
,
918 const FileChooserParams
& params
) {
922 if (!embedder_web_contents_
->GetDelegate())
925 embedder_web_contents_
->GetDelegate()->RunFileChooser(web_contents
, params
);
928 bool BrowserPluginGuest::ShouldFocusPageAfterCrash() {
929 // Rather than managing focus in WebContentsImpl::RenderViewReady, we will
930 // manage the focus ourselves.
934 WebContentsImpl
* BrowserPluginGuest::GetWebContents() {
935 return static_cast<WebContentsImpl
*>(web_contents());
938 base::SharedMemory
* BrowserPluginGuest::GetDamageBufferFromEmbedder(
939 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
941 LOG(WARNING
) << "Attempting to map a damage buffer prior to attachment.";
945 base::ProcessHandle handle
=
946 embedder_web_contents_
->GetRenderProcessHost()->GetHandle();
947 scoped_ptr
<base::SharedMemory
> shared_buf(
948 new base::SharedMemory(params
.damage_buffer_handle
, false, handle
));
949 #elif defined(OS_POSIX)
950 scoped_ptr
<base::SharedMemory
> shared_buf(
951 new base::SharedMemory(params
.damage_buffer_handle
, false));
953 if (!shared_buf
->Map(params
.damage_buffer_size
)) {
954 LOG(WARNING
) << "Unable to map the embedder's damage buffer.";
957 return shared_buf
.release();
960 void BrowserPluginGuest::SetDamageBuffer(
961 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
962 damage_buffer_
.reset(GetDamageBufferFromEmbedder(params
));
963 // Sanity check: Verify that we've correctly shared the damage buffer memory
964 // between the embedder and browser processes.
965 DCHECK(!damage_buffer_
||
966 *static_cast<unsigned int*>(damage_buffer_
->memory()) == 0xdeadbeef);
967 damage_buffer_sequence_id_
= params
.damage_buffer_sequence_id
;
968 damage_buffer_size_
= params
.damage_buffer_size
;
969 damage_view_size_
= params
.view_rect
.size();
970 damage_buffer_scale_factor_
= params
.scale_factor
;
973 gfx::Point
BrowserPluginGuest::GetScreenCoordinates(
974 const gfx::Point
& relative_position
) const {
975 gfx::Point
screen_pos(relative_position
);
976 screen_pos
+= guest_window_rect_
.OffsetFromOrigin();
980 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size
& size
) const {
981 return size
.width() <= max_auto_size_
.width() &&
982 size
.height() <= max_auto_size_
.height();
985 void BrowserPluginGuest::RequestNewWindowPermission(
986 WindowOpenDisposition disposition
,
987 const gfx::Rect
& initial_bounds
,
989 WebContentsImpl
* new_contents
) {
990 BrowserPluginGuest
* guest
= new_contents
->GetBrowserPluginGuest();
991 PendingWindowMap::iterator it
= pending_new_windows_
.find(guest
);
992 if (it
== pending_new_windows_
.end())
994 const NewWindowInfo
& new_window_info
= it
->second
;
996 base::DictionaryValue request_info
;
997 request_info
.Set(browser_plugin::kInitialHeight
,
998 base::Value::CreateIntegerValue(initial_bounds
.height()));
999 request_info
.Set(browser_plugin::kInitialWidth
,
1000 base::Value::CreateIntegerValue(initial_bounds
.width()));
1001 request_info
.Set(browser_plugin::kTargetURL
,
1002 base::Value::CreateStringValue(new_window_info
.url
.spec()));
1003 request_info
.Set(browser_plugin::kName
,
1004 base::Value::CreateStringValue(new_window_info
.name
));
1005 request_info
.Set(browser_plugin::kWindowID
,
1006 base::Value::CreateIntegerValue(guest
->instance_id()));
1007 request_info
.Set(browser_plugin::kWindowOpenDisposition
,
1008 base::Value::CreateStringValue(
1009 WindowOpenDispositionToString(disposition
)));
1011 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW
,
1012 new NewWindowRequest(weak_ptr_factory_
.GetWeakPtr(),
1013 guest
->instance_id()),
1017 bool BrowserPluginGuest::UnlockMouseIfNecessary(
1018 const NativeWebKeyboardEvent
& event
) {
1022 embedder_web_contents()->GotResponseToLockMouseRequest(false);
1026 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message
* msg
) {
1028 // Some pages such as data URLs, javascript URLs, and about:blank
1029 // do not load external resources and so they load prior to attachment.
1030 // As a result, we must save all these IPCs until attachment and then
1031 // forward them so that the embedder gets a chance to see and process
1033 pending_messages_
.push(msg
);
1036 msg
->set_routing_id(embedder_web_contents_
->GetRoutingID());
1037 embedder_web_contents_
->Send(msg
);
1040 void BrowserPluginGuest::DragSourceEndedAt(int client_x
, int client_y
,
1041 int screen_x
, int screen_y
, blink::WebDragOperation operation
) {
1042 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x
, client_y
,
1043 screen_x
, screen_y
, operation
);
1046 void BrowserPluginGuest::DragSourceMovedTo(int client_x
, int client_y
,
1047 int screen_x
, int screen_y
) {
1048 web_contents()->GetRenderViewHost()->DragSourceMovedTo(client_x
, client_y
,
1049 screen_x
, screen_y
);
1052 void BrowserPluginGuest::EndSystemDrag() {
1053 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
1054 GetWebContents()->GetRenderViewHost());
1055 guest_rvh
->DragSourceSystemDragEnded();
1058 void BrowserPluginGuest::SetDelegate(BrowserPluginGuestDelegate
* delegate
) {
1060 delegate_
.reset(delegate
);
1063 void BrowserPluginGuest::AskEmbedderForGeolocationPermission(
1065 const GURL
& requesting_frame
,
1066 const GeolocationCallback
& callback
) {
1067 base::DictionaryValue request_info
;
1068 request_info
.Set(browser_plugin::kURL
,
1069 base::Value::CreateStringValue(requesting_frame
.spec()));
1072 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION
,
1073 new GeolocationRequest(weak_ptr_factory_
.GetWeakPtr(),
1078 DCHECK(bridge_id_to_request_id_map_
.find(bridge_id
) ==
1079 bridge_id_to_request_id_map_
.end());
1080 bridge_id_to_request_id_map_
[bridge_id
] = request_id
;
1083 int BrowserPluginGuest::RemoveBridgeID(int bridge_id
) {
1084 std::map
<int, int>::iterator bridge_itr
=
1085 bridge_id_to_request_id_map_
.find(bridge_id
);
1086 if (bridge_itr
== bridge_id_to_request_id_map_
.end())
1087 return browser_plugin::kInvalidPermissionRequestID
;
1089 int request_id
= bridge_itr
->second
;
1090 bridge_id_to_request_id_map_
.erase(bridge_itr
);
1094 void BrowserPluginGuest::CancelGeolocationRequest(int bridge_id
) {
1095 int request_id
= RemoveBridgeID(bridge_id
);
1096 RequestMap::iterator request_itr
= permission_request_map_
.find(request_id
);
1097 if (request_itr
== permission_request_map_
.end())
1099 permission_request_map_
.erase(request_itr
);
1102 void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback
,
1105 callback
.Run(allowed
);
1106 RemoveBridgeID(bridge_id
);
1109 void BrowserPluginGuest::SendQueuedMessages() {
1113 while (!pending_messages_
.empty()) {
1114 IPC::Message
* message
= pending_messages_
.front();
1115 pending_messages_
.pop();
1116 SendMessageToEmbedder(message
);
1120 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
1122 const base::string16
& frame_unique_name
,
1125 PageTransition transition_type
,
1126 RenderViewHost
* render_view_host
) {
1127 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
1130 void BrowserPluginGuest::DidStopLoading(RenderViewHost
* render_view_host
) {
1131 bool enable_dragdrop
= delegate_
&& delegate_
->IsDragAndDropEnabled();
1132 if (!enable_dragdrop
) {
1133 // Initiating a drag from inside a guest is currently not supported without
1134 // the kEnableBrowserPluginDragDrop flag on a linux platform. So inject some
1135 // JS to disable it. http://crbug.com/161112
1136 const char script
[] = "window.addEventListener('dragstart', function() { "
1137 " window.event.preventDefault(); "
1139 render_view_host
->GetMainFrame()->ExecuteJavaScript(
1140 base::ASCIIToUTF16(script
));
1144 void BrowserPluginGuest::RenderViewReady() {
1145 RenderViewHost
* rvh
= GetWebContents()->GetRenderViewHost();
1146 // The guest RenderView should always live in a guest process.
1147 CHECK(rvh
->GetProcess()->IsGuest());
1148 // TODO(fsamuel): Investigate whether it's possible to update state earlier
1149 // here (see http://crbug.com/158151).
1150 Send(new InputMsg_SetFocus(routing_id(), focused_
));
1152 if (auto_size_enabled_
)
1153 rvh
->EnableAutoResize(min_auto_size_
, max_auto_size_
);
1155 rvh
->DisableAutoResize(damage_view_size_
);
1157 Send(new ViewMsg_SetName(routing_id(), name_
));
1158 OnSetContentsOpaque(instance_id_
, guest_opaque_
);
1160 RenderWidgetHostImpl::From(rvh
)->
1161 set_hung_renderer_delay_ms(guest_hang_timeout_
);
1164 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status
) {
1165 SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(instance_id()));
1167 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED
:
1168 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
1170 case base::TERMINATION_STATUS_PROCESS_CRASHED
:
1171 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
1173 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION
:
1175 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
1180 // TODO(fsamuel): Consider whether we should be clearing
1181 // |permission_request_map_| here.
1183 delegate_
->GuestProcessGone(status
);
1187 void BrowserPluginGuest::AcknowledgeBufferPresent(
1190 const gpu::Mailbox
& mailbox
,
1191 uint32 sync_point
) {
1192 AcceleratedSurfaceMsg_BufferPresented_Params ack_params
;
1193 ack_params
.mailbox
= mailbox
;
1194 ack_params
.sync_point
= sync_point
;
1195 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id
,
1201 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
1202 const IPC::Message
& message
) {
1203 switch (message
.type()) {
1204 case BrowserPluginHostMsg_BuffersSwappedACK::ID
:
1205 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID
:
1206 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID
:
1207 case BrowserPluginHostMsg_DragStatusUpdate::ID
:
1208 case BrowserPluginHostMsg_ExecuteEditCommand::ID
:
1209 case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID
:
1210 case BrowserPluginHostMsg_HandleInputEvent::ID
:
1211 case BrowserPluginHostMsg_ImeConfirmComposition::ID
:
1212 case BrowserPluginHostMsg_ImeSetComposition::ID
:
1213 case BrowserPluginHostMsg_LockMouse_ACK::ID
:
1214 case BrowserPluginHostMsg_NavigateGuest::ID
:
1215 case BrowserPluginHostMsg_PluginDestroyed::ID
:
1216 case BrowserPluginHostMsg_ReclaimCompositorResources::ID
:
1217 case BrowserPluginHostMsg_ResizeGuest::ID
:
1218 case BrowserPluginHostMsg_SetAutoSize::ID
:
1219 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID
:
1220 case BrowserPluginHostMsg_SetFocus::ID
:
1221 case BrowserPluginHostMsg_SetName::ID
:
1222 case BrowserPluginHostMsg_SetContentsOpaque::ID
:
1223 case BrowserPluginHostMsg_SetVisibility::ID
:
1224 case BrowserPluginHostMsg_UnlockMouse_ACK::ID
:
1225 case BrowserPluginHostMsg_UpdateGeometry::ID
:
1226 case BrowserPluginHostMsg_UpdateRect_ACK::ID
:
1233 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message
& message
) {
1234 bool handled
= true;
1235 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest
, message
)
1236 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers
,
1237 OnHasTouchEventHandlers
)
1238 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse
, OnLockMouse
)
1239 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor
, OnSetCursor
)
1240 #if defined(OS_MACOSX)
1241 // MacOSX creates and populates platform-specific select drop-down menus
1242 // whereas other platforms merely create a popup window that the guest
1243 // renderer process paints inside.
1244 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup
, OnShowPopup
)
1246 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget
, OnShowWidget
)
1247 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus
, OnTakeFocus
)
1248 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged
,
1249 OnTextInputTypeChanged
)
1250 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition
,
1251 OnImeCancelComposition
)
1252 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
1253 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged
,
1254 OnImeCompositionRangeChanged
)
1256 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse
, OnUnlockMouse
)
1257 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName
, OnUpdateFrameName
)
1258 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect
, OnUpdateRect
)
1259 IPC_MESSAGE_UNHANDLED(handled
= false)
1260 IPC_END_MESSAGE_MAP()
1264 void BrowserPluginGuest::Attach(
1265 WebContentsImpl
* embedder_web_contents
,
1266 BrowserPluginHostMsg_Attach_Params params
,
1267 const base::DictionaryValue
& extra_params
) {
1271 extra_attach_params_
.reset(extra_params
.DeepCopy());
1273 // Clear parameters that get inherited from the opener.
1274 params
.storage_partition_id
.clear();
1275 params
.persist_storage
= false;
1278 // If a RenderView has already been created for this new window, then we need
1279 // to initialize the browser-side state now so that the RenderFrameHostManager
1280 // does not create a new RenderView on navigation.
1281 if (has_render_view_
) {
1282 static_cast<RenderViewHostImpl
*>(
1283 GetWebContents()->GetRenderViewHost())->Init();
1284 WebContentsViewGuest
* new_view
=
1285 static_cast<WebContentsViewGuest
*>(GetWebContents()->GetView());
1286 new_view
->CreateViewForWidget(web_contents()->GetRenderViewHost());
1289 // We need to do a navigation here if the target URL has changed between
1290 // the time the WebContents was created and the time it was attached.
1291 // We also need to do an initial navigation if a RenderView was never
1292 // created for the new window in cases where there is no referrer.
1293 PendingWindowMap::iterator it
= opener()->pending_new_windows_
.find(this);
1294 if (it
!= opener()->pending_new_windows_
.end()) {
1295 const NewWindowInfo
& new_window_info
= it
->second
;
1296 if (new_window_info
.changed
|| !has_render_view_
)
1297 params
.src
= it
->second
.url
.spec();
1302 // Once a new guest is attached to the DOM of the embedder page, then the
1303 // lifetime of the new guest is no longer managed by the opener guest.
1304 opener()->pending_new_windows_
.erase(this);
1306 // The guest's frame name takes precedence over the BrowserPlugin's name.
1307 // The guest's frame name is assigned in
1308 // BrowserPluginGuest::WebContentsCreated.
1310 params
.name
.clear();
1312 Initialize(params
, embedder_web_contents
);
1314 SendQueuedMessages();
1316 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
1319 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
1321 const FrameHostMsg_CompositorFrameSwappedACK_Params
& params
) {
1322 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params
.producing_route_id
,
1323 params
.output_surface_id
,
1324 params
.producing_host_id
,
1328 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id
,
1329 blink::WebDragStatus drag_status
,
1330 const DropData
& drop_data
,
1331 blink::WebDragOperationsMask mask
,
1332 const gfx::Point
& location
) {
1333 RenderViewHost
* host
= GetWebContents()->GetRenderViewHost();
1334 switch (drag_status
) {
1335 case blink::WebDragStatusEnter
:
1336 embedder_web_contents_
->GetBrowserPluginEmbedder()->DragEnteredGuest(
1338 host
->DragTargetDragEnter(drop_data
, location
, location
, mask
, 0);
1340 case blink::WebDragStatusOver
:
1341 host
->DragTargetDragOver(location
, location
, mask
, 0);
1343 case blink::WebDragStatusLeave
:
1344 embedder_web_contents_
->GetBrowserPluginEmbedder()->DragLeftGuest(this);
1345 host
->DragTargetDragLeave();
1347 case blink::WebDragStatusDrop
:
1348 host
->DragTargetDrop(location
, location
, 0);
1351 case blink::WebDragStatusUnknown
:
1356 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id
,
1357 const std::string
& name
) {
1358 Send(new InputMsg_ExecuteEditCommand(routing_id(), name
, std::string()));
1361 void BrowserPluginGuest::OnImeSetComposition(
1363 const std::string
& text
,
1364 const std::vector
<blink::WebCompositionUnderline
>& underlines
,
1365 int selection_start
,
1366 int selection_end
) {
1367 Send(new ViewMsg_ImeSetComposition(routing_id(),
1368 base::UTF8ToUTF16(text
), underlines
,
1369 selection_start
, selection_end
));
1372 void BrowserPluginGuest::OnImeConfirmComposition(
1374 const std::string
& text
,
1375 bool keep_selection
) {
1376 Send(new ViewMsg_ImeConfirmComposition(routing_id(),
1377 base::UTF8ToUTF16(text
),
1378 gfx::Range::InvalidRange(),
1382 void BrowserPluginGuest::OnExtendSelectionAndDelete(
1386 RenderFrameHostImpl
* rfh
= static_cast<RenderFrameHostImpl
*>(
1387 web_contents()->GetFocusedFrame());
1389 rfh
->ExtendSelectionAndDelete(before
, after
);
1392 void BrowserPluginGuest::OnReclaimCompositorResources(
1394 const FrameHostMsg_ReclaimCompositorResources_Params
& params
) {
1395 RenderWidgetHostImpl::SendReclaimCompositorResources(params
.route_id
,
1396 params
.output_surface_id
,
1397 params
.renderer_host_id
,
1401 void BrowserPluginGuest::OnHandleInputEvent(
1403 const gfx::Rect
& guest_window_rect
,
1404 const blink::WebInputEvent
* event
) {
1405 guest_window_rect_
= guest_window_rect
;
1406 // If the embedder's RWHV is destroyed then that means that the embedder's
1407 // window has been closed but the embedder's WebContents has not yet been
1408 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
1409 // if there is a visible embedder.
1410 if (embedder_web_contents_
->GetRenderWidgetHostView()) {
1411 guest_screen_rect_
= guest_window_rect
;
1412 guest_screen_rect_
.Offset(
1413 embedder_web_contents_
->GetRenderWidgetHostView()->
1414 GetViewBounds().OffsetFromOrigin());
1416 RenderViewHostImpl
* guest_rvh
= static_cast<RenderViewHostImpl
*>(
1417 GetWebContents()->GetRenderViewHost());
1419 if (blink::WebInputEvent::isMouseEventType(event
->type
)) {
1420 guest_rvh
->ForwardMouseEvent(
1421 *static_cast<const blink::WebMouseEvent
*>(event
));
1425 if (event
->type
== blink::WebInputEvent::MouseWheel
) {
1426 guest_rvh
->ForwardWheelEvent(
1427 *static_cast<const blink::WebMouseWheelEvent
*>(event
));
1431 if (blink::WebInputEvent::isKeyboardEventType(event
->type
)) {
1432 RenderViewHostImpl
* embedder_rvh
= static_cast<RenderViewHostImpl
*>(
1433 embedder_web_contents_
->GetRenderViewHost());
1434 if (!embedder_rvh
->GetLastKeyboardEvent())
1436 NativeWebKeyboardEvent
keyboard_event(
1437 *embedder_rvh
->GetLastKeyboardEvent());
1438 guest_rvh
->ForwardKeyboardEvent(keyboard_event
);
1442 if (blink::WebInputEvent::isTouchEventType(event
->type
)) {
1443 guest_rvh
->ForwardTouchEventWithLatencyInfo(
1444 *static_cast<const blink::WebTouchEvent
*>(event
),
1449 if (blink::WebInputEvent::isGestureEventType(event
->type
)) {
1450 guest_rvh
->ForwardGestureEvent(
1451 *static_cast<const blink::WebGestureEvent
*>(event
));
1456 void BrowserPluginGuest::OnLockMouse(bool user_gesture
,
1457 bool last_unlocked_by_target
,
1459 if (pending_lock_request_
) {
1460 // Immediately reject the lock because only one pointerLock may be active
1462 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
1465 pending_lock_request_
= true;
1466 base::DictionaryValue request_info
;
1467 request_info
.Set(browser_plugin::kUserGesture
,
1468 base::Value::CreateBooleanValue(user_gesture
));
1469 request_info
.Set(browser_plugin::kLastUnlockedBySelf
,
1470 base::Value::CreateBooleanValue(last_unlocked_by_target
));
1471 request_info
.Set(browser_plugin::kURL
,
1472 base::Value::CreateStringValue(
1473 web_contents()->GetLastCommittedURL().spec()));
1475 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK
,
1476 new PointerLockRequest(weak_ptr_factory_
.GetWeakPtr()),
1480 void BrowserPluginGuest::OnLockMouseAck(int instance_id
, bool succeeded
) {
1481 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded
));
1482 pending_lock_request_
= false;
1484 mouse_locked_
= true;
1487 void BrowserPluginGuest::OnNavigateGuest(
1489 const std::string
& src
) {
1490 GURL url
= delegate_
? delegate_
->ResolveURL(src
) : GURL(src
);
1492 // Do not allow navigating a guest to schemes other than known safe schemes.
1493 // This will block the embedder trying to load unwanted schemes, e.g.
1494 // chrome://settings.
1495 bool scheme_is_blocked
=
1496 (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme(
1498 !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme(
1500 url
.SchemeIs(kJavaScriptScheme
);
1501 if (scheme_is_blocked
|| !url
.is_valid()) {
1503 std::string error_type
;
1504 base::RemoveChars(net::ErrorToString(net::ERR_ABORTED
), "net::",
1506 delegate_
->LoadAbort(true /* is_top_level */, url
, error_type
);
1511 GURL
validated_url(url
);
1512 GetWebContents()->GetRenderProcessHost()->FilterURL(false, &validated_url
);
1513 // As guests do not swap processes on navigation, only navigations to
1514 // normal web URLs are supported. No protocol handlers are installed for
1515 // other schemes (e.g., WebUI or extensions), and no permissions or bindings
1516 // can be granted to the guest process.
1517 LoadURLWithParams(validated_url
, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL
,
1521 void BrowserPluginGuest::OnPluginDestroyed(int instance_id
) {
1525 void BrowserPluginGuest::OnResizeGuest(
1527 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
1528 if (!params
.size_changed
)
1530 // BrowserPlugin manages resize flow control itself and does not depend
1531 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
1532 // here. If we are setting the size for the first time before navigating then
1533 // BrowserPluginGuest does not yet have a RenderViewHost.
1534 if (GetWebContents()->GetRenderViewHost()) {
1535 RenderWidgetHostImpl
* render_widget_host
=
1536 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
1537 render_widget_host
->ResetSizeAndRepaintPendingFlags();
1539 if (guest_device_scale_factor_
!= params
.scale_factor
) {
1540 guest_device_scale_factor_
= params
.scale_factor
;
1541 render_widget_host
->NotifyScreenInfoChanged();
1544 // When autosize is turned off and as a result there is a layout change, we
1545 // send a sizechanged event.
1546 if (!auto_size_enabled_
&& last_seen_auto_size_enabled_
&&
1547 !params
.view_rect
.size().IsEmpty() && delegate_
) {
1548 delegate_
->SizeChanged(last_seen_view_size_
, params
.view_rect
.size());
1549 last_seen_auto_size_enabled_
= false;
1551 // Invalid damage buffer means we are in HW compositing mode,
1552 // so just resize the WebContents and repaint if needed.
1553 if (base::SharedMemory::IsHandleValid(params
.damage_buffer_handle
))
1554 SetDamageBuffer(params
);
1555 if (!params
.view_rect
.size().IsEmpty())
1556 GetWebContents()->GetView()->SizeContents(params
.view_rect
.size());
1558 Send(new ViewMsg_Repaint(routing_id(), params
.view_rect
.size()));
1561 void BrowserPluginGuest::OnSetFocus(int instance_id
, bool focused
) {
1563 Send(new InputMsg_SetFocus(routing_id(), focused
));
1564 if (!focused
&& mouse_locked_
)
1567 // Restore the last seen state of text input to the view.
1568 RenderWidgetHostViewPort
* rwhv
= RenderWidgetHostViewPort::FromRWHV(
1569 web_contents()->GetRenderWidgetHostView());
1571 rwhv
->TextInputTypeChanged(last_text_input_type_
, last_input_mode_
,
1572 last_can_compose_inline_
);
1576 void BrowserPluginGuest::OnSetName(int instance_id
, const std::string
& name
) {
1580 Send(new ViewMsg_SetName(routing_id(), name
));
1583 void BrowserPluginGuest::OnSetSize(
1585 const BrowserPluginHostMsg_AutoSize_Params
& auto_size_params
,
1586 const BrowserPluginHostMsg_ResizeGuest_Params
& resize_guest_params
) {
1587 bool old_auto_size_enabled
= auto_size_enabled_
;
1588 gfx::Size old_max_size
= max_auto_size_
;
1589 gfx::Size old_min_size
= min_auto_size_
;
1590 auto_size_enabled_
= auto_size_params
.enable
;
1591 max_auto_size_
= auto_size_params
.max_size
;
1592 min_auto_size_
= auto_size_params
.min_size
;
1593 if (auto_size_enabled_
&& (!old_auto_size_enabled
||
1594 (old_max_size
!= max_auto_size_
) ||
1595 (old_min_size
!= min_auto_size_
))) {
1597 base::UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
1598 GetWebContents()->GetRenderViewHost()->EnableAutoResize(
1599 min_auto_size_
, max_auto_size_
);
1600 // TODO(fsamuel): If we're changing autosize parameters, then we force
1601 // the guest to completely repaint itself, because BrowserPlugin has
1602 // allocated a new damage buffer and expects a full frame of pixels.
1603 // Ideally, we shouldn't need to do this because we shouldn't need to
1604 // allocate a new damage buffer unless |max_auto_size_| has changed.
1605 // However, even in that case, layout may not change and so we may
1606 // not get a full frame worth of pixels.
1607 Send(new ViewMsg_Repaint(routing_id(), max_auto_size_
));
1608 } else if (!auto_size_enabled_
&& old_auto_size_enabled
) {
1609 GetWebContents()->GetRenderViewHost()->DisableAutoResize(
1610 resize_guest_params
.view_rect
.size());
1612 OnResizeGuest(instance_id_
, resize_guest_params
);
1615 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
1617 const std::vector
<EditCommand
>& edit_commands
) {
1618 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
1622 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id
, bool opaque
) {
1623 guest_opaque_
= opaque
;
1625 SkBitmap background
;
1626 if (!guest_opaque_
) {
1627 background
.setConfig(SkBitmap::kARGB_8888_Config
, 1, 1);
1628 unsigned int color
= 0;
1629 background
.setPixels(&color
);
1631 Send(new ViewMsg_SetBackground(routing_id(), background
));
1634 void BrowserPluginGuest::OnSetVisibility(int instance_id
, bool visible
) {
1635 guest_visible_
= visible
;
1636 if (embedder_visible_
&& guest_visible_
)
1637 GetWebContents()->WasShown();
1639 GetWebContents()->WasHidden();
1642 void BrowserPluginGuest::OnSwapBuffersACK(
1644 const FrameHostMsg_BuffersSwappedACK_Params
& params
) {
1645 AcknowledgeBufferPresent(params
.gpu_route_id
, params
.gpu_host_id
,
1646 params
.mailbox
, params
.sync_point
);
1648 // This is only relevant on MACOSX and WIN when threaded compositing
1649 // is not enabled. In threaded mode, above ACK is sufficient.
1650 #if defined(OS_MACOSX) || defined(OS_WIN)
1651 RenderWidgetHostImpl
* render_widget_host
=
1652 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
1653 render_widget_host
->AcknowledgeSwapBuffersToRenderer();
1654 #endif // defined(OS_MACOSX) || defined(OS_WIN)
1657 void BrowserPluginGuest::OnUnlockMouse() {
1658 SendMessageToEmbedder(
1659 new BrowserPluginMsg_SetMouseLock(instance_id(), false));
1662 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id
) {
1663 // mouse_locked_ could be false here if the lock attempt was cancelled due
1664 // to window focus, or for various other reasons before the guest was informed
1665 // of the lock's success.
1667 Send(new ViewMsg_MouseLockLost(routing_id()));
1668 mouse_locked_
= false;
1671 void BrowserPluginGuest::OnUpdateRectACK(
1674 const BrowserPluginHostMsg_AutoSize_Params
& auto_size_params
,
1675 const BrowserPluginHostMsg_ResizeGuest_Params
& resize_guest_params
) {
1676 // Only the software path expects an ACK.
1678 Send(new ViewMsg_UpdateRect_ACK(routing_id()));
1679 OnSetSize(instance_id_
, auto_size_params
, resize_guest_params
);
1682 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
1685 const SkBitmap
& bitmap
) {
1686 CHECK(copy_request_callbacks_
.count(request_id
));
1687 if (!copy_request_callbacks_
.count(request_id
))
1689 const CopyRequestCallback
& callback
= copy_request_callbacks_
[request_id
];
1690 callback
.Run(!bitmap
.empty() && !bitmap
.isNull(), bitmap
);
1691 copy_request_callbacks_
.erase(request_id
);
1694 void BrowserPluginGuest::OnUpdateGeometry(int instance_id
,
1695 const gfx::Rect
& view_rect
) {
1696 // The plugin has moved within the embedder without resizing or the
1697 // embedder/container's view rect changing.
1698 guest_window_rect_
= view_rect
;
1699 RenderViewHostImpl
* rvh
= static_cast<RenderViewHostImpl
*>(
1700 GetWebContents()->GetRenderViewHost());
1702 rvh
->SendScreenRects();
1705 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept
) {
1706 SendMessageToEmbedder(
1707 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept
));
1710 void BrowserPluginGuest::OnSetCursor(const WebCursor
& cursor
) {
1711 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor
));
1714 #if defined(OS_MACOSX)
1715 void BrowserPluginGuest::OnShowPopup(
1716 const ViewHostMsg_ShowPopup_Params
& params
) {
1717 gfx::Rect
translated_bounds(params
.bounds
);
1718 translated_bounds
.Offset(guest_window_rect_
.OffsetFromOrigin());
1719 BrowserPluginPopupMenuHelper
popup_menu_helper(
1720 embedder_web_contents_
->GetRenderViewHost(),
1721 GetWebContents()->GetRenderViewHost());
1722 popup_menu_helper
.ShowPopupMenu(translated_bounds
,
1724 params
.item_font_size
,
1725 params
.selected_item
,
1727 params
.right_aligned
,
1728 params
.allow_multiple_selection
);
1732 void BrowserPluginGuest::OnShowWidget(int route_id
,
1733 const gfx::Rect
& initial_pos
) {
1734 GetWebContents()->ShowCreatedWidget(route_id
, initial_pos
);
1737 void BrowserPluginGuest::OnTakeFocus(bool reverse
) {
1738 SendMessageToEmbedder(
1739 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse
));
1742 void BrowserPluginGuest::OnUpdateFrameName(int frame_id
,
1744 const std::string
& name
) {
1749 SendMessageToEmbedder(new BrowserPluginMsg_UpdatedName(instance_id_
, name
));
1752 void BrowserPluginGuest::RequestMediaAccessPermission(
1753 WebContents
* web_contents
,
1754 const MediaStreamRequest
& request
,
1755 const MediaResponseCallback
& callback
) {
1756 base::DictionaryValue request_info
;
1758 browser_plugin::kURL
,
1759 base::Value::CreateStringValue(request
.security_origin
.spec()));
1761 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA
,
1762 new MediaRequest(weak_ptr_factory_
.GetWeakPtr(),
1768 bool BrowserPluginGuest::PreHandleGestureEvent(
1769 WebContents
* source
, const blink::WebGestureEvent
& event
) {
1770 return event
.type
== blink::WebGestureEvent::GesturePinchBegin
||
1771 event
.type
== blink::WebGestureEvent::GesturePinchUpdate
||
1772 event
.type
== blink::WebGestureEvent::GesturePinchEnd
;
1775 void BrowserPluginGuest::RunJavaScriptDialog(
1776 WebContents
* web_contents
,
1777 const GURL
& origin_url
,
1778 const std::string
& accept_lang
,
1779 JavaScriptMessageType javascript_message_type
,
1780 const base::string16
& message_text
,
1781 const base::string16
& default_prompt_text
,
1782 const DialogClosedCallback
& callback
,
1783 bool* did_suppress_message
) {
1784 base::DictionaryValue request_info
;
1786 browser_plugin::kDefaultPromptText
,
1787 base::Value::CreateStringValue(base::UTF16ToUTF8(default_prompt_text
)));
1789 browser_plugin::kMessageText
,
1790 base::Value::CreateStringValue(base::UTF16ToUTF8(message_text
)));
1792 browser_plugin::kMessageType
,
1793 base::Value::CreateStringValue(
1794 JavaScriptMessageTypeToString(javascript_message_type
)));
1796 browser_plugin::kURL
,
1797 base::Value::CreateStringValue(origin_url
.spec()));
1799 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG
,
1800 new JavaScriptDialogRequest(weak_ptr_factory_
.GetWeakPtr(),
1805 void BrowserPluginGuest::RunBeforeUnloadDialog(
1806 WebContents
* web_contents
,
1807 const base::string16
& message_text
,
1809 const DialogClosedCallback
& callback
) {
1810 // This is called if the guest has a beforeunload event handler.
1811 // This callback allows navigation to proceed.
1812 callback
.Run(true, base::string16());
1815 bool BrowserPluginGuest::HandleJavaScriptDialog(
1816 WebContents
* web_contents
,
1818 const base::string16
* prompt_override
) {
1822 void BrowserPluginGuest::CancelActiveAndPendingDialogs(
1823 WebContents
* web_contents
) {
1826 void BrowserPluginGuest::WebContentsDestroyed(WebContents
* web_contents
) {
1829 void BrowserPluginGuest::OnUpdateRect(
1830 const ViewHostMsg_UpdateRect_Params
& params
) {
1831 BrowserPluginMsg_UpdateRect_Params relay_params
;
1832 relay_params
.view_size
= params
.view_size
;
1833 relay_params
.scale_factor
= params
.scale_factor
;
1834 relay_params
.is_resize_ack
= ViewHostMsg_UpdateRect_Flags::is_resize_ack(
1836 relay_params
.needs_ack
= params
.needs_ack
;
1838 bool size_changed
= last_seen_view_size_
!= params
.view_size
;
1839 gfx::Size old_size
= last_seen_view_size_
;
1840 last_seen_view_size_
= params
.view_size
;
1842 if ((auto_size_enabled_
|| last_seen_auto_size_enabled_
) &&
1843 size_changed
&& delegate_
) {
1844 delegate_
->SizeChanged(old_size
, last_seen_view_size_
);
1846 last_seen_auto_size_enabled_
= auto_size_enabled_
;
1848 // HW accelerated case, acknowledge resize only
1849 if (!params
.needs_ack
|| !damage_buffer_
) {
1850 relay_params
.damage_buffer_sequence_id
= 0;
1851 SendMessageToEmbedder(
1852 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params
));
1856 // Only copy damage if the guest is in autosize mode and the guest's view size
1857 // is less than the maximum size or the guest's view size is equal to the
1858 // damage buffer's size and the guest's scale factor is equal to the damage
1859 // buffer's scale factor.
1860 // The scaling change can happen due to asynchronous updates of the DPI on a
1861 // resolution change.
1862 if (((auto_size_enabled_
&& InAutoSizeBounds(params
.view_size
)) ||
1863 (params
.view_size
== damage_view_size())) &&
1864 params
.scale_factor
== damage_buffer_scale_factor()) {
1865 TransportDIB
* dib
= GetWebContents()->GetRenderProcessHost()->
1866 GetTransportDIB(params
.bitmap
);
1868 size_t guest_damage_buffer_size
=
1870 params
.bitmap_rect
.width() *
1871 params
.bitmap_rect
.height() * 4;
1875 size_t embedder_damage_buffer_size
= damage_buffer_size_
;
1876 void* guest_memory
= dib
->memory();
1877 void* embedder_memory
= damage_buffer_
->memory();
1878 size_t size
= std::min(guest_damage_buffer_size
,
1879 embedder_damage_buffer_size
);
1880 memcpy(embedder_memory
, guest_memory
, size
);
1883 relay_params
.damage_buffer_sequence_id
= damage_buffer_sequence_id_
;
1884 relay_params
.bitmap_rect
= params
.bitmap_rect
;
1885 relay_params
.scroll_delta
= params
.scroll_delta
;
1886 relay_params
.scroll_rect
= params
.scroll_rect
;
1887 relay_params
.copy_rects
= params
.copy_rects
;
1889 SendMessageToEmbedder(
1890 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params
));
1893 void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type
,
1894 ui::TextInputMode input_mode
,
1895 bool can_compose_inline
) {
1896 // Save the state of text input so we can restore it on focus.
1897 last_text_input_type_
= type
;
1898 last_input_mode_
= input_mode
;
1899 last_can_compose_inline_
= can_compose_inline
;
1901 RenderWidgetHostViewPort::FromRWHV(
1902 web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged(
1903 type
, input_mode
, can_compose_inline
);
1906 void BrowserPluginGuest::OnImeCancelComposition() {
1907 RenderWidgetHostViewPort::FromRWHV(
1908 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
1911 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
1912 void BrowserPluginGuest::OnImeCompositionRangeChanged(
1913 const gfx::Range
& range
,
1914 const std::vector
<gfx::Rect
>& character_bounds
) {
1915 RenderWidgetHostViewPort::FromRWHV(
1916 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
1917 range
, character_bounds
);
1921 void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
1922 const std::string
& request_method
,
1923 const base::Callback
<void(bool)>& callback
,
1924 const std::string
& url
) {
1926 callback
.Run(false);
1930 base::DictionaryValue request_info
;
1931 request_info
.Set(browser_plugin::kRequestMethod
,
1932 base::Value::CreateStringValue(request_method
));
1933 request_info
.Set(browser_plugin::kURL
, base::Value::CreateStringValue(url
));
1935 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD
,
1936 new DownloadRequest(weak_ptr_factory_
.GetWeakPtr(),
1941 } // namespace content