1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/browser_plugin/browser_plugin_guest.h"
6
7 #include <algorithm>
8
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
12 #include "content/browser/browser_thread_impl.h"
13 #include "content/browser/child_process_security_policy_impl.h"
14 #include "content/browser/frame_host/render_frame_host_impl.h"
15 #include "content/browser/frame_host/render_widget_host_view_guest.h"
16 #include "content/browser/loader/resource_dispatcher_host_impl.h"
17 #include "content/browser/renderer_host/render_view_host_impl.h"
18 #include "content/browser/renderer_host/render_widget_host_impl.h"
19 #include "content/browser/renderer_host/render_widget_host_view_base.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_messages.h"
23 #include "content/common/content_constants_internal.h"
24 #include "content/common/drag_messages.h"
25 #include "content/common/input_messages.h"
26 #include "content/common/view_messages.h"
27 #include "content/public/browser/browser_context.h"
28 #include "content/public/browser/browser_plugin_guest_manager.h"
29 #include "content/public/browser/content_browser_client.h"
30 #include "content/public/browser/render_widget_host_view.h"
31 #include "content/public/browser/user_metrics.h"
32 #include "content/public/browser/web_contents_observer.h"
33 #include "content/public/common/drop_data.h"
34 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
35
36 #if defined(OS_MACOSX)
37 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
38 #endif
39
40 namespace content {
41
42 class BrowserPluginGuest::EmbedderWebContentsObserver
43 : public WebContentsObserver {
44 public:
EmbedderWebContentsObserver(BrowserPluginGuest * guest)45 explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest)
46 : WebContentsObserver(guest->embedder_web_contents()),
47 browser_plugin_guest_(guest) {
48 }
49
~EmbedderWebContentsObserver()50 virtual ~EmbedderWebContentsObserver() {
51 }
52
53 // WebContentsObserver implementation.
WasShown()54 virtual void WasShown() OVERRIDE {
55 browser_plugin_guest_->EmbedderVisibilityChanged(true);
56 }
57
WasHidden()58 virtual void WasHidden() OVERRIDE {
59 browser_plugin_guest_->EmbedderVisibilityChanged(false);
60 }
61
62 private:
63 BrowserPluginGuest* browser_plugin_guest_;
64
65 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
66 };
67
BrowserPluginGuest(int instance_id,bool has_render_view,WebContentsImpl * web_contents)68 BrowserPluginGuest::BrowserPluginGuest(
69 int instance_id,
70 bool has_render_view,
71 WebContentsImpl* web_contents)
72 : WebContentsObserver(web_contents),
73 embedder_web_contents_(NULL),
74 instance_id_(instance_id),
75 guest_device_scale_factor_(1.0f),
76 focused_(false),
77 mouse_locked_(false),
78 pending_lock_request_(false),
79 guest_visible_(false),
80 guest_opaque_(true),
81 embedder_visible_(true),
82 auto_size_enabled_(false),
83 copy_request_id_(0),
84 has_render_view_(has_render_view),
85 last_seen_auto_size_enabled_(false),
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_(NULL),
91 weak_ptr_factory_(this) {
92 DCHECK(web_contents);
93 }
94
WillDestroy()95 void BrowserPluginGuest::WillDestroy() {
96 is_in_destruction_ = true;
97 embedder_web_contents_ = NULL;
98 delegate_ = NULL;
99 }
100
AsWeakPtr()101 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
102 return weak_ptr_factory_.GetWeakPtr();
103 }
104
LockMouse(bool allowed)105 bool BrowserPluginGuest::LockMouse(bool allowed) {
106 if (!attached() || (mouse_locked_ == allowed))
107 return false;
108
109 return embedder_web_contents()->GotResponseToLockMouseRequest(allowed);
110 }
111
Destroy()112 void BrowserPluginGuest::Destroy() {
113 if (!delegate_)
114 return;
115 delegate_->Destroy();
116 }
117
OnMessageReceivedFromEmbedder(const IPC::Message & message)118 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
119 const IPC::Message& message) {
120 bool handled = true;
121 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
122 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK,
123 OnCompositorFrameSwappedACK)
124 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
125 OnCopyFromCompositingSurfaceAck)
126 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
127 OnDragStatusUpdate)
128 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
129 OnExecuteEditCommand)
130 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
131 OnExtendSelectionAndDelete)
132 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
133 OnHandleInputEvent)
134 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition,
135 OnImeConfirmComposition)
136 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
137 OnImeSetComposition)
138 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
139 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
140 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
141 OnReclaimCompositorResources)
142 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
143 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetAutoSize)
144 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
145 OnSetEditCommandsForNextKeyEvent)
146 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
147 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque,
148 OnSetContentsOpaque)
149 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
150 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
151 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
152 IPC_MESSAGE_UNHANDLED(handled = false)
153 IPC_END_MESSAGE_MAP()
154 return handled;
155 }
156
Initialize(const BrowserPluginHostMsg_Attach_Params & params,WebContentsImpl * embedder_web_contents,const base::DictionaryValue & extra_params)157 void BrowserPluginGuest::Initialize(
158 const BrowserPluginHostMsg_Attach_Params& params,
159 WebContentsImpl* embedder_web_contents,
160 const base::DictionaryValue& extra_params) {
161 focused_ = params.focused;
162 guest_visible_ = params.visible;
163 guest_opaque_ = params.opaque;
164 guest_window_rect_ = gfx::Rect(params.origin,
165 params.resize_guest_params.view_size);
166
167 auto_size_enabled_ = params.auto_size_params.enable;
168 max_auto_size_ = params.auto_size_params.max_size;
169 min_auto_size_ = params.auto_size_params.min_size;
170
171 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
172 // be attached.
173 embedder_web_contents_ = embedder_web_contents;
174
175 WebContentsViewGuest* new_view =
176 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
177 new_view->OnGuestInitialized(embedder_web_contents->GetView());
178
179 RendererPreferences* renderer_prefs =
180 GetWebContents()->GetMutableRendererPrefs();
181 std::string guest_user_agent_override = renderer_prefs->user_agent_override;
182 // Copy renderer preferences (and nothing else) from the embedder's
183 // WebContents to the guest.
184 //
185 // For GTK and Aura this is necessary to get proper renderer configuration
186 // values for caret blinking interval, colors related to selection and
187 // focus.
188 *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
189 renderer_prefs->user_agent_override = guest_user_agent_override;
190
191 // We would like the guest to report changes to frame names so that we can
192 // update the BrowserPlugin's corresponding 'name' attribute.
193 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
194 renderer_prefs->report_frame_name_changes = true;
195 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
196 // navigations still continue to function inside the app.
197 renderer_prefs->browser_handles_all_top_level_requests = false;
198 // Disable "client blocked" error page for browser plugin.
199 renderer_prefs->disable_client_blocked_error_page = true;
200
201 embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
202
203 OnSetAutoSize(
204 instance_id_, params.auto_size_params, params.resize_guest_params);
205
206 // Create a swapped out RenderView for the guest in the embedder render
207 // process, so that the embedder can access the guest's window object.
208 int guest_routing_id =
209 GetWebContents()->CreateSwappedOutRenderView(
210 embedder_web_contents_->GetSiteInstance());
211 SendMessageToEmbedder(
212 new BrowserPluginMsg_GuestContentWindowReady(instance_id_,
213 guest_routing_id));
214
215 WebPreferences prefs = GetWebContents()->GetWebkitPrefs();
216 prefs.navigate_on_drag_drop = false;
217 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
218
219 // Enable input method for guest if it's enabled for the embedder.
220 if (static_cast<RenderViewHostImpl*>(
221 embedder_web_contents_->GetRenderViewHost())->input_method_active()) {
222 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
223 GetWebContents()->GetRenderViewHost());
224 guest_rvh->SetInputMethodActive(true);
225 }
226
227 // Inform the embedder of the guest's attachment.
228 SendMessageToEmbedder(new BrowserPluginMsg_Attach_ACK(instance_id_));
229 }
230
~BrowserPluginGuest()231 BrowserPluginGuest::~BrowserPluginGuest() {
232 }
233
234 // static
Create(int instance_id,SiteInstance * guest_site_instance,WebContentsImpl * web_contents,scoped_ptr<base::DictionaryValue> extra_params,BrowserPluginGuest * opener)235 BrowserPluginGuest* BrowserPluginGuest::Create(
236 int instance_id,
237 SiteInstance* guest_site_instance,
238 WebContentsImpl* web_contents,
239 scoped_ptr<base::DictionaryValue> extra_params,
240 BrowserPluginGuest* opener) {
241 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
242 BrowserPluginGuest* guest = new BrowserPluginGuest(
243 instance_id, web_contents->opener() != NULL, web_contents);
244 web_contents->SetBrowserPluginGuest(guest);
245 WebContents* opener_web_contents = NULL;
246 if (opener) {
247 opener_web_contents = opener->GetWebContents();
248 guest_site_instance = opener_web_contents->GetSiteInstance();
249 }
250 BrowserPluginGuestDelegate* delegate = NULL;
251 GetContentClient()->browser()->GuestWebContentsCreated(
252 instance_id,
253 guest_site_instance,
254 web_contents,
255 opener_web_contents,
256 &delegate,
257 extra_params.Pass());
258 if (delegate) {
259 delegate->RegisterDestructionCallback(
260 base::Bind(&BrowserPluginGuest::WillDestroy,
261 base::Unretained(guest)));
262 guest->set_delegate(delegate);
263 }
264 return guest;
265 }
266
267 // static
IsGuest(WebContentsImpl * web_contents)268 bool BrowserPluginGuest::IsGuest(WebContentsImpl* web_contents) {
269 return web_contents && web_contents->GetBrowserPluginGuest();
270 }
271
272 // static
IsGuest(RenderViewHostImpl * render_view_host)273 bool BrowserPluginGuest::IsGuest(RenderViewHostImpl* render_view_host) {
274 return render_view_host && IsGuest(
275 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
276 render_view_host)));
277 }
278
GetEmbedderRenderWidgetHostView()279 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
280 if (!attached())
281 return NULL;
282 return embedder_web_contents_->GetRenderWidgetHostView();
283 }
284
UpdateVisibility()285 void BrowserPluginGuest::UpdateVisibility() {
286 OnSetVisibility(instance_id_, visible());
287 }
288
CopyFromCompositingSurface(gfx::Rect src_subrect,gfx::Size dst_size,const base::Callback<void (bool,const SkBitmap &)> & callback)289 void BrowserPluginGuest::CopyFromCompositingSurface(
290 gfx::Rect src_subrect,
291 gfx::Size dst_size,
292 const base::Callback<void(bool, const SkBitmap&)>& callback) {
293 copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
294 SendMessageToEmbedder(
295 new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
296 copy_request_id_, src_subrect, dst_size));
297 }
298
299 BrowserPluginGuestManager*
GetBrowserPluginGuestManager() const300 BrowserPluginGuest::GetBrowserPluginGuestManager() const {
301 return GetWebContents()->GetBrowserContext()->GetGuestManager();
302 }
303
304 // screen.
ToGuestRect(const gfx::Rect & bounds)305 gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
306 gfx::Rect guest_rect(bounds);
307 guest_rect.Offset(guest_window_rect_.OffsetFromOrigin());
308 return guest_rect;
309 }
310
EmbedderVisibilityChanged(bool visible)311 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
312 embedder_visible_ = visible;
313 UpdateVisibility();
314 }
315
PointerLockPermissionResponse(bool allow)316 void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
317 SendMessageToEmbedder(
318 new BrowserPluginMsg_SetMouseLock(instance_id(), allow));
319 }
320
GetWebContents() const321 WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
322 return static_cast<WebContentsImpl*>(web_contents());
323 }
324
GetScreenCoordinates(const gfx::Point & relative_position) const325 gfx::Point BrowserPluginGuest::GetScreenCoordinates(
326 const gfx::Point& relative_position) const {
327 gfx::Point screen_pos(relative_position);
328 screen_pos += guest_window_rect_.OffsetFromOrigin();
329 return screen_pos;
330 }
331
InAutoSizeBounds(const gfx::Size & size) const332 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
333 return size.width() <= max_auto_size_.width() &&
334 size.height() <= max_auto_size_.height();
335 }
336
SendMessageToEmbedder(IPC::Message * msg)337 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
338 if (!attached()) {
339 // Some pages such as data URLs, javascript URLs, and about:blank
340 // do not load external resources and so they load prior to attachment.
341 // As a result, we must save all these IPCs until attachment and then
342 // forward them so that the embedder gets a chance to see and process
343 // the load events.
344 pending_messages_.push_back(linked_ptr<IPC::Message>(msg));
345 return;
346 }
347 msg->set_routing_id(embedder_web_contents_->GetRoutingID());
348 embedder_web_contents_->Send(msg);
349 }
350
DragSourceEndedAt(int client_x,int client_y,int screen_x,int screen_y,blink::WebDragOperation operation)351 void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
352 int screen_x, int screen_y, blink::WebDragOperation operation) {
353 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
354 screen_x, screen_y, operation);
355 }
356
EndSystemDrag()357 void BrowserPluginGuest::EndSystemDrag() {
358 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
359 GetWebContents()->GetRenderViewHost());
360 guest_rvh->DragSourceSystemDragEnded();
361 }
362
SendQueuedMessages()363 void BrowserPluginGuest::SendQueuedMessages() {
364 if (!attached())
365 return;
366
367 while (!pending_messages_.empty()) {
368 linked_ptr<IPC::Message> message_ptr = pending_messages_.front();
369 pending_messages_.pop_front();
370 SendMessageToEmbedder(message_ptr.release());
371 }
372 }
373
DidCommitProvisionalLoadForFrame(int64 frame_id,const base::string16 & frame_unique_name,bool is_main_frame,const GURL & url,PageTransition transition_type,RenderViewHost * render_view_host)374 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
375 int64 frame_id,
376 const base::string16& frame_unique_name,
377 bool is_main_frame,
378 const GURL& url,
379 PageTransition transition_type,
380 RenderViewHost* render_view_host) {
381 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
382 }
383
RenderViewReady()384 void BrowserPluginGuest::RenderViewReady() {
385 RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
386 // TODO(fsamuel): Investigate whether it's possible to update state earlier
387 // here (see http://crbug.com/158151).
388 Send(new InputMsg_SetFocus(routing_id(), focused_));
389 UpdateVisibility();
390 if (auto_size_enabled_)
391 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
392 else
393 rvh->DisableAutoResize(full_size_);
394
395 OnSetContentsOpaque(instance_id_, guest_opaque_);
396
397 RenderWidgetHostImpl::From(rvh)->set_hung_renderer_delay_ms(
398 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs));
399 }
400
RenderProcessGone(base::TerminationStatus status)401 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
402 SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(instance_id()));
403 switch (status) {
404 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
405 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
406 break;
407 case base::TERMINATION_STATUS_PROCESS_CRASHED:
408 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
409 break;
410 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
411 RecordAction(
412 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
413 break;
414 default:
415 break;
416 }
417 }
418
419 // static
ShouldForwardToBrowserPluginGuest(const IPC::Message & message)420 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
421 const IPC::Message& message) {
422 switch (message.type()) {
423 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID:
424 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
425 case BrowserPluginHostMsg_DragStatusUpdate::ID:
426 case BrowserPluginHostMsg_ExecuteEditCommand::ID:
427 case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID:
428 case BrowserPluginHostMsg_HandleInputEvent::ID:
429 case BrowserPluginHostMsg_ImeConfirmComposition::ID:
430 case BrowserPluginHostMsg_ImeSetComposition::ID:
431 case BrowserPluginHostMsg_LockMouse_ACK::ID:
432 case BrowserPluginHostMsg_PluginDestroyed::ID:
433 case BrowserPluginHostMsg_ReclaimCompositorResources::ID:
434 case BrowserPluginHostMsg_ResizeGuest::ID:
435 case BrowserPluginHostMsg_SetAutoSize::ID:
436 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
437 case BrowserPluginHostMsg_SetFocus::ID:
438 case BrowserPluginHostMsg_SetContentsOpaque::ID:
439 case BrowserPluginHostMsg_SetVisibility::ID:
440 case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
441 case BrowserPluginHostMsg_UpdateGeometry::ID:
442 return true;
443 default:
444 return false;
445 }
446 }
447
OnMessageReceived(const IPC::Message & message)448 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
449 bool handled = true;
450 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
451 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
452 OnHasTouchEventHandlers)
453 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
454 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
455 #if defined(OS_MACOSX)
456 // MacOSX creates and populates platform-specific select drop-down menus
457 // whereas other platforms merely create a popup window that the guest
458 // renderer process paints inside.
459 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
460 #endif
461 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
462 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
463 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
464 OnTextInputStateChanged)
465 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
466 OnImeCancelComposition)
467 #if defined(OS_MACOSX) || defined(USE_AURA)
468 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
469 OnImeCompositionRangeChanged)
470 #endif
471 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
472 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
473 IPC_MESSAGE_UNHANDLED(handled = false)
474 IPC_END_MESSAGE_MAP()
475 return handled;
476 }
477
Attach(WebContentsImpl * embedder_web_contents,const BrowserPluginHostMsg_Attach_Params & params,const base::DictionaryValue & extra_params)478 void BrowserPluginGuest::Attach(
479 WebContentsImpl* embedder_web_contents,
480 const BrowserPluginHostMsg_Attach_Params& params,
481 const base::DictionaryValue& extra_params) {
482 if (attached())
483 return;
484
485 if (delegate_)
486 delegate_->WillAttach(embedder_web_contents, extra_params);
487
488 // If a RenderView has already been created for this new window, then we need
489 // to initialize the browser-side state now so that the RenderFrameHostManager
490 // does not create a new RenderView on navigation.
491 if (has_render_view_) {
492 static_cast<RenderViewHostImpl*>(
493 GetWebContents()->GetRenderViewHost())->Init();
494 WebContentsViewGuest* new_view =
495 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
496 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
497 }
498
499 Initialize(params, embedder_web_contents, extra_params);
500
501 SendQueuedMessages();
502
503 if (delegate_)
504 delegate_->DidAttach();
505
506 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
507 }
508
OnCompositorFrameSwappedACK(int instance_id,const FrameHostMsg_CompositorFrameSwappedACK_Params & params)509 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
510 int instance_id,
511 const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
512 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
513 params.output_surface_id,
514 params.producing_host_id,
515 params.ack);
516 }
517
OnDragStatusUpdate(int instance_id,blink::WebDragStatus drag_status,const DropData & drop_data,blink::WebDragOperationsMask mask,const gfx::Point & location)518 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
519 blink::WebDragStatus drag_status,
520 const DropData& drop_data,
521 blink::WebDragOperationsMask mask,
522 const gfx::Point& location) {
523 RenderViewHost* host = GetWebContents()->GetRenderViewHost();
524 switch (drag_status) {
525 case blink::WebDragStatusEnter:
526 embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
527 this);
528 host->DragTargetDragEnter(drop_data, location, location, mask, 0);
529 break;
530 case blink::WebDragStatusOver:
531 host->DragTargetDragOver(location, location, mask, 0);
532 break;
533 case blink::WebDragStatusLeave:
534 embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
535 host->DragTargetDragLeave();
536 break;
537 case blink::WebDragStatusDrop:
538 host->DragTargetDrop(location, location, 0);
539 EndSystemDrag();
540 break;
541 case blink::WebDragStatusUnknown:
542 NOTREACHED();
543 }
544 }
545
OnExecuteEditCommand(int instance_id,const std::string & name)546 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
547 const std::string& name) {
548 Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
549 }
550
OnImeSetComposition(int instance_id,const std::string & text,const std::vector<blink::WebCompositionUnderline> & underlines,int selection_start,int selection_end)551 void BrowserPluginGuest::OnImeSetComposition(
552 int instance_id,
553 const std::string& text,
554 const std::vector<blink::WebCompositionUnderline>& underlines,
555 int selection_start,
556 int selection_end) {
557 Send(new ViewMsg_ImeSetComposition(routing_id(),
558 base::UTF8ToUTF16(text), underlines,
559 selection_start, selection_end));
560 }
561
OnImeConfirmComposition(int instance_id,const std::string & text,bool keep_selection)562 void BrowserPluginGuest::OnImeConfirmComposition(
563 int instance_id,
564 const std::string& text,
565 bool keep_selection) {
566 Send(new ViewMsg_ImeConfirmComposition(routing_id(),
567 base::UTF8ToUTF16(text),
568 gfx::Range::InvalidRange(),
569 keep_selection));
570 }
571
OnExtendSelectionAndDelete(int instance_id,int before,int after)572 void BrowserPluginGuest::OnExtendSelectionAndDelete(
573 int instance_id,
574 int before,
575 int after) {
576 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
577 web_contents()->GetFocusedFrame());
578 if (rfh)
579 rfh->ExtendSelectionAndDelete(before, after);
580 }
581
OnReclaimCompositorResources(int instance_id,const FrameHostMsg_ReclaimCompositorResources_Params & params)582 void BrowserPluginGuest::OnReclaimCompositorResources(
583 int instance_id,
584 const FrameHostMsg_ReclaimCompositorResources_Params& params) {
585 RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
586 params.output_surface_id,
587 params.renderer_host_id,
588 params.ack);
589 }
590
OnHandleInputEvent(int instance_id,const gfx::Rect & guest_window_rect,const blink::WebInputEvent * event)591 void BrowserPluginGuest::OnHandleInputEvent(
592 int instance_id,
593 const gfx::Rect& guest_window_rect,
594 const blink::WebInputEvent* event) {
595 guest_window_rect_ = guest_window_rect;
596 // If the embedder's RWHV is destroyed then that means that the embedder's
597 // window has been closed but the embedder's WebContents has not yet been
598 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
599 // if there is a visible embedder.
600 if (embedder_web_contents_->GetRenderWidgetHostView()) {
601 guest_screen_rect_ = guest_window_rect;
602 guest_screen_rect_.Offset(
603 embedder_web_contents_->GetRenderWidgetHostView()->
604 GetViewBounds().OffsetFromOrigin());
605 }
606 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
607 GetWebContents()->GetRenderViewHost());
608
609 if (blink::WebInputEvent::isMouseEventType(event->type)) {
610 guest_rvh->ForwardMouseEvent(
611 *static_cast<const blink::WebMouseEvent*>(event));
612 return;
613 }
614
615 if (event->type == blink::WebInputEvent::MouseWheel) {
616 guest_rvh->ForwardWheelEvent(
617 *static_cast<const blink::WebMouseWheelEvent*>(event));
618 return;
619 }
620
621 if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
622 RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
623 embedder_web_contents_->GetRenderViewHost());
624 if (!embedder_rvh->GetLastKeyboardEvent())
625 return;
626 NativeWebKeyboardEvent keyboard_event(
627 *embedder_rvh->GetLastKeyboardEvent());
628 guest_rvh->ForwardKeyboardEvent(keyboard_event);
629 return;
630 }
631
632 if (blink::WebInputEvent::isTouchEventType(event->type)) {
633 guest_rvh->ForwardTouchEventWithLatencyInfo(
634 *static_cast<const blink::WebTouchEvent*>(event),
635 ui::LatencyInfo());
636 return;
637 }
638
639 if (blink::WebInputEvent::isGestureEventType(event->type)) {
640 guest_rvh->ForwardGestureEvent(
641 *static_cast<const blink::WebGestureEvent*>(event));
642 return;
643 }
644 }
645
OnLockMouse(bool user_gesture,bool last_unlocked_by_target,bool privileged)646 void BrowserPluginGuest::OnLockMouse(bool user_gesture,
647 bool last_unlocked_by_target,
648 bool privileged) {
649 if (pending_lock_request_) {
650 // Immediately reject the lock because only one pointerLock may be active
651 // at a time.
652 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
653 return;
654 }
655
656 if (!delegate_)
657 return;
658
659 pending_lock_request_ = true;
660
661 delegate_->RequestPointerLockPermission(
662 user_gesture,
663 last_unlocked_by_target,
664 base::Bind(&BrowserPluginGuest::PointerLockPermissionResponse,
665 weak_ptr_factory_.GetWeakPtr()));
666 }
667
OnLockMouseAck(int instance_id,bool succeeded)668 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
669 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
670 pending_lock_request_ = false;
671 if (succeeded)
672 mouse_locked_ = true;
673 }
674
OnPluginDestroyed(int instance_id)675 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
676 Destroy();
677 }
678
OnResizeGuest(int instance_id,const BrowserPluginHostMsg_ResizeGuest_Params & params)679 void BrowserPluginGuest::OnResizeGuest(
680 int instance_id,
681 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
682 if (!params.size_changed)
683 return;
684 // BrowserPlugin manages resize flow control itself and does not depend
685 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
686 // here. If we are setting the size for the first time before navigating then
687 // BrowserPluginGuest does not yet have a RenderViewHost.
688 if (GetWebContents()->GetRenderViewHost()) {
689 RenderWidgetHostImpl* render_widget_host =
690 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
691 render_widget_host->ResetSizeAndRepaintPendingFlags();
692
693 if (guest_device_scale_factor_ != params.scale_factor) {
694 guest_device_scale_factor_ = params.scale_factor;
695 render_widget_host->NotifyScreenInfoChanged();
696 }
697 }
698 // When autosize is turned off and as a result there is a layout change, we
699 // send a sizechanged event.
700 if (!auto_size_enabled_ && last_seen_auto_size_enabled_ &&
701 !params.view_size.IsEmpty() && delegate_) {
702 delegate_->SizeChanged(last_seen_view_size_, params.view_size);
703 last_seen_auto_size_enabled_ = false;
704 }
705 // Just resize the WebContents and repaint if needed.
706 full_size_ = params.view_size;
707 if (!params.view_size.IsEmpty())
708 GetWebContents()->GetView()->SizeContents(params.view_size);
709 if (params.repaint)
710 Send(new ViewMsg_Repaint(routing_id(), params.view_size));
711 }
712
OnSetFocus(int instance_id,bool focused)713 void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
714 focused_ = focused;
715 Send(new InputMsg_SetFocus(routing_id(), focused));
716 if (!focused && mouse_locked_)
717 OnUnlockMouse();
718
719 // Restore the last seen state of text input to the view.
720 RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
721 web_contents()->GetRenderWidgetHostView());
722 if (rwhv) {
723 ViewHostMsg_TextInputState_Params params;
724 params.type = last_text_input_type_;
725 params.mode = last_input_mode_;
726 params.can_compose_inline = last_can_compose_inline_;
727 rwhv->TextInputStateChanged(params);
728 }
729 }
730
OnSetAutoSize(int instance_id,const BrowserPluginHostMsg_AutoSize_Params & auto_size_params,const BrowserPluginHostMsg_ResizeGuest_Params & resize_guest_params)731 void BrowserPluginGuest::OnSetAutoSize(
732 int instance_id,
733 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
734 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
735 bool old_auto_size_enabled = auto_size_enabled_;
736 gfx::Size old_max_size = max_auto_size_;
737 gfx::Size old_min_size = min_auto_size_;
738 auto_size_enabled_ = auto_size_params.enable;
739 max_auto_size_ = auto_size_params.max_size;
740 min_auto_size_ = auto_size_params.min_size;
741 if (auto_size_enabled_ && (!old_auto_size_enabled ||
742 (old_max_size != max_auto_size_) ||
743 (old_min_size != min_auto_size_))) {
744 RecordAction(
745 base::UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
746 GetWebContents()->GetRenderViewHost()->EnableAutoResize(
747 min_auto_size_, max_auto_size_);
748 // TODO(fsamuel): If we're changing autosize parameters, then we force
749 // the guest to completely repaint itself.
750 // Ideally, we shouldn't need to do this unless |max_auto_size_| has
751 // changed.
752 // However, even in that case, layout may not change and so we may
753 // not get a full frame worth of pixels.
754 Send(new ViewMsg_Repaint(routing_id(), max_auto_size_));
755 } else if (!auto_size_enabled_ && old_auto_size_enabled) {
756 GetWebContents()->GetRenderViewHost()->DisableAutoResize(
757 resize_guest_params.view_size);
758 }
759 OnResizeGuest(instance_id_, resize_guest_params);
760 }
761
OnSetEditCommandsForNextKeyEvent(int instance_id,const std::vector<EditCommand> & edit_commands)762 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
763 int instance_id,
764 const std::vector<EditCommand>& edit_commands) {
765 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
766 edit_commands));
767 }
768
OnSetContentsOpaque(int instance_id,bool opaque)769 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) {
770 guest_opaque_ = opaque;
771 Send(new ViewMsg_SetBackgroundOpaque(routing_id(), guest_opaque_));
772 }
773
OnSetVisibility(int instance_id,bool visible)774 void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
775 guest_visible_ = visible;
776 if (embedder_visible_ && guest_visible_)
777 GetWebContents()->WasShown();
778 else
779 GetWebContents()->WasHidden();
780 }
781
OnUnlockMouse()782 void BrowserPluginGuest::OnUnlockMouse() {
783 SendMessageToEmbedder(
784 new BrowserPluginMsg_SetMouseLock(instance_id(), false));
785 }
786
OnUnlockMouseAck(int instance_id)787 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
788 // mouse_locked_ could be false here if the lock attempt was cancelled due
789 // to window focus, or for various other reasons before the guest was informed
790 // of the lock's success.
791 if (mouse_locked_)
792 Send(new ViewMsg_MouseLockLost(routing_id()));
793 mouse_locked_ = false;
794 }
795
OnCopyFromCompositingSurfaceAck(int instance_id,int request_id,const SkBitmap & bitmap)796 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
797 int instance_id,
798 int request_id,
799 const SkBitmap& bitmap) {
800 CHECK(copy_request_callbacks_.count(request_id));
801 if (!copy_request_callbacks_.count(request_id))
802 return;
803 const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
804 callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
805 copy_request_callbacks_.erase(request_id);
806 }
807
OnUpdateGeometry(int instance_id,const gfx::Rect & view_rect)808 void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
809 const gfx::Rect& view_rect) {
810 // The plugin has moved within the embedder without resizing or the
811 // embedder/container's view rect changing.
812 guest_window_rect_ = view_rect;
813 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
814 GetWebContents()->GetRenderViewHost());
815 if (rvh)
816 rvh->SendScreenRects();
817 }
818
OnHasTouchEventHandlers(bool accept)819 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
820 SendMessageToEmbedder(
821 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
822 }
823
OnSetCursor(const WebCursor & cursor)824 void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
825 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
826 }
827
828 #if defined(OS_MACOSX)
OnShowPopup(const ViewHostMsg_ShowPopup_Params & params)829 void BrowserPluginGuest::OnShowPopup(
830 const ViewHostMsg_ShowPopup_Params& params) {
831 gfx::Rect translated_bounds(params.bounds);
832 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
833 BrowserPluginPopupMenuHelper popup_menu_helper(
834 embedder_web_contents_->GetRenderViewHost(),
835 GetWebContents()->GetRenderViewHost());
836 popup_menu_helper.ShowPopupMenu(translated_bounds,
837 params.item_height,
838 params.item_font_size,
839 params.selected_item,
840 params.popup_items,
841 params.right_aligned,
842 params.allow_multiple_selection);
843 }
844 #endif
845
OnShowWidget(int route_id,const gfx::Rect & initial_pos)846 void BrowserPluginGuest::OnShowWidget(int route_id,
847 const gfx::Rect& initial_pos) {
848 GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
849 }
850
OnTakeFocus(bool reverse)851 void BrowserPluginGuest::OnTakeFocus(bool reverse) {
852 SendMessageToEmbedder(
853 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
854 }
855
OnUpdateRect(const ViewHostMsg_UpdateRect_Params & params)856 void BrowserPluginGuest::OnUpdateRect(
857 const ViewHostMsg_UpdateRect_Params& params) {
858 BrowserPluginMsg_UpdateRect_Params relay_params;
859 relay_params.view_size = params.view_size;
860 relay_params.scale_factor = params.scale_factor;
861 relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
862 params.flags);
863
864 bool size_changed = last_seen_view_size_ != params.view_size;
865 gfx::Size old_size = last_seen_view_size_;
866 last_seen_view_size_ = params.view_size;
867
868 if ((auto_size_enabled_ || last_seen_auto_size_enabled_) &&
869 size_changed && delegate_) {
870 delegate_->SizeChanged(old_size, last_seen_view_size_);
871 }
872 last_seen_auto_size_enabled_ = auto_size_enabled_;
873
874 SendMessageToEmbedder(
875 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
876 }
877
OnTextInputStateChanged(const ViewHostMsg_TextInputState_Params & params)878 void BrowserPluginGuest::OnTextInputStateChanged(
879 const ViewHostMsg_TextInputState_Params& params) {
880 // Save the state of text input so we can restore it on focus.
881 last_text_input_type_ = params.type;
882 last_input_mode_ = params.mode;
883 last_can_compose_inline_ = params.can_compose_inline;
884
885 static_cast<RenderWidgetHostViewBase*>(
886 web_contents()->GetRenderWidgetHostView())->TextInputStateChanged(params);
887 }
888
OnImeCancelComposition()889 void BrowserPluginGuest::OnImeCancelComposition() {
890 static_cast<RenderWidgetHostViewBase*>(
891 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
892 }
893
894 #if defined(OS_MACOSX) || defined(USE_AURA)
OnImeCompositionRangeChanged(const gfx::Range & range,const std::vector<gfx::Rect> & character_bounds)895 void BrowserPluginGuest::OnImeCompositionRangeChanged(
896 const gfx::Range& range,
897 const std::vector<gfx::Rect>& character_bounds) {
898 static_cast<RenderWidgetHostViewBase*>(
899 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
900 range, character_bounds);
901 }
902 #endif
903
904 } // namespace content
905