Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / browser_plugin / browser_plugin_guest.cc
blobf8957ac7949a7d08f17e4b44abf9f54ba23b0889
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/browser_plugin/browser_plugin_guest.h"
7 #include <algorithm>
9 #include "base/message_loop/message_loop.h"
10 #include "base/pickle.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
13 #include "content/browser/browser_thread_impl.h"
14 #include "content/browser/child_process_security_policy_impl.h"
15 #include "content/browser/frame_host/render_frame_host_impl.h"
16 #include "content/browser/frame_host/render_widget_host_view_guest.h"
17 #include "content/browser/loader/resource_dispatcher_host_impl.h"
18 #include "content/browser/renderer_host/render_view_host_impl.h"
19 #include "content/browser/renderer_host/render_widget_host_impl.h"
20 #include "content/browser/renderer_host/render_widget_host_view_base.h"
21 #include "content/browser/web_contents/web_contents_impl.h"
22 #include "content/browser/web_contents/web_contents_view_guest.h"
23 #include "content/common/browser_plugin/browser_plugin_constants.h"
24 #include "content/common/browser_plugin/browser_plugin_messages.h"
25 #include "content/common/content_constants_internal.h"
26 #include "content/common/drag_messages.h"
27 #include "content/common/frame_messages.h"
28 #include "content/common/input_messages.h"
29 #include "content/common/view_messages.h"
30 #include "content/public/browser/browser_context.h"
31 #include "content/public/browser/browser_plugin_guest_manager.h"
32 #include "content/public/browser/content_browser_client.h"
33 #include "content/public/browser/render_widget_host_view.h"
34 #include "content/public/browser/user_metrics.h"
35 #include "content/public/browser/web_contents_observer.h"
36 #include "content/public/common/drop_data.h"
37 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
39 #if defined(OS_MACOSX)
40 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
41 #endif
43 namespace content {
45 class BrowserPluginGuest::EmbedderWebContentsObserver
46 : public WebContentsObserver {
47 public:
48 explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest)
49 : WebContentsObserver(guest->embedder_web_contents()),
50 browser_plugin_guest_(guest) {
53 virtual ~EmbedderWebContentsObserver() {
56 // WebContentsObserver implementation.
57 virtual void WasShown() OVERRIDE {
58 browser_plugin_guest_->EmbedderVisibilityChanged(true);
61 virtual void WasHidden() OVERRIDE {
62 browser_plugin_guest_->EmbedderVisibilityChanged(false);
65 private:
66 BrowserPluginGuest* browser_plugin_guest_;
68 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
71 BrowserPluginGuest::BrowserPluginGuest(bool has_render_view,
72 WebContentsImpl* web_contents,
73 BrowserPluginGuestDelegate* delegate)
74 : WebContentsObserver(web_contents),
75 embedder_web_contents_(NULL),
76 browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
77 guest_device_scale_factor_(1.0f),
78 focused_(false),
79 mouse_locked_(false),
80 pending_lock_request_(false),
81 guest_visible_(false),
82 guest_opaque_(true),
83 embedder_visible_(true),
84 copy_request_id_(0),
85 has_render_view_(has_render_view),
86 is_in_destruction_(false),
87 last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
88 last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
89 last_can_compose_inline_(true),
90 delegate_(delegate),
91 weak_ptr_factory_(this) {
92 DCHECK(web_contents);
93 DCHECK(delegate);
94 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
95 web_contents->SetBrowserPluginGuest(this);
96 delegate->RegisterDestructionCallback(
97 base::Bind(&BrowserPluginGuest::WillDestroy, AsWeakPtr()));
100 void BrowserPluginGuest::WillDestroy() {
101 is_in_destruction_ = true;
102 embedder_web_contents_ = NULL;
105 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
106 return weak_ptr_factory_.GetWeakPtr();
109 bool BrowserPluginGuest::LockMouse(bool allowed) {
110 if (!attached() || (mouse_locked_ == allowed))
111 return false;
113 return embedder_web_contents()->GotResponseToLockMouseRequest(allowed);
116 void BrowserPluginGuest::Destroy() {
117 delegate_->Destroy();
120 WebContentsImpl* BrowserPluginGuest::CreateNewGuestWindow(
121 const WebContents::CreateParams& params) {
122 WebContentsImpl* new_contents =
123 static_cast<WebContentsImpl*>(delegate_->CreateNewGuestWindow(params));
124 DCHECK(new_contents);
125 return new_contents;
128 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
129 const IPC::Message& message) {
130 bool handled = true;
131 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
132 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK,
133 OnCompositorFrameSwappedACK)
134 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
135 OnCopyFromCompositingSurfaceAck)
136 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
137 OnDragStatusUpdate)
138 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
139 OnExecuteEditCommand)
140 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
141 OnExtendSelectionAndDelete)
142 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
143 OnHandleInputEvent)
144 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition,
145 OnImeConfirmComposition)
146 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
147 OnImeSetComposition)
148 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
149 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
150 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
151 OnReclaimCompositorResources)
152 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
153 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
154 OnSetEditCommandsForNextKeyEvent)
155 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
156 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque,
157 OnSetContentsOpaque)
158 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
159 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
160 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
161 IPC_MESSAGE_UNHANDLED(handled = false)
162 IPC_END_MESSAGE_MAP()
163 return handled;
166 void BrowserPluginGuest::Initialize(
167 int browser_plugin_instance_id,
168 const BrowserPluginHostMsg_Attach_Params& params,
169 WebContentsImpl* embedder_web_contents) {
170 browser_plugin_instance_id_ = browser_plugin_instance_id;
171 focused_ = params.focused;
172 guest_visible_ = params.visible;
173 guest_opaque_ = params.opaque;
174 guest_window_rect_ = gfx::Rect(params.origin,
175 params.resize_guest_params.view_size);
177 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
178 // be attached.
179 embedder_web_contents_ = embedder_web_contents;
181 WebContentsViewGuest* new_view =
182 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
183 new_view->OnGuestInitialized(embedder_web_contents->GetView());
185 RendererPreferences* renderer_prefs =
186 GetWebContents()->GetMutableRendererPrefs();
187 std::string guest_user_agent_override = renderer_prefs->user_agent_override;
188 // Copy renderer preferences (and nothing else) from the embedder's
189 // WebContents to the guest.
191 // For GTK and Aura this is necessary to get proper renderer configuration
192 // values for caret blinking interval, colors related to selection and
193 // focus.
194 *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
195 renderer_prefs->user_agent_override = guest_user_agent_override;
197 // We would like the guest to report changes to frame names so that we can
198 // update the BrowserPlugin's corresponding 'name' attribute.
199 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
200 renderer_prefs->report_frame_name_changes = true;
201 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
202 // navigations still continue to function inside the app.
203 renderer_prefs->browser_handles_all_top_level_requests = false;
204 // Disable "client blocked" error page for browser plugin.
205 renderer_prefs->disable_client_blocked_error_page = true;
207 embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
209 OnResizeGuest(browser_plugin_instance_id_, params.resize_guest_params);
211 // Create a swapped out RenderView for the guest in the embedder render
212 // process, so that the embedder can access the guest's window object.
213 int guest_routing_id =
214 GetWebContents()->CreateSwappedOutRenderView(
215 embedder_web_contents_->GetSiteInstance());
217 // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will
218 // be reset again the next time preferences are updated.
219 WebPreferences prefs =
220 GetWebContents()->GetRenderViewHost()->GetWebkitPreferences();
221 prefs.navigate_on_drag_drop = false;
222 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
224 // Enable input method for guest if it's enabled for the embedder.
225 if (static_cast<RenderViewHostImpl*>(
226 embedder_web_contents_->GetRenderViewHost())->input_method_active()) {
227 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
228 GetWebContents()->GetRenderViewHost());
229 guest_rvh->SetInputMethodActive(true);
232 // Inform the embedder of the guest's attachment.
233 SendMessageToEmbedder(
234 new BrowserPluginMsg_Attach_ACK(browser_plugin_instance_id_));
236 SendMessageToEmbedder(new BrowserPluginMsg_GuestContentWindowReady(
237 browser_plugin_instance_id_, guest_routing_id));
240 BrowserPluginGuest::~BrowserPluginGuest() {
243 // static
244 BrowserPluginGuest* BrowserPluginGuest::Create(
245 WebContentsImpl* web_contents,
246 BrowserPluginGuestDelegate* delegate) {
247 return new BrowserPluginGuest(
248 web_contents->opener() != NULL, web_contents, delegate);
251 // static
252 bool BrowserPluginGuest::IsGuest(WebContentsImpl* web_contents) {
253 return web_contents && web_contents->GetBrowserPluginGuest();
256 // static
257 bool BrowserPluginGuest::IsGuest(RenderViewHostImpl* render_view_host) {
258 return render_view_host && IsGuest(
259 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
260 render_view_host)));
263 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
264 if (!attached())
265 return NULL;
266 return embedder_web_contents_->GetRenderWidgetHostView();
269 void BrowserPluginGuest::UpdateVisibility() {
270 OnSetVisibility(browser_plugin_instance_id(), visible());
273 void BrowserPluginGuest::CopyFromCompositingSurface(
274 gfx::Rect src_subrect,
275 gfx::Size dst_size,
276 const base::Callback<void(bool, const SkBitmap&)>& callback) {
277 copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
278 SendMessageToEmbedder(
279 new BrowserPluginMsg_CopyFromCompositingSurface(
280 browser_plugin_instance_id(),
281 copy_request_id_,
282 src_subrect,
283 dst_size));
286 BrowserPluginGuestManager*
287 BrowserPluginGuest::GetBrowserPluginGuestManager() const {
288 return GetWebContents()->GetBrowserContext()->GetGuestManager();
291 // screen.
292 gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
293 gfx::Rect guest_rect(bounds);
294 guest_rect.Offset(guest_window_rect_.OffsetFromOrigin());
295 if (embedder_web_contents()->GetBrowserPluginGuest()) {
296 BrowserPluginGuest* embedder_guest =
297 embedder_web_contents()->GetBrowserPluginGuest();
298 guest_rect.Offset(embedder_guest->guest_window_rect_.OffsetFromOrigin());
300 return guest_rect;
303 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
304 embedder_visible_ = visible;
305 UpdateVisibility();
308 void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
309 SendMessageToEmbedder(
310 new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), allow));
313 WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
314 return static_cast<WebContentsImpl*>(web_contents());
317 gfx::Point BrowserPluginGuest::GetScreenCoordinates(
318 const gfx::Point& relative_position) const {
319 if (!attached())
320 return relative_position;
322 gfx::Point screen_pos(relative_position);
323 screen_pos += guest_window_rect_.OffsetFromOrigin();
324 if (embedder_web_contents()->GetBrowserPluginGuest()) {
325 BrowserPluginGuest* embedder_guest =
326 embedder_web_contents()->GetBrowserPluginGuest();
327 screen_pos += embedder_guest->guest_window_rect_.OffsetFromOrigin();
329 return screen_pos;
332 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
333 if (!attached()) {
334 // Some pages such as data URLs, javascript URLs, and about:blank
335 // do not load external resources and so they load prior to attachment.
336 // As a result, we must save all these IPCs until attachment and then
337 // forward them so that the embedder gets a chance to see and process
338 // the load events.
339 pending_messages_.push_back(linked_ptr<IPC::Message>(msg));
340 return;
342 msg->set_routing_id(embedder_web_contents_->GetRoutingID());
343 embedder_web_contents_->Send(msg);
346 void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
347 int screen_x, int screen_y, blink::WebDragOperation operation) {
348 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
349 screen_x, screen_y, operation);
352 void BrowserPluginGuest::EndSystemDrag() {
353 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
354 GetWebContents()->GetRenderViewHost());
355 guest_rvh->DragSourceSystemDragEnded();
358 void BrowserPluginGuest::SendQueuedMessages() {
359 if (!attached())
360 return;
362 while (!pending_messages_.empty()) {
363 linked_ptr<IPC::Message> message_ptr = pending_messages_.front();
364 pending_messages_.pop_front();
365 SendMessageToEmbedder(message_ptr.release());
369 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
370 RenderFrameHost* render_frame_host,
371 const GURL& url,
372 PageTransition transition_type) {
373 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
376 void BrowserPluginGuest::RenderViewReady() {
377 RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
378 // TODO(fsamuel): Investigate whether it's possible to update state earlier
379 // here (see http://crbug.com/158151).
380 Send(new InputMsg_SetFocus(routing_id(), focused_));
381 UpdateVisibility();
383 OnSetContentsOpaque(browser_plugin_instance_id(), guest_opaque_);
385 RenderWidgetHostImpl::From(rvh)->set_hung_renderer_delay_ms(
386 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs));
389 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
390 SendMessageToEmbedder(
391 new BrowserPluginMsg_GuestGone(browser_plugin_instance_id()));
392 switch (status) {
393 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
394 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
395 break;
396 case base::TERMINATION_STATUS_PROCESS_CRASHED:
397 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
398 break;
399 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
400 RecordAction(
401 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
402 break;
403 default:
404 break;
408 // static
409 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
410 const IPC::Message& message) {
411 switch (message.type()) {
412 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID:
413 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
414 case BrowserPluginHostMsg_DragStatusUpdate::ID:
415 case BrowserPluginHostMsg_ExecuteEditCommand::ID:
416 case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID:
417 case BrowserPluginHostMsg_HandleInputEvent::ID:
418 case BrowserPluginHostMsg_ImeConfirmComposition::ID:
419 case BrowserPluginHostMsg_ImeSetComposition::ID:
420 case BrowserPluginHostMsg_LockMouse_ACK::ID:
421 case BrowserPluginHostMsg_PluginDestroyed::ID:
422 case BrowserPluginHostMsg_ReclaimCompositorResources::ID:
423 case BrowserPluginHostMsg_ResizeGuest::ID:
424 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
425 case BrowserPluginHostMsg_SetFocus::ID:
426 case BrowserPluginHostMsg_SetContentsOpaque::ID:
427 case BrowserPluginHostMsg_SetVisibility::ID:
428 case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
429 case BrowserPluginHostMsg_UpdateGeometry::ID:
430 return true;
431 default:
432 return false;
436 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
437 bool handled = true;
438 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
439 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
440 OnImeCancelComposition)
441 #if defined(OS_MACOSX) || defined(USE_AURA)
442 IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
443 OnImeCompositionRangeChanged)
444 #endif
445 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
446 OnHasTouchEventHandlers)
447 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
448 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
449 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
450 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
451 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
452 OnTextInputStateChanged)
453 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
454 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
455 IPC_MESSAGE_UNHANDLED(handled = false)
456 IPC_END_MESSAGE_MAP()
457 return handled;
460 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message,
461 RenderFrameHost* render_frame_host) {
462 // This will eventually be the home for more IPC handlers that depend on
463 // RenderFrameHost. Until more are moved here, though, the IPC_* macros won't
464 // compile if there are no handlers for a platform. So we have both #if guards
465 // around the whole thing (unfortunate but temporary), and #if guards where
466 // they belong, only around the one IPC handler. TODO(avi): Move more of the
467 // frame-based handlers to this function and remove the outer #if layer.
468 #if defined(OS_MACOSX)
469 bool handled = true;
470 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserPluginGuest, message,
471 render_frame_host)
472 #if defined(OS_MACOSX)
473 // MacOS X creates and populates platform-specific select drop-down menus
474 // whereas other platforms merely create a popup window that the guest
475 // renderer process paints inside.
476 IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
477 #endif
478 IPC_MESSAGE_UNHANDLED(handled = false)
479 IPC_END_MESSAGE_MAP()
480 return handled;
481 #else
482 return false;
483 #endif
486 void BrowserPluginGuest::Attach(
487 int browser_plugin_instance_id,
488 WebContentsImpl* embedder_web_contents,
489 const BrowserPluginHostMsg_Attach_Params& params) {
490 if (attached())
491 return;
493 delegate_->WillAttach(embedder_web_contents);
495 // If a RenderView has already been created for this new window, then we need
496 // to initialize the browser-side state now so that the RenderFrameHostManager
497 // does not create a new RenderView on navigation.
498 if (has_render_view_) {
499 static_cast<RenderViewHostImpl*>(
500 GetWebContents()->GetRenderViewHost())->Init();
501 WebContentsViewGuest* new_view =
502 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
503 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
506 Initialize(browser_plugin_instance_id, params, embedder_web_contents);
508 SendQueuedMessages();
510 delegate_->DidAttach();
512 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
515 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
516 int browser_plugin_instance_id,
517 const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
518 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
519 params.output_surface_id,
520 params.producing_host_id,
521 params.ack);
524 void BrowserPluginGuest::OnDragStatusUpdate(int browser_plugin_instance_id,
525 blink::WebDragStatus drag_status,
526 const DropData& drop_data,
527 blink::WebDragOperationsMask mask,
528 const gfx::Point& location) {
529 RenderViewHost* host = GetWebContents()->GetRenderViewHost();
530 switch (drag_status) {
531 case blink::WebDragStatusEnter:
532 embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
533 this);
534 host->DragTargetDragEnter(drop_data, location, location, mask, 0);
535 break;
536 case blink::WebDragStatusOver:
537 host->DragTargetDragOver(location, location, mask, 0);
538 break;
539 case blink::WebDragStatusLeave:
540 embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
541 host->DragTargetDragLeave();
542 break;
543 case blink::WebDragStatusDrop:
544 host->DragTargetDrop(location, location, 0);
545 EndSystemDrag();
546 break;
547 case blink::WebDragStatusUnknown:
548 NOTREACHED();
552 void BrowserPluginGuest::OnExecuteEditCommand(int browser_plugin_instance_id,
553 const std::string& name) {
554 Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
557 void BrowserPluginGuest::OnImeSetComposition(
558 int browser_plugin_instance_id,
559 const std::string& text,
560 const std::vector<blink::WebCompositionUnderline>& underlines,
561 int selection_start,
562 int selection_end) {
563 Send(new InputMsg_ImeSetComposition(routing_id(),
564 base::UTF8ToUTF16(text), underlines,
565 selection_start, selection_end));
568 void BrowserPluginGuest::OnImeConfirmComposition(
569 int browser_plugin_instance_id,
570 const std::string& text,
571 bool keep_selection) {
572 Send(new InputMsg_ImeConfirmComposition(routing_id(),
573 base::UTF8ToUTF16(text),
574 gfx::Range::InvalidRange(),
575 keep_selection));
578 void BrowserPluginGuest::OnExtendSelectionAndDelete(
579 int browser_plugin_instance_id,
580 int before,
581 int after) {
582 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
583 web_contents()->GetFocusedFrame());
584 if (rfh)
585 rfh->ExtendSelectionAndDelete(before, after);
588 void BrowserPluginGuest::OnReclaimCompositorResources(
589 int browser_plugin_instance_id,
590 const FrameHostMsg_ReclaimCompositorResources_Params& params) {
591 RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
592 params.output_surface_id,
593 params.renderer_host_id,
594 params.ack);
597 void BrowserPluginGuest::OnHandleInputEvent(
598 int browser_plugin_instance_id,
599 const gfx::Rect& guest_window_rect,
600 const blink::WebInputEvent* event) {
601 guest_window_rect_ = guest_window_rect;
602 // If the embedder's RWHV is destroyed then that means that the embedder's
603 // window has been closed but the embedder's WebContents has not yet been
604 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
605 // if there is a visible embedder.
606 if (embedder_web_contents_->GetRenderWidgetHostView()) {
607 guest_screen_rect_ = guest_window_rect;
608 guest_screen_rect_.Offset(
609 embedder_web_contents_->GetRenderWidgetHostView()->
610 GetViewBounds().OffsetFromOrigin());
612 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
613 GetWebContents()->GetRenderViewHost());
615 if (blink::WebInputEvent::isMouseEventType(event->type)) {
616 guest_rvh->ForwardMouseEvent(
617 *static_cast<const blink::WebMouseEvent*>(event));
618 return;
621 if (event->type == blink::WebInputEvent::MouseWheel) {
622 guest_rvh->ForwardWheelEvent(
623 *static_cast<const blink::WebMouseWheelEvent*>(event));
624 return;
627 if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
628 RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
629 embedder_web_contents_->GetRenderViewHost());
630 if (!embedder_rvh->GetLastKeyboardEvent())
631 return;
632 NativeWebKeyboardEvent keyboard_event(
633 *embedder_rvh->GetLastKeyboardEvent());
634 guest_rvh->ForwardKeyboardEvent(keyboard_event);
635 return;
638 if (blink::WebInputEvent::isTouchEventType(event->type)) {
639 guest_rvh->ForwardTouchEventWithLatencyInfo(
640 *static_cast<const blink::WebTouchEvent*>(event),
641 ui::LatencyInfo());
642 return;
645 if (blink::WebInputEvent::isGestureEventType(event->type)) {
646 guest_rvh->ForwardGestureEvent(
647 *static_cast<const blink::WebGestureEvent*>(event));
648 return;
652 void BrowserPluginGuest::OnLockMouse(bool user_gesture,
653 bool last_unlocked_by_target,
654 bool privileged) {
655 if (pending_lock_request_) {
656 // Immediately reject the lock because only one pointerLock may be active
657 // at a time.
658 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
659 return;
662 pending_lock_request_ = true;
664 delegate_->RequestPointerLockPermission(
665 user_gesture,
666 last_unlocked_by_target,
667 base::Bind(&BrowserPluginGuest::PointerLockPermissionResponse,
668 weak_ptr_factory_.GetWeakPtr()));
671 void BrowserPluginGuest::OnLockMouseAck(int browser_plugin_instance_id,
672 bool succeeded) {
673 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
674 pending_lock_request_ = false;
675 if (succeeded)
676 mouse_locked_ = true;
679 void BrowserPluginGuest::OnPluginDestroyed(int browser_plugin_instance_id) {
680 Destroy();
683 void BrowserPluginGuest::OnResizeGuest(
684 int browser_plugin_instance_id,
685 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
686 if (!params.size_changed)
687 return;
688 // BrowserPlugin manages resize flow control itself and does not depend
689 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
690 // here. If we are setting the size for the first time before navigating then
691 // BrowserPluginGuest does not yet have a RenderViewHost.
692 if (GetWebContents()->GetRenderViewHost()) {
693 RenderWidgetHostImpl* render_widget_host =
694 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
695 render_widget_host->ResetSizeAndRepaintPendingFlags();
697 if (guest_device_scale_factor_ != params.scale_factor) {
698 guest_device_scale_factor_ = params.scale_factor;
699 render_widget_host->NotifyScreenInfoChanged();
703 if (last_seen_browser_plugin_size_ != params.view_size) {
704 delegate_->ElementSizeChanged(last_seen_browser_plugin_size_,
705 params.view_size);
706 last_seen_browser_plugin_size_ = params.view_size;
709 // Just resize the WebContents and repaint if needed.
710 if (!params.view_size.IsEmpty())
711 GetWebContents()->GetView()->SizeContents(params.view_size);
712 if (params.repaint)
713 Send(new ViewMsg_Repaint(routing_id(), params.view_size));
716 void BrowserPluginGuest::OnSetFocus(int browser_plugin_instance_id,
717 bool focused) {
718 focused_ = focused;
719 Send(new InputMsg_SetFocus(routing_id(), focused));
720 if (!focused && mouse_locked_)
721 OnUnlockMouse();
723 // Restore the last seen state of text input to the view.
724 RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
725 web_contents()->GetRenderWidgetHostView());
726 if (rwhv) {
727 ViewHostMsg_TextInputState_Params params;
728 params.type = last_text_input_type_;
729 params.mode = last_input_mode_;
730 params.can_compose_inline = last_can_compose_inline_;
731 rwhv->TextInputStateChanged(params);
735 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
736 int browser_plugin_instance_id,
737 const std::vector<EditCommand>& edit_commands) {
738 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
739 edit_commands));
742 void BrowserPluginGuest::OnSetContentsOpaque(int browser_plugin_instance_id,
743 bool opaque) {
744 guest_opaque_ = opaque;
745 Send(new ViewMsg_SetBackgroundOpaque(routing_id(), guest_opaque_));
748 void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id,
749 bool visible) {
750 guest_visible_ = visible;
751 if (embedder_visible_ && guest_visible_)
752 GetWebContents()->WasShown();
753 else
754 GetWebContents()->WasHidden();
757 void BrowserPluginGuest::OnUnlockMouse() {
758 SendMessageToEmbedder(
759 new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), false));
762 void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id) {
763 // mouse_locked_ could be false here if the lock attempt was cancelled due
764 // to window focus, or for various other reasons before the guest was informed
765 // of the lock's success.
766 if (mouse_locked_)
767 Send(new ViewMsg_MouseLockLost(routing_id()));
768 mouse_locked_ = false;
771 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
772 int browser_plugin_instance_id,
773 int request_id,
774 const SkBitmap& bitmap) {
775 CHECK(copy_request_callbacks_.count(request_id));
776 if (!copy_request_callbacks_.count(request_id))
777 return;
778 const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
779 callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
780 copy_request_callbacks_.erase(request_id);
783 void BrowserPluginGuest::OnUpdateGeometry(int browser_plugin_instance_id,
784 const gfx::Rect& view_rect) {
785 // The plugin has moved within the embedder without resizing or the
786 // embedder/container's view rect changing.
787 guest_window_rect_ = view_rect;
788 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
789 GetWebContents()->GetRenderViewHost());
790 if (rvh)
791 rvh->SendScreenRects();
794 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
795 SendMessageToEmbedder(
796 new BrowserPluginMsg_ShouldAcceptTouchEvents(
797 browser_plugin_instance_id(), accept));
800 void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
801 SendMessageToEmbedder(
802 new BrowserPluginMsg_SetCursor(browser_plugin_instance_id(), cursor));
805 #if defined(OS_MACOSX)
806 void BrowserPluginGuest::OnShowPopup(
807 RenderFrameHost* render_frame_host,
808 const FrameHostMsg_ShowPopup_Params& params) {
809 gfx::Rect translated_bounds(params.bounds);
810 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
811 BrowserPluginPopupMenuHelper popup_menu_helper(
812 embedder_web_contents_->GetRenderViewHost(), render_frame_host);
813 popup_menu_helper.ShowPopupMenu(translated_bounds,
814 params.item_height,
815 params.item_font_size,
816 params.selected_item,
817 params.popup_items,
818 params.right_aligned,
819 params.allow_multiple_selection);
821 #endif
823 void BrowserPluginGuest::OnShowWidget(int route_id,
824 const gfx::Rect& initial_pos) {
825 GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
828 void BrowserPluginGuest::OnTakeFocus(bool reverse) {
829 SendMessageToEmbedder(
830 new BrowserPluginMsg_AdvanceFocus(browser_plugin_instance_id(), reverse));
833 void BrowserPluginGuest::OnUpdateRect(
834 const ViewHostMsg_UpdateRect_Params& params) {
835 BrowserPluginMsg_UpdateRect_Params relay_params;
836 relay_params.view_size = params.view_size;
837 relay_params.scale_factor = params.scale_factor;
838 relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
839 params.flags);
841 if (last_seen_view_size_ != params.view_size) {
842 delegate_->GuestSizeChanged(last_seen_view_size_, params.view_size);
843 last_seen_view_size_ = params.view_size;
846 SendMessageToEmbedder(
847 new BrowserPluginMsg_UpdateRect(browser_plugin_instance_id(),
848 relay_params));
851 void BrowserPluginGuest::OnTextInputStateChanged(
852 const ViewHostMsg_TextInputState_Params& params) {
853 // Save the state of text input so we can restore it on focus.
854 last_text_input_type_ = params.type;
855 last_input_mode_ = params.mode;
856 last_can_compose_inline_ = params.can_compose_inline;
858 static_cast<RenderWidgetHostViewBase*>(
859 web_contents()->GetRenderWidgetHostView())->TextInputStateChanged(params);
862 void BrowserPluginGuest::OnImeCancelComposition() {
863 static_cast<RenderWidgetHostViewBase*>(
864 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
867 #if defined(OS_MACOSX) || defined(USE_AURA)
868 void BrowserPluginGuest::OnImeCompositionRangeChanged(
869 const gfx::Range& range,
870 const std::vector<gfx::Rect>& character_bounds) {
871 static_cast<RenderWidgetHostViewBase*>(
872 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
873 range, character_bounds);
875 #endif
877 } // namespace content