<webview> Bring up color picker for <input type=color>
[chromium-blink-merge.git] / content / browser / browser_plugin / browser_plugin_guest.cc
blob61e93bd858073bacbe08ea68c47c9bc5b6a05791
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/browser_plugin/browser_plugin_guest.h"
7 #include <algorithm>
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
13 #include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
14 #include "content/browser/browser_plugin/browser_plugin_host_factory.h"
15 #include "content/browser/browser_thread_impl.h"
16 #include "content/browser/child_process_security_policy_impl.h"
17 #include "content/browser/frame_host/render_frame_host_impl.h"
18 #include "content/browser/frame_host/render_widget_host_view_guest.h"
19 #include "content/browser/loader/resource_dispatcher_host_impl.h"
20 #include "content/browser/renderer_host/render_view_host_impl.h"
21 #include "content/browser/renderer_host/render_widget_host_impl.h"
22 #include "content/browser/web_contents/web_contents_impl.h"
23 #include "content/browser/web_contents/web_contents_view_guest.h"
24 #include "content/common/browser_plugin/browser_plugin_constants.h"
25 #include "content/common/browser_plugin/browser_plugin_messages.h"
26 #include "content/common/content_constants_internal.h"
27 #include "content/common/drag_messages.h"
28 #include "content/common/gpu/gpu_messages.h"
29 #include "content/common/input_messages.h"
30 #include "content/common/view_messages.h"
31 #include "content/port/browser/render_view_host_delegate_view.h"
32 #include "content/port/browser/render_widget_host_view_port.h"
33 #include "content/public/browser/browser_context.h"
34 #include "content/public/browser/content_browser_client.h"
35 #include "content/public/browser/geolocation_permission_context.h"
36 #include "content/public/browser/navigation_controller.h"
37 #include "content/public/browser/render_process_host.h"
38 #include "content/public/browser/render_widget_host_view.h"
39 #include "content/public/browser/resource_request_details.h"
40 #include "content/public/browser/user_metrics.h"
41 #include "content/public/browser/web_contents_observer.h"
42 #include "content/public/browser/web_contents_view.h"
43 #include "content/public/common/drop_data.h"
44 #include "content/public/common/media_stream_request.h"
45 #include "content/public/common/result_codes.h"
46 #include "content/public/common/url_constants.h"
47 #include "content/public/common/url_utils.h"
48 #include "net/url_request/url_request.h"
49 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
50 #include "ui/events/keycodes/keyboard_codes.h"
51 #include "ui/surface/transport_dib.h"
52 #include "webkit/common/resource_type.h"
54 #if defined(OS_MACOSX)
55 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
56 #endif
58 namespace content {
60 // static
61 BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
63 // Parent class for the various types of permission requests, each of which
64 // should be able to handle the response to their permission request.
65 class BrowserPluginGuest::PermissionRequest :
66 public base::RefCounted<BrowserPluginGuest::PermissionRequest> {
67 public:
68 void Respond(bool should_allow, const std::string& user_input) {
69 if (!guest_)
70 return;
71 RespondImpl(should_allow, user_input);
73 virtual bool AllowedByDefault() const {
74 return false;
76 protected:
77 explicit PermissionRequest(const base::WeakPtr<BrowserPluginGuest>& guest)
78 : guest_(guest) {
79 RecordAction(
80 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest"));
82 virtual ~PermissionRequest() {}
84 virtual void RespondImpl(bool should_allow,
85 const std::string& user_input) = 0;
86 // Friend RefCounted so that the dtor can be non-public.
87 friend class base::RefCounted<BrowserPluginGuest::PermissionRequest>;
89 base::WeakPtr<BrowserPluginGuest> guest_;
92 class BrowserPluginGuest::DownloadRequest : public PermissionRequest {
93 public:
94 DownloadRequest(const base::WeakPtr<BrowserPluginGuest>& guest,
95 const base::Callback<void(bool)>& callback)
96 : PermissionRequest(guest),
97 callback_(callback) {
98 RecordAction(
99 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Download"));
101 virtual void RespondImpl(bool should_allow,
102 const std::string& user_input) OVERRIDE {
103 callback_.Run(should_allow);
106 private:
107 virtual ~DownloadRequest() {}
108 base::Callback<void(bool)> callback_;
111 class BrowserPluginGuest::GeolocationRequest : public PermissionRequest {
112 public:
113 GeolocationRequest(const base::WeakPtr<BrowserPluginGuest>& guest,
114 GeolocationCallback callback,
115 int bridge_id)
116 : PermissionRequest(guest),
117 callback_(callback),
118 bridge_id_(bridge_id) {
119 RecordAction(
120 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Geolocation"));
123 virtual void RespondImpl(bool should_allow,
124 const std::string& user_input) OVERRIDE {
125 WebContents* web_contents = guest_->embedder_web_contents();
126 if (should_allow && web_contents) {
127 // If renderer side embedder decides to allow gelocation, we need to check
128 // if the app/embedder itself has geolocation access.
129 BrowserContext* browser_context = web_contents->GetBrowserContext();
130 if (browser_context) {
131 GeolocationPermissionContext* geolocation_context =
132 browser_context->GetGeolocationPermissionContext();
133 if (geolocation_context) {
134 base::Callback<void(bool)> geolocation_callback = base::Bind(
135 &BrowserPluginGuest::SetGeolocationPermission,
136 guest_,
137 callback_,
138 bridge_id_);
139 geolocation_context->RequestGeolocationPermission(
140 web_contents->GetRenderProcessHost()->GetID(),
141 web_contents->GetRoutingID(),
142 // The geolocation permission request here is not initiated
143 // through WebGeolocationPermissionRequest. We are only interested
144 // in the fact whether the embedder/app has geolocation
145 // permission. Therefore we use an invalid |bridge_id|.
146 -1 /* bridge_id */,
147 web_contents->GetLastCommittedURL(),
148 geolocation_callback);
149 return;
153 guest_->SetGeolocationPermission(callback_, bridge_id_, false);
156 private:
157 virtual ~GeolocationRequest() {}
158 base::Callback<void(bool)> callback_;
159 int bridge_id_;
162 class BrowserPluginGuest::MediaRequest : public PermissionRequest {
163 public:
164 MediaRequest(const base::WeakPtr<BrowserPluginGuest>& guest,
165 const MediaStreamRequest& request,
166 const MediaResponseCallback& callback)
167 : PermissionRequest(guest),
168 request_(request),
169 callback_(callback) {
170 RecordAction(
171 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.Media"));
174 virtual void RespondImpl(bool should_allow,
175 const std::string& user_input) OVERRIDE {
176 WebContentsImpl* web_contents = guest_->embedder_web_contents();
177 if (should_allow && web_contents) {
178 // Re-route the request to the embedder's WebContents; the guest gets the
179 // permission this way.
180 web_contents->RequestMediaAccessPermission(request_, callback_);
181 } else {
182 // Deny the request.
183 callback_.Run(MediaStreamDevices(),
184 MEDIA_DEVICE_INVALID_STATE,
185 scoped_ptr<MediaStreamUI>());
189 private:
190 virtual ~MediaRequest() {}
191 MediaStreamRequest request_;
192 MediaResponseCallback callback_;
195 class BrowserPluginGuest::NewWindowRequest : public PermissionRequest {
196 public:
197 NewWindowRequest(const base::WeakPtr<BrowserPluginGuest>& guest,
198 int instance_id)
199 : PermissionRequest(guest),
200 instance_id_(instance_id) {
201 RecordAction(
202 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.NewWindow"));
205 virtual void RespondImpl(bool should_allow,
206 const std::string& user_input) OVERRIDE {
207 int embedder_render_process_id =
208 guest_->embedder_web_contents()->GetRenderProcessHost()->GetID();
209 BrowserPluginGuest* guest =
210 guest_->GetWebContents()->GetBrowserPluginGuestManager()->
211 GetGuestByInstanceID(instance_id_, embedder_render_process_id);
212 if (!guest) {
213 VLOG(0) << "Guest not found. Instance ID: " << instance_id_;
214 return;
217 // If we do not destroy the guest then we allow the new window.
218 if (!should_allow)
219 guest->Destroy();
222 private:
223 virtual ~NewWindowRequest() {}
224 int instance_id_;
227 class BrowserPluginGuest::JavaScriptDialogRequest : public PermissionRequest {
228 public:
229 JavaScriptDialogRequest(const base::WeakPtr<BrowserPluginGuest>& guest,
230 const DialogClosedCallback& callback)
231 : PermissionRequest(guest),
232 callback_(callback) {
233 RecordAction(
234 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.JSDialog"));
237 virtual void RespondImpl(bool should_allow,
238 const std::string& user_input) OVERRIDE {
239 callback_.Run(should_allow, base::UTF8ToUTF16(user_input));
242 private:
243 virtual ~JavaScriptDialogRequest() {}
244 DialogClosedCallback callback_;
247 class BrowserPluginGuest::PointerLockRequest : public PermissionRequest {
248 public:
249 explicit PointerLockRequest(const base::WeakPtr<BrowserPluginGuest>& guest)
250 : PermissionRequest(guest) {
251 RecordAction(
252 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.PointerLock"));
255 virtual void RespondImpl(bool should_allow,
256 const std::string& user_input) OVERRIDE {
257 guest_->SendMessageToEmbedder(
258 new BrowserPluginMsg_SetMouseLock(guest_->instance_id(), should_allow));
261 private:
262 virtual ~PointerLockRequest() {}
265 namespace {
266 std::string WindowOpenDispositionToString(
267 WindowOpenDisposition window_open_disposition) {
268 switch (window_open_disposition) {
269 case IGNORE_ACTION:
270 return "ignore";
271 case SAVE_TO_DISK:
272 return "save_to_disk";
273 case CURRENT_TAB:
274 return "current_tab";
275 case NEW_BACKGROUND_TAB:
276 return "new_background_tab";
277 case NEW_FOREGROUND_TAB:
278 return "new_foreground_tab";
279 case NEW_WINDOW:
280 return "new_window";
281 case NEW_POPUP:
282 return "new_popup";
283 default:
284 NOTREACHED() << "Unknown Window Open Disposition";
285 return "ignore";
289 std::string JavaScriptMessageTypeToString(JavaScriptMessageType message_type) {
290 switch (message_type) {
291 case JAVASCRIPT_MESSAGE_TYPE_ALERT:
292 return "alert";
293 case JAVASCRIPT_MESSAGE_TYPE_CONFIRM:
294 return "confirm";
295 case JAVASCRIPT_MESSAGE_TYPE_PROMPT:
296 return "prompt";
297 default:
298 NOTREACHED() << "Unknown JavaScript Message Type.";
299 return "unknown";
303 // Called on IO thread.
304 static std::string RetrieveDownloadURLFromRequestId(
305 RenderViewHost* render_view_host,
306 int url_request_id) {
307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
309 int render_process_id = render_view_host->GetProcess()->GetID();
310 GlobalRequestID global_id(render_process_id, url_request_id);
311 net::URLRequest* url_request =
312 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
313 if (url_request)
314 return url_request->url().possibly_invalid_spec();
315 return "";
318 } // namespace
320 class BrowserPluginGuest::EmbedderWebContentsObserver
321 : public WebContentsObserver {
322 public:
323 explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest)
324 : WebContentsObserver(guest->embedder_web_contents()),
325 browser_plugin_guest_(guest) {
328 virtual ~EmbedderWebContentsObserver() {
331 // WebContentsObserver:
332 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
333 browser_plugin_guest_->EmbedderDestroyed();
336 virtual void WasShown() OVERRIDE {
337 browser_plugin_guest_->EmbedderVisibilityChanged(true);
340 virtual void WasHidden() OVERRIDE {
341 browser_plugin_guest_->EmbedderVisibilityChanged(false);
344 private:
345 BrowserPluginGuest* browser_plugin_guest_;
347 DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
350 BrowserPluginGuest::BrowserPluginGuest(
351 int instance_id,
352 bool has_render_view,
353 WebContentsImpl* web_contents,
354 BrowserPluginGuest* opener)
355 : WebContentsObserver(web_contents),
356 embedder_web_contents_(NULL),
357 instance_id_(instance_id),
358 damage_buffer_sequence_id_(0),
359 damage_buffer_size_(0),
360 damage_buffer_scale_factor_(1.0f),
361 guest_device_scale_factor_(1.0f),
362 guest_hang_timeout_(
363 base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
364 focused_(false),
365 mouse_locked_(false),
366 pending_lock_request_(false),
367 embedder_visible_(true),
368 auto_size_enabled_(false),
369 copy_request_id_(0),
370 next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID),
371 has_render_view_(has_render_view),
372 last_seen_auto_size_enabled_(false),
373 is_in_destruction_(false),
374 last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
375 last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
376 last_can_compose_inline_(true),
377 weak_ptr_factory_(this) {
378 DCHECK(web_contents);
379 web_contents->SetDelegate(this);
380 if (opener)
381 opener_ = opener->AsWeakPtr();
382 GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_,
383 GetWebContents());
386 bool BrowserPluginGuest::AddMessageToConsole(WebContents* source,
387 int32 level,
388 const base::string16& message,
389 int32 line_no,
390 const base::string16& source_id) {
391 if (!delegate_)
392 return false;
394 delegate_->AddMessageToConsole(level, message, line_no, source_id);
395 return true;
398 void BrowserPluginGuest::DestroyUnattachedWindows() {
399 // Destroy() reaches in and removes the BrowserPluginGuest from its opener's
400 // pending_new_windows_ set. To avoid mutating the set while iterating, we
401 // create a copy of the pending new windows set and iterate over the copy.
402 PendingWindowMap pending_new_windows(pending_new_windows_);
403 // Clean up unattached new windows opened by this guest.
404 for (PendingWindowMap::const_iterator it = pending_new_windows.begin();
405 it != pending_new_windows.end(); ++it) {
406 it->first->Destroy();
408 // All pending windows should be removed from the set after Destroy() is
409 // called on all of them.
410 DCHECK(pending_new_windows_.empty());
413 void BrowserPluginGuest::LoadURLWithParams(const GURL& url,
414 const Referrer& referrer,
415 PageTransition transition_type,
416 WebContents* web_contents) {
417 NavigationController::LoadURLParams load_url_params(url);
418 load_url_params.referrer = referrer;
419 load_url_params.transition_type = transition_type;
420 load_url_params.extra_headers = std::string();
421 if (delegate_ && delegate_->IsOverridingUserAgent()) {
422 load_url_params.override_user_agent =
423 NavigationController::UA_OVERRIDE_TRUE;
425 web_contents->GetController().LoadURLWithParams(load_url_params);
428 void BrowserPluginGuest::RespondToPermissionRequest(
429 int request_id,
430 bool should_allow,
431 const std::string& user_input) {
432 RequestMap::iterator request_itr = permission_request_map_.find(request_id);
433 if (request_itr == permission_request_map_.end()) {
434 VLOG(0) << "Not a valid request ID.";
435 return;
437 request_itr->second->Respond(should_allow, user_input);
438 permission_request_map_.erase(request_itr);
441 int BrowserPluginGuest::RequestPermission(
442 BrowserPluginPermissionType permission_type,
443 scoped_refptr<BrowserPluginGuest::PermissionRequest> request,
444 const base::DictionaryValue& request_info) {
445 if (!delegate_) {
446 // Let the stack unwind before we deny the permission request so that
447 // objects held by the permission request are not destroyed immediately
448 // after creation. This is to allow those same objects to be accessed again
449 // in the same scope without fear of use after freeing.
450 base::MessageLoop::current()->PostTask(
451 FROM_HERE,
452 base::Bind(&BrowserPluginGuest::PermissionRequest::Respond,
453 request, false, ""));
454 return browser_plugin::kInvalidPermissionRequestID;
457 int request_id = ++next_permission_request_id_;
458 permission_request_map_[request_id] = request;
460 BrowserPluginGuestDelegate::PermissionResponseCallback callback =
461 base::Bind(&BrowserPluginGuest::RespondToPermissionRequest,
462 AsWeakPtr(),
463 request_id);
464 // If BrowserPluginGuestDelegate hasn't handled the permission then we simply
465 // perform the default action (which is one of allow or reject) immediately.
466 if (!delegate_->RequestPermission(
467 permission_type, request_info, callback, request->AllowedByDefault())) {
468 callback.Run(request->AllowedByDefault(), "");
469 return browser_plugin::kInvalidPermissionRequestID;
472 return request_id;
475 BrowserPluginGuest* BrowserPluginGuest::CreateNewGuestWindow(
476 const OpenURLParams& params) {
477 BrowserPluginGuestManager* guest_manager =
478 GetWebContents()->GetBrowserPluginGuestManager();
480 // Allocate a new instance ID for the new guest.
481 int instance_id = guest_manager->get_next_instance_id();
483 // Set the attach params to use the same partition as the opener.
484 // We pull the partition information from the site's URL, which is of the form
485 // guest://site/{persist}?{partition_name}.
486 const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
487 BrowserPluginHostMsg_Attach_Params attach_params;
488 attach_params.storage_partition_id = site_url.query();
489 attach_params.persist_storage =
490 site_url.path().find("persist") != std::string::npos;
492 // The new guest gets a copy of this guest's extra params so that the content
493 // embedder exposes the same API for this guest as its opener.
494 scoped_ptr<base::DictionaryValue> extra_params(
495 extra_attach_params_->DeepCopy());
496 BrowserPluginGuest* new_guest =
497 GetWebContents()->GetBrowserPluginGuestManager()->CreateGuest(
498 GetWebContents()->GetSiteInstance(), instance_id,
499 attach_params, extra_params.Pass());
500 new_guest->opener_ = AsWeakPtr();
502 // Take ownership of |new_guest|.
503 pending_new_windows_.insert(
504 std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
506 // Request permission to show the new window.
507 RequestNewWindowPermission(params.disposition, gfx::Rect(),
508 params.user_gesture, new_guest->GetWebContents());
510 return new_guest;
513 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
514 return weak_ptr_factory_.GetWeakPtr();
517 void BrowserPluginGuest::EmbedderDestroyed() {
518 embedder_web_contents_ = NULL;
519 if (delegate_)
520 delegate_->EmbedderDestroyed();
521 Destroy();
524 void BrowserPluginGuest::Destroy() {
525 is_in_destruction_ = true;
526 if (!attached() && opener())
527 opener()->pending_new_windows_.erase(this);
528 DestroyUnattachedWindows();
529 GetWebContents()->GetBrowserPluginGuestManager()->RemoveGuest(instance_id_);
530 delete GetWebContents();
533 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
534 const IPC::Message& message) {
535 bool handled = true;
536 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
537 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK,
538 OnSwapBuffersACK)
539 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK,
540 OnCompositorFrameSwappedACK)
541 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
542 OnCopyFromCompositingSurfaceAck)
543 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
544 OnDragStatusUpdate)
545 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
546 OnExecuteEditCommand)
547 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
548 OnExtendSelectionAndDelete)
549 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
550 OnHandleInputEvent)
551 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition,
552 OnImeConfirmComposition)
553 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
554 OnImeSetComposition)
555 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
556 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest, OnNavigateGuest)
557 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
558 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
559 OnReclaimCompositorResources)
560 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
561 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetSize)
562 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
563 OnSetEditCommandsForNextKeyEvent)
564 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
565 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetName, OnSetName)
566 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque,
567 OnSetContentsOpaque)
568 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
569 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
570 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
571 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateRect_ACK, OnUpdateRectACK)
572 IPC_MESSAGE_UNHANDLED(handled = false)
573 IPC_END_MESSAGE_MAP()
574 return handled;
577 void BrowserPluginGuest::Initialize(
578 const BrowserPluginHostMsg_Attach_Params& params,
579 WebContentsImpl* embedder_web_contents) {
580 focused_ = params.focused;
581 guest_visible_ = params.visible;
582 guest_opaque_ = params.opaque;
583 guest_window_rect_ = params.resize_guest_params.view_rect;
585 if (!params.name.empty())
586 name_ = params.name;
587 auto_size_enabled_ = params.auto_size_params.enable;
588 max_auto_size_ = params.auto_size_params.max_size;
589 min_auto_size_ = params.auto_size_params.min_size;
591 // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
592 // be attached.
593 embedder_web_contents_ = embedder_web_contents;
595 WebContentsViewGuest* new_view =
596 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
597 new_view->OnGuestInitialized(embedder_web_contents->GetView());
599 RendererPreferences* renderer_prefs =
600 GetWebContents()->GetMutableRendererPrefs();
601 std::string guest_user_agent_override = renderer_prefs->user_agent_override;
602 // Copy renderer preferences (and nothing else) from the embedder's
603 // WebContents to the guest.
605 // For GTK and Aura this is necessary to get proper renderer configuration
606 // values for caret blinking interval, colors related to selection and
607 // focus.
608 *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
609 renderer_prefs->user_agent_override = guest_user_agent_override;
611 // We would like the guest to report changes to frame names so that we can
612 // update the BrowserPlugin's corresponding 'name' attribute.
613 // TODO(fsamuel): Remove this once http://crbug.com/169110 is addressed.
614 renderer_prefs->report_frame_name_changes = true;
615 // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
616 // navigations still continue to function inside the app.
617 renderer_prefs->browser_handles_all_top_level_requests = false;
618 // Disable "client blocked" error page for browser plugin.
619 renderer_prefs->disable_client_blocked_error_page = true;
621 embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
623 OnSetSize(instance_id_, params.auto_size_params, params.resize_guest_params);
625 // Create a swapped out RenderView for the guest in the embedder render
626 // process, so that the embedder can access the guest's window object.
627 int guest_routing_id =
628 GetWebContents()->CreateSwappedOutRenderView(
629 embedder_web_contents_->GetSiteInstance());
630 SendMessageToEmbedder(
631 new BrowserPluginMsg_GuestContentWindowReady(instance_id_,
632 guest_routing_id));
634 if (!params.src.empty()) {
635 // params.src will be validated in BrowserPluginGuest::OnNavigateGuest.
636 OnNavigateGuest(instance_id_, params.src);
639 has_render_view_ = true;
641 WebPreferences prefs = GetWebContents()->GetWebkitPrefs();
642 prefs.navigate_on_drag_drop = false;
643 if (!embedder_web_contents_->
644 GetWebkitPrefs().accelerated_compositing_enabled) {
645 prefs.accelerated_compositing_enabled = false;
647 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
649 // Enable input method for guest if it's enabled for the embedder.
650 if (static_cast<RenderViewHostImpl*>(
651 embedder_web_contents_->GetRenderViewHost())->input_method_active()) {
652 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
653 GetWebContents()->GetRenderViewHost());
654 guest_rvh->SetInputMethodActive(true);
657 // Inform the embedder of the guest's information.
658 // We pull the partition information from the site's URL, which is of the form
659 // guest://site/{persist}?{partition_name}.
660 const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
661 BrowserPluginMsg_Attach_ACK_Params ack_params;
662 ack_params.storage_partition_id = site_url.query();
663 ack_params.persist_storage =
664 site_url.path().find("persist") != std::string::npos;
665 ack_params.name = name_;
666 SendMessageToEmbedder(
667 new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params));
669 if (delegate_)
670 delegate_->DidAttach();
673 BrowserPluginGuest::~BrowserPluginGuest() {
674 while (!pending_messages_.empty()) {
675 delete pending_messages_.front();
676 pending_messages_.pop();
680 // static
681 BrowserPluginGuest* BrowserPluginGuest::Create(
682 int instance_id,
683 SiteInstance* guest_site_instance,
684 WebContentsImpl* web_contents,
685 scoped_ptr<base::DictionaryValue> extra_params) {
686 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
687 BrowserPluginGuest* guest = NULL;
688 if (factory_) {
689 guest = factory_->CreateBrowserPluginGuest(instance_id, web_contents);
690 } else {
691 guest = new BrowserPluginGuest(instance_id, false, web_contents, NULL);
693 guest->extra_attach_params_.reset(extra_params->DeepCopy());
694 web_contents->SetBrowserPluginGuest(guest);
695 BrowserPluginGuestDelegate* delegate = NULL;
696 GetContentClient()->browser()->GuestWebContentsCreated(
697 guest_site_instance, web_contents, NULL, &delegate, extra_params.Pass());
698 guest->SetDelegate(delegate);
699 return guest;
702 // static
703 BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener(
704 int instance_id,
705 bool has_render_view,
706 WebContentsImpl* web_contents,
707 BrowserPluginGuest* opener) {
708 BrowserPluginGuest* guest =
709 new BrowserPluginGuest(
710 instance_id, has_render_view, web_contents, opener);
711 web_contents->SetBrowserPluginGuest(guest);
712 BrowserPluginGuestDelegate* delegate = NULL;
713 GetContentClient()->browser()->GuestWebContentsCreated(
714 opener->GetWebContents()->GetSiteInstance(),
715 web_contents, opener->GetWebContents(), &delegate,
716 scoped_ptr<base::DictionaryValue>());
717 guest->SetDelegate(delegate);
718 return guest;
721 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
722 if (!attached())
723 return NULL;
724 return embedder_web_contents_->GetRenderWidgetHostView();
727 void BrowserPluginGuest::UpdateVisibility() {
728 OnSetVisibility(instance_id_, visible());
731 void BrowserPluginGuest::CopyFromCompositingSurface(
732 gfx::Rect src_subrect,
733 gfx::Size dst_size,
734 const base::Callback<void(bool, const SkBitmap&)>& callback) {
735 copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
736 SendMessageToEmbedder(
737 new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
738 copy_request_id_, src_subrect, dst_size));
741 // screen.
742 gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
743 gfx::Rect guest_rect(bounds);
744 guest_rect.Offset(guest_window_rect_.OffsetFromOrigin());
745 return guest_rect;
748 void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
749 embedder_visible_ = visible;
750 UpdateVisibility();
753 void BrowserPluginGuest::AddNewContents(WebContents* source,
754 WebContents* new_contents,
755 WindowOpenDisposition disposition,
756 const gfx::Rect& initial_pos,
757 bool user_gesture,
758 bool* was_blocked) {
759 if (was_blocked)
760 *was_blocked = false;
761 RequestNewWindowPermission(disposition, initial_pos, user_gesture,
762 static_cast<WebContentsImpl*>(new_contents));
765 void BrowserPluginGuest::CanDownload(
766 RenderViewHost* render_view_host,
767 int request_id,
768 const std::string& request_method,
769 const base::Callback<void(bool)>& callback) {
770 BrowserThread::PostTaskAndReplyWithResult(
771 BrowserThread::IO, FROM_HERE,
772 base::Bind(&RetrieveDownloadURLFromRequestId,
773 render_view_host, request_id),
774 base::Bind(&BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId,
775 weak_ptr_factory_.GetWeakPtr(),
776 request_method,
777 callback));
780 void BrowserPluginGuest::LoadProgressChanged(WebContents* contents,
781 double progress) {
782 if (delegate_)
783 delegate_->LoadProgressed(progress);
786 void BrowserPluginGuest::CloseContents(WebContents* source) {
787 if (!delegate_)
788 return;
790 delegate_->Close();
793 JavaScriptDialogManager* BrowserPluginGuest::GetJavaScriptDialogManager() {
794 return this;
797 ColorChooser* BrowserPluginGuest::OpenColorChooser(
798 WebContents* web_contents,
799 SkColor color,
800 const std::vector<ColorSuggestion>& suggestions) {
801 if (!embedder_web_contents_ || !embedder_web_contents_->GetDelegate())
802 return NULL;
803 return embedder_web_contents_->GetDelegate()->OpenColorChooser(
804 web_contents, color, suggestions);
807 bool BrowserPluginGuest::HandleContextMenu(const ContextMenuParams& params) {
808 // TODO(fsamuel): We show the regular page context menu handler for now until
809 // we implement the Apps Context Menu API for Browser Plugin (see
810 // http://crbug.com/140315).
811 return false; // Will be handled by WebContentsViewGuest.
814 void BrowserPluginGuest::HandleKeyboardEvent(
815 WebContents* source,
816 const NativeWebKeyboardEvent& event) {
817 if (!attached())
818 return;
820 if (UnlockMouseIfNecessary(event))
821 return;
823 if (delegate_ && delegate_->HandleKeyboardEvent(event))
824 return;
826 if (!embedder_web_contents_->GetDelegate())
827 return;
829 // Send the unhandled keyboard events back to the embedder to reprocess them.
830 // TODO(fsamuel): This introduces the possibility of out-of-order keyboard
831 // events because the guest may be arbitrarily delayed when responding to
832 // keyboard events. In that time, the embedder may have received and processed
833 // additional key events. This needs to be fixed as soon as possible.
834 // See http://crbug.com/229882.
835 embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(
836 web_contents(), event);
839 void BrowserPluginGuest::SetZoom(double zoom_factor) {
840 if (delegate_)
841 delegate_->SetZoom(zoom_factor);
844 void BrowserPluginGuest::FindReply(WebContents* contents,
845 int request_id,
846 int number_of_matches,
847 const gfx::Rect& selection_rect,
848 int active_match_ordinal,
849 bool final_update) {
850 if (!delegate_)
851 return;
853 // |selection_rect| is updated to incorporate embedder coordinates.
854 delegate_->FindReply(request_id, number_of_matches,
855 ToGuestRect(selection_rect),
856 active_match_ordinal, final_update);
859 WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source,
860 const OpenURLParams& params) {
861 // If the guest wishes to navigate away prior to attachment then we save the
862 // navigation to perform upon attachment. Navigation initializes a lot of
863 // state that assumes an embedder exists, such as RenderWidgetHostViewGuest.
864 // Navigation also resumes resource loading which we don't want to allow
865 // until attachment.
866 if (!attached()) {
867 PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
868 if (it == opener()->pending_new_windows_.end())
869 return NULL;
870 const NewWindowInfo& old_target_url = it->second;
871 NewWindowInfo new_window_info(params.url, old_target_url.name);
872 new_window_info.changed = new_window_info.url != old_target_url.url;
873 it->second = new_window_info;
874 return NULL;
876 if (params.disposition == CURRENT_TAB) {
877 // This can happen for cross-site redirects.
878 LoadURLWithParams(params.url, params.referrer, params.transition, source);
879 return source;
882 return CreateNewGuestWindow(params)->GetWebContents();
885 void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
886 int opener_render_frame_id,
887 const base::string16& frame_name,
888 const GURL& target_url,
889 WebContents* new_contents) {
890 WebContentsImpl* new_contents_impl =
891 static_cast<WebContentsImpl*>(new_contents);
892 BrowserPluginGuest* guest = new_contents_impl->GetBrowserPluginGuest();
893 guest->opener_ = AsWeakPtr();
894 std::string guest_name = base::UTF16ToUTF8(frame_name);
895 guest->name_ = guest_name;
896 // Take ownership of the new guest until it is attached to the embedder's DOM
897 // tree to avoid leaking a guest if this guest is destroyed before attaching
898 // the new guest.
899 pending_new_windows_.insert(
900 std::make_pair(guest, NewWindowInfo(target_url, guest_name)));
903 void BrowserPluginGuest::RendererUnresponsive(WebContents* source) {
904 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Hung"));
905 if (!delegate_)
906 return;
907 delegate_->RendererUnresponsive();
910 void BrowserPluginGuest::RendererResponsive(WebContents* source) {
911 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Responsive"));
912 if (!delegate_)
913 return;
914 delegate_->RendererResponsive();
917 void BrowserPluginGuest::RunFileChooser(WebContents* web_contents,
918 const FileChooserParams& params) {
919 if (!attached())
920 return;
922 if (!embedder_web_contents_->GetDelegate())
923 return;
925 embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params);
928 bool BrowserPluginGuest::ShouldFocusPageAfterCrash() {
929 // Rather than managing focus in WebContentsImpl::RenderViewReady, we will
930 // manage the focus ourselves.
931 return false;
934 WebContentsImpl* BrowserPluginGuest::GetWebContents() {
935 return static_cast<WebContentsImpl*>(web_contents());
938 base::SharedMemory* BrowserPluginGuest::GetDamageBufferFromEmbedder(
939 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
940 if (!attached()) {
941 LOG(WARNING) << "Attempting to map a damage buffer prior to attachment.";
942 return NULL;
944 #if defined(OS_WIN)
945 base::ProcessHandle handle =
946 embedder_web_contents_->GetRenderProcessHost()->GetHandle();
947 scoped_ptr<base::SharedMemory> shared_buf(
948 new base::SharedMemory(params.damage_buffer_handle, false, handle));
949 #elif defined(OS_POSIX)
950 scoped_ptr<base::SharedMemory> shared_buf(
951 new base::SharedMemory(params.damage_buffer_handle, false));
952 #endif
953 if (!shared_buf->Map(params.damage_buffer_size)) {
954 LOG(WARNING) << "Unable to map the embedder's damage buffer.";
955 return NULL;
957 return shared_buf.release();
960 void BrowserPluginGuest::SetDamageBuffer(
961 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
962 damage_buffer_.reset(GetDamageBufferFromEmbedder(params));
963 // Sanity check: Verify that we've correctly shared the damage buffer memory
964 // between the embedder and browser processes.
965 DCHECK(!damage_buffer_ ||
966 *static_cast<unsigned int*>(damage_buffer_->memory()) == 0xdeadbeef);
967 damage_buffer_sequence_id_ = params.damage_buffer_sequence_id;
968 damage_buffer_size_ = params.damage_buffer_size;
969 damage_view_size_ = params.view_rect.size();
970 damage_buffer_scale_factor_ = params.scale_factor;
973 gfx::Point BrowserPluginGuest::GetScreenCoordinates(
974 const gfx::Point& relative_position) const {
975 gfx::Point screen_pos(relative_position);
976 screen_pos += guest_window_rect_.OffsetFromOrigin();
977 return screen_pos;
980 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
981 return size.width() <= max_auto_size_.width() &&
982 size.height() <= max_auto_size_.height();
985 void BrowserPluginGuest::RequestNewWindowPermission(
986 WindowOpenDisposition disposition,
987 const gfx::Rect& initial_bounds,
988 bool user_gesture,
989 WebContentsImpl* new_contents) {
990 BrowserPluginGuest* guest = new_contents->GetBrowserPluginGuest();
991 PendingWindowMap::iterator it = pending_new_windows_.find(guest);
992 if (it == pending_new_windows_.end())
993 return;
994 const NewWindowInfo& new_window_info = it->second;
996 base::DictionaryValue request_info;
997 request_info.Set(browser_plugin::kInitialHeight,
998 base::Value::CreateIntegerValue(initial_bounds.height()));
999 request_info.Set(browser_plugin::kInitialWidth,
1000 base::Value::CreateIntegerValue(initial_bounds.width()));
1001 request_info.Set(browser_plugin::kTargetURL,
1002 base::Value::CreateStringValue(new_window_info.url.spec()));
1003 request_info.Set(browser_plugin::kName,
1004 base::Value::CreateStringValue(new_window_info.name));
1005 request_info.Set(browser_plugin::kWindowID,
1006 base::Value::CreateIntegerValue(guest->instance_id()));
1007 request_info.Set(browser_plugin::kWindowOpenDisposition,
1008 base::Value::CreateStringValue(
1009 WindowOpenDispositionToString(disposition)));
1011 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW,
1012 new NewWindowRequest(weak_ptr_factory_.GetWeakPtr(),
1013 guest->instance_id()),
1014 request_info);
1017 bool BrowserPluginGuest::UnlockMouseIfNecessary(
1018 const NativeWebKeyboardEvent& event) {
1019 if (!mouse_locked_)
1020 return false;
1022 embedder_web_contents()->GotResponseToLockMouseRequest(false);
1023 return true;
1026 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
1027 if (!attached()) {
1028 // Some pages such as data URLs, javascript URLs, and about:blank
1029 // do not load external resources and so they load prior to attachment.
1030 // As a result, we must save all these IPCs until attachment and then
1031 // forward them so that the embedder gets a chance to see and process
1032 // the load events.
1033 pending_messages_.push(msg);
1034 return;
1036 msg->set_routing_id(embedder_web_contents_->GetRoutingID());
1037 embedder_web_contents_->Send(msg);
1040 void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
1041 int screen_x, int screen_y, blink::WebDragOperation operation) {
1042 web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
1043 screen_x, screen_y, operation);
1046 void BrowserPluginGuest::DragSourceMovedTo(int client_x, int client_y,
1047 int screen_x, int screen_y) {
1048 web_contents()->GetRenderViewHost()->DragSourceMovedTo(client_x, client_y,
1049 screen_x, screen_y);
1052 void BrowserPluginGuest::EndSystemDrag() {
1053 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
1054 GetWebContents()->GetRenderViewHost());
1055 guest_rvh->DragSourceSystemDragEnded();
1058 void BrowserPluginGuest::SetDelegate(BrowserPluginGuestDelegate* delegate) {
1059 DCHECK(!delegate_);
1060 delegate_.reset(delegate);
1063 void BrowserPluginGuest::AskEmbedderForGeolocationPermission(
1064 int bridge_id,
1065 const GURL& requesting_frame,
1066 const GeolocationCallback& callback) {
1067 base::DictionaryValue request_info;
1068 request_info.Set(browser_plugin::kURL,
1069 base::Value::CreateStringValue(requesting_frame.spec()));
1071 int request_id =
1072 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION,
1073 new GeolocationRequest(weak_ptr_factory_.GetWeakPtr(),
1074 callback,
1075 bridge_id),
1076 request_info);
1078 DCHECK(bridge_id_to_request_id_map_.find(bridge_id) ==
1079 bridge_id_to_request_id_map_.end());
1080 bridge_id_to_request_id_map_[bridge_id] = request_id;
1083 int BrowserPluginGuest::RemoveBridgeID(int bridge_id) {
1084 std::map<int, int>::iterator bridge_itr =
1085 bridge_id_to_request_id_map_.find(bridge_id);
1086 if (bridge_itr == bridge_id_to_request_id_map_.end())
1087 return browser_plugin::kInvalidPermissionRequestID;
1089 int request_id = bridge_itr->second;
1090 bridge_id_to_request_id_map_.erase(bridge_itr);
1091 return request_id;
1094 void BrowserPluginGuest::CancelGeolocationRequest(int bridge_id) {
1095 int request_id = RemoveBridgeID(bridge_id);
1096 RequestMap::iterator request_itr = permission_request_map_.find(request_id);
1097 if (request_itr == permission_request_map_.end())
1098 return;
1099 permission_request_map_.erase(request_itr);
1102 void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback,
1103 int bridge_id,
1104 bool allowed) {
1105 callback.Run(allowed);
1106 RemoveBridgeID(bridge_id);
1109 void BrowserPluginGuest::SendQueuedMessages() {
1110 if (!attached())
1111 return;
1113 while (!pending_messages_.empty()) {
1114 IPC::Message* message = pending_messages_.front();
1115 pending_messages_.pop();
1116 SendMessageToEmbedder(message);
1120 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
1121 int64 frame_id,
1122 const base::string16& frame_unique_name,
1123 bool is_main_frame,
1124 const GURL& url,
1125 PageTransition transition_type,
1126 RenderViewHost* render_view_host) {
1127 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
1130 void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) {
1131 bool enable_dragdrop = delegate_ && delegate_->IsDragAndDropEnabled();
1132 if (!enable_dragdrop) {
1133 // Initiating a drag from inside a guest is currently not supported without
1134 // the kEnableBrowserPluginDragDrop flag on a linux platform. So inject some
1135 // JS to disable it. http://crbug.com/161112
1136 const char script[] = "window.addEventListener('dragstart', function() { "
1137 " window.event.preventDefault(); "
1138 "});";
1139 render_view_host->GetMainFrame()->ExecuteJavaScript(
1140 base::ASCIIToUTF16(script));
1144 void BrowserPluginGuest::RenderViewReady() {
1145 RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
1146 // The guest RenderView should always live in a guest process.
1147 CHECK(rvh->GetProcess()->IsGuest());
1148 // TODO(fsamuel): Investigate whether it's possible to update state earlier
1149 // here (see http://crbug.com/158151).
1150 Send(new InputMsg_SetFocus(routing_id(), focused_));
1151 UpdateVisibility();
1152 if (auto_size_enabled_)
1153 rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
1154 else
1155 rvh->DisableAutoResize(damage_view_size_);
1157 Send(new ViewMsg_SetName(routing_id(), name_));
1158 OnSetContentsOpaque(instance_id_, guest_opaque_);
1160 RenderWidgetHostImpl::From(rvh)->
1161 set_hung_renderer_delay_ms(guest_hang_timeout_);
1164 void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
1165 SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(instance_id()));
1166 switch (status) {
1167 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
1168 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
1169 break;
1170 case base::TERMINATION_STATUS_PROCESS_CRASHED:
1171 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
1172 break;
1173 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
1174 RecordAction(
1175 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
1176 break;
1177 default:
1178 break;
1180 // TODO(fsamuel): Consider whether we should be clearing
1181 // |permission_request_map_| here.
1182 if (delegate_)
1183 delegate_->GuestProcessGone(status);
1186 // static
1187 void BrowserPluginGuest::AcknowledgeBufferPresent(
1188 int route_id,
1189 int gpu_host_id,
1190 const gpu::Mailbox& mailbox,
1191 uint32 sync_point) {
1192 AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1193 ack_params.mailbox = mailbox;
1194 ack_params.sync_point = sync_point;
1195 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id,
1196 gpu_host_id,
1197 ack_params);
1200 // static
1201 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
1202 const IPC::Message& message) {
1203 switch (message.type()) {
1204 case BrowserPluginHostMsg_BuffersSwappedACK::ID:
1205 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID:
1206 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
1207 case BrowserPluginHostMsg_DragStatusUpdate::ID:
1208 case BrowserPluginHostMsg_ExecuteEditCommand::ID:
1209 case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID:
1210 case BrowserPluginHostMsg_HandleInputEvent::ID:
1211 case BrowserPluginHostMsg_ImeConfirmComposition::ID:
1212 case BrowserPluginHostMsg_ImeSetComposition::ID:
1213 case BrowserPluginHostMsg_LockMouse_ACK::ID:
1214 case BrowserPluginHostMsg_NavigateGuest::ID:
1215 case BrowserPluginHostMsg_PluginDestroyed::ID:
1216 case BrowserPluginHostMsg_ReclaimCompositorResources::ID:
1217 case BrowserPluginHostMsg_ResizeGuest::ID:
1218 case BrowserPluginHostMsg_SetAutoSize::ID:
1219 case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
1220 case BrowserPluginHostMsg_SetFocus::ID:
1221 case BrowserPluginHostMsg_SetName::ID:
1222 case BrowserPluginHostMsg_SetContentsOpaque::ID:
1223 case BrowserPluginHostMsg_SetVisibility::ID:
1224 case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
1225 case BrowserPluginHostMsg_UpdateGeometry::ID:
1226 case BrowserPluginHostMsg_UpdateRect_ACK::ID:
1227 return true;
1228 default:
1229 return false;
1233 bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
1234 bool handled = true;
1235 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
1236 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
1237 OnHasTouchEventHandlers)
1238 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
1239 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
1240 #if defined(OS_MACOSX)
1241 // MacOSX creates and populates platform-specific select drop-down menus
1242 // whereas other platforms merely create a popup window that the guest
1243 // renderer process paints inside.
1244 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
1245 #endif
1246 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
1247 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
1248 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
1249 OnTextInputTypeChanged)
1250 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
1251 OnImeCancelComposition)
1252 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
1253 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
1254 OnImeCompositionRangeChanged)
1255 #endif
1256 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
1257 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName, OnUpdateFrameName)
1258 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
1259 IPC_MESSAGE_UNHANDLED(handled = false)
1260 IPC_END_MESSAGE_MAP()
1261 return handled;
1264 void BrowserPluginGuest::Attach(
1265 WebContentsImpl* embedder_web_contents,
1266 BrowserPluginHostMsg_Attach_Params params,
1267 const base::DictionaryValue& extra_params) {
1268 if (attached())
1269 return;
1271 extra_attach_params_.reset(extra_params.DeepCopy());
1273 // Clear parameters that get inherited from the opener.
1274 params.storage_partition_id.clear();
1275 params.persist_storage = false;
1276 params.src.clear();
1278 // If a RenderView has already been created for this new window, then we need
1279 // to initialize the browser-side state now so that the RenderFrameHostManager
1280 // does not create a new RenderView on navigation.
1281 if (has_render_view_) {
1282 static_cast<RenderViewHostImpl*>(
1283 GetWebContents()->GetRenderViewHost())->Init();
1284 WebContentsViewGuest* new_view =
1285 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
1286 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
1289 // We need to do a navigation here if the target URL has changed between
1290 // the time the WebContents was created and the time it was attached.
1291 // We also need to do an initial navigation if a RenderView was never
1292 // created for the new window in cases where there is no referrer.
1293 PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
1294 if (it != opener()->pending_new_windows_.end()) {
1295 const NewWindowInfo& new_window_info = it->second;
1296 if (new_window_info.changed || !has_render_view_)
1297 params.src = it->second.url.spec();
1298 } else {
1299 NOTREACHED();
1302 // Once a new guest is attached to the DOM of the embedder page, then the
1303 // lifetime of the new guest is no longer managed by the opener guest.
1304 opener()->pending_new_windows_.erase(this);
1306 // The guest's frame name takes precedence over the BrowserPlugin's name.
1307 // The guest's frame name is assigned in
1308 // BrowserPluginGuest::WebContentsCreated.
1309 if (!name_.empty())
1310 params.name.clear();
1312 Initialize(params, embedder_web_contents);
1314 SendQueuedMessages();
1316 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
1319 void BrowserPluginGuest::OnCompositorFrameSwappedACK(
1320 int instance_id,
1321 const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
1322 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
1323 params.output_surface_id,
1324 params.producing_host_id,
1325 params.ack);
1328 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
1329 blink::WebDragStatus drag_status,
1330 const DropData& drop_data,
1331 blink::WebDragOperationsMask mask,
1332 const gfx::Point& location) {
1333 RenderViewHost* host = GetWebContents()->GetRenderViewHost();
1334 switch (drag_status) {
1335 case blink::WebDragStatusEnter:
1336 embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
1337 this);
1338 host->DragTargetDragEnter(drop_data, location, location, mask, 0);
1339 break;
1340 case blink::WebDragStatusOver:
1341 host->DragTargetDragOver(location, location, mask, 0);
1342 break;
1343 case blink::WebDragStatusLeave:
1344 embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
1345 host->DragTargetDragLeave();
1346 break;
1347 case blink::WebDragStatusDrop:
1348 host->DragTargetDrop(location, location, 0);
1349 EndSystemDrag();
1350 break;
1351 case blink::WebDragStatusUnknown:
1352 NOTREACHED();
1356 void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
1357 const std::string& name) {
1358 Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
1361 void BrowserPluginGuest::OnImeSetComposition(
1362 int instance_id,
1363 const std::string& text,
1364 const std::vector<blink::WebCompositionUnderline>& underlines,
1365 int selection_start,
1366 int selection_end) {
1367 Send(new ViewMsg_ImeSetComposition(routing_id(),
1368 base::UTF8ToUTF16(text), underlines,
1369 selection_start, selection_end));
1372 void BrowserPluginGuest::OnImeConfirmComposition(
1373 int instance_id,
1374 const std::string& text,
1375 bool keep_selection) {
1376 Send(new ViewMsg_ImeConfirmComposition(routing_id(),
1377 base::UTF8ToUTF16(text),
1378 gfx::Range::InvalidRange(),
1379 keep_selection));
1382 void BrowserPluginGuest::OnExtendSelectionAndDelete(
1383 int instance_id,
1384 int before,
1385 int after) {
1386 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
1387 web_contents()->GetFocusedFrame());
1388 if (rfh)
1389 rfh->ExtendSelectionAndDelete(before, after);
1392 void BrowserPluginGuest::OnReclaimCompositorResources(
1393 int instance_id,
1394 const FrameHostMsg_ReclaimCompositorResources_Params& params) {
1395 RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
1396 params.output_surface_id,
1397 params.renderer_host_id,
1398 params.ack);
1401 void BrowserPluginGuest::OnHandleInputEvent(
1402 int instance_id,
1403 const gfx::Rect& guest_window_rect,
1404 const blink::WebInputEvent* event) {
1405 guest_window_rect_ = guest_window_rect;
1406 // If the embedder's RWHV is destroyed then that means that the embedder's
1407 // window has been closed but the embedder's WebContents has not yet been
1408 // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
1409 // if there is a visible embedder.
1410 if (embedder_web_contents_->GetRenderWidgetHostView()) {
1411 guest_screen_rect_ = guest_window_rect;
1412 guest_screen_rect_.Offset(
1413 embedder_web_contents_->GetRenderWidgetHostView()->
1414 GetViewBounds().OffsetFromOrigin());
1416 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
1417 GetWebContents()->GetRenderViewHost());
1419 if (blink::WebInputEvent::isMouseEventType(event->type)) {
1420 guest_rvh->ForwardMouseEvent(
1421 *static_cast<const blink::WebMouseEvent*>(event));
1422 return;
1425 if (event->type == blink::WebInputEvent::MouseWheel) {
1426 guest_rvh->ForwardWheelEvent(
1427 *static_cast<const blink::WebMouseWheelEvent*>(event));
1428 return;
1431 if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
1432 RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
1433 embedder_web_contents_->GetRenderViewHost());
1434 if (!embedder_rvh->GetLastKeyboardEvent())
1435 return;
1436 NativeWebKeyboardEvent keyboard_event(
1437 *embedder_rvh->GetLastKeyboardEvent());
1438 guest_rvh->ForwardKeyboardEvent(keyboard_event);
1439 return;
1442 if (blink::WebInputEvent::isTouchEventType(event->type)) {
1443 guest_rvh->ForwardTouchEventWithLatencyInfo(
1444 *static_cast<const blink::WebTouchEvent*>(event),
1445 ui::LatencyInfo());
1446 return;
1449 if (blink::WebInputEvent::isGestureEventType(event->type)) {
1450 guest_rvh->ForwardGestureEvent(
1451 *static_cast<const blink::WebGestureEvent*>(event));
1452 return;
1456 void BrowserPluginGuest::OnLockMouse(bool user_gesture,
1457 bool last_unlocked_by_target,
1458 bool privileged) {
1459 if (pending_lock_request_) {
1460 // Immediately reject the lock because only one pointerLock may be active
1461 // at a time.
1462 Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
1463 return;
1465 pending_lock_request_ = true;
1466 base::DictionaryValue request_info;
1467 request_info.Set(browser_plugin::kUserGesture,
1468 base::Value::CreateBooleanValue(user_gesture));
1469 request_info.Set(browser_plugin::kLastUnlockedBySelf,
1470 base::Value::CreateBooleanValue(last_unlocked_by_target));
1471 request_info.Set(browser_plugin::kURL,
1472 base::Value::CreateStringValue(
1473 web_contents()->GetLastCommittedURL().spec()));
1475 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK,
1476 new PointerLockRequest(weak_ptr_factory_.GetWeakPtr()),
1477 request_info);
1480 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
1481 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
1482 pending_lock_request_ = false;
1483 if (succeeded)
1484 mouse_locked_ = true;
1487 void BrowserPluginGuest::OnNavigateGuest(
1488 int instance_id,
1489 const std::string& src) {
1490 GURL url = delegate_ ? delegate_->ResolveURL(src) : GURL(src);
1492 // Do not allow navigating a guest to schemes other than known safe schemes.
1493 // This will block the embedder trying to load unwanted schemes, e.g.
1494 // chrome://settings.
1495 bool scheme_is_blocked =
1496 (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme(
1497 url.scheme()) &&
1498 !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme(
1499 url.scheme())) ||
1500 url.SchemeIs(kJavaScriptScheme);
1501 if (scheme_is_blocked || !url.is_valid()) {
1502 if (delegate_) {
1503 std::string error_type;
1504 base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::",
1505 &error_type);
1506 delegate_->LoadAbort(true /* is_top_level */, url, error_type);
1508 return;
1511 GURL validated_url(url);
1512 GetWebContents()->GetRenderProcessHost()->FilterURL(false, &validated_url);
1513 // As guests do not swap processes on navigation, only navigations to
1514 // normal web URLs are supported. No protocol handlers are installed for
1515 // other schemes (e.g., WebUI or extensions), and no permissions or bindings
1516 // can be granted to the guest process.
1517 LoadURLWithParams(validated_url, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL,
1518 GetWebContents());
1521 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
1522 Destroy();
1525 void BrowserPluginGuest::OnResizeGuest(
1526 int instance_id,
1527 const BrowserPluginHostMsg_ResizeGuest_Params& params) {
1528 if (!params.size_changed)
1529 return;
1530 // BrowserPlugin manages resize flow control itself and does not depend
1531 // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
1532 // here. If we are setting the size for the first time before navigating then
1533 // BrowserPluginGuest does not yet have a RenderViewHost.
1534 if (GetWebContents()->GetRenderViewHost()) {
1535 RenderWidgetHostImpl* render_widget_host =
1536 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
1537 render_widget_host->ResetSizeAndRepaintPendingFlags();
1539 if (guest_device_scale_factor_ != params.scale_factor) {
1540 guest_device_scale_factor_ = params.scale_factor;
1541 render_widget_host->NotifyScreenInfoChanged();
1544 // When autosize is turned off and as a result there is a layout change, we
1545 // send a sizechanged event.
1546 if (!auto_size_enabled_ && last_seen_auto_size_enabled_ &&
1547 !params.view_rect.size().IsEmpty() && delegate_) {
1548 delegate_->SizeChanged(last_seen_view_size_, params.view_rect.size());
1549 last_seen_auto_size_enabled_ = false;
1551 // Invalid damage buffer means we are in HW compositing mode,
1552 // so just resize the WebContents and repaint if needed.
1553 if (base::SharedMemory::IsHandleValid(params.damage_buffer_handle))
1554 SetDamageBuffer(params);
1555 if (!params.view_rect.size().IsEmpty())
1556 GetWebContents()->GetView()->SizeContents(params.view_rect.size());
1557 if (params.repaint)
1558 Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size()));
1561 void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
1562 focused_ = focused;
1563 Send(new InputMsg_SetFocus(routing_id(), focused));
1564 if (!focused && mouse_locked_)
1565 OnUnlockMouse();
1567 // Restore the last seen state of text input to the view.
1568 RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
1569 web_contents()->GetRenderWidgetHostView());
1570 if (rwhv) {
1571 rwhv->TextInputTypeChanged(last_text_input_type_, last_input_mode_,
1572 last_can_compose_inline_);
1576 void BrowserPluginGuest::OnSetName(int instance_id, const std::string& name) {
1577 if (name == name_)
1578 return;
1579 name_ = name;
1580 Send(new ViewMsg_SetName(routing_id(), name));
1583 void BrowserPluginGuest::OnSetSize(
1584 int instance_id,
1585 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
1586 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
1587 bool old_auto_size_enabled = auto_size_enabled_;
1588 gfx::Size old_max_size = max_auto_size_;
1589 gfx::Size old_min_size = min_auto_size_;
1590 auto_size_enabled_ = auto_size_params.enable;
1591 max_auto_size_ = auto_size_params.max_size;
1592 min_auto_size_ = auto_size_params.min_size;
1593 if (auto_size_enabled_ && (!old_auto_size_enabled ||
1594 (old_max_size != max_auto_size_) ||
1595 (old_min_size != min_auto_size_))) {
1596 RecordAction(
1597 base::UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
1598 GetWebContents()->GetRenderViewHost()->EnableAutoResize(
1599 min_auto_size_, max_auto_size_);
1600 // TODO(fsamuel): If we're changing autosize parameters, then we force
1601 // the guest to completely repaint itself, because BrowserPlugin has
1602 // allocated a new damage buffer and expects a full frame of pixels.
1603 // Ideally, we shouldn't need to do this because we shouldn't need to
1604 // allocate a new damage buffer unless |max_auto_size_| has changed.
1605 // However, even in that case, layout may not change and so we may
1606 // not get a full frame worth of pixels.
1607 Send(new ViewMsg_Repaint(routing_id(), max_auto_size_));
1608 } else if (!auto_size_enabled_ && old_auto_size_enabled) {
1609 GetWebContents()->GetRenderViewHost()->DisableAutoResize(
1610 resize_guest_params.view_rect.size());
1612 OnResizeGuest(instance_id_, resize_guest_params);
1615 void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
1616 int instance_id,
1617 const std::vector<EditCommand>& edit_commands) {
1618 Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
1619 edit_commands));
1622 void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) {
1623 guest_opaque_ = opaque;
1625 SkBitmap background;
1626 if (!guest_opaque_) {
1627 background.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
1628 unsigned int color = 0;
1629 background.setPixels(&color);
1631 Send(new ViewMsg_SetBackground(routing_id(), background));
1634 void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
1635 guest_visible_ = visible;
1636 if (embedder_visible_ && guest_visible_)
1637 GetWebContents()->WasShown();
1638 else
1639 GetWebContents()->WasHidden();
1642 void BrowserPluginGuest::OnSwapBuffersACK(
1643 int instance_id,
1644 const FrameHostMsg_BuffersSwappedACK_Params& params) {
1645 AcknowledgeBufferPresent(params.gpu_route_id, params.gpu_host_id,
1646 params.mailbox, params.sync_point);
1648 // This is only relevant on MACOSX and WIN when threaded compositing
1649 // is not enabled. In threaded mode, above ACK is sufficient.
1650 #if defined(OS_MACOSX) || defined(OS_WIN)
1651 RenderWidgetHostImpl* render_widget_host =
1652 RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
1653 render_widget_host->AcknowledgeSwapBuffersToRenderer();
1654 #endif // defined(OS_MACOSX) || defined(OS_WIN)
1657 void BrowserPluginGuest::OnUnlockMouse() {
1658 SendMessageToEmbedder(
1659 new BrowserPluginMsg_SetMouseLock(instance_id(), false));
1662 void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
1663 // mouse_locked_ could be false here if the lock attempt was cancelled due
1664 // to window focus, or for various other reasons before the guest was informed
1665 // of the lock's success.
1666 if (mouse_locked_)
1667 Send(new ViewMsg_MouseLockLost(routing_id()));
1668 mouse_locked_ = false;
1671 void BrowserPluginGuest::OnUpdateRectACK(
1672 int instance_id,
1673 bool needs_ack,
1674 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
1675 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
1676 // Only the software path expects an ACK.
1677 if (needs_ack)
1678 Send(new ViewMsg_UpdateRect_ACK(routing_id()));
1679 OnSetSize(instance_id_, auto_size_params, resize_guest_params);
1682 void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
1683 int instance_id,
1684 int request_id,
1685 const SkBitmap& bitmap) {
1686 CHECK(copy_request_callbacks_.count(request_id));
1687 if (!copy_request_callbacks_.count(request_id))
1688 return;
1689 const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
1690 callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
1691 copy_request_callbacks_.erase(request_id);
1694 void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
1695 const gfx::Rect& view_rect) {
1696 // The plugin has moved within the embedder without resizing or the
1697 // embedder/container's view rect changing.
1698 guest_window_rect_ = view_rect;
1699 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
1700 GetWebContents()->GetRenderViewHost());
1701 if (rvh)
1702 rvh->SendScreenRects();
1705 void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
1706 SendMessageToEmbedder(
1707 new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
1710 void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
1711 SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
1714 #if defined(OS_MACOSX)
1715 void BrowserPluginGuest::OnShowPopup(
1716 const ViewHostMsg_ShowPopup_Params& params) {
1717 gfx::Rect translated_bounds(params.bounds);
1718 translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
1719 BrowserPluginPopupMenuHelper popup_menu_helper(
1720 embedder_web_contents_->GetRenderViewHost(),
1721 GetWebContents()->GetRenderViewHost());
1722 popup_menu_helper.ShowPopupMenu(translated_bounds,
1723 params.item_height,
1724 params.item_font_size,
1725 params.selected_item,
1726 params.popup_items,
1727 params.right_aligned,
1728 params.allow_multiple_selection);
1730 #endif
1732 void BrowserPluginGuest::OnShowWidget(int route_id,
1733 const gfx::Rect& initial_pos) {
1734 GetWebContents()->ShowCreatedWidget(route_id, initial_pos);
1737 void BrowserPluginGuest::OnTakeFocus(bool reverse) {
1738 SendMessageToEmbedder(
1739 new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
1742 void BrowserPluginGuest::OnUpdateFrameName(int frame_id,
1743 bool is_top_level,
1744 const std::string& name) {
1745 if (!is_top_level)
1746 return;
1748 name_ = name;
1749 SendMessageToEmbedder(new BrowserPluginMsg_UpdatedName(instance_id_, name));
1752 void BrowserPluginGuest::RequestMediaAccessPermission(
1753 WebContents* web_contents,
1754 const MediaStreamRequest& request,
1755 const MediaResponseCallback& callback) {
1756 base::DictionaryValue request_info;
1757 request_info.Set(
1758 browser_plugin::kURL,
1759 base::Value::CreateStringValue(request.security_origin.spec()));
1761 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA,
1762 new MediaRequest(weak_ptr_factory_.GetWeakPtr(),
1763 request,
1764 callback),
1765 request_info);
1768 bool BrowserPluginGuest::PreHandleGestureEvent(
1769 WebContents* source, const blink::WebGestureEvent& event) {
1770 return event.type == blink::WebGestureEvent::GesturePinchBegin ||
1771 event.type == blink::WebGestureEvent::GesturePinchUpdate ||
1772 event.type == blink::WebGestureEvent::GesturePinchEnd;
1775 void BrowserPluginGuest::RunJavaScriptDialog(
1776 WebContents* web_contents,
1777 const GURL& origin_url,
1778 const std::string& accept_lang,
1779 JavaScriptMessageType javascript_message_type,
1780 const base::string16& message_text,
1781 const base::string16& default_prompt_text,
1782 const DialogClosedCallback& callback,
1783 bool* did_suppress_message) {
1784 base::DictionaryValue request_info;
1785 request_info.Set(
1786 browser_plugin::kDefaultPromptText,
1787 base::Value::CreateStringValue(base::UTF16ToUTF8(default_prompt_text)));
1788 request_info.Set(
1789 browser_plugin::kMessageText,
1790 base::Value::CreateStringValue(base::UTF16ToUTF8(message_text)));
1791 request_info.Set(
1792 browser_plugin::kMessageType,
1793 base::Value::CreateStringValue(
1794 JavaScriptMessageTypeToString(javascript_message_type)));
1795 request_info.Set(
1796 browser_plugin::kURL,
1797 base::Value::CreateStringValue(origin_url.spec()));
1799 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG,
1800 new JavaScriptDialogRequest(weak_ptr_factory_.GetWeakPtr(),
1801 callback),
1802 request_info);
1805 void BrowserPluginGuest::RunBeforeUnloadDialog(
1806 WebContents* web_contents,
1807 const base::string16& message_text,
1808 bool is_reload,
1809 const DialogClosedCallback& callback) {
1810 // This is called if the guest has a beforeunload event handler.
1811 // This callback allows navigation to proceed.
1812 callback.Run(true, base::string16());
1815 bool BrowserPluginGuest::HandleJavaScriptDialog(
1816 WebContents* web_contents,
1817 bool accept,
1818 const base::string16* prompt_override) {
1819 return false;
1822 void BrowserPluginGuest::CancelActiveAndPendingDialogs(
1823 WebContents* web_contents) {
1826 void BrowserPluginGuest::WebContentsDestroyed(WebContents* web_contents) {
1829 void BrowserPluginGuest::OnUpdateRect(
1830 const ViewHostMsg_UpdateRect_Params& params) {
1831 BrowserPluginMsg_UpdateRect_Params relay_params;
1832 relay_params.view_size = params.view_size;
1833 relay_params.scale_factor = params.scale_factor;
1834 relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
1835 params.flags);
1836 relay_params.needs_ack = params.needs_ack;
1838 bool size_changed = last_seen_view_size_ != params.view_size;
1839 gfx::Size old_size = last_seen_view_size_;
1840 last_seen_view_size_ = params.view_size;
1842 if ((auto_size_enabled_ || last_seen_auto_size_enabled_) &&
1843 size_changed && delegate_) {
1844 delegate_->SizeChanged(old_size, last_seen_view_size_);
1846 last_seen_auto_size_enabled_ = auto_size_enabled_;
1848 // HW accelerated case, acknowledge resize only
1849 if (!params.needs_ack || !damage_buffer_) {
1850 relay_params.damage_buffer_sequence_id = 0;
1851 SendMessageToEmbedder(
1852 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
1853 return;
1856 // Only copy damage if the guest is in autosize mode and the guest's view size
1857 // is less than the maximum size or the guest's view size is equal to the
1858 // damage buffer's size and the guest's scale factor is equal to the damage
1859 // buffer's scale factor.
1860 // The scaling change can happen due to asynchronous updates of the DPI on a
1861 // resolution change.
1862 if (((auto_size_enabled_ && InAutoSizeBounds(params.view_size)) ||
1863 (params.view_size == damage_view_size())) &&
1864 params.scale_factor == damage_buffer_scale_factor()) {
1865 TransportDIB* dib = GetWebContents()->GetRenderProcessHost()->
1866 GetTransportDIB(params.bitmap);
1867 if (dib) {
1868 size_t guest_damage_buffer_size =
1869 #if defined(OS_WIN)
1870 params.bitmap_rect.width() *
1871 params.bitmap_rect.height() * 4;
1872 #else
1873 dib->size();
1874 #endif
1875 size_t embedder_damage_buffer_size = damage_buffer_size_;
1876 void* guest_memory = dib->memory();
1877 void* embedder_memory = damage_buffer_->memory();
1878 size_t size = std::min(guest_damage_buffer_size,
1879 embedder_damage_buffer_size);
1880 memcpy(embedder_memory, guest_memory, size);
1883 relay_params.damage_buffer_sequence_id = damage_buffer_sequence_id_;
1884 relay_params.bitmap_rect = params.bitmap_rect;
1885 relay_params.scroll_delta = params.scroll_delta;
1886 relay_params.scroll_rect = params.scroll_rect;
1887 relay_params.copy_rects = params.copy_rects;
1889 SendMessageToEmbedder(
1890 new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
1893 void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type,
1894 ui::TextInputMode input_mode,
1895 bool can_compose_inline) {
1896 // Save the state of text input so we can restore it on focus.
1897 last_text_input_type_ = type;
1898 last_input_mode_ = input_mode;
1899 last_can_compose_inline_ = can_compose_inline;
1901 RenderWidgetHostViewPort::FromRWHV(
1902 web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged(
1903 type, input_mode, can_compose_inline);
1906 void BrowserPluginGuest::OnImeCancelComposition() {
1907 RenderWidgetHostViewPort::FromRWHV(
1908 web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
1911 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
1912 void BrowserPluginGuest::OnImeCompositionRangeChanged(
1913 const gfx::Range& range,
1914 const std::vector<gfx::Rect>& character_bounds) {
1915 RenderWidgetHostViewPort::FromRWHV(
1916 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
1917 range, character_bounds);
1919 #endif
1921 void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
1922 const std::string& request_method,
1923 const base::Callback<void(bool)>& callback,
1924 const std::string& url) {
1925 if (url.empty()) {
1926 callback.Run(false);
1927 return;
1930 base::DictionaryValue request_info;
1931 request_info.Set(browser_plugin::kRequestMethod,
1932 base::Value::CreateStringValue(request_method));
1933 request_info.Set(browser_plugin::kURL, base::Value::CreateStringValue(url));
1935 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD,
1936 new DownloadRequest(weak_ptr_factory_.GetWeakPtr(),
1937 callback),
1938 request_info);
1941 } // namespace content