blob: cffa56c91676232826f2edac6284b3c01d5027fb [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]cf200a562013-05-03 16:24:299#include "base/command_line.h"
[email protected]b371a5652013-02-20 11:25:5110#include "base/message_loop.h"
[email protected]4aefa0c2012-10-04 20:01:1911#include "base/string_util.h"
[email protected]29aec7082013-01-25 06:54:0112#include "base/utf_string_conversions.h"
[email protected]c88b2a562012-10-27 03:36:5613#include "content/browser/browser_plugin/browser_plugin_embedder.h"
[email protected]7a846df2012-09-20 19:17:3914#include "content/browser/browser_plugin/browser_plugin_guest_helper.h"
[email protected]8eb04562013-03-06 03:41:1415#include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
[email protected]7a846df2012-09-20 19:17:3916#include "content/browser/browser_plugin/browser_plugin_host_factory.h"
[email protected]f85f5032013-04-03 09:01:5417#include "content/browser/browser_thread_impl.h"
18#include "content/browser/loader/resource_dispatcher_host_impl.h"
[email protected]7a846df2012-09-20 19:17:3919#include "content/browser/renderer_host/render_view_host_impl.h"
20#include "content/browser/renderer_host/render_widget_host_impl.h"
21#include "content/browser/web_contents/web_contents_impl.h"
[email protected]c4538072013-03-18 02:17:5522#include "content/browser/web_contents/web_contents_view_guest.h"
[email protected]8eb04562013-03-06 03:41:1423#include "content/common/browser_plugin/browser_plugin_constants.h"
[email protected]703dd662013-03-05 07:37:4224#include "content/common/browser_plugin/browser_plugin_messages.h"
[email protected]f8501b12012-12-07 04:55:4325#include "content/common/content_constants_internal.h"
[email protected]a7fac9a2012-12-18 23:26:0726#include "content/common/drag_messages.h"
[email protected]cc8ed212013-02-07 22:31:0327#include "content/common/gpu/gpu_messages.h"
[email protected]c084330e02013-04-27 01:08:1528#include "content/common/input_messages.h"
[email protected]c006fb52013-03-01 09:36:4529#include "content/common/view_messages.h"
[email protected]972cdd82012-10-12 00:19:0330#include "content/port/browser/render_view_host_delegate_view.h"
[email protected]8eb04562013-03-06 03:41:1431#include "content/public/browser/browser_context.h"
[email protected]44703cc72013-01-24 04:56:0632#include "content/public/browser/content_browser_client.h"
[email protected]e4a55a52013-03-09 01:32:4933#include "content/public/browser/geolocation_permission_context.h"
[email protected]31942c82012-10-05 17:01:5434#include "content/public/browser/notification_service.h"
35#include "content/public/browser/notification_types.h"
[email protected]7a846df2012-09-20 19:17:3936#include "content/public/browser/render_process_host.h"
37#include "content/public/browser/render_widget_host_view.h"
[email protected]31942c82012-10-05 17:01:5438#include "content/public/browser/resource_request_details.h"
[email protected]2fae2c42012-10-03 21:20:0439#include "content/public/browser/user_metrics.h"
[email protected]1a0c0052012-11-05 21:06:2640#include "content/public/browser/web_contents_view.h"
[email protected]cf200a562013-05-03 16:24:2941#include "content/public/common/content_switches.h"
[email protected]c006fb52013-03-01 09:36:4542#include "content/public/common/media_stream_request.h"
[email protected]7a846df2012-09-20 19:17:3943#include "content/public/common/result_codes.h"
[email protected]4aefa0c2012-10-04 20:01:1944#include "net/base/net_errors.h"
[email protected]f85f5032013-04-03 09:01:5445#include "net/url_request/url_request.h"
[email protected]972cdd82012-10-12 00:19:0346#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
[email protected]6dd17a8a2013-05-01 05:50:1047#include "ui/base/keycodes/keyboard_codes.h"
[email protected]7a846df2012-09-20 19:17:3948#include "ui/surface/transport_dib.h"
[email protected]31942c82012-10-05 17:01:5449#include "webkit/glue/resource_type.h"
[email protected]f8f0fc22013-01-18 03:29:2650#include "webkit/glue/webdropdata.h"
[email protected]7a846df2012-09-20 19:17:3951
[email protected]4f89d9d2012-12-12 01:38:4852#if defined(OS_MACOSX)
53#include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
54#endif
55
[email protected]7a846df2012-09-20 19:17:3956namespace content {
57
58// static
59BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
60
[email protected]cf4c9e052013-05-04 04:53:4461// Parent class for the various types of permission requests, each of which
62// should be able to handle the response to their permission request.
63class BrowserPluginGuest::PermissionRequest {
64 public:
65 virtual void Respond(bool should_allow) = 0;
66 virtual ~PermissionRequest() {}
67 protected:
68 PermissionRequest() {}
69};
70
71class BrowserPluginGuest::DownloadRequest : public PermissionRequest {
72 public:
73 explicit DownloadRequest(base::Callback<void(bool)> callback)
74 : callback_(callback) {}
75 virtual void Respond(bool should_allow) OVERRIDE {
76 callback_.Run(should_allow);
77 }
78 virtual ~DownloadRequest() {}
79 private:
80 base::Callback<void(bool)> callback_;
81};
82
83class BrowserPluginGuest::GeolocationRequest : public PermissionRequest {
84 public:
85 GeolocationRequest(GeolocationCallback callback,
86 int bridge_id,
87 BrowserPluginGuest* guest,
88 base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory)
89 : callback_(callback),
90 bridge_id_(bridge_id),
91 guest_(guest),
92 weak_ptr_factory_(weak_ptr_factory) {}
93
94 virtual void Respond(bool should_allow) OVERRIDE {
95 WebContents* web_contents = guest_->embedder_web_contents();
96 if (should_allow && web_contents) {
97 // If renderer side embedder decides to allow gelocation, we need to check
98 // if the app/embedder itself has geolocation access.
99 BrowserContext* browser_context = web_contents->GetBrowserContext();
100 if (browser_context) {
101 GeolocationPermissionContext* geolocation_context =
102 browser_context->GetGeolocationPermissionContext();
103 if (geolocation_context) {
104 base::Callback<void(bool)> geolocation_callback = base::Bind(
105 &BrowserPluginGuest::SetGeolocationPermission,
106 weak_ptr_factory_->GetWeakPtr(),
107 callback_,
108 bridge_id_);
109 geolocation_context->RequestGeolocationPermission(
110 web_contents->GetRenderProcessHost()->GetID(),
111 web_contents->GetRoutingID(),
112 // The geolocation permission request here is not initiated
113 // through WebGeolocationPermissionRequest. We are only interested
114 // in the fact whether the embedder/app has geolocation
115 // permission. Therefore we use an invalid |bridge_id|.
116 -1 /* bridge_id */,
117 web_contents->GetURL(),
118 geolocation_callback);
119 return;
120 }
121 }
122 }
123 guest_->SetGeolocationPermission(callback_, bridge_id_, false);
124 }
125 virtual ~GeolocationRequest() {}
126 private:
127 base::Callback<void(bool)> callback_;
128 int bridge_id_;
129 BrowserPluginGuest* guest_;
130 base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory_;
131};
132
133class BrowserPluginGuest::MediaRequest : public PermissionRequest {
134 public:
135 MediaRequest(const MediaStreamRequest& request,
136 const MediaResponseCallback& callback,
137 BrowserPluginGuest* guest)
138 : request_(request),
139 callback_(callback),
140 guest_(guest) {}
141
142 virtual void Respond(bool should_allow) OVERRIDE {
143 WebContentsImpl* web_contents = guest_->embedder_web_contents();
144 if (should_allow && web_contents) {
145 // Re-route the request to the embedder's WebContents; the guest gets the
146 // permission this way.
147 web_contents->RequestMediaAccessPermission(request_, callback_);
148 } else {
149 // Deny the request.
150 callback_.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
151 }
152
153 }
154 virtual ~MediaRequest() {}
155 private:
156 MediaStreamRequest request_;
157 MediaResponseCallback callback_;
158 BrowserPluginGuest* guest_;
159};
160
161class BrowserPluginGuest::NewWindowRequest : public PermissionRequest {
162 public:
163 NewWindowRequest(int instance_id, BrowserPluginGuest* guest)
164 : instance_id_(instance_id),
165 guest_(guest) {}
166
167 virtual void Respond(bool should_allow) OVERRIDE {
168 int embedder_render_process_id =
169 guest_->embedder_web_contents()->GetRenderProcessHost()->GetID();
170 BrowserPluginGuest* guest =
171 guest_->GetWebContents()->GetBrowserPluginGuestManager()->
172 GetGuestByInstanceID(instance_id_, embedder_render_process_id);
173 if (!guest) {
174 LOG(INFO) << "Guest not found. Instance ID: " << instance_id_;
175 return;
176 }
177
178 // If we do not destroy the guest then we allow the new window.
179 if (!should_allow)
180 guest->Destroy();
181 }
182 virtual ~NewWindowRequest() {}
183 private:
184 int instance_id_;
185 BrowserPluginGuest* guest_;
186};
187
[email protected]c006fb52013-03-01 09:36:45188namespace {
[email protected]e4a55a52013-03-09 01:32:49189const size_t kNumMaxOutstandingPermissionRequests = 1024;
[email protected]c4538072013-03-18 02:17:55190
191static std::string WindowOpenDispositionToString(
192 WindowOpenDisposition window_open_disposition) {
193 switch (window_open_disposition) {
194 case IGNORE_ACTION:
195 return "ignore";
196 case SAVE_TO_DISK:
197 return "save_to_disk";
198 case CURRENT_TAB:
199 return "current_tab";
200 case NEW_BACKGROUND_TAB:
201 return "new_background_tab";
202 case NEW_FOREGROUND_TAB:
203 return "new_foreground_tab";
204 case NEW_WINDOW:
205 return "new_window";
206 case NEW_POPUP:
207 return "new_popup";
208 default:
209 NOTREACHED() << "Unknown Window Open Disposition";
210 return "ignore";
211 }
212}
213
[email protected]f85f5032013-04-03 09:01:54214// Called on IO thread.
215static std::string RetrieveDownloadURLFromRequestId(
216 RenderViewHost* render_view_host,
217 int url_request_id) {
218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
219
220 int render_process_id = render_view_host->GetProcess()->GetID();
221 GlobalRequestID global_id(render_process_id, url_request_id);
222 net::URLRequest* url_request =
223 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
224 if (url_request)
225 return url_request->url().possibly_invalid_spec();
[email protected]007b3f82013-04-09 08:46:45226 return std::string();
[email protected]f85f5032013-04-03 09:01:54227}
228
[email protected]cf4c9e052013-05-04 04:53:44229} // namespace
[email protected]c006fb52013-03-01 09:36:45230
[email protected]ce0e2602013-03-15 20:53:27231class BrowserPluginGuest::EmbedderRenderViewHostObserver
232 : public RenderViewHostObserver {
233 public:
234 explicit EmbedderRenderViewHostObserver(BrowserPluginGuest* guest)
235 : RenderViewHostObserver(
236 guest->embedder_web_contents()->GetRenderViewHost()),
237 browser_plugin_guest_(guest) {
238 }
239
240 virtual ~EmbedderRenderViewHostObserver() {
241 }
242
243 // RenderViewHostObserver:
244 virtual void RenderViewHostDestroyed(
245 RenderViewHost* render_view_host) OVERRIDE {
[email protected]6dd17a8a2013-05-01 05:50:10246 browser_plugin_guest_->embedder_web_contents_ = NULL;
[email protected]ce0e2602013-03-15 20:53:27247 browser_plugin_guest_->Destroy();
248 }
249
250 private:
251 BrowserPluginGuest* browser_plugin_guest_;
252
253 DISALLOW_COPY_AND_ASSIGN(EmbedderRenderViewHostObserver);
254};
255
[email protected]dd8c8232012-11-03 00:49:36256BrowserPluginGuest::BrowserPluginGuest(
257 int instance_id,
[email protected]0c6d41752013-05-01 15:49:09258 WebContentsImpl* web_contents,
259 BrowserPluginGuest* opener,
260 bool has_render_view)
[email protected]7a846df2012-09-20 19:17:39261 : WebContentsObserver(web_contents),
[email protected]69e797f2013-04-30 01:10:22262 weak_ptr_factory_(this),
[email protected]8eb04562013-03-06 03:41:14263 embedder_web_contents_(NULL),
[email protected]7a846df2012-09-20 19:17:39264 instance_id_(instance_id),
[email protected]4d1afd62012-12-21 03:09:40265 damage_buffer_sequence_id_(0),
[email protected]7a846df2012-09-20 19:17:39266 damage_buffer_size_(0),
[email protected]fda17082012-10-04 00:25:21267 damage_buffer_scale_factor_(1.0f),
[email protected]caaf2482013-05-01 20:33:32268 guest_device_scale_factor_(1.0f),
[email protected]7a846df2012-09-20 19:17:39269 guest_hang_timeout_(
[email protected]f8501b12012-12-07 04:55:43270 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
[email protected]c4538072013-03-18 02:17:55271 focused_(false),
[email protected]861f9782013-03-05 03:29:54272 mouse_locked_(false),
[email protected]a25acea72013-03-10 23:41:28273 pending_lock_request_(false),
[email protected]93564f72013-02-15 13:26:19274 embedder_visible_(true),
[email protected]0c6d41752013-05-01 15:49:09275 next_permission_request_id_(0),
276 has_render_view_(has_render_view) {
[email protected]7a846df2012-09-20 19:17:39277 DCHECK(web_contents);
[email protected]93564f72013-02-15 13:26:19278 web_contents->SetDelegate(this);
[email protected]0c6d41752013-05-01 15:49:09279 if (opener)
280 opener_ = opener->AsWeakPtr();
[email protected]8eb04562013-03-06 03:41:14281 GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_,
282 GetWebContents());
[email protected]b5a40842012-11-28 15:26:11283}
284
[email protected]eb72af632013-04-30 01:05:21285bool BrowserPluginGuest::AddMessageToConsole(WebContents* source,
286 int32 level,
287 const string16& message,
288 int32 line_no,
289 const string16& source_id) {
290 base::DictionaryValue message_info;
291 // Log levels are from base/logging.h: LogSeverity.
292 message_info.Set(browser_plugin::kLevel,
293 base::Value::CreateIntegerValue(level));
294 message_info.Set(browser_plugin::kMessage,
295 base::Value::CreateStringValue(message));
296 message_info.Set(browser_plugin::kLine,
297 base::Value::CreateIntegerValue(line_no));
298 message_info.Set(browser_plugin::kSourceId,
299 base::Value::CreateStringValue(source_id));
300 SendMessageToEmbedder(
301 new BrowserPluginMsg_AddMessageToConsole(instance_id_, message_info));
302 return false;
303}
304
[email protected]c4538072013-03-18 02:17:55305void BrowserPluginGuest::DestroyUnattachedWindows() {
306 // Destroy() reaches in and removes the BrowserPluginGuest from its opener's
307 // pending_new_windows_ set. To avoid mutating the set while iterating, we
308 // create a copy of the pending new windows set and iterate over the copy.
309 PendingWindowMap pending_new_windows(pending_new_windows_);
310 // Clean up unattached new windows opened by this guest.
311 for (PendingWindowMap::const_iterator it = pending_new_windows.begin();
312 it != pending_new_windows.end(); ++it) {
313 it->first->Destroy();
314 }
315 // All pending windows should be removed from the set after Destroy() is
316 // called on all of them.
317 DCHECK_EQ(0ul, pending_new_windows_.size());
318}
319
[email protected]b371a5652013-02-20 11:25:51320void BrowserPluginGuest::Destroy() {
[email protected]c4538072013-03-18 02:17:55321 if (!attached() && opener())
322 opener()->pending_new_windows_.erase(this);
323 DestroyUnattachedWindows();
[email protected]8eb04562013-03-06 03:41:14324 GetWebContents()->GetBrowserPluginGuestManager()->RemoveGuest(instance_id_);
325 delete GetWebContents();
[email protected]b371a5652013-02-20 11:25:51326}
327
[email protected]3997b1b22012-12-20 01:02:54328bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
329 const IPC::Message& message) {
330 bool handled = true;
331 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
[email protected]cc8ed212013-02-07 22:31:03332 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK,
333 OnSwapBuffersACK)
[email protected]f5b4b0f2013-04-02 18:16:28334 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameACK,
335 OnCompositorFrameACK)
[email protected]3997b1b22012-12-20 01:02:54336 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
337 OnDragStatusUpdate)
[email protected]6dd17a8a2013-05-01 05:50:10338 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
339 OnExecuteEditCommand)
[email protected]3997b1b22012-12-20 01:02:54340 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Go, OnGo)
341 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
342 OnHandleInputEvent)
[email protected]861f9782013-03-05 03:29:54343 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
[email protected]5e7967972013-01-15 22:45:33344 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest, OnNavigateGuest)
[email protected]b371a5652013-02-20 11:25:51345 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
[email protected]3997b1b22012-12-20 01:02:54346 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Reload, OnReload)
347 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
[email protected]c006fb52013-03-01 09:36:45348 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_RespondPermission,
349 OnRespondPermission)
[email protected]3997b1b22012-12-20 01:02:54350 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetSize)
351 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
[email protected]25bcc8f2013-01-09 02:49:25352 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetName, OnSetName)
[email protected]3997b1b22012-12-20 01:02:54353 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
354 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Stop, OnStop)
355 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_TerminateGuest, OnTerminateGuest)
[email protected]861f9782013-03-05 03:29:54356 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
[email protected]3997b1b22012-12-20 01:02:54357 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateRect_ACK, OnUpdateRectACK)
358 IPC_MESSAGE_UNHANDLED(handled = false)
359 IPC_END_MESSAGE_MAP()
360 return handled;
361}
362
363void BrowserPluginGuest::Initialize(
[email protected]8eb04562013-03-06 03:41:14364 WebContentsImpl* embedder_web_contents,
[email protected]4b4ed582013-05-01 00:16:23365 const BrowserPluginHostMsg_Attach_Params& params) {
[email protected]c4538072013-03-18 02:17:55366 focused_ = params.focused;
367 guest_visible_ = params.visible;
[email protected]50de3222013-03-20 15:36:13368 if (!params.name.empty())
369 name_ = params.name;
[email protected]c4538072013-03-18 02:17:55370 auto_size_enabled_ = params.auto_size_params.enable;
371 max_auto_size_ = params.auto_size_params.max_size;
372 min_auto_size_ = params.auto_size_params.min_size;
373
374 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
375 // be attached.
376 embedder_web_contents_ = embedder_web_contents;
377
[email protected]7a846df2012-09-20 19:17:39378 // |render_view_host| manages the ownership of this BrowserPluginGuestHelper.
[email protected]8eb04562013-03-06 03:41:14379 new BrowserPluginGuestHelper(this, GetWebContents()->GetRenderViewHost());
380
[email protected]8eb04562013-03-06 03:41:14381 RendererPreferences* renderer_prefs =
382 GetWebContents()->GetMutableRendererPrefs();
383 // Copy renderer preferences (and nothing else) from the embedder's
384 // WebContents to the guest.
385 //
386 // For GTK and Aura this is necessary to get proper renderer configuration
387 // values for caret blinking interval, colors related to selection and
388 // focus.
389 *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
390
[email protected]8eb04562013-03-06 03:41:14391 // We would like the guest to report changes to frame names so that we can
392 // update the BrowserPlugin's corresponding 'name' attribute.
393 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
394 renderer_prefs->report_frame_name_changes = true;
395 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
396 // navigations still continue to function inside the app.
397 renderer_prefs->browser_handles_all_top_level_requests = false;
[email protected]31942c82012-10-05 17:01:54398
399 notification_registrar_.Add(
[email protected]ce0e2602013-03-15 20:53:27400 this, NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
[email protected]8eb04562013-03-06 03:41:14401 Source<WebContents>(GetWebContents()));
[email protected]3997b1b22012-12-20 01:02:54402
[email protected]93564f72013-02-15 13:26:19403 // Listen to embedder visibility changes so that the guest is in a 'shown'
404 // state if both the embedder is visible and the BrowserPlugin is marked as
405 // visible.
406 notification_registrar_.Add(
[email protected]ce0e2602013-03-15 20:53:27407 this, NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
[email protected]b371a5652013-02-20 11:25:51408 Source<WebContents>(embedder_web_contents_));
409
[email protected]ce0e2602013-03-15 20:53:27410 embedder_rvh_observer_.reset(new EmbedderRenderViewHostObserver(this));
[email protected]93564f72013-02-15 13:26:19411
[email protected]3997b1b22012-12-20 01:02:54412 OnSetSize(instance_id_, params.auto_size_params, params.resize_guest_params);
[email protected]44703cc72013-01-24 04:56:06413
[email protected]93564f72013-02-15 13:26:19414 // Create a swapped out RenderView for the guest in the embedder render
415 // process, so that the embedder can access the guest's window object.
416 int guest_routing_id =
[email protected]8eb04562013-03-06 03:41:14417 GetWebContents()->CreateSwappedOutRenderView(
418 embedder_web_contents_->GetSiteInstance());
[email protected]d752fe62013-03-01 03:46:01419 SendMessageToEmbedder(
420 new BrowserPluginMsg_GuestContentWindowReady(instance_id_,
421 guest_routing_id));
[email protected]93564f72013-02-15 13:26:19422
423 if (!params.src.empty())
424 OnNavigateGuest(instance_id_, params.src);
425
[email protected]0c6d41752013-05-01 15:49:09426 has_render_view_ = true;
427
[email protected]44703cc72013-01-24 04:56:06428 GetContentClient()->browser()->GuestWebContentsCreated(
[email protected]8eb04562013-03-06 03:41:14429 GetWebContents(), embedder_web_contents_);
[email protected]7a846df2012-09-20 19:17:39430}
431
432BrowserPluginGuest::~BrowserPluginGuest() {
433}
434
435// static
436BrowserPluginGuest* BrowserPluginGuest::Create(
437 int instance_id,
[email protected]c4538072013-03-18 02:17:55438 WebContentsImpl* web_contents) {
[email protected]2fae2c42012-10-03 21:20:04439 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create"));
[email protected]c4538072013-03-18 02:17:55440 if (factory_)
441 return factory_->CreateBrowserPluginGuest(instance_id, web_contents);
[email protected]0c6d41752013-05-01 15:49:09442 return new BrowserPluginGuest(instance_id, web_contents, NULL, false);
443}
444
445// static
446BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener(
447 int instance_id,
448 WebContentsImpl* web_contents,
449 BrowserPluginGuest* opener,
450 bool has_render_view) {
451 return new BrowserPluginGuest(instance_id,
452 web_contents,
453 opener,
454 has_render_view);
[email protected]7a846df2012-09-20 19:17:39455}
456
[email protected]44327692013-02-26 21:21:22457RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
458 return embedder_web_contents_->GetRenderWidgetHostView();
459}
460
[email protected]3997b1b22012-12-20 01:02:54461void BrowserPluginGuest::UpdateVisibility() {
462 OnSetVisibility(instance_id_, visible());
463}
464
[email protected]31942c82012-10-05 17:01:54465void BrowserPluginGuest::Observe(int type,
466 const NotificationSource& source,
467 const NotificationDetails& details) {
468 switch (type) {
469 case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
[email protected]8eb04562013-03-06 03:41:14470 DCHECK_EQ(Source<WebContents>(source).ptr(), GetWebContents());
[email protected]31942c82012-10-05 17:01:54471 ResourceRedirectDetails* resource_redirect_details =
472 Details<ResourceRedirectDetails>(details).ptr();
473 bool is_top_level =
474 resource_redirect_details->resource_type == ResourceType::MAIN_FRAME;
475 LoadRedirect(resource_redirect_details->url,
476 resource_redirect_details->new_url,
477 is_top_level);
478 break;
479 }
[email protected]93564f72013-02-15 13:26:19480 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: {
481 DCHECK_EQ(Source<WebContents>(source).ptr(), embedder_web_contents_);
482 embedder_visible_ = *Details<bool>(details).ptr();
483 UpdateVisibility();
484 break;
485 }
[email protected]31942c82012-10-05 17:01:54486 default:
487 NOTREACHED() << "Unexpected notification sent.";
488 break;
489 }
490}
491
[email protected]c4538072013-03-18 02:17:55492void BrowserPluginGuest::AddNewContents(WebContents* source,
493 WebContents* new_contents,
494 WindowOpenDisposition disposition,
495 const gfx::Rect& initial_pos,
496 bool user_gesture,
497 bool* was_blocked) {
[email protected]d70bea92013-04-05 04:23:34498 if (was_blocked)
499 *was_blocked = false;
[email protected]c4538072013-03-18 02:17:55500 RequestNewWindowPermission(static_cast<WebContentsImpl*>(new_contents),
501 disposition, initial_pos, user_gesture);
502}
503
[email protected]f85f5032013-04-03 09:01:54504void BrowserPluginGuest::CanDownload(
505 RenderViewHost* render_view_host,
506 int request_id,
507 const std::string& request_method,
508 const base::Callback<void(bool)>& callback) {
[email protected]cf4c9e052013-05-04 04:53:44509 if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
[email protected]f85f5032013-04-03 09:01:54510 // Deny the download request.
511 callback.Run(false);
512 return;
513 }
514
[email protected]f85f5032013-04-03 09:01:54515 int permission_request_id = next_permission_request_id_++;
[email protected]cf4c9e052013-05-04 04:53:44516 permission_request_map_[permission_request_id] =
517 new DownloadRequest(callback);
[email protected]f85f5032013-04-03 09:01:54518
519 BrowserThread::PostTaskAndReplyWithResult(
520 BrowserThread::IO, FROM_HERE,
521 base::Bind(&RetrieveDownloadURLFromRequestId,
522 render_view_host, request_id),
523 base::Bind(&BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId,
524 weak_ptr_factory_.GetWeakPtr(),
525 request_method,
526 permission_request_id));
[email protected]4aefa0c2012-10-04 20:01:19527}
528
[email protected]f9fb1032013-05-02 22:12:57529void BrowserPluginGuest::CloseContents(WebContents* source) {
530 SendMessageToEmbedder(new BrowserPluginMsg_Close(instance_id_));
531}
532
[email protected]14d59b332012-10-05 01:40:28533bool BrowserPluginGuest::HandleContextMenu(
534 const ContextMenuParams& params) {
535 // TODO(fsamuel): We have a do nothing context menu handler for now until
536 // we implement the Apps Context Menu API for Browser Plugin (see
537 // http://crbug.com/140315).
538 return true;
539}
540
[email protected]6dd17a8a2013-05-01 05:50:10541void BrowserPluginGuest::HandleKeyboardEvent(
542 WebContents* source,
543 const NativeWebKeyboardEvent& event) {
544 if (!attached())
545 return;
546
547 // Send the unhandled keyboard events back to the embedder to reprocess them.
548 // TODO(fsamuel): This introduces the possibility of out-of-order keyboard
549 // events because the guest may be arbitrarily delayed when responding to
550 // keyboard events. In that time, the embedder may have received and processed
551 // additional key events. This needs to be fixed as soon as possible.
552 // See http://crbug.com/229882.
553 embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(
554 web_contents(), event);
555}
556
[email protected]0c6d41752013-05-01 15:49:09557WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source,
558 const OpenURLParams& params) {
559 // If the guest wishes to navigate away prior to attachment then we save the
560 // navigation to perform upon attachment. Navigation initializes a lot of
561 // state that assumes an embedder exists, such as RenderWidgetHostViewGuest.
562 // Navigation also resumes resource loading which we don't want to allow
563 // until attachment.
564 if (!attached()) {
565 PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
566 if (it == opener()->pending_new_windows_.end())
567 return NULL;
568 const TargetURL& old_target_url = it->second;
569 TargetURL new_target_url(params.url);
570 new_target_url.changed = new_target_url.url != old_target_url.url;
571 it->second = new_target_url;
572 return NULL;
573 }
574 // This can happen for cross-site redirects.
575 source->GetController().LoadURL(
576 params.url, params.referrer, params.transition, std::string());
577 return source;
578}
579
[email protected]c4538072013-03-18 02:17:55580void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
581 int64 source_frame_id,
[email protected]50de3222013-03-20 15:36:13582 const string16& frame_name,
[email protected]c4538072013-03-18 02:17:55583 const GURL& target_url,
584 WebContents* new_contents) {
585 WebContentsImpl* new_contents_impl =
586 static_cast<WebContentsImpl*>(new_contents);
587 BrowserPluginGuest* guest = new_contents_impl->GetBrowserPluginGuest();
[email protected]6dd17a8a2013-05-01 05:50:10588 guest->opener_ = AsWeakPtr();
[email protected]50de3222013-03-20 15:36:13589 guest->name_ = UTF16ToUTF8(frame_name);
[email protected]c4538072013-03-18 02:17:55590 // Take ownership of the new guest until it is attached to the embedder's DOM
591 // tree to avoid leaking a guest if this guest is destroyed before attaching
592 // the new guest.
[email protected]0c6d41752013-05-01 15:49:09593 pending_new_windows_.insert(std::make_pair(guest, TargetURL(target_url)));
[email protected]c4538072013-03-18 02:17:55594}
595
[email protected]7a846df2012-09-20 19:17:39596void BrowserPluginGuest::RendererUnresponsive(WebContents* source) {
[email protected]f8501b12012-12-07 04:55:43597 int process_id =
[email protected]8eb04562013-03-06 03:41:14598 GetWebContents()->GetRenderProcessHost()->GetID();
[email protected]f8501b12012-12-07 04:55:43599 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01600 new BrowserPluginMsg_GuestUnresponsive(instance_id(), process_id));
[email protected]2fae2c42012-10-03 21:20:04601 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Hung"));
[email protected]7a846df2012-09-20 19:17:39602}
603
[email protected]f8501b12012-12-07 04:55:43604void BrowserPluginGuest::RendererResponsive(WebContents* source) {
605 int process_id =
[email protected]8eb04562013-03-06 03:41:14606 GetWebContents()->GetRenderProcessHost()->GetID();
[email protected]f8501b12012-12-07 04:55:43607 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01608 new BrowserPluginMsg_GuestResponsive(instance_id(), process_id));
[email protected]f8501b12012-12-07 04:55:43609 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Responsive"));
610}
611
[email protected]19c1c373e2012-10-17 14:12:18612void BrowserPluginGuest::RunFileChooser(WebContents* web_contents,
613 const FileChooserParams& params) {
614 embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params);
615}
616
[email protected]6a121f22012-10-30 03:19:48617bool BrowserPluginGuest::ShouldFocusPageAfterCrash() {
618 // Rather than managing focus in WebContentsImpl::RenderViewReady, we will
619 // manage the focus ourselves.
620 return false;
621}
622
[email protected]8eb04562013-03-06 03:41:14623WebContentsImpl* BrowserPluginGuest::GetWebContents() {
624 return static_cast<WebContentsImpl*>(web_contents());
[email protected]e17b7c62012-09-21 21:05:46625}
626
[email protected]4d1afd62012-12-21 03:09:40627base::SharedMemory* BrowserPluginGuest::GetDamageBufferFromEmbedder(
[email protected]1a0c0052012-11-05 21:06:26628 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
[email protected]1a0c0052012-11-05 21:06:26629#if defined(OS_WIN)
[email protected]4d1afd62012-12-21 03:09:40630 base::ProcessHandle handle =
631 embedder_web_contents_->GetRenderProcessHost()->GetHandle();
632 scoped_ptr<base::SharedMemory> shared_buf(
633 new base::SharedMemory(params.damage_buffer_handle, false, handle));
[email protected]1a0c0052012-11-05 21:06:26634#elif defined(OS_POSIX)
[email protected]4d1afd62012-12-21 03:09:40635 scoped_ptr<base::SharedMemory> shared_buf(
636 new base::SharedMemory(params.damage_buffer_handle, false));
637#endif
638 if (!shared_buf->Map(params.damage_buffer_size)) {
639 NOTREACHED();
640 return NULL;
641 }
642 return shared_buf.release();
[email protected]1a0c0052012-11-05 21:06:26643}
644
[email protected]7a846df2012-09-20 19:17:39645void BrowserPluginGuest::SetDamageBuffer(
[email protected]4d1afd62012-12-21 03:09:40646 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
647 damage_buffer_.reset(GetDamageBufferFromEmbedder(params));
[email protected]7a846df2012-09-20 19:17:39648 // Sanity check: Verify that we've correctly shared the damage buffer memory
649 // between the embedder and browser processes.
[email protected]4d1afd62012-12-21 03:09:40650 DCHECK(*static_cast<unsigned int*>(damage_buffer_->memory()) == 0xdeadbeef);
651 damage_buffer_sequence_id_ = params.damage_buffer_sequence_id;
652 damage_buffer_size_ = params.damage_buffer_size;
653 damage_view_size_ = params.view_size;
654 damage_buffer_scale_factor_ = params.scale_factor;
[email protected]7a846df2012-09-20 19:17:39655}
656
[email protected]ca61ce142012-11-27 21:32:57657gfx::Point BrowserPluginGuest::GetScreenCoordinates(
658 const gfx::Point& relative_position) const {
659 gfx::Point screen_pos(relative_position);
660 screen_pos += guest_window_rect_.OffsetFromOrigin();
661 return screen_pos;
662}
663
[email protected]240b5c32012-11-09 19:17:18664bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
665 return size.width() <= max_auto_size_.width() &&
666 size.height() <= max_auto_size_.height();
667}
668
[email protected]c4538072013-03-18 02:17:55669void BrowserPluginGuest::RequestNewWindowPermission(
670 WebContentsImpl* new_contents,
671 WindowOpenDisposition disposition,
672 const gfx::Rect& initial_bounds,
673 bool user_gesture) {
674 BrowserPluginGuest* guest = new_contents->GetBrowserPluginGuest();
675 PendingWindowMap::iterator it = pending_new_windows_.find(guest);
676 if (it == pending_new_windows_.end())
677 return;
[email protected]0c6d41752013-05-01 15:49:09678 const TargetURL& target_url = it->second;
[email protected]c4538072013-03-18 02:17:55679 base::DictionaryValue request_info;
680 request_info.Set(browser_plugin::kInitialHeight,
681 base::Value::CreateIntegerValue(initial_bounds.height()));
682 request_info.Set(browser_plugin::kInitialWidth,
683 base::Value::CreateIntegerValue(initial_bounds.width()));
684 request_info.Set(browser_plugin::kTargetURL,
[email protected]0c6d41752013-05-01 15:49:09685 base::Value::CreateStringValue(target_url.url.spec()));
[email protected]c4538072013-03-18 02:17:55686 request_info.Set(browser_plugin::kWindowID,
687 base::Value::CreateIntegerValue(guest->instance_id()));
688 request_info.Set(browser_plugin::kWindowOpenDisposition,
689 base::Value::CreateStringValue(
690 WindowOpenDispositionToString(disposition)));
691 int request_id = next_permission_request_id_++;
[email protected]cf4c9e052013-05-04 04:53:44692 permission_request_map_[request_id] =
693 new NewWindowRequest(guest->instance_id(), this);
[email protected]c4538072013-03-18 02:17:55694 SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
695 instance_id(), BrowserPluginPermissionTypeNewWindow,
696 request_id, request_info));
697}
698
[email protected]4aefa0c2012-10-04 20:01:19699void BrowserPluginGuest::DidStartProvisionalLoadForFrame(
700 int64 frame_id,
[email protected]d37c33e2012-10-12 13:35:13701 int64 parent_frame_id,
[email protected]4aefa0c2012-10-04 20:01:19702 bool is_main_frame,
703 const GURL& validated_url,
704 bool is_error_page,
[email protected]ead9009e2013-01-07 22:06:32705 bool is_iframe_srcdoc,
[email protected]4aefa0c2012-10-04 20:01:19706 RenderViewHost* render_view_host) {
707 // Inform the embedder of the loadStart.
708 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01709 new BrowserPluginMsg_LoadStart(instance_id(),
[email protected]4aefa0c2012-10-04 20:01:19710 validated_url,
711 is_main_frame));
712}
713
714void BrowserPluginGuest::DidFailProvisionalLoad(
715 int64 frame_id,
716 bool is_main_frame,
717 const GURL& validated_url,
718 int error_code,
719 const string16& error_description,
720 RenderViewHost* render_view_host) {
721 // Translate the |error_code| into an error string.
722 std::string error_type;
723 RemoveChars(net::ErrorToString(error_code), "net::", &error_type);
724 // Inform the embedder of the loadAbort.
725 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01726 new BrowserPluginMsg_LoadAbort(instance_id(),
[email protected]4aefa0c2012-10-04 20:01:19727 validated_url,
728 is_main_frame,
729 error_type));
730}
731
[email protected]a7fac9a2012-12-18 23:26:07732void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
[email protected]c4538072013-03-18 02:17:55733 if (!attached()) {
734 delete msg;
735 return;
736 }
737 msg->set_routing_id(embedder_web_contents_->GetRoutingID());
[email protected]a7fac9a2012-12-18 23:26:07738 embedder_web_contents_->Send(msg);
739}
740
[email protected]cf200a562013-05-03 16:24:29741void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
742 int screen_x, int screen_y, WebKit::WebDragOperation operation) {
743 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
744 screen_x, screen_y, operation);
745}
746
747void BrowserPluginGuest::DragSourceMovedTo(int client_x, int client_y,
748 int screen_x, int screen_y) {
749 web_contents()->GetRenderViewHost()->DragSourceMovedTo(client_x, client_y,
750 screen_x, screen_y);
751}
752
753void BrowserPluginGuest::EndSystemDrag() {
754 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
755 GetWebContents()->GetRenderViewHost());
756 guest_rvh->DragSourceSystemDragEnded();
757 // Issue a MouseUp event to get out of a selection state.
758 WebKit::WebMouseEvent mouse_event;
759 mouse_event.type = WebKit::WebInputEvent::MouseUp;
760 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
761 guest_rvh->ForwardMouseEvent(mouse_event);
762}
763
[email protected]31942c82012-10-05 17:01:54764void BrowserPluginGuest::LoadRedirect(
765 const GURL& old_url,
766 const GURL& new_url,
767 bool is_top_level) {
768 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01769 new BrowserPluginMsg_LoadRedirect(instance_id(),
[email protected]fb325d122012-11-20 23:58:05770 old_url,
771 new_url,
772 is_top_level));
[email protected]31942c82012-10-05 17:01:54773}
774
[email protected]e4a55a52013-03-09 01:32:49775void BrowserPluginGuest::AskEmbedderForGeolocationPermission(
776 int bridge_id,
777 const GURL& requesting_frame,
[email protected]c47ddb22013-03-23 23:50:31778 const GeolocationCallback& callback) {
[email protected]cf4c9e052013-05-04 04:53:44779 if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
[email protected]e4a55a52013-03-09 01:32:49780 // Deny the geolocation request.
781 callback.Run(false);
782 return;
783 }
784 int request_id = next_permission_request_id_++;
[email protected]cf4c9e052013-05-04 04:53:44785 permission_request_map_[request_id] = new GeolocationRequest(
786 callback, bridge_id, this, &weak_ptr_factory_);
[email protected]40974d02013-04-09 22:11:19787 DCHECK(bridge_id_to_request_id_map_.find(bridge_id) ==
788 bridge_id_to_request_id_map_.end());
789 bridge_id_to_request_id_map_[bridge_id] = request_id;
[email protected]e4a55a52013-03-09 01:32:49790
791 base::DictionaryValue request_info;
792 request_info.Set(browser_plugin::kURL,
793 base::Value::CreateStringValue(requesting_frame.spec()));
794
795 SendMessageToEmbedder(
796 new BrowserPluginMsg_RequestPermission(instance_id(),
797 BrowserPluginPermissionTypeGeolocation, request_id, request_info));
798}
799
800void BrowserPluginGuest::CancelGeolocationRequest(int bridge_id) {
[email protected]cf4c9e052013-05-04 04:53:44801 std::map<int, int>::iterator bridge_itr =
[email protected]40974d02013-04-09 22:11:19802 bridge_id_to_request_id_map_.find(bridge_id);
[email protected]cf4c9e052013-05-04 04:53:44803 if (bridge_itr == bridge_id_to_request_id_map_.end())
[email protected]40974d02013-04-09 22:11:19804 return;
805
[email protected]cf4c9e052013-05-04 04:53:44806 int request_id = bridge_itr->second;
807 bridge_id_to_request_id_map_.erase(bridge_itr);
808 RequestMap::iterator request_itr = permission_request_map_.find(request_id);
809 if (request_itr == permission_request_map_.end())
810 return;
811 delete request_itr->second;
812 permission_request_map_.erase(request_itr);
[email protected]e4a55a52013-03-09 01:32:49813}
814
[email protected]cf4c9e052013-05-04 04:53:44815void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback,
816 int bridge_id,
[email protected]e4a55a52013-03-09 01:32:49817 bool allowed) {
[email protected]cf4c9e052013-05-04 04:53:44818 callback.Run(allowed);
819 CancelGeolocationRequest(bridge_id);
[email protected]e4a55a52013-03-09 01:32:49820}
821
[email protected]7a846df2012-09-20 19:17:39822void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
823 int64 frame_id,
824 bool is_main_frame,
825 const GURL& url,
826 PageTransition transition_type,
827 RenderViewHost* render_view_host) {
828 // Inform its embedder of the updated URL.
[email protected]eb92f632012-10-19 00:56:12829 BrowserPluginMsg_LoadCommit_Params params;
[email protected]81289ac32012-10-11 21:50:06830 params.url = url;
831 params.is_top_level = is_main_frame;
832 params.process_id = render_view_host->GetProcess()->GetID();
[email protected]44703cc72013-01-24 04:56:06833 params.route_id = render_view_host->GetRoutingID();
[email protected]81289ac32012-10-11 21:50:06834 params.current_entry_index =
[email protected]8eb04562013-03-06 03:41:14835 GetWebContents()->GetController().GetCurrentEntryIndex();
[email protected]81289ac32012-10-11 21:50:06836 params.entry_count =
[email protected]8eb04562013-03-06 03:41:14837 GetWebContents()->GetController().GetEntryCount();
[email protected]81289ac32012-10-11 21:50:06838 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01839 new BrowserPluginMsg_LoadCommit(instance_id(), params));
[email protected]81289ac32012-10-11 21:50:06840 RecordAction(UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
[email protected]7a846df2012-09-20 19:17:39841}
842
[email protected]eb92f632012-10-19 00:56:12843void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) {
[email protected]cf200a562013-05-03 16:24:29844 bool disable_dragdrop = true;
845#if defined(OS_LINUX) || defined(OS_MACOSX)
846 if (CommandLine::ForCurrentProcess()->HasSwitch(
847 switches::kEnableBrowserPluginDragDrop))
848 disable_dragdrop = false;
849#endif // defined(OS_LINUX) || defined(OS_MACOSX)
850 if (disable_dragdrop) {
851 // Initiating a drag from inside a guest is currently not supported without
852 // the kEnableBrowserPluginDragDrop flag on a linux platform. So inject some
853 // JS to disable it. http://crbug.com/161112
854 const char script[] = "window.addEventListener('dragstart', function() { "
855 " window.event.preventDefault(); "
856 "});";
857 render_view_host->ExecuteJavascriptInWebFrame(string16(),
858 ASCIIToUTF16(script));
859 }
[email protected]d752fe62013-03-01 03:46:01860 SendMessageToEmbedder(new BrowserPluginMsg_LoadStop(instance_id()));
[email protected]eb92f632012-10-19 00:56:12861}
862
[email protected]c88b2a562012-10-27 03:36:56863void BrowserPluginGuest::RenderViewReady() {
864 // TODO(fsamuel): Investigate whether it's possible to update state earlier
[email protected]dba9bd22012-12-06 23:04:03865 // here (see http://crbug.com/158151).
[email protected]c084330e02013-04-27 01:08:15866 Send(new InputMsg_SetFocus(routing_id(), focused_));
[email protected]3997b1b22012-12-20 01:02:54867 UpdateVisibility();
[email protected]8eb04562013-03-06 03:41:14868 RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
[email protected]25bcc8f2013-01-09 02:49:25869 if (auto_size_enabled_)
870 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
871 else
872 rvh->DisableAutoResize(damage_view_size_);
873
[email protected]8eb04562013-03-06 03:41:14874 Send(new ViewMsg_SetName(routing_id(), name_));
[email protected]bca6c2c2013-03-24 03:55:07875
876 RenderWidgetHostImpl::From(rvh)->
877 set_hung_renderer_delay_ms(guest_hang_timeout_);
[email protected]c88b2a562012-10-27 03:36:56878}
879
[email protected]7a846df2012-09-20 19:17:39880void BrowserPluginGuest::RenderViewGone(base::TerminationStatus status) {
[email protected]8eb04562013-03-06 03:41:14881 int process_id = GetWebContents()->GetRenderProcessHost()->GetID();
[email protected]d752fe62013-03-01 03:46:01882 SendMessageToEmbedder(
883 new BrowserPluginMsg_GuestGone(instance_id(), process_id, status));
[email protected]2fae2c42012-10-03 21:20:04884 switch (status) {
885 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
886 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Killed"));
887 break;
888 case base::TERMINATION_STATUS_PROCESS_CRASHED:
889 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Crashed"));
890 break;
891 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
892 RecordAction(UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
893 break;
894 default:
895 break;
896 }
[email protected]7a846df2012-09-20 19:17:39897}
898
[email protected]8eb04562013-03-06 03:41:14899// static
900void BrowserPluginGuest::AcknowledgeBufferPresent(
901 int route_id,
902 int gpu_host_id,
[email protected]06666c02013-03-07 19:32:30903 const std::string& mailbox_name,
[email protected]8eb04562013-03-06 03:41:14904 uint32 sync_point) {
905 AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
906 ack_params.mailbox_name = mailbox_name;
907 ack_params.sync_point = sync_point;
908 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id,
909 gpu_host_id,
910 ack_params);
911}
912
913// static
914bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
915 const IPC::Message& message) {
916 switch (message.type()) {
917 case BrowserPluginHostMsg_BuffersSwappedACK::ID:
[email protected]f5b4b0f2013-04-02 18:16:28918 case BrowserPluginHostMsg_CompositorFrameACK::ID:
[email protected]8eb04562013-03-06 03:41:14919 case BrowserPluginHostMsg_DragStatusUpdate::ID:
[email protected]6dd17a8a2013-05-01 05:50:10920 case BrowserPluginHostMsg_ExecuteEditCommand::ID:
[email protected]8eb04562013-03-06 03:41:14921 case BrowserPluginHostMsg_Go::ID:
922 case BrowserPluginHostMsg_HandleInputEvent::ID:
923 case BrowserPluginHostMsg_LockMouse_ACK::ID:
924 case BrowserPluginHostMsg_NavigateGuest::ID:
925 case BrowserPluginHostMsg_PluginDestroyed::ID:
926 case BrowserPluginHostMsg_Reload::ID:
927 case BrowserPluginHostMsg_ResizeGuest::ID:
928 case BrowserPluginHostMsg_RespondPermission::ID:
929 case BrowserPluginHostMsg_SetAutoSize::ID:
930 case BrowserPluginHostMsg_SetFocus::ID:
931 case BrowserPluginHostMsg_SetName::ID:
932 case BrowserPluginHostMsg_SetVisibility::ID:
933 case BrowserPluginHostMsg_Stop::ID:
934 case BrowserPluginHostMsg_TerminateGuest::ID:
935 case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
936 case BrowserPluginHostMsg_UpdateRect_ACK::ID:
937 return true;
938 default:
939 break;
940 }
941 return false;
942}
943
[email protected]a7fac9a2012-12-18 23:26:07944bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
945 bool handled = true;
946 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
[email protected]a7fac9a2012-12-18 23:26:07947 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
948 OnHasTouchEventHandlers)
[email protected]861f9782013-03-05 03:29:54949 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
[email protected]a7fac9a2012-12-18 23:26:07950 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
951 #if defined(OS_MACOSX)
952 // MacOSX creates and populates platform-specific select drop-down menus
953 // whereas other platforms merely create a popup window that the guest
954 // renderer process paints inside.
955 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
956 #endif
957 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
958 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
[email protected]861f9782013-03-05 03:29:54959 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
[email protected]25bcc8f2013-01-09 02:49:25960 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName, OnUpdateFrameName)
[email protected]a7fac9a2012-12-18 23:26:07961 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
962 IPC_MESSAGE_UNHANDLED(handled = false)
963 IPC_END_MESSAGE_MAP()
964 return handled;
965}
966
[email protected]c4538072013-03-18 02:17:55967void BrowserPluginGuest::Attach(
968 WebContentsImpl* embedder_web_contents,
[email protected]4b4ed582013-05-01 00:16:23969 BrowserPluginHostMsg_Attach_Params params) {
970 if (attached())
971 return;
972
973 // Clear parameters that get inherited from the opener.
974 params.storage_partition_id.clear();
975 params.persist_storage = false;
976 params.src.clear();
977
[email protected]0c6d41752013-05-01 15:49:09978 // If a RenderView has already been created for this new window, then we need
979 // to initialize the browser-side state now so that the RenderViewHostManager
980 // does not create a new RenderView on navigation.
981 if (has_render_view_) {
982 static_cast<RenderViewHostImpl*>(
983 GetWebContents()->GetRenderViewHost())->Init();
[email protected]c4538072013-03-18 02:17:55984 WebContentsViewGuest* new_view =
985 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
986 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
[email protected]c4538072013-03-18 02:17:55987 }
[email protected]0c6d41752013-05-01 15:49:09988
989 // We need to do a navigation here if the target URL has changed between
990 // the time the WebContents was created and the time it was attached.
991 // We also need to do an initial navigation if a RenderView was never
992 // created for the new window in cases where there is no referrer.
993 PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
994 if (it != opener()->pending_new_windows_.end()) {
995 const TargetURL& target_url = it->second;
996 if (target_url.changed || !has_render_view_)
997 params.src = it->second.url.spec();
998 } else {
999 NOTREACHED();
1000 }
1001
[email protected]c4538072013-03-18 02:17:551002 // Once a new guest is attached to the DOM of the embedder page, then the
1003 // lifetime of the new guest is no longer managed by the opener guest.
1004 opener()->pending_new_windows_.erase(this);
1005
[email protected]50de3222013-03-20 15:36:131006 // The guest's frame name takes precedence over the BrowserPlugin's name.
1007 // The guest's frame name is assigned in
1008 // BrowserPluginGuest::WebContentsCreated.
1009 if (!name_.empty())
1010 params.name.clear();
1011
[email protected]c4538072013-03-18 02:17:551012 Initialize(embedder_web_contents, params);
1013
[email protected]620d5de52013-04-05 23:27:561014 // Inform the embedder of the guest's information.
1015 // We pull the partition information from the site's URL, which is of the form
1016 // guest://site/{persist}?{partition_name}.
1017 const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
1018 BrowserPluginMsg_Attach_ACK_Params ack_params;
1019 ack_params.storage_partition_id = site_url.query();
1020 ack_params.persist_storage =
1021 site_url.path().find("persist") != std::string::npos;
1022 ack_params.name = name_;
1023 SendMessageToEmbedder(
1024 new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params));
[email protected]c4538072013-03-18 02:17:551025}
1026
[email protected]f5b4b0f2013-04-02 18:16:281027void BrowserPluginGuest::OnCompositorFrameACK(
1028 int instance_id,
1029 int route_id,
1030 int renderer_host_id,
1031 const cc::CompositorFrameAck& ack) {
1032 RenderWidgetHostImpl::SendSwapCompositorFrameAck(route_id,
1033 renderer_host_id,
1034 ack);
1035}
1036
[email protected]3997b1b22012-12-20 01:02:541037void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
1038 WebKit::WebDragStatus drag_status,
1039 const WebDropData& drop_data,
1040 WebKit::WebDragOperationsMask mask,
1041 const gfx::Point& location) {
[email protected]8eb04562013-03-06 03:41:141042 RenderViewHost* host = GetWebContents()->GetRenderViewHost();
[email protected]3997b1b22012-12-20 01:02:541043 switch (drag_status) {
1044 case WebKit::WebDragStatusEnter:
[email protected]cf200a562013-05-03 16:24:291045 embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
1046 this);
[email protected]3997b1b22012-12-20 01:02:541047 host->DragTargetDragEnter(drop_data, location, location, mask, 0);
1048 break;
1049 case WebKit::WebDragStatusOver:
1050 host->DragTargetDragOver(location, location, mask, 0);
1051 break;
1052 case WebKit::WebDragStatusLeave:
[email protected]cf200a562013-05-03 16:24:291053 embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
[email protected]3997b1b22012-12-20 01:02:541054 host->DragTargetDragLeave();
1055 break;
1056 case WebKit::WebDragStatusDrop:
1057 host->DragTargetDrop(location, location, 0);
[email protected]cf200a562013-05-03 16:24:291058 EndSystemDrag();
[email protected]3997b1b22012-12-20 01:02:541059 break;
1060 case WebKit::WebDragStatusUnknown:
1061 NOTREACHED();
1062 }
1063}
1064
[email protected]6dd17a8a2013-05-01 05:50:101065void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
1066 const std::string& name) {
1067 Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
1068}
1069
[email protected]56ffe70b2013-01-11 17:00:521070void BrowserPluginGuest::OnGo(int instance_id, int relative_index) {
[email protected]8eb04562013-03-06 03:41:141071 GetWebContents()->GetController().GoToOffset(relative_index);
[email protected]56ffe70b2013-01-11 17:00:521072}
1073
[email protected]3997b1b22012-12-20 01:02:541074void BrowserPluginGuest::OnHandleInputEvent(
1075 int instance_id,
1076 const gfx::Rect& guest_window_rect,
1077 const WebKit::WebInputEvent* event) {
1078 guest_window_rect_ = guest_window_rect;
[email protected]c6ea9212013-04-09 18:51:561079 // If the embedder's RWHV is destroyed then that means that the embedder's
1080 // window has been closed but the embedder's WebContents has not yet been
1081 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
1082 // if there is a visible embedder.
1083 if (embedder_web_contents_->GetRenderWidgetHostView()) {
1084 guest_screen_rect_ = guest_window_rect;
1085 guest_screen_rect_.Offset(
1086 embedder_web_contents_->GetRenderWidgetHostView()->
1087 GetViewBounds().OffsetFromOrigin());
1088 }
[email protected]3997b1b22012-12-20 01:02:541089 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
[email protected]8eb04562013-03-06 03:41:141090 GetWebContents()->GetRenderViewHost());
[email protected]3997b1b22012-12-20 01:02:541091
[email protected]bca6c2c2013-03-24 03:55:071092 if (WebKit::WebInputEvent::isMouseEventType(event->type)) {
1093 guest_rvh->ForwardMouseEvent(
1094 *static_cast<const WebKit::WebMouseEvent*>(event));
1095 return;
[email protected]3997b1b22012-12-20 01:02:541096 }
1097
[email protected]bca6c2c2013-03-24 03:55:071098 if (event->type == WebKit::WebInputEvent::MouseWheel) {
1099 guest_rvh->ForwardWheelEvent(
1100 *static_cast<const WebKit::WebMouseWheelEvent*>(event));
1101 return;
1102 }
1103
1104 if (WebKit::WebInputEvent::isKeyboardEventType(event->type)) {
[email protected]6dd17a8a2013-05-01 05:50:101105 RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
1106 embedder_web_contents_->GetRenderViewHost());
1107 if (!embedder_rvh->GetLastKeyboardEvent())
1108 return;
1109 NativeWebKeyboardEvent keyboard_event(
1110 *embedder_rvh->GetLastKeyboardEvent());
[email protected]bca6c2c2013-03-24 03:55:071111 guest_rvh->ForwardKeyboardEvent(keyboard_event);
1112 return;
1113 }
1114
1115 if (WebKit::WebInputEvent::isTouchEventType(event->type)) {
1116 guest_rvh->ForwardTouchEvent(
1117 *static_cast<const WebKit::WebTouchEvent*>(event));
1118 return;
1119 }
1120
1121 if (WebKit::WebInputEvent::isGestureEventType(event->type)) {
1122 guest_rvh->ForwardGestureEvent(
1123 *static_cast<const WebKit::WebGestureEvent*>(event));
1124 return;
1125 }
[email protected]3997b1b22012-12-20 01:02:541126}
1127
[email protected]861f9782013-03-05 03:29:541128void BrowserPluginGuest::OnLockMouse(bool user_gesture,
1129 bool last_unlocked_by_target,
1130 bool privileged) {
[email protected]a25acea72013-03-10 23:41:281131 if (pending_lock_request_) {
1132 // Immediately reject the lock because only one pointerLock may be active
1133 // at a time.
1134 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
1135 return;
1136 }
1137 pending_lock_request_ = true;
1138 int request_id = next_permission_request_id_++;
1139 base::DictionaryValue request_info;
1140 request_info.Set(browser_plugin::kUserGesture,
1141 base::Value::CreateBooleanValue(user_gesture));
1142 request_info.Set(browser_plugin::kLastUnlockedBySelf,
1143 base::Value::CreateBooleanValue(last_unlocked_by_target));
1144 request_info.Set(browser_plugin::kURL,
1145 base::Value::CreateStringValue(
1146 web_contents()->GetURL().spec()));
1147
1148 SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
1149 instance_id(), BrowserPluginPermissionTypePointerLock,
1150 request_id, request_info));
[email protected]861f9782013-03-05 03:29:541151}
1152
1153void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
1154 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
[email protected]a25acea72013-03-10 23:41:281155 pending_lock_request_ = false;
[email protected]861f9782013-03-05 03:29:541156 if (succeeded)
1157 mouse_locked_ = true;
1158}
1159
[email protected]5e7967972013-01-15 22:45:331160void BrowserPluginGuest::OnNavigateGuest(
1161 int instance_id,
1162 const std::string& src) {
1163 GURL url(src);
[email protected]5e7967972013-01-15 22:45:331164 // We do not load empty urls in web_contents.
1165 // If a guest sets empty src attribute after it has navigated to some
1166 // non-empty page, the action is considered no-op. This empty src navigation
[email protected]e1eef4f2013-01-15 23:18:211167 // should never be sent to BrowserPluginGuest (browser process).
[email protected]5e7967972013-01-15 22:45:331168 DCHECK(!src.empty());
1169 if (!src.empty()) {
[email protected]e1eef4f2013-01-15 23:18:211170 // As guests do not swap processes on navigation, only navigations to
[email protected]5e7967972013-01-15 22:45:331171 // normal web URLs are supported. No protocol handlers are installed for
1172 // other schemes (e.g., WebUI or extensions), and no permissions or bindings
1173 // can be granted to the guest process.
[email protected]8eb04562013-03-06 03:41:141174 GetWebContents()->GetController().LoadURL(url, Referrer(),
[email protected]e1eef4f2013-01-15 23:18:211175 PAGE_TRANSITION_AUTO_TOPLEVEL,
1176 std::string());
[email protected]5e7967972013-01-15 22:45:331177 }
1178}
1179
[email protected]b371a5652013-02-20 11:25:511180void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
[email protected]b371a5652013-02-20 11:25:511181 Destroy();
1182}
1183
[email protected]3997b1b22012-12-20 01:02:541184void BrowserPluginGuest::OnReload(int instance_id) {
1185 // TODO(fsamuel): Don't check for repost because we don't want to show
1186 // Chromium's repost warning. We might want to implement a separate API
1187 // for registering a callback if a repost is about to happen.
[email protected]8eb04562013-03-06 03:41:141188 GetWebContents()->GetController().Reload(false);
[email protected]3997b1b22012-12-20 01:02:541189}
1190
1191void BrowserPluginGuest::OnResizeGuest(
1192 int instance_id,
1193 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
1194 // BrowserPlugin manages resize flow control itself and does not depend
1195 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
1196 // here. If we are setting the size for the first time before navigating then
1197 // BrowserPluginGuest does not yet have a RenderViewHost.
[email protected]8eb04562013-03-06 03:41:141198 if (GetWebContents()->GetRenderViewHost()) {
[email protected]3997b1b22012-12-20 01:02:541199 RenderWidgetHostImpl* render_widget_host =
[email protected]8eb04562013-03-06 03:41:141200 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
[email protected]3997b1b22012-12-20 01:02:541201 render_widget_host->ResetSizeAndRepaintPendingFlags();
[email protected]caaf2482013-05-01 20:33:321202
1203 if (guest_device_scale_factor_ != params.scale_factor) {
1204 guest_device_scale_factor_ = params.scale_factor;
1205 render_widget_host->NotifyScreenInfoChanged();
1206 }
[email protected]3997b1b22012-12-20 01:02:541207 }
[email protected]caaf2482013-05-01 20:33:321208 // Invalid damage buffer means we are in HW compositing mode,
1209 // so just resize the WebContents and repaint if needed.
[email protected]4d1afd62012-12-21 03:09:401210 if (!base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) {
[email protected]3997b1b22012-12-20 01:02:541211 if (!params.view_size.IsEmpty())
[email protected]8eb04562013-03-06 03:41:141212 GetWebContents()->GetView()->SizeContents(params.view_size);
[email protected]caaf2482013-05-01 20:33:321213 if (params.repaint)
1214 Send(new ViewMsg_Repaint(routing_id(), params.view_size));
[email protected]3997b1b22012-12-20 01:02:541215 return;
1216 }
[email protected]4d1afd62012-12-21 03:09:401217 SetDamageBuffer(params);
[email protected]8eb04562013-03-06 03:41:141218 GetWebContents()->GetView()->SizeContents(params.view_size);
1219 if (params.repaint)
1220 Send(new ViewMsg_Repaint(routing_id(), params.view_size));
[email protected]3997b1b22012-12-20 01:02:541221}
1222
[email protected]423838472013-01-09 00:16:461223void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
1224 if (focused_ == focused)
1225 return;
1226 focused_ = focused;
[email protected]c084330e02013-04-27 01:08:151227 Send(new InputMsg_SetFocus(routing_id(), focused));
[email protected]79733a02013-04-30 15:05:351228 if (!focused && mouse_locked_)
1229 OnUnlockMouse();
[email protected]423838472013-01-09 00:16:461230}
1231
[email protected]25bcc8f2013-01-09 02:49:251232void BrowserPluginGuest::OnSetName(int instance_id, const std::string& name) {
1233 if (name == name_)
1234 return;
1235 name_ = name;
[email protected]8eb04562013-03-06 03:41:141236 Send(new ViewMsg_SetName(routing_id(), name));
[email protected]25bcc8f2013-01-09 02:49:251237}
1238
[email protected]3997b1b22012-12-20 01:02:541239void BrowserPluginGuest::OnSetSize(
1240 int instance_id,
1241 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
1242 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
1243 bool old_auto_size_enabled = auto_size_enabled_;
1244 gfx::Size old_max_size = max_auto_size_;
1245 gfx::Size old_min_size = min_auto_size_;
1246 auto_size_enabled_ = auto_size_params.enable;
1247 max_auto_size_ = auto_size_params.max_size;
1248 min_auto_size_ = auto_size_params.min_size;
1249 if (auto_size_enabled_ && (!old_auto_size_enabled ||
1250 (old_max_size != max_auto_size_) ||
1251 (old_min_size != min_auto_size_))) {
[email protected]8eb04562013-03-06 03:41:141252 GetWebContents()->GetRenderViewHost()->EnableAutoResize(
[email protected]3997b1b22012-12-20 01:02:541253 min_auto_size_, max_auto_size_);
1254 // TODO(fsamuel): If we're changing autosize parameters, then we force
1255 // the guest to completely repaint itself, because BrowserPlugin has
1256 // allocated a new damage buffer and expects a full frame of pixels.
1257 // Ideally, we shouldn't need to do this because we shouldn't need to
1258 // allocate a new damage buffer unless |max_auto_size_| has changed.
1259 // However, even in that case, layout may not change and so we may
1260 // not get a full frame worth of pixels.
[email protected]8eb04562013-03-06 03:41:141261 Send(new ViewMsg_Repaint(routing_id(), max_auto_size_));
[email protected]3997b1b22012-12-20 01:02:541262 } else if (!auto_size_enabled_ && old_auto_size_enabled) {
[email protected]8eb04562013-03-06 03:41:141263 GetWebContents()->GetRenderViewHost()->DisableAutoResize(
[email protected]3997b1b22012-12-20 01:02:541264 resize_guest_params.view_size);
1265 }
1266 OnResizeGuest(instance_id_, resize_guest_params);
1267}
1268
[email protected]3997b1b22012-12-20 01:02:541269void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
[email protected]93564f72013-02-15 13:26:191270 guest_visible_ = visible;
1271 if (embedder_visible_ && guest_visible_)
[email protected]8eb04562013-03-06 03:41:141272 GetWebContents()->WasShown();
[email protected]3997b1b22012-12-20 01:02:541273 else
[email protected]8eb04562013-03-06 03:41:141274 GetWebContents()->WasHidden();
[email protected]3997b1b22012-12-20 01:02:541275}
1276
1277void BrowserPluginGuest::OnStop(int instance_id) {
[email protected]8eb04562013-03-06 03:41:141278 GetWebContents()->Stop();
[email protected]cc8ed212013-02-07 22:31:031279}
1280
[email protected]c006fb52013-03-01 09:36:451281void BrowserPluginGuest::OnRespondPermission(
[email protected]e4a55a52013-03-09 01:32:491282 int instance_id,
[email protected]c006fb52013-03-01 09:36:451283 BrowserPluginPermissionType permission_type,
1284 int request_id,
1285 bool should_allow) {
[email protected]cf4c9e052013-05-04 04:53:441286 RequestMap::iterator request_itr = permission_request_map_.find(request_id);
1287 if (request_itr == permission_request_map_.end()) {
1288 LOG(INFO) << "Not a valid request ID.";
1289 return;
1290 }
1291 request_itr->second->Respond(should_allow);
1292
1293 // Geolocation requests have to hang around for a while, so we don't delete
1294 // them here.
1295 if (permission_type != BrowserPluginPermissionTypeGeolocation) {
1296 delete request_itr->second;
1297 permission_request_map_.erase(request_itr);
[email protected]c006fb52013-03-01 09:36:451298 }
[email protected]c006fb52013-03-01 09:36:451299}
1300
[email protected]cc8ed212013-02-07 22:31:031301void BrowserPluginGuest::OnSwapBuffersACK(int instance_id,
1302 int route_id,
1303 int gpu_host_id,
[email protected]06666c02013-03-07 19:32:301304 const std::string& mailbox_name,
[email protected]cc8ed212013-02-07 22:31:031305 uint32 sync_point) {
1306 AcknowledgeBufferPresent(route_id, gpu_host_id, mailbox_name, sync_point);
1307
1308// This is only relevant on MACOSX and WIN when threaded compositing
1309// is not enabled. In threaded mode, above ACK is sufficient.
1310#if defined(OS_MACOSX) || defined(OS_WIN)
1311 RenderWidgetHostImpl* render_widget_host =
[email protected]8eb04562013-03-06 03:41:141312 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
[email protected]cc8ed212013-02-07 22:31:031313 render_widget_host->AcknowledgeSwapBuffersToRenderer();
1314#endif // defined(OS_MACOSX) || defined(OS_WIN)
1315}
1316
[email protected]3997b1b22012-12-20 01:02:541317void BrowserPluginGuest::OnTerminateGuest(int instance_id) {
1318 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Terminate"));
1319 base::ProcessHandle process_handle =
[email protected]8eb04562013-03-06 03:41:141320 GetWebContents()->GetRenderProcessHost()->GetHandle();
[email protected]a6e43aa2013-02-07 03:22:031321 if (process_handle)
1322 base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
[email protected]3997b1b22012-12-20 01:02:541323}
1324
[email protected]861f9782013-03-05 03:29:541325void BrowserPluginGuest::OnUnlockMouse() {
[email protected]c4538072013-03-18 02:17:551326 SendMessageToEmbedder(new BrowserPluginMsg_UnlockMouse(instance_id()));
[email protected]861f9782013-03-05 03:29:541327}
1328
1329void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
1330 // mouse_locked_ could be false here if the lock attempt was cancelled due
1331 // to window focus, or for various other reasons before the guest was informed
1332 // of the lock's success.
1333 if (mouse_locked_)
1334 Send(new ViewMsg_MouseLockLost(routing_id()));
1335 mouse_locked_ = false;
1336}
1337
[email protected]3997b1b22012-12-20 01:02:541338void BrowserPluginGuest::OnUpdateRectACK(
1339 int instance_id,
1340 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
1341 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
[email protected]8eb04562013-03-06 03:41:141342 Send(new ViewMsg_UpdateRect_ACK(routing_id()));
[email protected]3997b1b22012-12-20 01:02:541343 OnSetSize(instance_id_, auto_size_params, resize_guest_params);
1344}
1345
[email protected]a7fac9a2012-12-18 23:26:071346void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
1347 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:011348 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
[email protected]a7fac9a2012-12-18 23:26:071349}
1350
1351void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
[email protected]d752fe62013-03-01 03:46:011352 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
[email protected]a7fac9a2012-12-18 23:26:071353}
1354
1355#if defined(OS_MACOSX)
1356void BrowserPluginGuest::OnShowPopup(
1357 const ViewHostMsg_ShowPopup_Params& params) {
1358 gfx::Rect translated_bounds(params.bounds);
1359 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
1360 BrowserPluginPopupMenuHelper popup_menu_helper(
1361 embedder_web_contents_->GetRenderViewHost(),
[email protected]8eb04562013-03-06 03:41:141362 GetWebContents()->GetRenderViewHost());
[email protected]a7fac9a2012-12-18 23:26:071363 popup_menu_helper.ShowPopupMenu(translated_bounds,
1364 params.item_height,
1365 params.item_font_size,
1366 params.selected_item,
1367 params.popup_items,
1368 params.right_aligned,
1369 params.allow_multiple_selection);
1370}
1371#endif
1372
1373void BrowserPluginGuest::OnShowWidget(int route_id,
1374 const gfx::Rect& initial_pos) {
1375 gfx::Rect screen_pos(initial_pos);
1376 screen_pos.Offset(guest_screen_rect_.OffsetFromOrigin());
[email protected]8eb04562013-03-06 03:41:141377 GetWebContents()->ShowCreatedWidget(route_id, screen_pos);
[email protected]a7fac9a2012-12-18 23:26:071378}
1379
1380void BrowserPluginGuest::OnTakeFocus(bool reverse) {
1381 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:011382 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
[email protected]a7fac9a2012-12-18 23:26:071383}
1384
[email protected]25bcc8f2013-01-09 02:49:251385void BrowserPluginGuest::OnUpdateFrameName(int frame_id,
1386 bool is_top_level,
1387 const std::string& name) {
1388 if (!is_top_level)
1389 return;
1390
1391 name_ = name;
[email protected]d752fe62013-03-01 03:46:011392 SendMessageToEmbedder(new BrowserPluginMsg_UpdatedName(instance_id_, name));
[email protected]25bcc8f2013-01-09 02:49:251393}
1394
[email protected]c006fb52013-03-01 09:36:451395void BrowserPluginGuest::RequestMediaAccessPermission(
1396 WebContents* web_contents,
[email protected]ce0e2602013-03-15 20:53:271397 const MediaStreamRequest& request,
1398 const MediaResponseCallback& callback) {
[email protected]cf4c9e052013-05-04 04:53:441399 if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
[email protected]c006fb52013-03-01 09:36:451400 // Deny the media request.
[email protected]b5f76742013-04-29 15:05:591401 callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
[email protected]c006fb52013-03-01 09:36:451402 return;
1403 }
[email protected]b80a28722013-03-07 06:17:441404 int request_id = next_permission_request_id_++;
[email protected]cf4c9e052013-05-04 04:53:441405 permission_request_map_[request_id] =
1406 new MediaRequest(request, callback, this);
[email protected]c006fb52013-03-01 09:36:451407
1408 base::DictionaryValue request_info;
1409 request_info.Set(
[email protected]8eb04562013-03-06 03:41:141410 browser_plugin::kURL,
1411 base::Value::CreateStringValue(request.security_origin.spec()));
[email protected]c006fb52013-03-01 09:36:451412 SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
1413 instance_id(), BrowserPluginPermissionTypeMedia,
1414 request_id, request_info));
1415}
1416
[email protected]a7fac9a2012-12-18 23:26:071417void BrowserPluginGuest::OnUpdateRect(
1418 const ViewHostMsg_UpdateRect_Params& params) {
1419
1420 BrowserPluginMsg_UpdateRect_Params relay_params;
1421 relay_params.view_size = params.view_size;
1422 relay_params.scale_factor = params.scale_factor;
1423 relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
1424 params.flags);
[email protected]166f61a2013-01-09 23:54:491425 relay_params.needs_ack = params.needs_ack;
[email protected]a7fac9a2012-12-18 23:26:071426
1427 // HW accelerated case, acknowledge resize only
[email protected]61c555422013-01-31 19:31:061428 if (!params.needs_ack || !damage_buffer_) {
[email protected]4d1afd62012-12-21 03:09:401429 relay_params.damage_buffer_sequence_id = 0;
[email protected]d752fe62013-03-01 03:46:011430 SendMessageToEmbedder(
1431 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
1432 return;
[email protected]a7fac9a2012-12-18 23:26:071433 }
1434
[email protected]a7fac9a2012-12-18 23:26:071435 // Only copy damage if the guest is in autosize mode and the guest's view size
1436 // is less than the maximum size or the guest's view size is equal to the
1437 // damage buffer's size and the guest's scale factor is equal to the damage
1438 // buffer's scale factor.
1439 // The scaling change can happen due to asynchronous updates of the DPI on a
1440 // resolution change.
1441 if (((auto_size_enabled_ && InAutoSizeBounds(params.view_size)) ||
1442 (params.view_size.width() == damage_view_size().width() &&
1443 params.view_size.height() == damage_view_size().height())) &&
1444 params.scale_factor == damage_buffer_scale_factor()) {
[email protected]8eb04562013-03-06 03:41:141445 TransportDIB* dib = GetWebContents()->GetRenderProcessHost()->
[email protected]a7fac9a2012-12-18 23:26:071446 GetTransportDIB(params.bitmap);
1447 if (dib) {
[email protected]4d1afd62012-12-21 03:09:401448 size_t guest_damage_buffer_size =
[email protected]a7fac9a2012-12-18 23:26:071449#if defined(OS_WIN)
[email protected]4d1afd62012-12-21 03:09:401450 params.bitmap_rect.width() *
1451 params.bitmap_rect.height() * 4;
[email protected]a7fac9a2012-12-18 23:26:071452#else
[email protected]4d1afd62012-12-21 03:09:401453 dib->size();
[email protected]a7fac9a2012-12-18 23:26:071454#endif
[email protected]4d1afd62012-12-21 03:09:401455 size_t embedder_damage_buffer_size = damage_buffer_size_;
[email protected]a7fac9a2012-12-18 23:26:071456 void* guest_memory = dib->memory();
1457 void* embedder_memory = damage_buffer_->memory();
1458 size_t size = std::min(guest_damage_buffer_size,
1459 embedder_damage_buffer_size);
1460 memcpy(embedder_memory, guest_memory, size);
1461 }
1462 }
[email protected]4d1afd62012-12-21 03:09:401463 relay_params.damage_buffer_sequence_id = damage_buffer_sequence_id_;
[email protected]a7fac9a2012-12-18 23:26:071464 relay_params.bitmap_rect = params.bitmap_rect;
1465 relay_params.scroll_delta = params.scroll_delta;
1466 relay_params.scroll_rect = params.scroll_rect;
1467 relay_params.copy_rects = params.copy_rects;
1468
[email protected]d752fe62013-03-01 03:46:011469 SendMessageToEmbedder(
1470 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
[email protected]7a846df2012-09-20 19:17:391471}
1472
[email protected]f85f5032013-04-03 09:01:541473void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
1474 const std::string& request_method,
1475 int permission_request_id,
1476 const std::string& url) {
1477 if (url.empty()) {
[email protected]cf4c9e052013-05-04 04:53:441478 OnRespondPermission(instance_id(), BrowserPluginPermissionTypeDownload,
1479 permission_request_id, false);
[email protected]f85f5032013-04-03 09:01:541480 return;
1481 }
1482
1483 base::DictionaryValue request_info;
1484 request_info.Set(browser_plugin::kRequestMethod,
1485 base::Value::CreateStringValue(request_method));
1486 request_info.Set(browser_plugin::kURL, base::Value::CreateStringValue(url));
1487
1488 SendMessageToEmbedder(
1489 new BrowserPluginMsg_RequestPermission(instance_id(),
1490 BrowserPluginPermissionTypeDownload, permission_request_id,
1491 request_info));
1492}
1493
[email protected]7a846df2012-09-20 19:17:391494} // namespace content