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/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"
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
> {
66 virtual void Respond(bool should_allow
, const std::string
& user_input
) = 0;
67 virtual bool AllowedByDefault() const {
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
{
81 explicit DownloadRequest(base::Callback
<void(bool)> callback
)
82 : callback_(callback
) {
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
);
92 virtual ~DownloadRequest() {}
93 base::Callback
<void(bool)> callback_
;
96 class BrowserPluginGuest::GeolocationRequest
: public PermissionRequest
{
98 GeolocationRequest(GeolocationCallback callback
,
100 base::WeakPtrFactory
<BrowserPluginGuest
>* weak_ptr_factory
)
101 : callback_(callback
),
102 bridge_id_(bridge_id
),
103 weak_ptr_factory_(weak_ptr_factory
) {
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
,
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|.
134 web_contents
->GetLastCommittedURL(),
135 geolocation_callback
);
140 guest
->SetGeolocationPermission(callback_
, bridge_id_
, false);
144 virtual ~GeolocationRequest() {}
145 base::Callback
<void(bool)> callback_
;
147 base::WeakPtrFactory
<BrowserPluginGuest
>* weak_ptr_factory_
;
150 class BrowserPluginGuest::MediaRequest
: public PermissionRequest
{
152 MediaRequest(const MediaStreamRequest
& request
,
153 const MediaResponseCallback
& callback
,
154 BrowserPluginGuest
* guest
)
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_
);
171 callback_
.Run(MediaStreamDevices(), scoped_ptr
<MediaStreamUI
>());
176 virtual ~MediaRequest() {}
177 MediaStreamRequest request_
;
178 MediaResponseCallback callback_
;
179 BrowserPluginGuest
* guest_
;
182 class BrowserPluginGuest::NewWindowRequest
: public PermissionRequest
{
184 NewWindowRequest(int instance_id
, BrowserPluginGuest
* guest
)
185 : instance_id_(instance_id
),
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
);
199 VLOG(0) << "Guest not found. Instance ID: " << instance_id_
;
203 // If we do not destroy the guest then we allow the new window.
209 virtual ~NewWindowRequest() {}
211 BrowserPluginGuest
* guest_
;
214 class BrowserPluginGuest::JavaScriptDialogRequest
: public PermissionRequest
{
216 JavaScriptDialogRequest(const DialogClosedCallback
& callback
)
217 : callback_(callback
) {
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
));
228 virtual ~JavaScriptDialogRequest() {}
229 DialogClosedCallback callback_
;
232 class BrowserPluginGuest::PointerLockRequest
: public PermissionRequest
{
234 PointerLockRequest(BrowserPluginGuest
* guest
)
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
));
247 virtual ~PointerLockRequest() {}
248 BrowserPluginGuest
* guest_
;
252 std::string
WindowOpenDispositionToString(
253 WindowOpenDisposition window_open_disposition
) {
254 switch (window_open_disposition
) {
258 return "save_to_disk";
260 return "current_tab";
261 case NEW_BACKGROUND_TAB
:
262 return "new_background_tab";
263 case NEW_FOREGROUND_TAB
:
264 return "new_foreground_tab";
270 NOTREACHED() << "Unknown Window Open Disposition";
275 std::string
JavaScriptMessageTypeToString(JavaScriptMessageType message_type
) {
276 switch (message_type
) {
277 case JAVASCRIPT_MESSAGE_TYPE_ALERT
:
279 case JAVASCRIPT_MESSAGE_TYPE_CONFIRM
:
281 case JAVASCRIPT_MESSAGE_TYPE_PROMPT
:
284 NOTREACHED() << "Unknown JavaScript Message Type.";
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
);
300 return url_request
->url().possibly_invalid_spec();
306 class BrowserPluginGuest::EmbedderWebContentsObserver
307 : public WebContentsObserver
{
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);
331 BrowserPluginGuest
* browser_plugin_guest_
;
333 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver
);
336 BrowserPluginGuest::BrowserPluginGuest(
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
),
350 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs
)),
352 mouse_locked_(false),
353 pending_lock_request_(false),
354 embedder_visible_(true),
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);
363 opener_
= opener
->AsWeakPtr();
364 GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_
,
368 bool BrowserPluginGuest::AddMessageToConsole(WebContents
* source
,
370 const base::string16
& message
,
372 const base::string16
& source_id
) {
376 delegate_
->AddMessageToConsole(level
, message
, line_no
, source_id
);
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(
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.";
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
) {
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
,
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
;
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());
488 void BrowserPluginGuest::EmbedderDestroyed() {
489 embedder_web_contents_
= NULL
;
491 delegate_
->EmbedderDestroyed();
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
) {
507 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest
, message
)
508 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK
,
510 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK
,
511 OnCompositorFrameSwappedACK
)
512 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck
,
513 OnCopyFromCompositingSurfaceAck
)
514 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate
,
516 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand
,
517 OnExecuteEditCommand
)
518 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete
,
519 OnExtendSelectionAndDelete
)
520 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent
,
522 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition
,
523 OnImeConfirmComposition
)
524 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition
,
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
,
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()
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())
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
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
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_
,
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
));
640 delegate_
->DidAttach();
643 BrowserPluginGuest::~BrowserPluginGuest() {
644 while (!pending_messages_
.empty()) {
645 delete pending_messages_
.front();
646 pending_messages_
.pop();
651 BrowserPluginGuest
* BrowserPluginGuest::Create(
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
;
659 guest
= factory_
->CreateBrowserPluginGuest(instance_id
, web_contents
);
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
);
673 BrowserPluginGuest
* BrowserPluginGuest::CreateWithOpener(
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
);
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
,
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
));
710 gfx::Rect
BrowserPluginGuest::ToGuestRect(const gfx::Rect
& bounds
) {
711 gfx::Rect
guest_rect(bounds
);
712 guest_rect
.Offset(guest_window_rect_
.OffsetFromOrigin());
716 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible
) {
717 embedder_visible_
= visible
;
721 void BrowserPluginGuest::AddNewContents(WebContents
* source
,
722 WebContents
* new_contents
,
723 WindowOpenDisposition disposition
,
724 const gfx::Rect
& initial_pos
,
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
,
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(),
748 void BrowserPluginGuest::LoadProgressChanged(WebContents
* contents
,
751 delegate_
->LoadProgressed(progress
);
754 void BrowserPluginGuest::CloseContents(WebContents
* source
) {
761 JavaScriptDialogManager
* BrowserPluginGuest::GetJavaScriptDialogManager() {
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(
774 const NativeWebKeyboardEvent
& event
) {
778 if (UnlockMouseIfNecessary(event
))
781 if (delegate_
&& delegate_
->HandleKeyboardEvent(event
))
784 if (!embedder_web_contents_
->GetDelegate())
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
805 PendingWindowMap::iterator it
= opener()->pending_new_windows_
.find(this);
806 if (it
== opener()->pending_new_windows_
.end())
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
;
814 if (params
.disposition
== CURRENT_TAB
) {
815 // This can happen for cross-site redirects.
816 LoadURLWithParams(params
.url
, params
.referrer
, params
.transition
, 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
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"));
845 delegate_
->RendererUnresponsive();
848 void BrowserPluginGuest::RendererResponsive(WebContents
* source
) {
849 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Responsive"));
852 delegate_
->RendererResponsive();
855 void BrowserPluginGuest::RunFileChooser(WebContents
* web_contents
,
856 const FileChooserParams
& params
) {
860 if (!embedder_web_contents_
->GetDelegate())
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.
872 WebContentsImpl
* BrowserPluginGuest::GetWebContents() {
873 return static_cast<WebContentsImpl
*>(web_contents());
876 base::SharedMemory
* BrowserPluginGuest::GetDamageBufferFromEmbedder(
877 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
879 LOG(WARNING
) << "Attempting to map a damage buffer prior to attachment.";
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));
891 if (!shared_buf
->Map(params
.damage_buffer_size
)) {
892 LOG(WARNING
) << "Unable to map the embedder's damage buffer.";
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();
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
,
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())
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),
954 bool BrowserPluginGuest::UnlockMouseIfNecessary(
955 const NativeWebKeyboardEvent
& event
) {
959 embedder_web_contents()->GotResponseToLockMouseRequest(false);
963 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message
* msg
) {
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
970 pending_messages_
.push(msg
);
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
,
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
) {
1002 delegate_
.reset(delegate
);
1005 void BrowserPluginGuest::AskEmbedderForGeolocationPermission(
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()));
1014 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION
,
1015 new GeolocationRequest(
1016 callback
, bridge_id
, &weak_ptr_factory_
),
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
);
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())
1040 permission_request_map_
.erase(request_itr
);
1043 void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback
,
1046 callback
.Run(allowed
);
1047 RemoveBridgeID(bridge_id
);
1050 void BrowserPluginGuest::SendQueuedMessages() {
1054 while (!pending_messages_
.empty()) {
1055 IPC::Message
* message
= pending_messages_
.front();
1056 pending_messages_
.pop();
1057 SendMessageToEmbedder(message
);
1061 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
1063 const base::string16
& frame_unique_name
,
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(); "
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_
));
1093 if (auto_size_enabled_
)
1094 rvh
->EnableAutoResize(min_auto_size_
, max_auto_size_
);
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()));
1108 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED
:
1109 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Killed"));
1111 case base::TERMINATION_STATUS_PROCESS_CRASHED
:
1112 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Crashed"));
1114 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION
:
1115 RecordAction(UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
1120 // TODO(fsamuel): Consider whether we should be clearing
1121 // |permission_request_map_| here.
1123 delegate_
->GuestProcessGone(status
);
1127 void BrowserPluginGuest::AcknowledgeBufferPresent(
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
,
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
:
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
)
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
)
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()
1204 void BrowserPluginGuest::Attach(
1205 WebContentsImpl
* embedder_web_contents
,
1206 BrowserPluginHostMsg_Attach_Params params
,
1207 const base::DictionaryValue
& extra_params
) {
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;
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();
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.
1250 params
.name
.clear();
1252 Initialize(params
, embedder_web_contents
);
1254 SendQueuedMessages();
1256 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Attached"));
1259 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
1261 const FrameHostMsg_CompositorFrameSwappedACK_Params
& params
) {
1262 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params
.producing_route_id
,
1263 params
.output_surface_id
,
1264 params
.producing_host_id
,
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(
1278 host
->DragTargetDragEnter(drop_data
, location
, location
, mask
, 0);
1280 case blink::WebDragStatusOver
:
1281 host
->DragTargetDragOver(location
, location
, mask
, 0);
1283 case blink::WebDragStatusLeave
:
1284 embedder_web_contents_
->GetBrowserPluginEmbedder()->DragLeftGuest(this);
1285 host
->DragTargetDragLeave();
1287 case blink::WebDragStatusDrop
:
1288 host
->DragTargetDrop(location
, location
, 0);
1291 case blink::WebDragStatusUnknown
:
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(
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(
1314 const std::string
& text
,
1315 bool keep_selection
) {
1316 Send(new ViewMsg_ImeConfirmComposition(routing_id(),
1317 base::UTF8ToUTF16(text
),
1318 gfx::Range::InvalidRange(),
1322 void BrowserPluginGuest::OnExtendSelectionAndDelete(
1326 Send(new ViewMsg_ExtendSelectionAndDelete(routing_id(), before
, after
));
1329 void BrowserPluginGuest::OnReclaimCompositorResources(
1332 uint32 output_surface_id
,
1333 int renderer_host_id
,
1334 const cc::CompositorFrameAck
& ack
) {
1335 RenderWidgetHostImpl::SendReclaimCompositorResources(route_id
,
1341 void BrowserPluginGuest::OnHandleInputEvent(
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
));
1365 if (event
->type
== blink::WebInputEvent::MouseWheel
) {
1366 guest_rvh
->ForwardWheelEvent(
1367 *static_cast<const blink::WebMouseWheelEvent
*>(event
));
1371 if (blink::WebInputEvent::isKeyboardEventType(event
->type
)) {
1372 RenderViewHostImpl
* embedder_rvh
= static_cast<RenderViewHostImpl
*>(
1373 embedder_web_contents_
->GetRenderViewHost());
1374 if (!embedder_rvh
->GetLastKeyboardEvent())
1376 NativeWebKeyboardEvent
keyboard_event(
1377 *embedder_rvh
->GetLastKeyboardEvent());
1378 guest_rvh
->ForwardKeyboardEvent(keyboard_event
);
1382 if (blink::WebInputEvent::isTouchEventType(event
->type
)) {
1383 guest_rvh
->ForwardTouchEventWithLatencyInfo(
1384 *static_cast<const blink::WebTouchEvent
*>(event
),
1389 if (blink::WebInputEvent::isGestureEventType(event
->type
)) {
1390 guest_rvh
->ForwardGestureEvent(
1391 *static_cast<const blink::WebGestureEvent
*>(event
));
1396 void BrowserPluginGuest::OnLockMouse(bool user_gesture
,
1397 bool last_unlocked_by_target
,
1399 if (pending_lock_request_
) {
1400 // Immediately reject the lock because only one pointerLock may be active
1402 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
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),
1420 void BrowserPluginGuest::OnLockMouseAck(int instance_id
, bool succeeded
) {
1421 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded
));
1422 pending_lock_request_
= false;
1424 mouse_locked_
= true;
1427 void BrowserPluginGuest::OnNavigateGuest(
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(
1438 !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme(
1440 url
.SchemeIs(kJavaScriptScheme
);
1441 if (scheme_is_blocked
|| !url
.is_valid()) {
1443 std::string error_type
;
1444 base::RemoveChars(net::ErrorToString(net::ERR_ABORTED
), "net::",
1446 delegate_
->LoadAbort(true /* is_top_level */, url
, error_type
);
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
,
1461 void BrowserPluginGuest::OnPluginDestroyed(int instance_id
) {
1465 void BrowserPluginGuest::OnResizeGuest(
1467 const BrowserPluginHostMsg_ResizeGuest_Params
& params
) {
1468 if (!params
.size_changed
)
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());
1498 Send(new ViewMsg_Repaint(routing_id(), params
.view_rect
.size()));
1501 void BrowserPluginGuest::OnSetFocus(int instance_id
, bool focused
) {
1502 if (focused_
== focused
)
1505 Send(new InputMsg_SetFocus(routing_id(), focused
));
1506 if (!focused
&& mouse_locked_
)
1510 void BrowserPluginGuest::OnSetName(int instance_id
, const std::string
& name
) {
1514 Send(new ViewMsg_SetName(routing_id(), name
));
1517 void BrowserPluginGuest::OnSetSize(
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(
1550 const std::vector
<EditCommand
>& edit_commands
) {
1551 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
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();
1572 GetWebContents()->WasHidden();
1575 void BrowserPluginGuest::OnSwapBuffersACK(
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.
1600 Send(new ViewMsg_MouseLockLost(routing_id()));
1601 mouse_locked_
= false;
1604 void BrowserPluginGuest::OnUpdateRectACK(
1607 const BrowserPluginHostMsg_AutoSize_Params
& auto_size_params
,
1608 const BrowserPluginHostMsg_ResizeGuest_Params
& resize_guest_params
) {
1609 // Only the software path expects an ACK.
1611 Send(new ViewMsg_UpdateRect_ACK(routing_id()));
1612 OnSetSize(instance_id_
, auto_size_params
, resize_guest_params
);
1615 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
1618 const SkBitmap
& bitmap
) {
1619 CHECK(copy_request_callbacks_
.count(request_id
));
1620 if (!copy_request_callbacks_
.count(request_id
))
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());
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
,
1657 params
.item_font_size
,
1658 params
.selected_item
,
1660 params
.right_aligned
,
1661 params
.allow_multiple_selection
);
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
,
1677 const std::string
& 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
;
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),
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
;
1710 browser_plugin::kDefaultPromptText
,
1711 base::Value::CreateStringValue(base::UTF16ToUTF8(default_prompt_text
)));
1713 browser_plugin::kMessageText
,
1714 base::Value::CreateStringValue(base::UTF16ToUTF8(message_text
)));
1716 browser_plugin::kMessageType
,
1717 base::Value::CreateStringValue(
1718 JavaScriptMessageTypeToString(javascript_message_type
)));
1720 browser_plugin::kURL
,
1721 base::Value::CreateStringValue(origin_url
.spec()));
1723 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG
,
1724 new JavaScriptDialogRequest(callback
),
1728 void BrowserPluginGuest::RunBeforeUnloadDialog(
1729 WebContents
* web_contents
,
1730 const base::string16
& message_text
,
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
,
1741 const base::string16
* prompt_override
) {
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(
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
));
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
);
1791 size_t guest_damage_buffer_size
=
1793 params
.bitmap_rect
.width() *
1794 params
.bitmap_rect
.height() * 4;
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
);
1839 void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
1840 const std::string
& request_method
,
1841 const base::Callback
<void(bool)>& callback
,
1842 const std::string
& url
) {
1844 callback
.Run(false);
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
),
1858 } // namespace content