blob: 8c1e915a03e991524a6fb337ff39909ff0744002 [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]10994d132013-06-11 07:16:1811#include "base/strings/string_util.h"
[email protected]74ebfb12013-06-07 20:48:0012#include "base/strings/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]c10680312013-05-31 15:22:0549#include "webkit/common/webdropdata.h"
[email protected]31942c82012-10-05 17:01:5450#include "webkit/glue/resource_type.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:
[email protected]abc7d5c2013-05-15 09:19:2568 PermissionRequest() {
69 RecordAction(UserMetricsAction("BrowserPlugin.Guest.PermissionRequest"));
70 }
[email protected]cf4c9e052013-05-04 04:53:4471};
72
73class BrowserPluginGuest::DownloadRequest : public PermissionRequest {
74 public:
75 explicit DownloadRequest(base::Callback<void(bool)> callback)
76 : callback_(callback) {}
77 virtual void Respond(bool should_allow) OVERRIDE {
78 callback_.Run(should_allow);
79 }
80 virtual ~DownloadRequest() {}
81 private:
82 base::Callback<void(bool)> callback_;
83};
84
85class BrowserPluginGuest::GeolocationRequest : public PermissionRequest {
86 public:
87 GeolocationRequest(GeolocationCallback callback,
88 int bridge_id,
89 BrowserPluginGuest* guest,
90 base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory)
91 : callback_(callback),
92 bridge_id_(bridge_id),
93 guest_(guest),
94 weak_ptr_factory_(weak_ptr_factory) {}
95
96 virtual void Respond(bool should_allow) OVERRIDE {
97 WebContents* web_contents = guest_->embedder_web_contents();
98 if (should_allow && web_contents) {
99 // If renderer side embedder decides to allow gelocation, we need to check
100 // if the app/embedder itself has geolocation access.
101 BrowserContext* browser_context = web_contents->GetBrowserContext();
102 if (browser_context) {
103 GeolocationPermissionContext* geolocation_context =
104 browser_context->GetGeolocationPermissionContext();
105 if (geolocation_context) {
106 base::Callback<void(bool)> geolocation_callback = base::Bind(
107 &BrowserPluginGuest::SetGeolocationPermission,
108 weak_ptr_factory_->GetWeakPtr(),
109 callback_,
110 bridge_id_);
111 geolocation_context->RequestGeolocationPermission(
112 web_contents->GetRenderProcessHost()->GetID(),
113 web_contents->GetRoutingID(),
114 // The geolocation permission request here is not initiated
115 // through WebGeolocationPermissionRequest. We are only interested
116 // in the fact whether the embedder/app has geolocation
117 // permission. Therefore we use an invalid |bridge_id|.
118 -1 /* bridge_id */,
119 web_contents->GetURL(),
120 geolocation_callback);
121 return;
122 }
123 }
124 }
125 guest_->SetGeolocationPermission(callback_, bridge_id_, false);
126 }
127 virtual ~GeolocationRequest() {}
128 private:
129 base::Callback<void(bool)> callback_;
130 int bridge_id_;
131 BrowserPluginGuest* guest_;
132 base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory_;
133};
134
135class BrowserPluginGuest::MediaRequest : public PermissionRequest {
136 public:
137 MediaRequest(const MediaStreamRequest& request,
138 const MediaResponseCallback& callback,
139 BrowserPluginGuest* guest)
140 : request_(request),
141 callback_(callback),
142 guest_(guest) {}
143
144 virtual void Respond(bool should_allow) OVERRIDE {
145 WebContentsImpl* web_contents = guest_->embedder_web_contents();
146 if (should_allow && web_contents) {
147 // Re-route the request to the embedder's WebContents; the guest gets the
148 // permission this way.
149 web_contents->RequestMediaAccessPermission(request_, callback_);
150 } else {
151 // Deny the request.
152 callback_.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
153 }
154
155 }
156 virtual ~MediaRequest() {}
157 private:
158 MediaStreamRequest request_;
159 MediaResponseCallback callback_;
160 BrowserPluginGuest* guest_;
161};
162
163class BrowserPluginGuest::NewWindowRequest : public PermissionRequest {
164 public:
165 NewWindowRequest(int instance_id, BrowserPluginGuest* guest)
166 : instance_id_(instance_id),
167 guest_(guest) {}
168
169 virtual void Respond(bool should_allow) OVERRIDE {
170 int embedder_render_process_id =
171 guest_->embedder_web_contents()->GetRenderProcessHost()->GetID();
172 BrowserPluginGuest* guest =
173 guest_->GetWebContents()->GetBrowserPluginGuestManager()->
174 GetGuestByInstanceID(instance_id_, embedder_render_process_id);
175 if (!guest) {
176 LOG(INFO) << "Guest not found. Instance ID: " << instance_id_;
177 return;
178 }
179
180 // If we do not destroy the guest then we allow the new window.
181 if (!should_allow)
182 guest->Destroy();
183 }
184 virtual ~NewWindowRequest() {}
185 private:
186 int instance_id_;
187 BrowserPluginGuest* guest_;
188};
189
[email protected]c006fb52013-03-01 09:36:45190namespace {
[email protected]e4a55a52013-03-09 01:32:49191const size_t kNumMaxOutstandingPermissionRequests = 1024;
[email protected]c4538072013-03-18 02:17:55192
193static std::string WindowOpenDispositionToString(
194 WindowOpenDisposition window_open_disposition) {
195 switch (window_open_disposition) {
196 case IGNORE_ACTION:
197 return "ignore";
198 case SAVE_TO_DISK:
199 return "save_to_disk";
200 case CURRENT_TAB:
201 return "current_tab";
202 case NEW_BACKGROUND_TAB:
203 return "new_background_tab";
204 case NEW_FOREGROUND_TAB:
205 return "new_foreground_tab";
206 case NEW_WINDOW:
207 return "new_window";
208 case NEW_POPUP:
209 return "new_popup";
210 default:
211 NOTREACHED() << "Unknown Window Open Disposition";
212 return "ignore";
213 }
214}
215
[email protected]f85f5032013-04-03 09:01:54216// Called on IO thread.
217static std::string RetrieveDownloadURLFromRequestId(
218 RenderViewHost* render_view_host,
219 int url_request_id) {
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
221
222 int render_process_id = render_view_host->GetProcess()->GetID();
223 GlobalRequestID global_id(render_process_id, url_request_id);
224 net::URLRequest* url_request =
225 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
226 if (url_request)
227 return url_request->url().possibly_invalid_spec();
[email protected]007b3f82013-04-09 08:46:45228 return std::string();
[email protected]f85f5032013-04-03 09:01:54229}
230
[email protected]cf4c9e052013-05-04 04:53:44231} // namespace
[email protected]c006fb52013-03-01 09:36:45232
[email protected]ce0e2602013-03-15 20:53:27233class BrowserPluginGuest::EmbedderRenderViewHostObserver
234 : public RenderViewHostObserver {
235 public:
236 explicit EmbedderRenderViewHostObserver(BrowserPluginGuest* guest)
237 : RenderViewHostObserver(
238 guest->embedder_web_contents()->GetRenderViewHost()),
239 browser_plugin_guest_(guest) {
240 }
241
242 virtual ~EmbedderRenderViewHostObserver() {
243 }
244
245 // RenderViewHostObserver:
246 virtual void RenderViewHostDestroyed(
247 RenderViewHost* render_view_host) OVERRIDE {
[email protected]6dd17a8a2013-05-01 05:50:10248 browser_plugin_guest_->embedder_web_contents_ = NULL;
[email protected]ce0e2602013-03-15 20:53:27249 browser_plugin_guest_->Destroy();
250 }
251
252 private:
253 BrowserPluginGuest* browser_plugin_guest_;
254
255 DISALLOW_COPY_AND_ASSIGN(EmbedderRenderViewHostObserver);
256};
257
[email protected]dd8c8232012-11-03 00:49:36258BrowserPluginGuest::BrowserPluginGuest(
259 int instance_id,
[email protected]0c6d41752013-05-01 15:49:09260 WebContentsImpl* web_contents,
261 BrowserPluginGuest* opener,
262 bool has_render_view)
[email protected]7a846df2012-09-20 19:17:39263 : WebContentsObserver(web_contents),
[email protected]69e797f2013-04-30 01:10:22264 weak_ptr_factory_(this),
[email protected]8eb04562013-03-06 03:41:14265 embedder_web_contents_(NULL),
[email protected]7a846df2012-09-20 19:17:39266 instance_id_(instance_id),
[email protected]4d1afd62012-12-21 03:09:40267 damage_buffer_sequence_id_(0),
[email protected]7a846df2012-09-20 19:17:39268 damage_buffer_size_(0),
[email protected]fda17082012-10-04 00:25:21269 damage_buffer_scale_factor_(1.0f),
[email protected]caaf2482013-05-01 20:33:32270 guest_device_scale_factor_(1.0f),
[email protected]7a846df2012-09-20 19:17:39271 guest_hang_timeout_(
[email protected]f8501b12012-12-07 04:55:43272 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
[email protected]c4538072013-03-18 02:17:55273 focused_(false),
[email protected]861f9782013-03-05 03:29:54274 mouse_locked_(false),
[email protected]a25acea72013-03-10 23:41:28275 pending_lock_request_(false),
[email protected]93564f72013-02-15 13:26:19276 embedder_visible_(true),
[email protected]0c6d41752013-05-01 15:49:09277 next_permission_request_id_(0),
278 has_render_view_(has_render_view) {
[email protected]7a846df2012-09-20 19:17:39279 DCHECK(web_contents);
[email protected]93564f72013-02-15 13:26:19280 web_contents->SetDelegate(this);
[email protected]0c6d41752013-05-01 15:49:09281 if (opener)
282 opener_ = opener->AsWeakPtr();
[email protected]8eb04562013-03-06 03:41:14283 GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_,
284 GetWebContents());
[email protected]b5a40842012-11-28 15:26:11285}
286
[email protected]eb72af632013-04-30 01:05:21287bool BrowserPluginGuest::AddMessageToConsole(WebContents* source,
288 int32 level,
289 const string16& message,
290 int32 line_no,
291 const string16& source_id) {
292 base::DictionaryValue message_info;
293 // Log levels are from base/logging.h: LogSeverity.
294 message_info.Set(browser_plugin::kLevel,
295 base::Value::CreateIntegerValue(level));
296 message_info.Set(browser_plugin::kMessage,
297 base::Value::CreateStringValue(message));
298 message_info.Set(browser_plugin::kLine,
299 base::Value::CreateIntegerValue(line_no));
300 message_info.Set(browser_plugin::kSourceId,
301 base::Value::CreateStringValue(source_id));
302 SendMessageToEmbedder(
303 new BrowserPluginMsg_AddMessageToConsole(instance_id_, message_info));
304 return false;
305}
306
[email protected]c4538072013-03-18 02:17:55307void BrowserPluginGuest::DestroyUnattachedWindows() {
308 // Destroy() reaches in and removes the BrowserPluginGuest from its opener's
309 // pending_new_windows_ set. To avoid mutating the set while iterating, we
310 // create a copy of the pending new windows set and iterate over the copy.
311 PendingWindowMap pending_new_windows(pending_new_windows_);
312 // Clean up unattached new windows opened by this guest.
313 for (PendingWindowMap::const_iterator it = pending_new_windows.begin();
314 it != pending_new_windows.end(); ++it) {
315 it->first->Destroy();
316 }
317 // All pending windows should be removed from the set after Destroy() is
318 // called on all of them.
319 DCHECK_EQ(0ul, pending_new_windows_.size());
320}
321
[email protected]b371a5652013-02-20 11:25:51322void BrowserPluginGuest::Destroy() {
[email protected]c4538072013-03-18 02:17:55323 if (!attached() && opener())
324 opener()->pending_new_windows_.erase(this);
325 DestroyUnattachedWindows();
[email protected]8eb04562013-03-06 03:41:14326 GetWebContents()->GetBrowserPluginGuestManager()->RemoveGuest(instance_id_);
327 delete GetWebContents();
[email protected]b371a5652013-02-20 11:25:51328}
329
[email protected]3997b1b22012-12-20 01:02:54330bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
331 const IPC::Message& message) {
332 bool handled = true;
333 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
[email protected]cc8ed212013-02-07 22:31:03334 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK,
335 OnSwapBuffersACK)
[email protected]f5b4b0f2013-04-02 18:16:28336 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameACK,
337 OnCompositorFrameACK)
[email protected]3997b1b22012-12-20 01:02:54338 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
339 OnDragStatusUpdate)
[email protected]6dd17a8a2013-05-01 05:50:10340 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
341 OnExecuteEditCommand)
[email protected]3997b1b22012-12-20 01:02:54342 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Go, OnGo)
343 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
344 OnHandleInputEvent)
[email protected]861f9782013-03-05 03:29:54345 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
[email protected]5e7967972013-01-15 22:45:33346 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest, OnNavigateGuest)
[email protected]b371a5652013-02-20 11:25:51347 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
[email protected]3997b1b22012-12-20 01:02:54348 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Reload, OnReload)
349 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
[email protected]c006fb52013-03-01 09:36:45350 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_RespondPermission,
351 OnRespondPermission)
[email protected]3997b1b22012-12-20 01:02:54352 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetSize)
[email protected]b77fac52013-06-01 01:03:46353 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
354 OnSetEditCommandsForNextKeyEvent)
[email protected]3997b1b22012-12-20 01:02:54355 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
[email protected]25bcc8f2013-01-09 02:49:25356 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetName, OnSetName)
[email protected]3997b1b22012-12-20 01:02:54357 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
358 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Stop, OnStop)
359 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_TerminateGuest, OnTerminateGuest)
[email protected]861f9782013-03-05 03:29:54360 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
[email protected]32deec62013-05-15 23:55:04361 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
[email protected]3997b1b22012-12-20 01:02:54362 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateRect_ACK, OnUpdateRectACK)
363 IPC_MESSAGE_UNHANDLED(handled = false)
364 IPC_END_MESSAGE_MAP()
365 return handled;
366}
367
368void BrowserPluginGuest::Initialize(
[email protected]8eb04562013-03-06 03:41:14369 WebContentsImpl* embedder_web_contents,
[email protected]4b4ed582013-05-01 00:16:23370 const BrowserPluginHostMsg_Attach_Params& params) {
[email protected]c4538072013-03-18 02:17:55371 focused_ = params.focused;
372 guest_visible_ = params.visible;
[email protected]32deec62013-05-15 23:55:04373 guest_window_rect_ = params.resize_guest_params.view_rect;
374
[email protected]50de3222013-03-20 15:36:13375 if (!params.name.empty())
376 name_ = params.name;
[email protected]c4538072013-03-18 02:17:55377 auto_size_enabled_ = params.auto_size_params.enable;
378 max_auto_size_ = params.auto_size_params.max_size;
379 min_auto_size_ = params.auto_size_params.min_size;
380
381 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
382 // be attached.
383 embedder_web_contents_ = embedder_web_contents;
384
[email protected]7a846df2012-09-20 19:17:39385 // |render_view_host| manages the ownership of this BrowserPluginGuestHelper.
[email protected]8eb04562013-03-06 03:41:14386 new BrowserPluginGuestHelper(this, GetWebContents()->GetRenderViewHost());
387
[email protected]8eb04562013-03-06 03:41:14388 RendererPreferences* renderer_prefs =
389 GetWebContents()->GetMutableRendererPrefs();
390 // Copy renderer preferences (and nothing else) from the embedder's
391 // WebContents to the guest.
392 //
393 // For GTK and Aura this is necessary to get proper renderer configuration
394 // values for caret blinking interval, colors related to selection and
395 // focus.
396 *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
397
[email protected]8eb04562013-03-06 03:41:14398 // We would like the guest to report changes to frame names so that we can
399 // update the BrowserPlugin's corresponding 'name' attribute.
400 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
401 renderer_prefs->report_frame_name_changes = true;
402 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
403 // navigations still continue to function inside the app.
404 renderer_prefs->browser_handles_all_top_level_requests = false;
[email protected]31942c82012-10-05 17:01:54405
406 notification_registrar_.Add(
[email protected]660ddc32013-05-08 21:27:37407 this, NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
408 Source<WebContents>(GetWebContents()));
409
410 notification_registrar_.Add(
[email protected]ce0e2602013-03-15 20:53:27411 this, NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
[email protected]8eb04562013-03-06 03:41:14412 Source<WebContents>(GetWebContents()));
[email protected]3997b1b22012-12-20 01:02:54413
[email protected]93564f72013-02-15 13:26:19414 // Listen to embedder visibility changes so that the guest is in a 'shown'
415 // state if both the embedder is visible and the BrowserPlugin is marked as
416 // visible.
417 notification_registrar_.Add(
[email protected]ce0e2602013-03-15 20:53:27418 this, NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
[email protected]b371a5652013-02-20 11:25:51419 Source<WebContents>(embedder_web_contents_));
420
[email protected]ce0e2602013-03-15 20:53:27421 embedder_rvh_observer_.reset(new EmbedderRenderViewHostObserver(this));
[email protected]93564f72013-02-15 13:26:19422
[email protected]3997b1b22012-12-20 01:02:54423 OnSetSize(instance_id_, params.auto_size_params, params.resize_guest_params);
[email protected]44703cc72013-01-24 04:56:06424
[email protected]93564f72013-02-15 13:26:19425 // Create a swapped out RenderView for the guest in the embedder render
426 // process, so that the embedder can access the guest's window object.
427 int guest_routing_id =
[email protected]8eb04562013-03-06 03:41:14428 GetWebContents()->CreateSwappedOutRenderView(
429 embedder_web_contents_->GetSiteInstance());
[email protected]d752fe62013-03-01 03:46:01430 SendMessageToEmbedder(
431 new BrowserPluginMsg_GuestContentWindowReady(instance_id_,
432 guest_routing_id));
[email protected]93564f72013-02-15 13:26:19433
434 if (!params.src.empty())
435 OnNavigateGuest(instance_id_, params.src);
436
[email protected]0c6d41752013-05-01 15:49:09437 has_render_view_ = true;
[email protected]d10bbddf2013-06-06 23:38:31438
439 if (!embedder_web_contents_->
440 GetWebkitPrefs().accelerated_compositing_enabled) {
441 WebPreferences prefs = GetWebContents()->GetWebkitPrefs();
442 prefs.accelerated_compositing_enabled = false;
443 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
444 }
[email protected]523c89de2013-06-12 16:30:04445
446 // Enable input method for guest if it's enabled for the embedder.
447 if (static_cast<RenderViewHostImpl*>(
448 embedder_web_contents_->GetRenderViewHost())->input_method_active()) {
449 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
450 GetWebContents()->GetRenderViewHost());
451 guest_rvh->SetInputMethodActive(true);
452 }
[email protected]7a846df2012-09-20 19:17:39453}
454
455BrowserPluginGuest::~BrowserPluginGuest() {
[email protected]697f16b52013-05-10 06:01:18456 while (!pending_messages_.empty()) {
457 delete pending_messages_.front();
458 pending_messages_.pop();
459 }
[email protected]7a846df2012-09-20 19:17:39460}
461
462// static
463BrowserPluginGuest* BrowserPluginGuest::Create(
464 int instance_id,
[email protected]c4538072013-03-18 02:17:55465 WebContentsImpl* web_contents) {
[email protected]2fae2c42012-10-03 21:20:04466 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create"));
[email protected]c4538072013-03-18 02:17:55467 if (factory_)
468 return factory_->CreateBrowserPluginGuest(instance_id, web_contents);
[email protected]0c6d41752013-05-01 15:49:09469 return new BrowserPluginGuest(instance_id, web_contents, NULL, false);
470}
471
472// static
473BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener(
474 int instance_id,
475 WebContentsImpl* web_contents,
476 BrowserPluginGuest* opener,
477 bool has_render_view) {
478 return new BrowserPluginGuest(instance_id,
479 web_contents,
480 opener,
481 has_render_view);
[email protected]7a846df2012-09-20 19:17:39482}
483
[email protected]44327692013-02-26 21:21:22484RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
485 return embedder_web_contents_->GetRenderWidgetHostView();
486}
487
[email protected]3997b1b22012-12-20 01:02:54488void BrowserPluginGuest::UpdateVisibility() {
489 OnSetVisibility(instance_id_, visible());
490}
491
[email protected]32deec62013-05-15 23:55:04492// screen.
493gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
494 gfx::Rect guest_rect(bounds);
495 guest_rect.Offset(guest_window_rect_.OffsetFromOrigin());
496 return guest_rect;
497}
498
[email protected]31942c82012-10-05 17:01:54499void BrowserPluginGuest::Observe(int type,
500 const NotificationSource& source,
501 const NotificationDetails& details) {
502 switch (type) {
[email protected]660ddc32013-05-08 21:27:37503 case NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
504 DCHECK_EQ(Source<WebContents>(source).ptr(), GetWebContents());
505 LoadHandlerCalled();
506 break;
507 }
[email protected]31942c82012-10-05 17:01:54508 case NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
[email protected]8eb04562013-03-06 03:41:14509 DCHECK_EQ(Source<WebContents>(source).ptr(), GetWebContents());
[email protected]31942c82012-10-05 17:01:54510 ResourceRedirectDetails* resource_redirect_details =
511 Details<ResourceRedirectDetails>(details).ptr();
512 bool is_top_level =
513 resource_redirect_details->resource_type == ResourceType::MAIN_FRAME;
514 LoadRedirect(resource_redirect_details->url,
515 resource_redirect_details->new_url,
516 is_top_level);
517 break;
518 }
[email protected]93564f72013-02-15 13:26:19519 case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: {
520 DCHECK_EQ(Source<WebContents>(source).ptr(), embedder_web_contents_);
521 embedder_visible_ = *Details<bool>(details).ptr();
522 UpdateVisibility();
523 break;
524 }
[email protected]31942c82012-10-05 17:01:54525 default:
526 NOTREACHED() << "Unexpected notification sent.";
527 break;
528 }
529}
530
[email protected]c4538072013-03-18 02:17:55531void BrowserPluginGuest::AddNewContents(WebContents* source,
532 WebContents* new_contents,
533 WindowOpenDisposition disposition,
534 const gfx::Rect& initial_pos,
535 bool user_gesture,
536 bool* was_blocked) {
[email protected]d70bea92013-04-05 04:23:34537 if (was_blocked)
538 *was_blocked = false;
[email protected]c4538072013-03-18 02:17:55539 RequestNewWindowPermission(static_cast<WebContentsImpl*>(new_contents),
540 disposition, initial_pos, user_gesture);
541}
542
[email protected]f85f5032013-04-03 09:01:54543void BrowserPluginGuest::CanDownload(
544 RenderViewHost* render_view_host,
545 int request_id,
546 const std::string& request_method,
547 const base::Callback<void(bool)>& callback) {
[email protected]cf4c9e052013-05-04 04:53:44548 if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
[email protected]f85f5032013-04-03 09:01:54549 // Deny the download request.
550 callback.Run(false);
551 return;
552 }
553
[email protected]f85f5032013-04-03 09:01:54554 int permission_request_id = next_permission_request_id_++;
[email protected]cf4c9e052013-05-04 04:53:44555 permission_request_map_[permission_request_id] =
556 new DownloadRequest(callback);
[email protected]f85f5032013-04-03 09:01:54557
558 BrowserThread::PostTaskAndReplyWithResult(
559 BrowserThread::IO, FROM_HERE,
560 base::Bind(&RetrieveDownloadURLFromRequestId,
561 render_view_host, request_id),
562 base::Bind(&BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId,
563 weak_ptr_factory_.GetWeakPtr(),
564 request_method,
565 permission_request_id));
[email protected]4aefa0c2012-10-04 20:01:19566}
567
[email protected]f9fb1032013-05-02 22:12:57568void BrowserPluginGuest::CloseContents(WebContents* source) {
569 SendMessageToEmbedder(new BrowserPluginMsg_Close(instance_id_));
570}
571
[email protected]14d59b332012-10-05 01:40:28572bool BrowserPluginGuest::HandleContextMenu(
573 const ContextMenuParams& params) {
574 // TODO(fsamuel): We have a do nothing context menu handler for now until
575 // we implement the Apps Context Menu API for Browser Plugin (see
576 // http://crbug.com/140315).
577 return true;
578}
579
[email protected]6dd17a8a2013-05-01 05:50:10580void BrowserPluginGuest::HandleKeyboardEvent(
581 WebContents* source,
582 const NativeWebKeyboardEvent& event) {
583 if (!attached())
584 return;
585
586 // Send the unhandled keyboard events back to the embedder to reprocess them.
587 // TODO(fsamuel): This introduces the possibility of out-of-order keyboard
588 // events because the guest may be arbitrarily delayed when responding to
589 // keyboard events. In that time, the embedder may have received and processed
590 // additional key events. This needs to be fixed as soon as possible.
591 // See http://crbug.com/229882.
592 embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(
593 web_contents(), event);
594}
595
[email protected]0c6d41752013-05-01 15:49:09596WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source,
597 const OpenURLParams& params) {
598 // If the guest wishes to navigate away prior to attachment then we save the
599 // navigation to perform upon attachment. Navigation initializes a lot of
600 // state that assumes an embedder exists, such as RenderWidgetHostViewGuest.
601 // Navigation also resumes resource loading which we don't want to allow
602 // until attachment.
603 if (!attached()) {
604 PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
605 if (it == opener()->pending_new_windows_.end())
606 return NULL;
[email protected]96584eec2013-05-07 13:25:32607 const NewWindowInfo& old_target_url = it->second;
608 NewWindowInfo new_window_info(params.url, old_target_url.name);
609 new_window_info.changed = new_window_info.url != old_target_url.url;
610 it->second = new_window_info;
[email protected]0c6d41752013-05-01 15:49:09611 return NULL;
612 }
613 // This can happen for cross-site redirects.
614 source->GetController().LoadURL(
615 params.url, params.referrer, params.transition, std::string());
616 return source;
617}
618
[email protected]c4538072013-03-18 02:17:55619void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
620 int64 source_frame_id,
[email protected]50de3222013-03-20 15:36:13621 const string16& frame_name,
[email protected]c4538072013-03-18 02:17:55622 const GURL& target_url,
623 WebContents* new_contents) {
624 WebContentsImpl* new_contents_impl =
625 static_cast<WebContentsImpl*>(new_contents);
626 BrowserPluginGuest* guest = new_contents_impl->GetBrowserPluginGuest();
[email protected]6dd17a8a2013-05-01 05:50:10627 guest->opener_ = AsWeakPtr();
[email protected]96584eec2013-05-07 13:25:32628 std::string guest_name = UTF16ToUTF8(frame_name);
629 guest->name_ = guest_name;
[email protected]c4538072013-03-18 02:17:55630 // Take ownership of the new guest until it is attached to the embedder's DOM
631 // tree to avoid leaking a guest if this guest is destroyed before attaching
632 // the new guest.
[email protected]96584eec2013-05-07 13:25:32633 pending_new_windows_.insert(
634 std::make_pair(guest, NewWindowInfo(target_url, guest_name)));
[email protected]c4538072013-03-18 02:17:55635}
636
[email protected]7a846df2012-09-20 19:17:39637void BrowserPluginGuest::RendererUnresponsive(WebContents* source) {
[email protected]f8501b12012-12-07 04:55:43638 int process_id =
[email protected]8eb04562013-03-06 03:41:14639 GetWebContents()->GetRenderProcessHost()->GetID();
[email protected]f8501b12012-12-07 04:55:43640 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01641 new BrowserPluginMsg_GuestUnresponsive(instance_id(), process_id));
[email protected]2fae2c42012-10-03 21:20:04642 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Hung"));
[email protected]7a846df2012-09-20 19:17:39643}
644
[email protected]f8501b12012-12-07 04:55:43645void BrowserPluginGuest::RendererResponsive(WebContents* source) {
646 int process_id =
[email protected]8eb04562013-03-06 03:41:14647 GetWebContents()->GetRenderProcessHost()->GetID();
[email protected]f8501b12012-12-07 04:55:43648 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01649 new BrowserPluginMsg_GuestResponsive(instance_id(), process_id));
[email protected]f8501b12012-12-07 04:55:43650 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Responsive"));
651}
652
[email protected]19c1c373e2012-10-17 14:12:18653void BrowserPluginGuest::RunFileChooser(WebContents* web_contents,
654 const FileChooserParams& params) {
655 embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params);
656}
657
[email protected]6a121f22012-10-30 03:19:48658bool BrowserPluginGuest::ShouldFocusPageAfterCrash() {
659 // Rather than managing focus in WebContentsImpl::RenderViewReady, we will
660 // manage the focus ourselves.
661 return false;
662}
663
[email protected]8eb04562013-03-06 03:41:14664WebContentsImpl* BrowserPluginGuest::GetWebContents() {
665 return static_cast<WebContentsImpl*>(web_contents());
[email protected]e17b7c62012-09-21 21:05:46666}
667
[email protected]4d1afd62012-12-21 03:09:40668base::SharedMemory* BrowserPluginGuest::GetDamageBufferFromEmbedder(
[email protected]1a0c0052012-11-05 21:06:26669 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
[email protected]1a0c0052012-11-05 21:06:26670#if defined(OS_WIN)
[email protected]4d1afd62012-12-21 03:09:40671 base::ProcessHandle handle =
672 embedder_web_contents_->GetRenderProcessHost()->GetHandle();
673 scoped_ptr<base::SharedMemory> shared_buf(
674 new base::SharedMemory(params.damage_buffer_handle, false, handle));
[email protected]1a0c0052012-11-05 21:06:26675#elif defined(OS_POSIX)
[email protected]4d1afd62012-12-21 03:09:40676 scoped_ptr<base::SharedMemory> shared_buf(
677 new base::SharedMemory(params.damage_buffer_handle, false));
678#endif
679 if (!shared_buf->Map(params.damage_buffer_size)) {
[email protected]c072073402013-06-04 21:53:59680 LOG(WARNING) << "Unable to map the embedder's damage buffer.";
[email protected]4d1afd62012-12-21 03:09:40681 return NULL;
682 }
683 return shared_buf.release();
[email protected]1a0c0052012-11-05 21:06:26684}
685
[email protected]7a846df2012-09-20 19:17:39686void BrowserPluginGuest::SetDamageBuffer(
[email protected]4d1afd62012-12-21 03:09:40687 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
688 damage_buffer_.reset(GetDamageBufferFromEmbedder(params));
[email protected]7a846df2012-09-20 19:17:39689 // Sanity check: Verify that we've correctly shared the damage buffer memory
690 // between the embedder and browser processes.
[email protected]c072073402013-06-04 21:53:59691 DCHECK(!damage_buffer_ ||
692 *static_cast<unsigned int*>(damage_buffer_->memory()) == 0xdeadbeef);
[email protected]4d1afd62012-12-21 03:09:40693 damage_buffer_sequence_id_ = params.damage_buffer_sequence_id;
694 damage_buffer_size_ = params.damage_buffer_size;
[email protected]32deec62013-05-15 23:55:04695 damage_view_size_ = params.view_rect.size();
[email protected]4d1afd62012-12-21 03:09:40696 damage_buffer_scale_factor_ = params.scale_factor;
[email protected]7a846df2012-09-20 19:17:39697}
698
[email protected]ca61ce142012-11-27 21:32:57699gfx::Point BrowserPluginGuest::GetScreenCoordinates(
700 const gfx::Point& relative_position) const {
701 gfx::Point screen_pos(relative_position);
702 screen_pos += guest_window_rect_.OffsetFromOrigin();
703 return screen_pos;
704}
705
[email protected]240b5c32012-11-09 19:17:18706bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
707 return size.width() <= max_auto_size_.width() &&
708 size.height() <= max_auto_size_.height();
709}
710
[email protected]c4538072013-03-18 02:17:55711void BrowserPluginGuest::RequestNewWindowPermission(
712 WebContentsImpl* new_contents,
713 WindowOpenDisposition disposition,
714 const gfx::Rect& initial_bounds,
715 bool user_gesture) {
716 BrowserPluginGuest* guest = new_contents->GetBrowserPluginGuest();
717 PendingWindowMap::iterator it = pending_new_windows_.find(guest);
718 if (it == pending_new_windows_.end())
719 return;
[email protected]96584eec2013-05-07 13:25:32720 const NewWindowInfo& new_window_info = it->second;
[email protected]c4538072013-03-18 02:17:55721 base::DictionaryValue request_info;
722 request_info.Set(browser_plugin::kInitialHeight,
723 base::Value::CreateIntegerValue(initial_bounds.height()));
724 request_info.Set(browser_plugin::kInitialWidth,
725 base::Value::CreateIntegerValue(initial_bounds.width()));
726 request_info.Set(browser_plugin::kTargetURL,
[email protected]96584eec2013-05-07 13:25:32727 base::Value::CreateStringValue(new_window_info.url.spec()));
728 request_info.Set(browser_plugin::kName,
729 base::Value::CreateStringValue(new_window_info.name));
[email protected]c4538072013-03-18 02:17:55730 request_info.Set(browser_plugin::kWindowID,
731 base::Value::CreateIntegerValue(guest->instance_id()));
732 request_info.Set(browser_plugin::kWindowOpenDisposition,
733 base::Value::CreateStringValue(
734 WindowOpenDispositionToString(disposition)));
735 int request_id = next_permission_request_id_++;
[email protected]cf4c9e052013-05-04 04:53:44736 permission_request_map_[request_id] =
737 new NewWindowRequest(guest->instance_id(), this);
[email protected]c4538072013-03-18 02:17:55738 SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
739 instance_id(), BrowserPluginPermissionTypeNewWindow,
740 request_id, request_info));
741}
742
[email protected]4aefa0c2012-10-04 20:01:19743void BrowserPluginGuest::DidStartProvisionalLoadForFrame(
744 int64 frame_id,
[email protected]d37c33e2012-10-12 13:35:13745 int64 parent_frame_id,
[email protected]4aefa0c2012-10-04 20:01:19746 bool is_main_frame,
747 const GURL& validated_url,
748 bool is_error_page,
[email protected]ead9009e2013-01-07 22:06:32749 bool is_iframe_srcdoc,
[email protected]4aefa0c2012-10-04 20:01:19750 RenderViewHost* render_view_host) {
751 // Inform the embedder of the loadStart.
752 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01753 new BrowserPluginMsg_LoadStart(instance_id(),
[email protected]4aefa0c2012-10-04 20:01:19754 validated_url,
755 is_main_frame));
756}
757
758void BrowserPluginGuest::DidFailProvisionalLoad(
759 int64 frame_id,
760 bool is_main_frame,
761 const GURL& validated_url,
762 int error_code,
763 const string16& error_description,
764 RenderViewHost* render_view_host) {
765 // Translate the |error_code| into an error string.
766 std::string error_type;
767 RemoveChars(net::ErrorToString(error_code), "net::", &error_type);
768 // Inform the embedder of the loadAbort.
769 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01770 new BrowserPluginMsg_LoadAbort(instance_id(),
[email protected]4aefa0c2012-10-04 20:01:19771 validated_url,
772 is_main_frame,
773 error_type));
774}
775
[email protected]a7fac9a2012-12-18 23:26:07776void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
[email protected]c4538072013-03-18 02:17:55777 if (!attached()) {
[email protected]697f16b52013-05-10 06:01:18778 // Some pages such as data URLs, javascript URLs, and about:blank
779 // do not load external resources and so they load prior to attachment.
780 // As a result, we must save all these IPCs until attachment and then
781 // forward them so that the embedder gets a chance to see and process
782 // the load events.
783 pending_messages_.push(msg);
[email protected]c4538072013-03-18 02:17:55784 return;
785 }
786 msg->set_routing_id(embedder_web_contents_->GetRoutingID());
[email protected]a7fac9a2012-12-18 23:26:07787 embedder_web_contents_->Send(msg);
788}
789
[email protected]660ddc32013-05-08 21:27:37790void BrowserPluginGuest::LoadHandlerCalled() {
791 SendMessageToEmbedder(new BrowserPluginMsg_LoadHandlerCalled(instance_id()));
792}
793
[email protected]cf200a562013-05-03 16:24:29794void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
795 int screen_x, int screen_y, WebKit::WebDragOperation operation) {
796 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
797 screen_x, screen_y, operation);
798}
799
800void BrowserPluginGuest::DragSourceMovedTo(int client_x, int client_y,
801 int screen_x, int screen_y) {
802 web_contents()->GetRenderViewHost()->DragSourceMovedTo(client_x, client_y,
803 screen_x, screen_y);
804}
805
806void BrowserPluginGuest::EndSystemDrag() {
807 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
808 GetWebContents()->GetRenderViewHost());
809 guest_rvh->DragSourceSystemDragEnded();
810 // Issue a MouseUp event to get out of a selection state.
811 WebKit::WebMouseEvent mouse_event;
812 mouse_event.type = WebKit::WebInputEvent::MouseUp;
813 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
814 guest_rvh->ForwardMouseEvent(mouse_event);
815}
816
[email protected]31942c82012-10-05 17:01:54817void BrowserPluginGuest::LoadRedirect(
818 const GURL& old_url,
819 const GURL& new_url,
820 bool is_top_level) {
821 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01822 new BrowserPluginMsg_LoadRedirect(instance_id(),
[email protected]fb325d122012-11-20 23:58:05823 old_url,
824 new_url,
825 is_top_level));
[email protected]31942c82012-10-05 17:01:54826}
827
[email protected]e4a55a52013-03-09 01:32:49828void BrowserPluginGuest::AskEmbedderForGeolocationPermission(
829 int bridge_id,
830 const GURL& requesting_frame,
[email protected]c47ddb22013-03-23 23:50:31831 const GeolocationCallback& callback) {
[email protected]cf4c9e052013-05-04 04:53:44832 if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
[email protected]e4a55a52013-03-09 01:32:49833 // Deny the geolocation request.
834 callback.Run(false);
835 return;
836 }
837 int request_id = next_permission_request_id_++;
[email protected]cf4c9e052013-05-04 04:53:44838 permission_request_map_[request_id] = new GeolocationRequest(
839 callback, bridge_id, this, &weak_ptr_factory_);
[email protected]40974d02013-04-09 22:11:19840 DCHECK(bridge_id_to_request_id_map_.find(bridge_id) ==
841 bridge_id_to_request_id_map_.end());
842 bridge_id_to_request_id_map_[bridge_id] = request_id;
[email protected]e4a55a52013-03-09 01:32:49843
844 base::DictionaryValue request_info;
845 request_info.Set(browser_plugin::kURL,
846 base::Value::CreateStringValue(requesting_frame.spec()));
847
848 SendMessageToEmbedder(
849 new BrowserPluginMsg_RequestPermission(instance_id(),
850 BrowserPluginPermissionTypeGeolocation, request_id, request_info));
851}
852
853void BrowserPluginGuest::CancelGeolocationRequest(int bridge_id) {
[email protected]cf4c9e052013-05-04 04:53:44854 std::map<int, int>::iterator bridge_itr =
[email protected]40974d02013-04-09 22:11:19855 bridge_id_to_request_id_map_.find(bridge_id);
[email protected]cf4c9e052013-05-04 04:53:44856 if (bridge_itr == bridge_id_to_request_id_map_.end())
[email protected]40974d02013-04-09 22:11:19857 return;
858
[email protected]cf4c9e052013-05-04 04:53:44859 int request_id = bridge_itr->second;
860 bridge_id_to_request_id_map_.erase(bridge_itr);
861 RequestMap::iterator request_itr = permission_request_map_.find(request_id);
862 if (request_itr == permission_request_map_.end())
863 return;
864 delete request_itr->second;
865 permission_request_map_.erase(request_itr);
[email protected]e4a55a52013-03-09 01:32:49866}
867
[email protected]cf4c9e052013-05-04 04:53:44868void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback,
869 int bridge_id,
[email protected]e4a55a52013-03-09 01:32:49870 bool allowed) {
[email protected]cf4c9e052013-05-04 04:53:44871 callback.Run(allowed);
872 CancelGeolocationRequest(bridge_id);
[email protected]e4a55a52013-03-09 01:32:49873}
874
[email protected]697f16b52013-05-10 06:01:18875void BrowserPluginGuest::SendQueuedMessages() {
876 if (!attached())
877 return;
878
879 while (!pending_messages_.empty()) {
880 IPC::Message* message = pending_messages_.front();
881 pending_messages_.pop();
882 SendMessageToEmbedder(message);
883 }
884}
885
[email protected]7a846df2012-09-20 19:17:39886void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
887 int64 frame_id,
888 bool is_main_frame,
889 const GURL& url,
890 PageTransition transition_type,
891 RenderViewHost* render_view_host) {
892 // Inform its embedder of the updated URL.
[email protected]eb92f632012-10-19 00:56:12893 BrowserPluginMsg_LoadCommit_Params params;
[email protected]81289ac32012-10-11 21:50:06894 params.url = url;
895 params.is_top_level = is_main_frame;
[email protected]81289ac32012-10-11 21:50:06896 params.current_entry_index =
[email protected]8eb04562013-03-06 03:41:14897 GetWebContents()->GetController().GetCurrentEntryIndex();
[email protected]81289ac32012-10-11 21:50:06898 params.entry_count =
[email protected]8eb04562013-03-06 03:41:14899 GetWebContents()->GetController().GetEntryCount();
[email protected]81289ac32012-10-11 21:50:06900 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:01901 new BrowserPluginMsg_LoadCommit(instance_id(), params));
[email protected]81289ac32012-10-11 21:50:06902 RecordAction(UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
[email protected]7a846df2012-09-20 19:17:39903}
904
[email protected]eb92f632012-10-19 00:56:12905void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) {
[email protected]cf200a562013-05-03 16:24:29906 bool disable_dragdrop = true;
907#if defined(OS_LINUX) || defined(OS_MACOSX)
908 if (CommandLine::ForCurrentProcess()->HasSwitch(
909 switches::kEnableBrowserPluginDragDrop))
910 disable_dragdrop = false;
911#endif // defined(OS_LINUX) || defined(OS_MACOSX)
912 if (disable_dragdrop) {
913 // Initiating a drag from inside a guest is currently not supported without
914 // the kEnableBrowserPluginDragDrop flag on a linux platform. So inject some
915 // JS to disable it. http://crbug.com/161112
916 const char script[] = "window.addEventListener('dragstart', function() { "
917 " window.event.preventDefault(); "
918 "});";
919 render_view_host->ExecuteJavascriptInWebFrame(string16(),
920 ASCIIToUTF16(script));
921 }
[email protected]d752fe62013-03-01 03:46:01922 SendMessageToEmbedder(new BrowserPluginMsg_LoadStop(instance_id()));
[email protected]eb92f632012-10-19 00:56:12923}
924
[email protected]c88b2a562012-10-27 03:36:56925void BrowserPluginGuest::RenderViewReady() {
926 // TODO(fsamuel): Investigate whether it's possible to update state earlier
[email protected]dba9bd22012-12-06 23:04:03927 // here (see http://crbug.com/158151).
[email protected]c084330e02013-04-27 01:08:15928 Send(new InputMsg_SetFocus(routing_id(), focused_));
[email protected]3997b1b22012-12-20 01:02:54929 UpdateVisibility();
[email protected]8eb04562013-03-06 03:41:14930 RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
[email protected]25bcc8f2013-01-09 02:49:25931 if (auto_size_enabled_)
932 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
933 else
934 rvh->DisableAutoResize(damage_view_size_);
935
[email protected]8eb04562013-03-06 03:41:14936 Send(new ViewMsg_SetName(routing_id(), name_));
[email protected]bca6c2c2013-03-24 03:55:07937
938 RenderWidgetHostImpl::From(rvh)->
939 set_hung_renderer_delay_ms(guest_hang_timeout_);
[email protected]c88b2a562012-10-27 03:36:56940}
941
[email protected]7a846df2012-09-20 19:17:39942void BrowserPluginGuest::RenderViewGone(base::TerminationStatus status) {
[email protected]8eb04562013-03-06 03:41:14943 int process_id = GetWebContents()->GetRenderProcessHost()->GetID();
[email protected]d752fe62013-03-01 03:46:01944 SendMessageToEmbedder(
945 new BrowserPluginMsg_GuestGone(instance_id(), process_id, status));
[email protected]2fae2c42012-10-03 21:20:04946 switch (status) {
947 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
948 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Killed"));
949 break;
950 case base::TERMINATION_STATUS_PROCESS_CRASHED:
951 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Crashed"));
952 break;
953 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
954 RecordAction(UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
955 break;
956 default:
957 break;
958 }
[email protected]7a846df2012-09-20 19:17:39959}
960
[email protected]8eb04562013-03-06 03:41:14961// static
962void BrowserPluginGuest::AcknowledgeBufferPresent(
963 int route_id,
964 int gpu_host_id,
[email protected]06666c02013-03-07 19:32:30965 const std::string& mailbox_name,
[email protected]8eb04562013-03-06 03:41:14966 uint32 sync_point) {
967 AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
968 ack_params.mailbox_name = mailbox_name;
969 ack_params.sync_point = sync_point;
970 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id,
971 gpu_host_id,
972 ack_params);
973}
974
975// static
976bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
977 const IPC::Message& message) {
978 switch (message.type()) {
979 case BrowserPluginHostMsg_BuffersSwappedACK::ID:
[email protected]f5b4b0f2013-04-02 18:16:28980 case BrowserPluginHostMsg_CompositorFrameACK::ID:
[email protected]8eb04562013-03-06 03:41:14981 case BrowserPluginHostMsg_DragStatusUpdate::ID:
[email protected]6dd17a8a2013-05-01 05:50:10982 case BrowserPluginHostMsg_ExecuteEditCommand::ID:
[email protected]8eb04562013-03-06 03:41:14983 case BrowserPluginHostMsg_Go::ID:
984 case BrowserPluginHostMsg_HandleInputEvent::ID:
985 case BrowserPluginHostMsg_LockMouse_ACK::ID:
986 case BrowserPluginHostMsg_NavigateGuest::ID:
987 case BrowserPluginHostMsg_PluginDestroyed::ID:
988 case BrowserPluginHostMsg_Reload::ID:
989 case BrowserPluginHostMsg_ResizeGuest::ID:
990 case BrowserPluginHostMsg_RespondPermission::ID:
991 case BrowserPluginHostMsg_SetAutoSize::ID:
[email protected]b77fac52013-06-01 01:03:46992 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
[email protected]8eb04562013-03-06 03:41:14993 case BrowserPluginHostMsg_SetFocus::ID:
994 case BrowserPluginHostMsg_SetName::ID:
995 case BrowserPluginHostMsg_SetVisibility::ID:
996 case BrowserPluginHostMsg_Stop::ID:
997 case BrowserPluginHostMsg_TerminateGuest::ID:
998 case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
[email protected]32deec62013-05-15 23:55:04999 case BrowserPluginHostMsg_UpdateGeometry::ID:
[email protected]8eb04562013-03-06 03:41:141000 case BrowserPluginHostMsg_UpdateRect_ACK::ID:
1001 return true;
1002 default:
1003 break;
1004 }
1005 return false;
1006}
1007
[email protected]a7fac9a2012-12-18 23:26:071008bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
1009 bool handled = true;
1010 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
[email protected]a7fac9a2012-12-18 23:26:071011 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
1012 OnHasTouchEventHandlers)
[email protected]861f9782013-03-05 03:29:541013 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
[email protected]a7fac9a2012-12-18 23:26:071014 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
1015 #if defined(OS_MACOSX)
1016 // MacOSX creates and populates platform-specific select drop-down menus
1017 // whereas other platforms merely create a popup window that the guest
1018 // renderer process paints inside.
1019 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
1020 #endif
1021 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
1022 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
[email protected]861f9782013-03-05 03:29:541023 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
[email protected]25bcc8f2013-01-09 02:49:251024 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName, OnUpdateFrameName)
[email protected]a7fac9a2012-12-18 23:26:071025 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
1026 IPC_MESSAGE_UNHANDLED(handled = false)
1027 IPC_END_MESSAGE_MAP()
1028 return handled;
1029}
1030
[email protected]c4538072013-03-18 02:17:551031void BrowserPluginGuest::Attach(
1032 WebContentsImpl* embedder_web_contents,
[email protected]4b4ed582013-05-01 00:16:231033 BrowserPluginHostMsg_Attach_Params params) {
1034 if (attached())
1035 return;
1036
1037 // Clear parameters that get inherited from the opener.
1038 params.storage_partition_id.clear();
1039 params.persist_storage = false;
1040 params.src.clear();
1041
[email protected]0c6d41752013-05-01 15:49:091042 // If a RenderView has already been created for this new window, then we need
1043 // to initialize the browser-side state now so that the RenderViewHostManager
1044 // does not create a new RenderView on navigation.
1045 if (has_render_view_) {
1046 static_cast<RenderViewHostImpl*>(
1047 GetWebContents()->GetRenderViewHost())->Init();
[email protected]c4538072013-03-18 02:17:551048 WebContentsViewGuest* new_view =
1049 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
1050 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
[email protected]c4538072013-03-18 02:17:551051 }
[email protected]0c6d41752013-05-01 15:49:091052
1053 // We need to do a navigation here if the target URL has changed between
1054 // the time the WebContents was created and the time it was attached.
1055 // We also need to do an initial navigation if a RenderView was never
1056 // created for the new window in cases where there is no referrer.
1057 PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
1058 if (it != opener()->pending_new_windows_.end()) {
[email protected]96584eec2013-05-07 13:25:321059 const NewWindowInfo& new_window_info = it->second;
1060 if (new_window_info.changed || !has_render_view_)
[email protected]0c6d41752013-05-01 15:49:091061 params.src = it->second.url.spec();
1062 } else {
1063 NOTREACHED();
1064 }
1065
[email protected]c4538072013-03-18 02:17:551066 // Once a new guest is attached to the DOM of the embedder page, then the
1067 // lifetime of the new guest is no longer managed by the opener guest.
1068 opener()->pending_new_windows_.erase(this);
1069
[email protected]50de3222013-03-20 15:36:131070 // The guest's frame name takes precedence over the BrowserPlugin's name.
1071 // The guest's frame name is assigned in
1072 // BrowserPluginGuest::WebContentsCreated.
1073 if (!name_.empty())
1074 params.name.clear();
1075
[email protected]c4538072013-03-18 02:17:551076 Initialize(embedder_web_contents, params);
1077
[email protected]620d5de52013-04-05 23:27:561078 // Inform the embedder of the guest's information.
1079 // We pull the partition information from the site's URL, which is of the form
1080 // guest://site/{persist}?{partition_name}.
1081 const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
1082 BrowserPluginMsg_Attach_ACK_Params ack_params;
1083 ack_params.storage_partition_id = site_url.query();
1084 ack_params.persist_storage =
1085 site_url.path().find("persist") != std::string::npos;
1086 ack_params.name = name_;
1087 SendMessageToEmbedder(
1088 new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params));
[email protected]697f16b52013-05-10 06:01:181089
1090 SendQueuedMessages();
[email protected]abc7d5c2013-05-15 09:19:251091
1092 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Attached"));
[email protected]c4538072013-03-18 02:17:551093}
1094
[email protected]f5b4b0f2013-04-02 18:16:281095void BrowserPluginGuest::OnCompositorFrameACK(
1096 int instance_id,
1097 int route_id,
1098 int renderer_host_id,
1099 const cc::CompositorFrameAck& ack) {
1100 RenderWidgetHostImpl::SendSwapCompositorFrameAck(route_id,
1101 renderer_host_id,
1102 ack);
1103}
1104
[email protected]3997b1b22012-12-20 01:02:541105void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
1106 WebKit::WebDragStatus drag_status,
1107 const WebDropData& drop_data,
1108 WebKit::WebDragOperationsMask mask,
1109 const gfx::Point& location) {
[email protected]8eb04562013-03-06 03:41:141110 RenderViewHost* host = GetWebContents()->GetRenderViewHost();
[email protected]3997b1b22012-12-20 01:02:541111 switch (drag_status) {
1112 case WebKit::WebDragStatusEnter:
[email protected]cf200a562013-05-03 16:24:291113 embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
1114 this);
[email protected]3997b1b22012-12-20 01:02:541115 host->DragTargetDragEnter(drop_data, location, location, mask, 0);
1116 break;
1117 case WebKit::WebDragStatusOver:
1118 host->DragTargetDragOver(location, location, mask, 0);
1119 break;
1120 case WebKit::WebDragStatusLeave:
[email protected]cf200a562013-05-03 16:24:291121 embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
[email protected]3997b1b22012-12-20 01:02:541122 host->DragTargetDragLeave();
1123 break;
1124 case WebKit::WebDragStatusDrop:
1125 host->DragTargetDrop(location, location, 0);
[email protected]cf200a562013-05-03 16:24:291126 EndSystemDrag();
[email protected]3997b1b22012-12-20 01:02:541127 break;
1128 case WebKit::WebDragStatusUnknown:
1129 NOTREACHED();
1130 }
1131}
1132
[email protected]6dd17a8a2013-05-01 05:50:101133void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
1134 const std::string& name) {
1135 Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
1136}
1137
[email protected]56ffe70b2013-01-11 17:00:521138void BrowserPluginGuest::OnGo(int instance_id, int relative_index) {
[email protected]8eb04562013-03-06 03:41:141139 GetWebContents()->GetController().GoToOffset(relative_index);
[email protected]56ffe70b2013-01-11 17:00:521140}
1141
[email protected]3997b1b22012-12-20 01:02:541142void BrowserPluginGuest::OnHandleInputEvent(
1143 int instance_id,
1144 const gfx::Rect& guest_window_rect,
1145 const WebKit::WebInputEvent* event) {
1146 guest_window_rect_ = guest_window_rect;
[email protected]c6ea9212013-04-09 18:51:561147 // If the embedder's RWHV is destroyed then that means that the embedder's
1148 // window has been closed but the embedder's WebContents has not yet been
1149 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
1150 // if there is a visible embedder.
1151 if (embedder_web_contents_->GetRenderWidgetHostView()) {
1152 guest_screen_rect_ = guest_window_rect;
1153 guest_screen_rect_.Offset(
1154 embedder_web_contents_->GetRenderWidgetHostView()->
1155 GetViewBounds().OffsetFromOrigin());
1156 }
[email protected]3997b1b22012-12-20 01:02:541157 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
[email protected]8eb04562013-03-06 03:41:141158 GetWebContents()->GetRenderViewHost());
[email protected]3997b1b22012-12-20 01:02:541159
[email protected]bca6c2c2013-03-24 03:55:071160 if (WebKit::WebInputEvent::isMouseEventType(event->type)) {
1161 guest_rvh->ForwardMouseEvent(
1162 *static_cast<const WebKit::WebMouseEvent*>(event));
1163 return;
[email protected]3997b1b22012-12-20 01:02:541164 }
1165
[email protected]bca6c2c2013-03-24 03:55:071166 if (event->type == WebKit::WebInputEvent::MouseWheel) {
1167 guest_rvh->ForwardWheelEvent(
1168 *static_cast<const WebKit::WebMouseWheelEvent*>(event));
1169 return;
1170 }
1171
1172 if (WebKit::WebInputEvent::isKeyboardEventType(event->type)) {
[email protected]6dd17a8a2013-05-01 05:50:101173 RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
1174 embedder_web_contents_->GetRenderViewHost());
1175 if (!embedder_rvh->GetLastKeyboardEvent())
1176 return;
1177 NativeWebKeyboardEvent keyboard_event(
1178 *embedder_rvh->GetLastKeyboardEvent());
[email protected]bca6c2c2013-03-24 03:55:071179 guest_rvh->ForwardKeyboardEvent(keyboard_event);
1180 return;
1181 }
1182
1183 if (WebKit::WebInputEvent::isTouchEventType(event->type)) {
1184 guest_rvh->ForwardTouchEvent(
1185 *static_cast<const WebKit::WebTouchEvent*>(event));
1186 return;
1187 }
1188
1189 if (WebKit::WebInputEvent::isGestureEventType(event->type)) {
1190 guest_rvh->ForwardGestureEvent(
1191 *static_cast<const WebKit::WebGestureEvent*>(event));
1192 return;
1193 }
[email protected]3997b1b22012-12-20 01:02:541194}
1195
[email protected]861f9782013-03-05 03:29:541196void BrowserPluginGuest::OnLockMouse(bool user_gesture,
1197 bool last_unlocked_by_target,
1198 bool privileged) {
[email protected]a25acea72013-03-10 23:41:281199 if (pending_lock_request_) {
1200 // Immediately reject the lock because only one pointerLock may be active
1201 // at a time.
1202 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
1203 return;
1204 }
1205 pending_lock_request_ = true;
1206 int request_id = next_permission_request_id_++;
1207 base::DictionaryValue request_info;
1208 request_info.Set(browser_plugin::kUserGesture,
1209 base::Value::CreateBooleanValue(user_gesture));
1210 request_info.Set(browser_plugin::kLastUnlockedBySelf,
1211 base::Value::CreateBooleanValue(last_unlocked_by_target));
1212 request_info.Set(browser_plugin::kURL,
1213 base::Value::CreateStringValue(
1214 web_contents()->GetURL().spec()));
1215
1216 SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
1217 instance_id(), BrowserPluginPermissionTypePointerLock,
1218 request_id, request_info));
[email protected]861f9782013-03-05 03:29:541219}
1220
1221void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
1222 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
[email protected]a25acea72013-03-10 23:41:281223 pending_lock_request_ = false;
[email protected]861f9782013-03-05 03:29:541224 if (succeeded)
1225 mouse_locked_ = true;
1226}
1227
[email protected]5e7967972013-01-15 22:45:331228void BrowserPluginGuest::OnNavigateGuest(
1229 int instance_id,
1230 const std::string& src) {
1231 GURL url(src);
[email protected]5e7967972013-01-15 22:45:331232 // We do not load empty urls in web_contents.
1233 // If a guest sets empty src attribute after it has navigated to some
1234 // non-empty page, the action is considered no-op. This empty src navigation
[email protected]e1eef4f2013-01-15 23:18:211235 // should never be sent to BrowserPluginGuest (browser process).
[email protected]5e7967972013-01-15 22:45:331236 DCHECK(!src.empty());
1237 if (!src.empty()) {
[email protected]e1eef4f2013-01-15 23:18:211238 // As guests do not swap processes on navigation, only navigations to
[email protected]5e7967972013-01-15 22:45:331239 // normal web URLs are supported. No protocol handlers are installed for
1240 // other schemes (e.g., WebUI or extensions), and no permissions or bindings
1241 // can be granted to the guest process.
[email protected]8eb04562013-03-06 03:41:141242 GetWebContents()->GetController().LoadURL(url, Referrer(),
[email protected]e1eef4f2013-01-15 23:18:211243 PAGE_TRANSITION_AUTO_TOPLEVEL,
1244 std::string());
[email protected]5e7967972013-01-15 22:45:331245 }
1246}
1247
[email protected]b371a5652013-02-20 11:25:511248void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
[email protected]b371a5652013-02-20 11:25:511249 Destroy();
1250}
1251
[email protected]3997b1b22012-12-20 01:02:541252void BrowserPluginGuest::OnReload(int instance_id) {
1253 // TODO(fsamuel): Don't check for repost because we don't want to show
1254 // Chromium's repost warning. We might want to implement a separate API
1255 // for registering a callback if a repost is about to happen.
[email protected]8eb04562013-03-06 03:41:141256 GetWebContents()->GetController().Reload(false);
[email protected]3997b1b22012-12-20 01:02:541257}
1258
1259void BrowserPluginGuest::OnResizeGuest(
1260 int instance_id,
1261 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
1262 // BrowserPlugin manages resize flow control itself and does not depend
1263 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
1264 // here. If we are setting the size for the first time before navigating then
1265 // BrowserPluginGuest does not yet have a RenderViewHost.
[email protected]8eb04562013-03-06 03:41:141266 if (GetWebContents()->GetRenderViewHost()) {
[email protected]3997b1b22012-12-20 01:02:541267 RenderWidgetHostImpl* render_widget_host =
[email protected]8eb04562013-03-06 03:41:141268 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
[email protected]3997b1b22012-12-20 01:02:541269 render_widget_host->ResetSizeAndRepaintPendingFlags();
[email protected]caaf2482013-05-01 20:33:321270
1271 if (guest_device_scale_factor_ != params.scale_factor) {
1272 guest_device_scale_factor_ = params.scale_factor;
1273 render_widget_host->NotifyScreenInfoChanged();
1274 }
[email protected]3997b1b22012-12-20 01:02:541275 }
[email protected]caaf2482013-05-01 20:33:321276 // Invalid damage buffer means we are in HW compositing mode,
1277 // so just resize the WebContents and repaint if needed.
[email protected]4d1afd62012-12-21 03:09:401278 if (!base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) {
[email protected]32deec62013-05-15 23:55:041279 if (!params.view_rect.size().IsEmpty())
1280 GetWebContents()->GetView()->SizeContents(params.view_rect.size());
[email protected]caaf2482013-05-01 20:33:321281 if (params.repaint)
[email protected]32deec62013-05-15 23:55:041282 Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size()));
[email protected]3997b1b22012-12-20 01:02:541283 return;
1284 }
[email protected]4d1afd62012-12-21 03:09:401285 SetDamageBuffer(params);
[email protected]32deec62013-05-15 23:55:041286 GetWebContents()->GetView()->SizeContents(params.view_rect.size());
[email protected]8eb04562013-03-06 03:41:141287 if (params.repaint)
[email protected]32deec62013-05-15 23:55:041288 Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size()));
[email protected]3997b1b22012-12-20 01:02:541289}
1290
[email protected]423838472013-01-09 00:16:461291void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
1292 if (focused_ == focused)
1293 return;
1294 focused_ = focused;
[email protected]c084330e02013-04-27 01:08:151295 Send(new InputMsg_SetFocus(routing_id(), focused));
[email protected]79733a02013-04-30 15:05:351296 if (!focused && mouse_locked_)
1297 OnUnlockMouse();
[email protected]423838472013-01-09 00:16:461298}
1299
[email protected]25bcc8f2013-01-09 02:49:251300void BrowserPluginGuest::OnSetName(int instance_id, const std::string& name) {
1301 if (name == name_)
1302 return;
1303 name_ = name;
[email protected]8eb04562013-03-06 03:41:141304 Send(new ViewMsg_SetName(routing_id(), name));
[email protected]25bcc8f2013-01-09 02:49:251305}
1306
[email protected]3997b1b22012-12-20 01:02:541307void BrowserPluginGuest::OnSetSize(
1308 int instance_id,
1309 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
1310 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
1311 bool old_auto_size_enabled = auto_size_enabled_;
1312 gfx::Size old_max_size = max_auto_size_;
1313 gfx::Size old_min_size = min_auto_size_;
1314 auto_size_enabled_ = auto_size_params.enable;
1315 max_auto_size_ = auto_size_params.max_size;
1316 min_auto_size_ = auto_size_params.min_size;
1317 if (auto_size_enabled_ && (!old_auto_size_enabled ||
1318 (old_max_size != max_auto_size_) ||
1319 (old_min_size != min_auto_size_))) {
[email protected]8eb04562013-03-06 03:41:141320 GetWebContents()->GetRenderViewHost()->EnableAutoResize(
[email protected]3997b1b22012-12-20 01:02:541321 min_auto_size_, max_auto_size_);
1322 // TODO(fsamuel): If we're changing autosize parameters, then we force
1323 // the guest to completely repaint itself, because BrowserPlugin has
1324 // allocated a new damage buffer and expects a full frame of pixels.
1325 // Ideally, we shouldn't need to do this because we shouldn't need to
1326 // allocate a new damage buffer unless |max_auto_size_| has changed.
1327 // However, even in that case, layout may not change and so we may
1328 // not get a full frame worth of pixels.
[email protected]8eb04562013-03-06 03:41:141329 Send(new ViewMsg_Repaint(routing_id(), max_auto_size_));
[email protected]3997b1b22012-12-20 01:02:541330 } else if (!auto_size_enabled_ && old_auto_size_enabled) {
[email protected]8eb04562013-03-06 03:41:141331 GetWebContents()->GetRenderViewHost()->DisableAutoResize(
[email protected]32deec62013-05-15 23:55:041332 resize_guest_params.view_rect.size());
[email protected]3997b1b22012-12-20 01:02:541333 }
1334 OnResizeGuest(instance_id_, resize_guest_params);
1335}
1336
[email protected]b77fac52013-06-01 01:03:461337void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
1338 int instance_id,
1339 const std::vector<EditCommand>& edit_commands) {
1340 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
1341 edit_commands));
1342}
1343
[email protected]3997b1b22012-12-20 01:02:541344void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
[email protected]93564f72013-02-15 13:26:191345 guest_visible_ = visible;
1346 if (embedder_visible_ && guest_visible_)
[email protected]8eb04562013-03-06 03:41:141347 GetWebContents()->WasShown();
[email protected]3997b1b22012-12-20 01:02:541348 else
[email protected]8eb04562013-03-06 03:41:141349 GetWebContents()->WasHidden();
[email protected]3997b1b22012-12-20 01:02:541350}
1351
1352void BrowserPluginGuest::OnStop(int instance_id) {
[email protected]8eb04562013-03-06 03:41:141353 GetWebContents()->Stop();
[email protected]cc8ed212013-02-07 22:31:031354}
1355
[email protected]c006fb52013-03-01 09:36:451356void BrowserPluginGuest::OnRespondPermission(
[email protected]e4a55a52013-03-09 01:32:491357 int instance_id,
[email protected]c006fb52013-03-01 09:36:451358 BrowserPluginPermissionType permission_type,
1359 int request_id,
1360 bool should_allow) {
[email protected]cf4c9e052013-05-04 04:53:441361 RequestMap::iterator request_itr = permission_request_map_.find(request_id);
1362 if (request_itr == permission_request_map_.end()) {
1363 LOG(INFO) << "Not a valid request ID.";
1364 return;
1365 }
1366 request_itr->second->Respond(should_allow);
1367
1368 // Geolocation requests have to hang around for a while, so we don't delete
1369 // them here.
1370 if (permission_type != BrowserPluginPermissionTypeGeolocation) {
1371 delete request_itr->second;
1372 permission_request_map_.erase(request_itr);
[email protected]c006fb52013-03-01 09:36:451373 }
[email protected]c006fb52013-03-01 09:36:451374}
1375
[email protected]cc8ed212013-02-07 22:31:031376void BrowserPluginGuest::OnSwapBuffersACK(int instance_id,
1377 int route_id,
1378 int gpu_host_id,
[email protected]06666c02013-03-07 19:32:301379 const std::string& mailbox_name,
[email protected]cc8ed212013-02-07 22:31:031380 uint32 sync_point) {
1381 AcknowledgeBufferPresent(route_id, gpu_host_id, mailbox_name, sync_point);
1382
1383// This is only relevant on MACOSX and WIN when threaded compositing
1384// is not enabled. In threaded mode, above ACK is sufficient.
1385#if defined(OS_MACOSX) || defined(OS_WIN)
1386 RenderWidgetHostImpl* render_widget_host =
[email protected]8eb04562013-03-06 03:41:141387 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
[email protected]cc8ed212013-02-07 22:31:031388 render_widget_host->AcknowledgeSwapBuffersToRenderer();
1389#endif // defined(OS_MACOSX) || defined(OS_WIN)
1390}
1391
[email protected]3997b1b22012-12-20 01:02:541392void BrowserPluginGuest::OnTerminateGuest(int instance_id) {
1393 RecordAction(UserMetricsAction("BrowserPlugin.Guest.Terminate"));
1394 base::ProcessHandle process_handle =
[email protected]8eb04562013-03-06 03:41:141395 GetWebContents()->GetRenderProcessHost()->GetHandle();
[email protected]a6e43aa2013-02-07 03:22:031396 if (process_handle)
1397 base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
[email protected]3997b1b22012-12-20 01:02:541398}
1399
[email protected]861f9782013-03-05 03:29:541400void BrowserPluginGuest::OnUnlockMouse() {
[email protected]c4538072013-03-18 02:17:551401 SendMessageToEmbedder(new BrowserPluginMsg_UnlockMouse(instance_id()));
[email protected]861f9782013-03-05 03:29:541402}
1403
1404void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
1405 // mouse_locked_ could be false here if the lock attempt was cancelled due
1406 // to window focus, or for various other reasons before the guest was informed
1407 // of the lock's success.
1408 if (mouse_locked_)
1409 Send(new ViewMsg_MouseLockLost(routing_id()));
1410 mouse_locked_ = false;
1411}
1412
[email protected]3997b1b22012-12-20 01:02:541413void BrowserPluginGuest::OnUpdateRectACK(
1414 int instance_id,
1415 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
1416 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
[email protected]8eb04562013-03-06 03:41:141417 Send(new ViewMsg_UpdateRect_ACK(routing_id()));
[email protected]3997b1b22012-12-20 01:02:541418 OnSetSize(instance_id_, auto_size_params, resize_guest_params);
1419}
1420
[email protected]32deec62013-05-15 23:55:041421void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
1422 const gfx::Rect& view_rect) {
1423 // The plugin has moved within the embedder without resizing or the
1424 // embedder/container's view rect changing.
1425 guest_window_rect_ = view_rect;
1426 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
1427 GetWebContents()->GetRenderViewHost());
1428 if (rvh)
1429 rvh->SendScreenRects();
1430}
1431
[email protected]a7fac9a2012-12-18 23:26:071432void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
1433 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:011434 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
[email protected]a7fac9a2012-12-18 23:26:071435}
1436
1437void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
[email protected]d752fe62013-03-01 03:46:011438 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
[email protected]a7fac9a2012-12-18 23:26:071439}
1440
1441#if defined(OS_MACOSX)
1442void BrowserPluginGuest::OnShowPopup(
1443 const ViewHostMsg_ShowPopup_Params& params) {
1444 gfx::Rect translated_bounds(params.bounds);
1445 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
1446 BrowserPluginPopupMenuHelper popup_menu_helper(
1447 embedder_web_contents_->GetRenderViewHost(),
[email protected]8eb04562013-03-06 03:41:141448 GetWebContents()->GetRenderViewHost());
[email protected]a7fac9a2012-12-18 23:26:071449 popup_menu_helper.ShowPopupMenu(translated_bounds,
1450 params.item_height,
1451 params.item_font_size,
1452 params.selected_item,
1453 params.popup_items,
1454 params.right_aligned,
1455 params.allow_multiple_selection);
1456}
1457#endif
1458
1459void BrowserPluginGuest::OnShowWidget(int route_id,
1460 const gfx::Rect& initial_pos) {
[email protected]32deec62013-05-15 23:55:041461 GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
[email protected]a7fac9a2012-12-18 23:26:071462}
1463
1464void BrowserPluginGuest::OnTakeFocus(bool reverse) {
1465 SendMessageToEmbedder(
[email protected]d752fe62013-03-01 03:46:011466 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
[email protected]a7fac9a2012-12-18 23:26:071467}
1468
[email protected]25bcc8f2013-01-09 02:49:251469void BrowserPluginGuest::OnUpdateFrameName(int frame_id,
1470 bool is_top_level,
1471 const std::string& name) {
1472 if (!is_top_level)
1473 return;
1474
1475 name_ = name;
[email protected]d752fe62013-03-01 03:46:011476 SendMessageToEmbedder(new BrowserPluginMsg_UpdatedName(instance_id_, name));
[email protected]25bcc8f2013-01-09 02:49:251477}
1478
[email protected]c006fb52013-03-01 09:36:451479void BrowserPluginGuest::RequestMediaAccessPermission(
1480 WebContents* web_contents,
[email protected]ce0e2602013-03-15 20:53:271481 const MediaStreamRequest& request,
1482 const MediaResponseCallback& callback) {
[email protected]cf4c9e052013-05-04 04:53:441483 if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
[email protected]c006fb52013-03-01 09:36:451484 // Deny the media request.
[email protected]b5f76742013-04-29 15:05:591485 callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
[email protected]c006fb52013-03-01 09:36:451486 return;
1487 }
[email protected]b80a28722013-03-07 06:17:441488 int request_id = next_permission_request_id_++;
[email protected]cf4c9e052013-05-04 04:53:441489 permission_request_map_[request_id] =
1490 new MediaRequest(request, callback, this);
[email protected]c006fb52013-03-01 09:36:451491
1492 base::DictionaryValue request_info;
1493 request_info.Set(
[email protected]8eb04562013-03-06 03:41:141494 browser_plugin::kURL,
1495 base::Value::CreateStringValue(request.security_origin.spec()));
[email protected]c006fb52013-03-01 09:36:451496 SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
1497 instance_id(), BrowserPluginPermissionTypeMedia,
1498 request_id, request_info));
1499}
1500
[email protected]a7fac9a2012-12-18 23:26:071501void BrowserPluginGuest::OnUpdateRect(
1502 const ViewHostMsg_UpdateRect_Params& params) {
1503
1504 BrowserPluginMsg_UpdateRect_Params relay_params;
1505 relay_params.view_size = params.view_size;
1506 relay_params.scale_factor = params.scale_factor;
1507 relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
1508 params.flags);
[email protected]166f61a2013-01-09 23:54:491509 relay_params.needs_ack = params.needs_ack;
[email protected]a7fac9a2012-12-18 23:26:071510
1511 // HW accelerated case, acknowledge resize only
[email protected]61c555422013-01-31 19:31:061512 if (!params.needs_ack || !damage_buffer_) {
[email protected]4d1afd62012-12-21 03:09:401513 relay_params.damage_buffer_sequence_id = 0;
[email protected]d752fe62013-03-01 03:46:011514 SendMessageToEmbedder(
1515 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
1516 return;
[email protected]a7fac9a2012-12-18 23:26:071517 }
1518
[email protected]a7fac9a2012-12-18 23:26:071519 // Only copy damage if the guest is in autosize mode and the guest's view size
1520 // is less than the maximum size or the guest's view size is equal to the
1521 // damage buffer's size and the guest's scale factor is equal to the damage
1522 // buffer's scale factor.
1523 // The scaling change can happen due to asynchronous updates of the DPI on a
1524 // resolution change.
1525 if (((auto_size_enabled_ && InAutoSizeBounds(params.view_size)) ||
[email protected]32deec62013-05-15 23:55:041526 (params.view_size == damage_view_size())) &&
[email protected]a7fac9a2012-12-18 23:26:071527 params.scale_factor == damage_buffer_scale_factor()) {
[email protected]8eb04562013-03-06 03:41:141528 TransportDIB* dib = GetWebContents()->GetRenderProcessHost()->
[email protected]a7fac9a2012-12-18 23:26:071529 GetTransportDIB(params.bitmap);
1530 if (dib) {
[email protected]4d1afd62012-12-21 03:09:401531 size_t guest_damage_buffer_size =
[email protected]a7fac9a2012-12-18 23:26:071532#if defined(OS_WIN)
[email protected]4d1afd62012-12-21 03:09:401533 params.bitmap_rect.width() *
1534 params.bitmap_rect.height() * 4;
[email protected]a7fac9a2012-12-18 23:26:071535#else
[email protected]4d1afd62012-12-21 03:09:401536 dib->size();
[email protected]a7fac9a2012-12-18 23:26:071537#endif
[email protected]4d1afd62012-12-21 03:09:401538 size_t embedder_damage_buffer_size = damage_buffer_size_;
[email protected]a7fac9a2012-12-18 23:26:071539 void* guest_memory = dib->memory();
1540 void* embedder_memory = damage_buffer_->memory();
1541 size_t size = std::min(guest_damage_buffer_size,
1542 embedder_damage_buffer_size);
1543 memcpy(embedder_memory, guest_memory, size);
1544 }
1545 }
[email protected]4d1afd62012-12-21 03:09:401546 relay_params.damage_buffer_sequence_id = damage_buffer_sequence_id_;
[email protected]a7fac9a2012-12-18 23:26:071547 relay_params.bitmap_rect = params.bitmap_rect;
1548 relay_params.scroll_delta = params.scroll_delta;
1549 relay_params.scroll_rect = params.scroll_rect;
1550 relay_params.copy_rects = params.copy_rects;
1551
[email protected]d752fe62013-03-01 03:46:011552 SendMessageToEmbedder(
1553 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
[email protected]7a846df2012-09-20 19:17:391554}
1555
[email protected]f85f5032013-04-03 09:01:541556void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
1557 const std::string& request_method,
1558 int permission_request_id,
1559 const std::string& url) {
1560 if (url.empty()) {
[email protected]cf4c9e052013-05-04 04:53:441561 OnRespondPermission(instance_id(), BrowserPluginPermissionTypeDownload,
1562 permission_request_id, false);
[email protected]f85f5032013-04-03 09:01:541563 return;
1564 }
1565
1566 base::DictionaryValue request_info;
1567 request_info.Set(browser_plugin::kRequestMethod,
1568 base::Value::CreateStringValue(request_method));
1569 request_info.Set(browser_plugin::kURL, base::Value::CreateStringValue(url));
1570
1571 SendMessageToEmbedder(
1572 new BrowserPluginMsg_RequestPermission(instance_id(),
1573 BrowserPluginPermissionTypeDownload, permission_request_id,
1574 request_info));
1575}
1576
[email protected]7a846df2012-09-20 19:17:391577} // namespace content