blob: a4cfbea37afc0c1039ac932af54443ed84b296de [file] [log] [blame]
[email protected]7a846df2012-09-20 19:17:391// 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
[email protected]4aefa0c2012-10-04 20:01:199#include "base/string_util.h"
[email protected]c88b2a562012-10-27 03:36:5610#include "content/browser/browser_plugin/browser_plugin_embedder.h"
[email protected]7a846df2012-09-20 19:17:3911#include "content/browser/browser_plugin/browser_plugin_guest_helper.h"
12#include "content/browser/browser_plugin/browser_plugin_host_factory.h"
13#include "content/browser/renderer_host/render_view_host_impl.h"
14#include "content/browser/renderer_host/render_widget_host_impl.h"
15#include "content/browser/web_contents/web_contents_impl.h"
16#include "content/common/browser_plugin_messages.h"
[email protected]f8501b12012-12-07 04:55:4317#include "content/common/content_constants_internal.h"
[email protected]a7fac9a2012-12-18 23:26:0718#include "content/common/drag_messages.h"
[email protected]7a846df2012-09-20 19:17:3919#include "content/common/view_messages.h"
[email protected]972cdd82012-10-12 00:19:0320#include "content/port/browser/render_view_host_delegate_view.h"
[email protected]31942c82012-10-05 17:01:5421#include "content/public/browser/notification_service.h"
22#include "content/public/browser/notification_types.h"
[email protected]7a846df2012-09-20 19:17:3923#include "content/public/browser/render_process_host.h"
24#include "content/public/browser/render_widget_host_view.h"
[email protected]31942c82012-10-05 17:01:5425#include "content/public/browser/resource_request_details.h"
[email protected]2fae2c42012-10-03 21:20:0426#include "content/public/browser/user_metrics.h"
[email protected]1a0c0052012-11-05 21:06:2627#include "content/public/browser/web_contents_view.h"
[email protected]7a846df2012-09-20 19:17:3928#include "content/public/common/result_codes.h"
29#include "content/browser/browser_plugin/browser_plugin_host_factory.h"
[email protected]4aefa0c2012-10-04 20:01:1930#include "net/base/net_errors.h"
[email protected]972cdd82012-10-12 00:19:0331#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
[email protected]7a846df2012-09-20 19:17:3932#include "ui/surface/transport_dib.h"
[email protected]972cdd82012-10-12 00:19:0333#include "webkit/glue/webdropdata.h"
[email protected]31942c82012-10-05 17:01:5434#include "webkit/glue/resource_type.h"
[email protected]7a846df2012-09-20 19:17:3935
[email protected]4f89d9d2012-12-12 01:38:4836#if defined(OS_MACOSX)
37#include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
38#endif
39
[email protected]7a846df2012-09-20 19:17:3940namespace content {
41
42// static
43BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
44
[email protected]dd8c8232012-11-03 00:49:3645BrowserPluginGuest::BrowserPluginGuest(
46 int instance_id,
47 WebContentsImpl* web_contents,
[email protected]dd8c8232012-11-03 00:49:3648 const BrowserPluginHostMsg_CreateGuest_Params& params)
[email protected]7a846df2012-09-20 19:17:3949 : WebContentsObserver(web_contents),
[email protected]19c1c373e2012-10-17 14:12:1850 embedder_web_contents_(NULL),
[email protected]7a846df2012-09-20 19:17:3951 instance_id_(instance_id),
52#if defined(OS_WIN)
53 damage_buffer_size_(0),
[email protected]ffba8bf2012-11-26 23:53:3254 remote_damage_buffer_handle_(0),
[email protected]7a846df2012-09-20 19:17:3955#endif
[email protected]fda17082012-10-04 00:25:2156 damage_buffer_scale_factor_(1.0f),
[email protected]7a846df2012-09-20 19:17:3957 guest_hang_timeout_(
[email protected]f8501b12012-12-07 04:55:4358 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
[email protected]dd8c8232012-11-03 00:49:3659 focused_(params.focused),
60 visible_(params.visible),
[email protected]ffba8bf2012-11-26 23:53:3261 auto_size_enabled_(params.auto_size_params.enable),
62 max_auto_size_(params.auto_size_params.max_size),
63 min_auto_size_(params.auto_size_params.min_size) {
[email protected]7a846df2012-09-20 19:17:3964 DCHECK(web_contents);
[email protected]b5a40842012-11-28 15:26:1165}
66
[email protected]3997b1b22012-12-20 01:02:5467bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
68 const IPC::Message& message) {
69 bool handled = true;
70 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
71 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
72 OnDragStatusUpdate)
73 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Go, OnGo)
74 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
75 OnHandleInputEvent)
76 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Reload, OnReload)
77 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
78 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetSize)
79 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
80 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
81 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Stop, OnStop)
82 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_TerminateGuest, OnTerminateGuest)
83 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateRect_ACK, OnUpdateRectACK)
84 IPC_MESSAGE_UNHANDLED(handled = false)
85 IPC_END_MESSAGE_MAP()
86 return handled;
87}
88
89void BrowserPluginGuest::Initialize(
90 const BrowserPluginHostMsg_CreateGuest_Params& params,
[email protected]b5a40842012-11-28 15:26:1191 content::RenderViewHost* render_view_host) {
[email protected]7a846df2012-09-20 19:17:3992 // |render_view_host| manages the ownership of this BrowserPluginGuestHelper.
93 new BrowserPluginGuestHelper(this, render_view_host);
[email protected]31942c82012-10-05 17:01:5494
95 notification_registrar_.Add(
96 this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
[email protected]b5a40842012-11-28 15:26:1197 content::Source<content::WebContents>(web_contents()));
[email protected]3997b1b22012-12-20 01:02:5498
99 OnSetSize(instance_id_, params.auto_size_params, params.resize_guest_params);
[email protected]7a846df2012-09-20 19:17:39100}
101
102BrowserPluginGuest::~BrowserPluginGuest() {
103}
104
105// static
106BrowserPluginGuest* BrowserPluginGuest::Create(
107 int instance_id,
108 WebContentsImpl* web_contents,
[email protected]dd8c8232012-11-03 00:49:36109 const BrowserPluginHostMsg_CreateGuest_Params& params) {
[email protected]2fae2c42012-10-03 21:20:04110 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create"));
[email protected]7a846df2012-09-20 19:17:39111 if (factory_) {
112 return factory_->CreateBrowserPluginGuest(instance_id,
113 web_contents,
[email protected]dd8c8232012-11-03 00:49:36114 params);
[email protected]7a846df2012-09-20 19:17:39115 }
[email protected]b5a40842012-11-28 15:26:11116 return new BrowserPluginGuest(instance_id, web_contents,params);
[email protected]7a846df2012-09-20 19:17:39117}
118
[email protected]3997b1b22012-12-20 01:02:54119void BrowserPluginGuest::UpdateVisibility() {
120 OnSetVisibility(instance_id_, visible());
121}
122
[email protected]31942c82012-10-05 17:01:54123void BrowserPluginGuest::Observe(int type,
124 const NotificationSource& source,
125 const NotificationDetails& details) {
126 switch (type) {
127 case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
128 DCHECK_EQ(Source<WebContents>(source).ptr(), web_contents());
129 ResourceRedirectDetails* resource_redirect_details =
130 Details<ResourceRedirectDetails>(details).ptr();
131 bool is_top_level =
132 resource_redirect_details->resource_type == ResourceType::MAIN_FRAME;
133 LoadRedirect(resource_redirect_details->url,
134 resource_redirect_details->new_url,
135 is_top_level);
136 break;
137 }
138 default:
139 NOTREACHED() << "Unexpected notification sent.";
140 break;
141 }
142}
143
[email protected]4aefa0c2012-10-04 20:01:19144bool BrowserPluginGuest::CanDownload(RenderViewHost* render_view_host,
145 int request_id,
146 const std::string& request_method) {
147 // TODO(fsamuel): We disable downloads in guests for now, but we will later
148 // expose API to allow embedders to handle them.
149 // Note: it seems content_shell ignores this. This should be fixed
150 // for debugging and test purposes.
151 return false;
152}
153
[email protected]14d59b332012-10-05 01:40:28154bool BrowserPluginGuest::HandleContextMenu(
155 const ContextMenuParams& params) {
156 // TODO(fsamuel): We have a do nothing context menu handler for now until
157 // we implement the Apps Context Menu API for Browser Plugin (see
158 // http://crbug.com/140315).
159 return true;
160}
161
[email protected]7a846df2012-09-20 19:17:39162void BrowserPluginGuest::RendererUnresponsive(WebContents* source) {
[email protected]f8501b12012-12-07 04:55:43163 int process_id =
164 web_contents()->GetRenderProcessHost()->GetID();
165 SendMessageToEmbedder(
166 new BrowserPluginMsg_GuestUnresponsive(embedder_routing_id(),
167 instance_id(),
168 process_id));
[email protected]2fae2c42012-10-03 21:20:04169 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Hung"));
[email protected]7a846df2012-09-20 19:17:39170}
171
[email protected]f8501b12012-12-07 04:55:43172void BrowserPluginGuest::RendererResponsive(WebContents* source) {
173 int process_id =
174 web_contents()->GetRenderProcessHost()->GetID();
175 SendMessageToEmbedder(
176 new BrowserPluginMsg_GuestResponsive(embedder_routing_id(),
177 instance_id(),
178 process_id));
179 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Responsive"));
180}
181
[email protected]19c1c373e2012-10-17 14:12:18182void BrowserPluginGuest::RunFileChooser(WebContents* web_contents,
183 const FileChooserParams& params) {
184 embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params);
185}
186
[email protected]6a121f22012-10-30 03:19:48187bool BrowserPluginGuest::ShouldFocusPageAfterCrash() {
188 // Rather than managing focus in WebContentsImpl::RenderViewReady, we will
189 // manage the focus ourselves.
190 return false;
191}
192
[email protected]e17b7c62012-09-21 21:05:46193WebContents* BrowserPluginGuest::GetWebContents() {
194 return web_contents();
195}
196
[email protected]1a0c0052012-11-05 21:06:26197TransportDIB* BrowserPluginGuest::GetDamageBufferFromEmbedder(
[email protected]1a0c0052012-11-05 21:06:26198 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
199 TransportDIB* damage_buffer = NULL;
200#if defined(OS_WIN)
201 // On Windows we need to duplicate the handle from the remote process.
202 HANDLE section;
[email protected]3997b1b22012-12-20 01:02:54203 DuplicateHandle(embedder_web_contents_->GetRenderProcessHost()->GetHandle(),
[email protected]1a0c0052012-11-05 21:06:26204 params.damage_buffer_id.handle,
205 GetCurrentProcess(),
206 &section,
207 STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE,
208 FALSE,
209 0);
210 damage_buffer = TransportDIB::Map(section);
211#elif defined(OS_MACOSX)
212 // On OSX, we need the handle to map the transport dib.
213 damage_buffer = TransportDIB::Map(params.damage_buffer_handle);
214#elif defined(OS_ANDROID)
215 damage_buffer = TransportDIB::Map(params.damage_buffer_id);
216#elif defined(OS_POSIX)
217 damage_buffer = TransportDIB::Map(params.damage_buffer_id.shmkey);
218#endif // defined(OS_POSIX)
219 DCHECK(damage_buffer);
220 return damage_buffer;
221}
222
[email protected]7a846df2012-09-20 19:17:39223void BrowserPluginGuest::SetDamageBuffer(
224 TransportDIB* damage_buffer,
225#if defined(OS_WIN)
226 int damage_buffer_size,
[email protected]ffba8bf2012-11-26 23:53:32227 TransportDIB::Handle remote_handle,
[email protected]7a846df2012-09-20 19:17:39228#endif
229 const gfx::Size& damage_view_size,
230 float scale_factor) {
231 // Sanity check: Verify that we've correctly shared the damage buffer memory
232 // between the embedder and browser processes.
233 DCHECK(*static_cast<unsigned int*>(damage_buffer->memory()) == 0xdeadbeef);
234 damage_buffer_.reset(damage_buffer);
235#if defined(OS_WIN)
236 damage_buffer_size_ = damage_buffer_size;
[email protected]ffba8bf2012-11-26 23:53:32237 remote_damage_buffer_handle_ = remote_handle;
[email protected]7a846df2012-09-20 19:17:39238#endif
239 damage_view_size_ = damage_view_size;
240 damage_buffer_scale_factor_ = scale_factor;
241}
242
[email protected]ca61ce142012-11-27 21:32:57243gfx::Point BrowserPluginGuest::GetScreenCoordinates(
244 const gfx::Point& relative_position) const {
245 gfx::Point screen_pos(relative_position);
246 screen_pos += guest_window_rect_.OffsetFromOrigin();
247 return screen_pos;
248}
249
[email protected]fb325d122012-11-20 23:58:05250int BrowserPluginGuest::embedder_routing_id() const {
251 return embedder_web_contents_->GetRoutingID();
252}
253
[email protected]240b5c32012-11-09 19:17:18254bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
255 return size.width() <= max_auto_size_.width() &&
256 size.height() <= max_auto_size_.height();
257}
258
[email protected]4aefa0c2012-10-04 20:01:19259void BrowserPluginGuest::DidStartProvisionalLoadForFrame(
260 int64 frame_id,
[email protected]d37c33e2012-10-12 13:35:13261 int64 parent_frame_id,
[email protected]4aefa0c2012-10-04 20:01:19262 bool is_main_frame,
263 const GURL& validated_url,
264 bool is_error_page,
265 RenderViewHost* render_view_host) {
266 // Inform the embedder of the loadStart.
267 SendMessageToEmbedder(
[email protected]fb325d122012-11-20 23:58:05268 new BrowserPluginMsg_LoadStart(embedder_routing_id(),
269 instance_id(),
[email protected]4aefa0c2012-10-04 20:01:19270 validated_url,
271 is_main_frame));
272}
273
274void BrowserPluginGuest::DidFailProvisionalLoad(
275 int64 frame_id,
276 bool is_main_frame,
277 const GURL& validated_url,
278 int error_code,
279 const string16& error_description,
280 RenderViewHost* render_view_host) {
281 // Translate the |error_code| into an error string.
282 std::string error_type;
283 RemoveChars(net::ErrorToString(error_code), "net::", &error_type);
284 // Inform the embedder of the loadAbort.
285 SendMessageToEmbedder(
[email protected]fb325d122012-11-20 23:58:05286 new BrowserPluginMsg_LoadAbort(embedder_routing_id(),
287 instance_id(),
[email protected]4aefa0c2012-10-04 20:01:19288 validated_url,
289 is_main_frame,
290 error_type));
291}
292
[email protected]a7fac9a2012-12-18 23:26:07293void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
294 embedder_web_contents_->Send(msg);
295}
296
[email protected]31942c82012-10-05 17:01:54297void BrowserPluginGuest::LoadRedirect(
298 const GURL& old_url,
299 const GURL& new_url,
300 bool is_top_level) {
301 SendMessageToEmbedder(
[email protected]fb325d122012-11-20 23:58:05302 new BrowserPluginMsg_LoadRedirect(embedder_routing_id(),
303 instance_id(),
304 old_url,
305 new_url,
306 is_top_level));
[email protected]31942c82012-10-05 17:01:54307}
308
[email protected]7a846df2012-09-20 19:17:39309void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
310 int64 frame_id,
311 bool is_main_frame,
312 const GURL& url,
313 PageTransition transition_type,
314 RenderViewHost* render_view_host) {
315 // Inform its embedder of the updated URL.
[email protected]eb92f632012-10-19 00:56:12316 BrowserPluginMsg_LoadCommit_Params params;
[email protected]81289ac32012-10-11 21:50:06317 params.url = url;
318 params.is_top_level = is_main_frame;
319 params.process_id = render_view_host->GetProcess()->GetID();
320 params.current_entry_index =
321 web_contents()->GetController().GetCurrentEntryIndex();
322 params.entry_count =
323 web_contents()->GetController().GetEntryCount();
324 SendMessageToEmbedder(
[email protected]fb325d122012-11-20 23:58:05325 new BrowserPluginMsg_LoadCommit(embedder_routing_id(),
326 instance_id(),
327 params));
[email protected]81289ac32012-10-11 21:50:06328 RecordAction(UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
[email protected]7a846df2012-09-20 19:17:39329}
330
[email protected]eb92f632012-10-19 00:56:12331void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) {
[email protected]fb325d122012-11-20 23:58:05332 SendMessageToEmbedder(new BrowserPluginMsg_LoadStop(embedder_routing_id(),
333 instance_id()));
[email protected]eb92f632012-10-19 00:56:12334}
335
[email protected]c88b2a562012-10-27 03:36:56336void BrowserPluginGuest::RenderViewReady() {
337 // TODO(fsamuel): Investigate whether it's possible to update state earlier
[email protected]dba9bd22012-12-06 23:04:03338 // here (see http://crbug.com/158151).
[email protected]93f59c42012-11-27 20:35:29339 Send(new ViewMsg_SetFocus(routing_id(), focused_));
[email protected]3997b1b22012-12-20 01:02:54340 UpdateVisibility();
[email protected]ffba8bf2012-11-26 23:53:32341 if (auto_size_enabled_) {
[email protected]240b5c32012-11-09 19:17:18342 web_contents()->GetRenderViewHost()->EnableAutoResize(
343 min_auto_size_, max_auto_size_);
344 } else {
345 web_contents()->GetRenderViewHost()->DisableAutoResize(damage_view_size_);
346 }
[email protected]c88b2a562012-10-27 03:36:56347}
348
[email protected]7a846df2012-09-20 19:17:39349void BrowserPluginGuest::RenderViewGone(base::TerminationStatus status) {
[email protected]199961a82012-10-20 00:28:21350 int process_id = web_contents()->GetRenderProcessHost()->GetID();
[email protected]fb325d122012-11-20 23:58:05351 SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(embedder_routing_id(),
352 instance_id(),
[email protected]199961a82012-10-20 00:28:21353 process_id,
354 status));
[email protected]2fae2c42012-10-03 21:20:04355 switch (status) {
356 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
357 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Killed"));
358 break;
359 case base::TERMINATION_STATUS_PROCESS_CRASHED:
360 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Crashed"));
361 break;
362 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
363 RecordAction(UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
364 break;
365 default:
366 break;
367 }
[email protected]7a846df2012-09-20 19:17:39368}
369
[email protected]a7fac9a2012-12-18 23:26:07370bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
371 bool handled = true;
372 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
373 IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK, OnHandleInputEventAck)
374 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
375 OnHasTouchEventHandlers)
376 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
377 #if defined(OS_MACOSX)
378 // MacOSX creates and populates platform-specific select drop-down menus
379 // whereas other platforms merely create a popup window that the guest
380 // renderer process paints inside.
381 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
382 #endif
383 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
384 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
385 IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
386 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
387 IPC_MESSAGE_UNHANDLED(handled = false)
388 IPC_END_MESSAGE_MAP()
389 return handled;
390}
391
[email protected]3997b1b22012-12-20 01:02:54392void BrowserPluginGuest::OnGo(int instance_id, int relative_index) {
393 web_contents()->GetController().GoToOffset(relative_index);
394}
395
396void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
397 WebKit::WebDragStatus drag_status,
398 const WebDropData& drop_data,
399 WebKit::WebDragOperationsMask mask,
400 const gfx::Point& location) {
401 RenderViewHost* host = web_contents()->GetRenderViewHost();
402 switch (drag_status) {
403 case WebKit::WebDragStatusEnter:
404 host->DragTargetDragEnter(drop_data, location, location, mask, 0);
405 break;
406 case WebKit::WebDragStatusOver:
407 host->DragTargetDragOver(location, location, mask, 0);
408 break;
409 case WebKit::WebDragStatusLeave:
410 host->DragTargetDragLeave();
411 break;
412 case WebKit::WebDragStatusDrop:
413 host->DragTargetDrop(location, location, 0);
414 break;
415 case WebKit::WebDragStatusUnknown:
416 NOTREACHED();
417 }
418}
419
420void BrowserPluginGuest::OnHandleInputEvent(
421 int instance_id,
422 const gfx::Rect& guest_window_rect,
423 const WebKit::WebInputEvent* event) {
424 guest_window_rect_ = guest_window_rect;
425 guest_screen_rect_ = guest_window_rect;
426 guest_screen_rect_.Offset(
427 embedder_web_contents_->GetRenderViewHost()->GetView()->
428 GetViewBounds().OffsetFromOrigin());
429 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
430 web_contents()->GetRenderViewHost());
431
432 IPC::Message* message = NULL;
433
434 // TODO(fsamuel): What should we do for keyboard_shortcut field?
435 if (event->type == WebKit::WebInputEvent::KeyDown) {
436 CHECK_EQ(sizeof(WebKit::WebKeyboardEvent), event->size);
437 WebKit::WebKeyboardEvent key_event;
438 memcpy(&key_event, event, event->size);
439 key_event.type = WebKit::WebInputEvent::RawKeyDown;
440 message = new ViewMsg_HandleInputEvent(routing_id(), &key_event, false);
441 } else {
442 message = new ViewMsg_HandleInputEvent(routing_id(), event, false);
443 }
444
445 guest_rvh->Send(message);
446 guest_rvh->StartHangMonitorTimeout(guest_hang_timeout_);
447}
448
449void BrowserPluginGuest::OnReload(int instance_id) {
450 // TODO(fsamuel): Don't check for repost because we don't want to show
451 // Chromium's repost warning. We might want to implement a separate API
452 // for registering a callback if a repost is about to happen.
453 web_contents()->GetController().Reload(false);
454}
455
456void BrowserPluginGuest::OnResizeGuest(
457 int instance_id,
458 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
459 // BrowserPlugin manages resize flow control itself and does not depend
460 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
461 // here. If we are setting the size for the first time before navigating then
462 // BrowserPluginGuest does not yet have a RenderViewHost.
463 if (web_contents()->GetRenderViewHost()) {
464 RenderWidgetHostImpl* render_widget_host =
465 RenderWidgetHostImpl::From(web_contents()->GetRenderViewHost());
466 render_widget_host->ResetSizeAndRepaintPendingFlags();
467 }
468 if (!TransportDIB::is_valid_id(params.damage_buffer_id)) {
469 // Invalid transport dib, so just resize the WebContents.
470 if (!params.view_size.IsEmpty())
471 web_contents()->GetView()->SizeContents(params.view_size);
472 return;
473 }
474 TransportDIB* damage_buffer = GetDamageBufferFromEmbedder(params);
475 SetDamageBuffer(damage_buffer,
476#if defined(OS_WIN)
477 params.damage_buffer_size,
478 params.damage_buffer_id.handle,
479#endif
480 params.view_size,
481 params.scale_factor);
482 web_contents()->GetView()->SizeContents(params.view_size);
483}
484
485void BrowserPluginGuest::OnSetSize(
486 int instance_id,
487 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
488 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
489 bool old_auto_size_enabled = auto_size_enabled_;
490 gfx::Size old_max_size = max_auto_size_;
491 gfx::Size old_min_size = min_auto_size_;
492 auto_size_enabled_ = auto_size_params.enable;
493 max_auto_size_ = auto_size_params.max_size;
494 min_auto_size_ = auto_size_params.min_size;
495 if (auto_size_enabled_ && (!old_auto_size_enabled ||
496 (old_max_size != max_auto_size_) ||
497 (old_min_size != min_auto_size_))) {
498 web_contents()->GetRenderViewHost()->EnableAutoResize(
499 min_auto_size_, max_auto_size_);
500 // TODO(fsamuel): If we're changing autosize parameters, then we force
501 // the guest to completely repaint itself, because BrowserPlugin has
502 // allocated a new damage buffer and expects a full frame of pixels.
503 // Ideally, we shouldn't need to do this because we shouldn't need to
504 // allocate a new damage buffer unless |max_auto_size_| has changed.
505 // However, even in that case, layout may not change and so we may
506 // not get a full frame worth of pixels.
507 web_contents()->GetRenderViewHost()->Send(new ViewMsg_Repaint(
508 web_contents()->GetRenderViewHost()->GetRoutingID(),
509 max_auto_size_));
510 } else if (!auto_size_enabled_ && old_auto_size_enabled) {
511 web_contents()->GetRenderViewHost()->DisableAutoResize(
512 resize_guest_params.view_size);
513 }
514 OnResizeGuest(instance_id_, resize_guest_params);
515}
516
517void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
518 if (focused_ == focused)
519 return;
520 focused_ = focused;
521 Send(new ViewMsg_SetFocus(routing_id(), focused));
522}
523
524void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
525 visible_ = visible;
526 BrowserPluginEmbedder* embedder =
527 embedder_web_contents_->GetBrowserPluginEmbedder();
528 if (embedder->visible() && visible)
529 web_contents()->WasShown();
530 else
531 web_contents()->WasHidden();
532}
533
534void BrowserPluginGuest::OnStop(int instance_id) {
535 web_contents()->Stop();
536}
537
538void BrowserPluginGuest::OnTerminateGuest(int instance_id) {
539 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Terminate"));
540 base::ProcessHandle process_handle =
541 web_contents()->GetRenderProcessHost()->GetHandle();
542 base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
543}
544
545void BrowserPluginGuest::OnUpdateRectACK(
546 int instance_id,
547 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
548 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
549 RenderViewHost* render_view_host = web_contents()->GetRenderViewHost();
550 render_view_host->Send(
551 new ViewMsg_UpdateRect_ACK(render_view_host->GetRoutingID()));
552 OnSetSize(instance_id_, auto_size_params, resize_guest_params);
553}
554
[email protected]a7fac9a2012-12-18 23:26:07555void BrowserPluginGuest::OnHandleInputEventAck(
556 WebKit::WebInputEvent::Type event_type,
557 InputEventAckState ack_result) {
558 RenderViewHostImpl* guest_rvh =
559 static_cast<RenderViewHostImpl*>(web_contents()->GetRenderViewHost());
560 guest_rvh->StopHangMonitorTimeout();
561}
562
563void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
564 SendMessageToEmbedder(
565 new BrowserPluginMsg_ShouldAcceptTouchEvents(embedder_routing_id(),
566 instance_id(),
567 accept));
568}
569
570void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
571 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(embedder_routing_id(),
572 instance_id(),
573 cursor));
574}
575
576#if defined(OS_MACOSX)
577void BrowserPluginGuest::OnShowPopup(
578 const ViewHostMsg_ShowPopup_Params& params) {
579 gfx::Rect translated_bounds(params.bounds);
580 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
581 BrowserPluginPopupMenuHelper popup_menu_helper(
582 embedder_web_contents_->GetRenderViewHost(),
583 web_contents()->GetRenderViewHost());
584 popup_menu_helper.ShowPopupMenu(translated_bounds,
585 params.item_height,
586 params.item_font_size,
587 params.selected_item,
588 params.popup_items,
589 params.right_aligned,
590 params.allow_multiple_selection);
591}
592#endif
593
594void BrowserPluginGuest::OnShowWidget(int route_id,
595 const gfx::Rect& initial_pos) {
596 gfx::Rect screen_pos(initial_pos);
597 screen_pos.Offset(guest_screen_rect_.OffsetFromOrigin());
598 static_cast<WebContentsImpl*>(web_contents())->ShowCreatedWidget(route_id,
599 screen_pos);
600}
601
602void BrowserPluginGuest::OnTakeFocus(bool reverse) {
603 SendMessageToEmbedder(
604 new BrowserPluginMsg_AdvanceFocus(embedder_routing_id(),
605 instance_id(),
606 reverse));
607}
608
609void BrowserPluginGuest::OnUpdateDragCursor(
610 WebKit::WebDragOperation operation) {
611 RenderViewHostImpl* embedder_render_view_host =
612 static_cast<RenderViewHostImpl*>(
613 embedder_web_contents_->GetRenderViewHost());
614 CHECK(embedder_render_view_host);
615 RenderViewHostDelegateView* view =
616 embedder_render_view_host->GetDelegate()->GetDelegateView();
617 if (view)
618 view->UpdateDragCursor(operation);
619}
620
621void BrowserPluginGuest::OnUpdateRect(
622 const ViewHostMsg_UpdateRect_Params& params) {
623
624 BrowserPluginMsg_UpdateRect_Params relay_params;
625 relay_params.view_size = params.view_size;
626 relay_params.scale_factor = params.scale_factor;
627 relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
628 params.flags);
629
630 // HW accelerated case, acknowledge resize only
631 if (!params.needs_ack) {
632#if defined(OS_MACOSX)
633 relay_params.damage_buffer_identifier = 0;
634#else
635 relay_params.damage_buffer_identifier = TransportDIB::DefaultHandleValue();
636#endif
637 SendMessageToEmbedder(new BrowserPluginMsg_UpdateRect(
638 embedder_routing_id(),
639 instance_id(),
640 relay_params));
641 return;
642 }
643
644 RenderViewHost* render_view_host = web_contents()->GetRenderViewHost();
645 // Only copy damage if the guest is in autosize mode and the guest's view size
646 // is less than the maximum size or the guest's view size is equal to the
647 // damage buffer's size and the guest's scale factor is equal to the damage
648 // buffer's scale factor.
649 // The scaling change can happen due to asynchronous updates of the DPI on a
650 // resolution change.
651 if (((auto_size_enabled_ && InAutoSizeBounds(params.view_size)) ||
652 (params.view_size.width() == damage_view_size().width() &&
653 params.view_size.height() == damage_view_size().height())) &&
654 params.scale_factor == damage_buffer_scale_factor()) {
655 TransportDIB* dib = render_view_host->GetProcess()->
656 GetTransportDIB(params.bitmap);
657 if (dib) {
658#if defined(OS_WIN)
659 size_t guest_damage_buffer_size = params.bitmap_rect.width() *
660 params.bitmap_rect.height() * 4;
661 size_t embedder_damage_buffer_size = damage_buffer_size_;
662#else
663 size_t guest_damage_buffer_size = dib->size();
664 size_t embedder_damage_buffer_size = damage_buffer_->size();
665#endif
666 void* guest_memory = dib->memory();
667 void* embedder_memory = damage_buffer_->memory();
668 size_t size = std::min(guest_damage_buffer_size,
669 embedder_damage_buffer_size);
670 memcpy(embedder_memory, guest_memory, size);
671 }
672 }
673#if defined(OS_MACOSX)
674 relay_params.damage_buffer_identifier = damage_buffer_->id();
675#elif defined(OS_WIN)
676 // On Windows, the handle used locally differs from the handle received from
677 // the embedder process, since we duplicate the remote handle.
678 relay_params.damage_buffer_identifier = remote_damage_buffer_handle_;
679#else
680 relay_params.damage_buffer_identifier = damage_buffer_->handle();
681#endif
682 relay_params.bitmap_rect = params.bitmap_rect;
683 relay_params.scroll_delta = params.scroll_delta;
684 relay_params.scroll_rect = params.scroll_rect;
685 relay_params.copy_rects = params.copy_rects;
686
687 SendMessageToEmbedder(new BrowserPluginMsg_UpdateRect(embedder_routing_id(),
688 instance_id(),
689 relay_params));
[email protected]7a846df2012-09-20 19:17:39690}
691
692} // namespace content