1 // Copyright 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/renderer/browser_plugin/browser_plugin.h"
7 #include "base/command_line.h"
8 #include "base/json/json_string_value_serializer.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/common/browser_plugin/browser_plugin_constants.h"
14 #include "content/common/browser_plugin/browser_plugin_messages.h"
15 #include "content/common/view_messages.h"
16 #include "content/public/common/content_client.h"
17 #include "content/public/common/content_switches.h"
18 #include "content/public/renderer/content_renderer_client.h"
19 #include "content/renderer/browser_plugin/browser_plugin_bindings.h"
20 #include "content/renderer/browser_plugin/browser_plugin_compositing_helper.h"
21 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
22 #include "content/renderer/cursor_utils.h"
23 #include "content/renderer/drop_data_builder.h"
24 #include "content/renderer/render_process_impl.h"
25 #include "content/renderer/render_thread_impl.h"
26 #include "content/renderer/sad_plugin.h"
27 #include "content/renderer/v8_value_converter_impl.h"
28 #include "skia/ext/platform_canvas.h"
29 #include "third_party/WebKit/public/platform/WebRect.h"
30 #include "third_party/WebKit/public/web/WebBindings.h"
31 #include "third_party/WebKit/public/web/WebDOMCustomEvent.h"
32 #include "third_party/WebKit/public/web/WebDocument.h"
33 #include "third_party/WebKit/public/web/WebElement.h"
34 #include "third_party/WebKit/public/web/WebFrame.h"
35 #include "third_party/WebKit/public/web/WebInputEvent.h"
36 #include "third_party/WebKit/public/web/WebPluginContainer.h"
37 #include "third_party/WebKit/public/web/WebPluginParams.h"
38 #include "third_party/WebKit/public/web/WebScriptSource.h"
39 #include "third_party/WebKit/public/web/WebView.h"
40 #include "ui/events/keycodes/keyboard_codes.h"
43 #include "base/sys_info.h"
46 using blink::WebCanvas
;
47 using blink::WebPluginContainer
;
48 using blink::WebPluginParams
;
49 using blink::WebPoint
;
52 using blink::WebVector
;
58 static std::string
GetInternalEventName(const char* event_name
) {
59 return base::StringPrintf("-internal-%s", event_name
);
62 typedef std::map
<blink::WebPluginContainer
*,
63 BrowserPlugin
*> PluginContainerMap
;
64 static base::LazyInstance
<PluginContainerMap
> g_plugin_container_map
=
65 LAZY_INSTANCE_INITIALIZER
;
69 BrowserPlugin::BrowserPlugin(RenderViewImpl
* render_view
,
70 blink::WebFrame
* frame
)
71 : guest_instance_id_(browser_plugin::kInstanceIDNone
),
73 render_view_(render_view
->AsWeakPtr()),
74 render_view_routing_id_(render_view
->GetRoutingID()),
76 damage_buffer_sequence_id_(0),
77 paint_ack_received_(true),
78 last_device_scale_factor_(1.0f
),
80 guest_crashed_(false),
81 is_auto_size_state_dirty_(false),
82 persist_storage_(false),
83 valid_partition_id_(true),
84 content_window_routing_id_(MSG_ROUTING_NONE
),
85 plugin_focused_(false),
87 before_first_navigation_(true),
89 browser_plugin_manager_(render_view
->GetBrowserPluginManager()),
90 compositing_enabled_(false),
91 embedder_frame_url_(frame
->document().url()),
92 weak_ptr_factory_(this) {
95 BrowserPlugin::~BrowserPlugin() {
96 // If the BrowserPlugin has never navigated then the browser process and
97 // BrowserPluginManager don't know about it and so there is nothing to do
99 if (!HasGuestInstanceID())
101 browser_plugin_manager()->RemoveBrowserPlugin(guest_instance_id_
);
102 browser_plugin_manager()->Send(
103 new BrowserPluginHostMsg_PluginDestroyed(render_view_routing_id_
,
104 guest_instance_id_
));
108 BrowserPlugin
* BrowserPlugin::FromContainer(
109 blink::WebPluginContainer
* container
) {
110 PluginContainerMap
* browser_plugins
= g_plugin_container_map
.Pointer();
111 PluginContainerMap::iterator it
= browser_plugins
->find(container
);
112 return it
== browser_plugins
->end() ? NULL
: it
->second
;
115 bool BrowserPlugin::OnMessageReceived(const IPC::Message
& message
) {
117 IPC_BEGIN_MESSAGE_MAP(BrowserPlugin
, message
)
118 IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus
, OnAdvanceFocus
)
119 IPC_MESSAGE_HANDLER(BrowserPluginMsg_Attach_ACK
, OnAttachACK
)
120 IPC_MESSAGE_HANDLER(BrowserPluginMsg_BuffersSwapped
, OnBuffersSwapped
)
121 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginMsg_CompositorFrameSwapped
,
122 OnCompositorFrameSwapped(message
))
123 IPC_MESSAGE_HANDLER(BrowserPluginMsg_CopyFromCompositingSurface
,
124 OnCopyFromCompositingSurface
)
125 IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestContentWindowReady
,
126 OnGuestContentWindowReady
)
127 IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone
, OnGuestGone
)
128 IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor
, OnSetCursor
)
129 IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock
, OnSetMouseLock
)
130 IPC_MESSAGE_HANDLER(BrowserPluginMsg_ShouldAcceptTouchEvents
,
131 OnShouldAcceptTouchEvents
)
132 IPC_MESSAGE_HANDLER(BrowserPluginMsg_UpdatedName
, OnUpdatedName
)
133 IPC_MESSAGE_HANDLER(BrowserPluginMsg_UpdateRect
, OnUpdateRect
)
134 IPC_MESSAGE_UNHANDLED(handled
= false)
135 IPC_END_MESSAGE_MAP()
139 void BrowserPlugin::UpdateDOMAttribute(const std::string
& attribute_name
,
140 const std::string
& attribute_value
) {
144 blink::WebElement element
= container()->element();
145 blink::WebString web_attribute_name
=
146 blink::WebString::fromUTF8(attribute_name
);
147 if (!HasDOMAttribute(attribute_name
) ||
148 (std::string(element
.getAttribute(web_attribute_name
).utf8()) !=
150 element
.setAttribute(web_attribute_name
,
151 blink::WebString::fromUTF8(attribute_value
));
155 void BrowserPlugin::RemoveDOMAttribute(const std::string
& attribute_name
) {
159 container()->element().removeAttribute(
160 blink::WebString::fromUTF8(attribute_name
));
163 std::string
BrowserPlugin::GetDOMAttributeValue(
164 const std::string
& attribute_name
) const {
166 return std::string();
168 return container()->element().getAttribute(
169 blink::WebString::fromUTF8(attribute_name
)).utf8();
172 bool BrowserPlugin::HasDOMAttribute(const std::string
& attribute_name
) const {
176 return container()->element().hasAttribute(
177 blink::WebString::fromUTF8(attribute_name
));
180 std::string
BrowserPlugin::GetNameAttribute() const {
181 return GetDOMAttributeValue(browser_plugin::kAttributeName
);
184 bool BrowserPlugin::GetAllowTransparencyAttribute() const {
185 return HasDOMAttribute(browser_plugin::kAttributeAllowTransparency
);
188 std::string
BrowserPlugin::GetSrcAttribute() const {
189 return GetDOMAttributeValue(browser_plugin::kAttributeSrc
);
192 bool BrowserPlugin::GetAutoSizeAttribute() const {
193 return HasDOMAttribute(browser_plugin::kAttributeAutoSize
);
196 int BrowserPlugin::GetMaxHeightAttribute() const {
198 base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMaxHeight
),
203 int BrowserPlugin::GetMaxWidthAttribute() const {
205 base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMaxWidth
),
210 int BrowserPlugin::GetMinHeightAttribute() const {
212 base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMinHeight
),
217 int BrowserPlugin::GetMinWidthAttribute() const {
219 base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMinWidth
),
224 int BrowserPlugin::GetAdjustedMaxHeight() const {
225 int max_height
= GetMaxHeightAttribute();
226 return max_height
? max_height
: height();
229 int BrowserPlugin::GetAdjustedMaxWidth() const {
230 int max_width
= GetMaxWidthAttribute();
231 return max_width
? max_width
: width();
234 int BrowserPlugin::GetAdjustedMinHeight() const {
235 int min_height
= GetMinHeightAttribute();
236 // FrameView.cpp does not allow this value to be <= 0, so when the value is
237 // unset (or set to 0), we set it to the container size.
238 min_height
= min_height
? min_height
: height();
239 // For autosize, minHeight should not be bigger than maxHeight.
240 return std::min(min_height
, GetAdjustedMaxHeight());
243 int BrowserPlugin::GetAdjustedMinWidth() const {
244 int min_width
= GetMinWidthAttribute();
245 // FrameView.cpp does not allow this value to be <= 0, so when the value is
246 // unset (or set to 0), we set it to the container size.
247 min_width
= min_width
? min_width
: width();
248 // For autosize, minWidth should not be bigger than maxWidth.
249 return std::min(min_width
, GetAdjustedMaxWidth());
252 std::string
BrowserPlugin::GetPartitionAttribute() const {
253 return GetDOMAttributeValue(browser_plugin::kAttributePartition
);
256 void BrowserPlugin::ParseNameAttribute() {
257 if (!HasGuestInstanceID())
259 browser_plugin_manager()->Send(
260 new BrowserPluginHostMsg_SetName(render_view_routing_id_
,
262 GetNameAttribute()));
265 void BrowserPlugin::ParseAllowTransparencyAttribute() {
266 if (!HasGuestInstanceID())
269 bool opaque
= !GetAllowTransparencyAttribute();
271 if (compositing_helper_
)
272 compositing_helper_
->SetContentsOpaque(opaque
);
274 browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetContentsOpaque(
275 render_view_routing_id_
,
280 bool BrowserPlugin::ParseSrcAttribute(std::string
* error_message
) {
281 if (!valid_partition_id_
) {
282 *error_message
= browser_plugin::kErrorInvalidPartition
;
285 std::string src
= GetSrcAttribute();
289 // If we haven't created the guest yet, do so now. We will navigate it right
290 // after creation. If |src| is empty, we can delay the creation until we
292 if (!HasGuestInstanceID()) {
293 // On initial navigation, we request an instance ID from the browser
294 // process. We essentially ignore all subsequent calls to SetSrcAttribute
295 // until we receive an instance ID. |before_first_navigation_|
296 // prevents BrowserPlugin from allocating more than one instance ID.
297 // Upon receiving an instance ID from the browser process, we continue
298 // the process of navigation by populating the
299 // BrowserPluginHostMsg_Attach_Params with the current state of
300 // BrowserPlugin and sending a BrowserPluginHostMsg_CreateGuest to the
301 // browser process in order to create a new guest.
302 if (before_first_navigation_
) {
303 browser_plugin_manager()->AllocateInstanceID(
304 weak_ptr_factory_
.GetWeakPtr());
305 before_first_navigation_
= false;
310 browser_plugin_manager()->Send(
311 new BrowserPluginHostMsg_NavigateGuest(render_view_routing_id_
,
317 void BrowserPlugin::ParseAutoSizeAttribute() {
318 last_view_size_
= plugin_rect_
.size();
319 is_auto_size_state_dirty_
= true;
320 UpdateGuestAutoSizeState(GetAutoSizeAttribute());
323 void BrowserPlugin::PopulateAutoSizeParameters(
324 BrowserPluginHostMsg_AutoSize_Params
* params
, bool auto_size_enabled
) {
325 params
->enable
= auto_size_enabled
;
326 // No need to populate the params if autosize is off.
327 if (auto_size_enabled
) {
328 params
->max_size
= gfx::Size(GetAdjustedMaxWidth(), GetAdjustedMaxHeight());
329 params
->min_size
= gfx::Size(GetAdjustedMinWidth(), GetAdjustedMinHeight());
331 if (max_auto_size_
!= params
->max_size
)
332 is_auto_size_state_dirty_
= true;
334 max_auto_size_
= params
->max_size
;
336 max_auto_size_
= gfx::Size();
340 void BrowserPlugin::UpdateGuestAutoSizeState(bool auto_size_enabled
) {
341 // If we haven't yet heard back from the guest about the last resize request,
342 // then we don't issue another request until we do in
343 // BrowserPlugin::UpdateRect.
344 if (!HasGuestInstanceID() || !paint_ack_received_
)
347 BrowserPluginHostMsg_AutoSize_Params auto_size_params
;
348 BrowserPluginHostMsg_ResizeGuest_Params resize_guest_params
;
349 if (auto_size_enabled
) {
350 GetDamageBufferWithSizeParams(&auto_size_params
,
351 &resize_guest_params
,
354 GetDamageBufferWithSizeParams(NULL
, &resize_guest_params
, true);
356 paint_ack_received_
= false;
357 browser_plugin_manager()->Send(
358 new BrowserPluginHostMsg_SetAutoSize(render_view_routing_id_
,
361 resize_guest_params
));
365 bool BrowserPlugin::UsesDamageBuffer(
366 const BrowserPluginMsg_UpdateRect_Params
& params
) {
367 return params
.damage_buffer_sequence_id
!= 0 || params
.needs_ack
;
370 bool BrowserPlugin::UsesPendingDamageBuffer(
371 const BrowserPluginMsg_UpdateRect_Params
& params
) {
372 if (!pending_damage_buffer_
)
374 return damage_buffer_sequence_id_
== params
.damage_buffer_sequence_id
;
377 void BrowserPlugin::OnInstanceIDAllocated(int guest_instance_id
) {
378 CHECK(guest_instance_id
!= browser_plugin::kInstanceIDNone
);
379 before_first_navigation_
= false;
380 guest_instance_id_
= guest_instance_id
;
381 browser_plugin_manager()->AddBrowserPlugin(guest_instance_id
, this);
383 std::map
<std::string
, base::Value
*> props
;
384 props
[browser_plugin::kWindowID
] =
385 new base::FundamentalValue(guest_instance_id
);
386 TriggerEvent(browser_plugin::kEventInternalInstanceIDAllocated
, &props
);
389 void BrowserPlugin::Attach(scoped_ptr
<base::DictionaryValue
> extra_params
) {
390 BrowserPluginHostMsg_Attach_Params attach_params
;
391 attach_params
.focused
= ShouldGuestBeFocused();
392 attach_params
.visible
= visible_
;
393 attach_params
.opaque
= !GetAllowTransparencyAttribute();
394 attach_params
.name
= GetNameAttribute();
395 attach_params
.storage_partition_id
= storage_partition_id_
;
396 attach_params
.persist_storage
= persist_storage_
;
397 attach_params
.src
= GetSrcAttribute();
398 attach_params
.embedder_frame_url
= embedder_frame_url_
;
399 GetDamageBufferWithSizeParams(&attach_params
.auto_size_params
,
400 &attach_params
.resize_guest_params
,
403 browser_plugin_manager()->Send(
404 new BrowserPluginHostMsg_Attach(render_view_routing_id_
,
405 guest_instance_id_
, attach_params
,
409 void BrowserPlugin::DidCommitCompositorFrame() {
410 if (compositing_helper_
.get())
411 compositing_helper_
->DidCommitCompositorFrame();
414 void BrowserPlugin::OnAdvanceFocus(int guest_instance_id
, bool reverse
) {
415 DCHECK(render_view_
.get());
416 render_view_
->GetWebView()->advanceFocus(reverse
);
419 void BrowserPlugin::OnAttachACK(
420 int guest_instance_id
,
421 const BrowserPluginMsg_Attach_ACK_Params
& params
) {
422 // Update BrowserPlugin attributes to match the state of the guest.
423 if (!params
.name
.empty())
424 OnUpdatedName(guest_instance_id
, params
.name
);
425 if (!params
.storage_partition_id
.empty()) {
426 std::string partition_name
=
427 (params
.persist_storage
? browser_plugin::kPersistPrefix
: "") +
428 params
.storage_partition_id
;
429 UpdateDOMAttribute(browser_plugin::kAttributePartition
, partition_name
);
434 void BrowserPlugin::OnBuffersSwapped(
436 const FrameMsg_BuffersSwapped_Params
& params
) {
437 EnableCompositing(true);
439 compositing_helper_
->OnBuffersSwapped(params
.size
,
443 GetDeviceScaleFactor());
446 void BrowserPlugin::OnCompositorFrameSwapped(const IPC::Message
& message
) {
447 BrowserPluginMsg_CompositorFrameSwapped::Param param
;
448 if (!BrowserPluginMsg_CompositorFrameSwapped::Read(&message
, ¶m
))
450 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
451 param
.b
.frame
.AssignTo(frame
.get());
453 EnableCompositing(true);
454 compositing_helper_
->OnCompositorFrameSwapped(frame
.Pass(),
455 param
.b
.producing_route_id
,
456 param
.b
.output_surface_id
,
457 param
.b
.producing_host_id
);
460 void BrowserPlugin::OnCopyFromCompositingSurface(int guest_instance_id
,
462 gfx::Rect source_rect
,
463 gfx::Size dest_size
) {
464 if (!compositing_enabled_
) {
465 browser_plugin_manager()->Send(
466 new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck(
467 render_view_routing_id_
,
473 compositing_helper_
->CopyFromCompositingSurface(request_id
, source_rect
,
477 void BrowserPlugin::OnGuestContentWindowReady(int guest_instance_id
,
478 int content_window_routing_id
) {
479 DCHECK(content_window_routing_id
!= MSG_ROUTING_NONE
);
480 content_window_routing_id_
= content_window_routing_id
;
483 void BrowserPlugin::OnGuestGone(int guest_instance_id
) {
484 guest_crashed_
= true;
486 // Turn off compositing so we can display the sad graphic. Changes to
487 // compositing state will show up at a later time after a layout and commit.
488 EnableCompositing(false);
489 if (compositing_helper_
) {
490 compositing_helper_
->OnContainerDestroy();
491 compositing_helper_
= NULL
;
494 // Queue up showing the sad graphic to give content embedders an opportunity
495 // to fire their listeners and potentially overlay the webview with custom
496 // behavior. If the BrowserPlugin is destroyed in the meantime, then the
497 // task will not be executed.
498 base::MessageLoop::current()->PostTask(
500 base::Bind(&BrowserPlugin::ShowSadGraphic
,
501 weak_ptr_factory_
.GetWeakPtr()));
504 void BrowserPlugin::OnSetCursor(int guest_instance_id
,
505 const WebCursor
& cursor
) {
509 void BrowserPlugin::OnSetMouseLock(int guest_instance_id
,
514 render_view_
->mouse_lock_dispatcher()->LockMouse(this);
516 if (!mouse_locked_
) {
517 OnLockMouseACK(false);
520 render_view_
->mouse_lock_dispatcher()->UnlockMouse(this);
524 void BrowserPlugin::OnShouldAcceptTouchEvents(int guest_instance_id
,
527 container()->requestTouchEventType(accept
?
528 blink::WebPluginContainer::TouchEventRequestTypeRaw
:
529 blink::WebPluginContainer::TouchEventRequestTypeNone
);
533 void BrowserPlugin::OnUpdatedName(int guest_instance_id
,
534 const std::string
& name
) {
535 UpdateDOMAttribute(browser_plugin::kAttributeName
, name
);
538 void BrowserPlugin::OnUpdateRect(
539 int guest_instance_id
,
540 const BrowserPluginMsg_UpdateRect_Params
& params
) {
541 // If the guest has updated pixels then it is no longer crashed.
542 guest_crashed_
= false;
544 bool use_new_damage_buffer
= !backing_store_
;
545 BrowserPluginHostMsg_AutoSize_Params auto_size_params
;
546 BrowserPluginHostMsg_ResizeGuest_Params resize_guest_params
;
547 // If we have a pending damage buffer, and the guest has begun to use the
548 // damage buffer then we know the guest will no longer use the current
549 // damage buffer. At this point, we drop the current damage buffer, and
550 // mark the pending damage buffer as the current damage buffer.
551 if (UsesPendingDamageBuffer(params
)) {
553 use_new_damage_buffer
= true;
556 bool auto_size
= GetAutoSizeAttribute();
557 // We receive a resize ACK in regular mode, but not in autosize.
558 // In SW, |paint_ack_received_| is reset in SwapDamageBuffers().
559 // In HW mode, we need to do it here so we can continue sending
560 // resize messages when needed.
561 if (params
.is_resize_ack
||
562 (!params
.needs_ack
&& (auto_size
|| is_auto_size_state_dirty_
))) {
563 paint_ack_received_
= true;
566 bool was_auto_size_state_dirty
= auto_size
&& is_auto_size_state_dirty_
;
567 is_auto_size_state_dirty_
= false;
569 if ((!auto_size
&& (width() != params
.view_size
.width() ||
570 height() != params
.view_size
.height())) ||
571 (auto_size
&& was_auto_size_state_dirty
) ||
572 GetDeviceScaleFactor() != params
.scale_factor
) {
573 // We are HW accelerated, render widget does not expect an ack,
574 // but we still need to update the size.
575 if (!params
.needs_ack
) {
576 UpdateGuestAutoSizeState(auto_size
);
580 if (!paint_ack_received_
) {
581 // The guest has not yet responded to the last resize request, and
582 // so we don't want to do anything at this point other than ACK the guest.
584 PopulateAutoSizeParameters(&auto_size_params
, auto_size
);
586 // If we have no pending damage buffer, then the guest has not caught up
587 // with the BrowserPlugin container. We now tell the guest about the new
590 GetDamageBufferWithSizeParams(&auto_size_params
,
591 &resize_guest_params
,
592 was_auto_size_state_dirty
);
594 GetDamageBufferWithSizeParams(NULL
,
595 &resize_guest_params
,
596 was_auto_size_state_dirty
);
599 browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateRect_ACK(
600 render_view_routing_id_
,
604 resize_guest_params
));
608 if (auto_size
&& (params
.view_size
!= last_view_size_
)) {
610 backing_store_
->Clear(SK_ColorWHITE
);
611 last_view_size_
= params
.view_size
;
614 if (UsesDamageBuffer(params
)) {
616 // If we are seeing damage buffers, HW compositing should be turned off.
617 EnableCompositing(false);
619 // If we are now using a new damage buffer, then that means that the guest
620 // has updated its size state in response to a resize request. We change
621 // the backing store's size to accomodate the new damage buffer size.
622 if (use_new_damage_buffer
) {
623 int backing_store_width
= auto_size
? GetAdjustedMaxWidth() : width();
624 int backing_store_height
= auto_size
? GetAdjustedMaxHeight(): height();
625 backing_store_
.reset(
626 new BrowserPluginBackingStore(
627 gfx::Size(backing_store_width
, backing_store_height
),
628 params
.scale_factor
));
631 // If we just transitioned from the compositing path to the software path
632 // then we might not yet have a damage buffer.
633 if (current_damage_buffer_
) {
634 // Update the backing store.
635 if (!params
.scroll_rect
.IsEmpty()) {
636 backing_store_
->ScrollBackingStore(params
.scroll_delta
,
640 backing_store_
->PaintToBackingStore(params
.bitmap_rect
,
642 current_damage_buffer_
->memory());
643 // Invalidate the container.
644 // If the BrowserPlugin is scheduled to be deleted, then container_ will
645 // be NULL so we shouldn't attempt to access it.
647 container_
->invalidate();
651 // BrowserPluginHostMsg_UpdateRect_ACK is used by both the compositing and
652 // software paths to piggyback updated autosize parameters.
654 PopulateAutoSizeParameters(&auto_size_params
, auto_size
);
655 browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateRect_ACK(
656 render_view_routing_id_
,
658 UsesDamageBuffer(params
),
660 resize_guest_params
));
663 void BrowserPlugin::ParseSizeContraintsChanged() {
664 bool auto_size
= GetAutoSizeAttribute();
666 is_auto_size_state_dirty_
= true;
667 UpdateGuestAutoSizeState(true);
671 bool BrowserPlugin::InAutoSizeBounds(const gfx::Size
& size
) const {
672 return size
.width() <= GetAdjustedMaxWidth() &&
673 size
.height() <= GetAdjustedMaxHeight();
676 NPObject
* BrowserPlugin::GetContentWindow() const {
677 if (content_window_routing_id_
== MSG_ROUTING_NONE
)
679 RenderViewImpl
* guest_render_view
= RenderViewImpl::FromRoutingID(
680 content_window_routing_id_
);
681 if (!guest_render_view
)
683 blink::WebFrame
* guest_frame
= guest_render_view
->GetWebView()->mainFrame();
684 return guest_frame
->windowObject();
688 bool BrowserPlugin::AttachWindowTo(const blink::WebNode
& node
, int window_id
) {
692 if (!node
.isElementNode())
695 blink::WebElement shim_element
= node
.toConst
<blink::WebElement
>();
696 // The shim containing the BrowserPlugin must be attached to a document.
697 if (shim_element
.document().isNull())
700 blink::WebNode shadow_root
= shim_element
.shadowRoot();
701 if (shadow_root
.isNull() || !shadow_root
.hasChildNodes())
704 blink::WebNode plugin_element
= shadow_root
.firstChild();
705 blink::WebPluginContainer
* plugin_container
=
706 plugin_element
.pluginContainer();
707 if (!plugin_container
)
710 BrowserPlugin
* browser_plugin
=
711 BrowserPlugin::FromContainer(plugin_container
);
715 // If the BrowserPlugin has already begun to navigate then we shouldn't allow
716 // attaching a different guest.
718 // Navigation happens in two stages.
719 // 1. BrowserPlugin requests an instance ID from the browser process.
720 // 2. The browser process returns an instance ID and BrowserPlugin is
721 // "Attach"ed to that instance ID.
722 // If the instance ID is new then a new guest will be created.
723 // If the instance ID corresponds to an unattached guest then BrowserPlugin
724 // is attached to that guest.
726 // Between step 1, and step 2, BrowserPlugin::AttachWindowTo may be called.
727 // The check below ensures that BrowserPlugin:Attach does not get called with
728 // a different instance ID after step 1 has happened.
729 // TODO(fsamuel): We may wish to support reattaching guests in the future:
730 // http://crbug.com/156219.
731 if (browser_plugin
->HasNavigated())
734 browser_plugin
->OnInstanceIDAllocated(window_id
);
738 bool BrowserPlugin::HasNavigated() const {
739 return !before_first_navigation_
;
742 bool BrowserPlugin::HasGuestInstanceID() const {
743 return guest_instance_id_
!= browser_plugin::kInstanceIDNone
;
746 bool BrowserPlugin::ParsePartitionAttribute(std::string
* error_message
) {
747 if (HasNavigated()) {
748 *error_message
= browser_plugin::kErrorAlreadyNavigated
;
752 std::string input
= GetPartitionAttribute();
754 // Since the "persist:" prefix is in ASCII, StartsWith will work fine on
755 // UTF-8 encoded |partition_id|. If the prefix is a match, we can safely
756 // remove the prefix without splicing in the middle of a multi-byte codepoint.
757 // We can use the rest of the string as UTF-8 encoded one.
758 if (StartsWithASCII(input
, browser_plugin::kPersistPrefix
, true)) {
759 size_t index
= input
.find(":");
760 CHECK(index
!= std::string::npos
);
761 // It is safe to do index + 1, since we tested for the full prefix above.
762 input
= input
.substr(index
+ 1);
764 valid_partition_id_
= false;
765 *error_message
= browser_plugin::kErrorInvalidPartition
;
768 persist_storage_
= true;
770 persist_storage_
= false;
773 valid_partition_id_
= true;
774 storage_partition_id_
= input
;
778 bool BrowserPlugin::CanRemovePartitionAttribute(std::string
* error_message
) {
779 if (HasGuestInstanceID())
780 *error_message
= browser_plugin::kErrorCannotRemovePartition
;
781 return !HasGuestInstanceID();
784 void BrowserPlugin::ShowSadGraphic() {
785 // We won't paint the contents of the current backing store again so we might
786 // as well toss it out and save memory.
787 backing_store_
.reset();
788 // If the BrowserPlugin is scheduled to be deleted, then container_ will be
789 // NULL so we shouldn't attempt to access it.
791 container_
->invalidate();
794 void BrowserPlugin::ParseAttributes() {
795 // TODO(mthiesse): Handle errors here?
797 ParsePartitionAttribute(&error
);
799 // Parse the 'src' attribute last, as it will set the has_navigated_ flag to
800 // true, which prevents changing the 'partition' attribute.
801 ParseSrcAttribute(&error
);
804 float BrowserPlugin::GetDeviceScaleFactor() const {
805 if (!render_view_
.get())
807 return render_view_
->GetWebView()->deviceScaleFactor();
810 void BrowserPlugin::UpdateDeviceScaleFactor(float device_scale_factor
) {
811 if (last_device_scale_factor_
== device_scale_factor
|| !paint_ack_received_
)
814 BrowserPluginHostMsg_ResizeGuest_Params params
;
815 PopulateResizeGuestParameters(¶ms
, plugin_rect(), false);
816 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
817 render_view_routing_id_
,
822 void BrowserPlugin::TriggerEvent(const std::string
& event_name
,
823 std::map
<std::string
, base::Value
*>* props
) {
827 blink::WebFrame
* frame
= container()->element().document().frame();
831 v8::HandleScope
handle_scope(v8::Isolate::GetCurrent());
832 v8::Local
<v8::Context
> context
= frame
->mainWorldScriptContext();
833 v8::Context::Scope
context_scope(context
);
835 std::string json_string
;
837 base::DictionaryValue dict
;
838 for (std::map
<std::string
, base::Value
*>::iterator iter
= props
->begin(),
839 end
= props
->end(); iter
!= end
; ++iter
) {
840 dict
.Set(iter
->first
, iter
->second
);
843 JSONStringValueSerializer
serializer(&json_string
);
844 if (!serializer
.Serialize(dict
))
848 blink::WebDOMEvent dom_event
= frame
->document().createEvent("CustomEvent");
849 blink::WebDOMCustomEvent event
= dom_event
.to
<blink::WebDOMCustomEvent
>();
851 // The events triggered directly from the plugin <object> are internal events
852 // whose implementation details can (and likely will) change over time. The
853 // wrapper/shim (e.g. <webview> tag) should receive these events, and expose a
854 // more appropriate (and stable) event to the consumers as part of the API.
855 event
.initCustomEvent(
856 blink::WebString::fromUTF8(GetInternalEventName(event_name
.c_str())),
859 blink::WebSerializedScriptValue::serialize(
860 v8::String::NewFromUtf8(context
->GetIsolate(),
862 v8::String::kNormalString
,
863 json_string
.size())));
864 container()->element().dispatchEvent(event
);
867 void BrowserPlugin::UpdateGuestFocusState() {
868 if (!HasGuestInstanceID())
870 bool should_be_focused
= ShouldGuestBeFocused();
871 browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetFocus(
872 render_view_routing_id_
,
877 bool BrowserPlugin::ShouldGuestBeFocused() const {
878 bool embedder_focused
= false;
879 if (render_view_
.get())
880 embedder_focused
= render_view_
->has_focus();
881 return plugin_focused_
&& embedder_focused
;
884 blink::WebPluginContainer
* BrowserPlugin::container() const {
888 bool BrowserPlugin::initialize(WebPluginContainer
* container
) {
892 if (!GetContentClient()->renderer()->AllowBrowserPlugin(container
))
895 // Tell |container| to allow this plugin to use script objects.
896 npp_
.reset(new NPP_t
);
897 container
->allowScriptObjects();
899 bindings_
.reset(new BrowserPluginBindings(this));
900 container_
= container
;
901 container_
->setWantsWheelEvents(true);
903 g_plugin_container_map
.Get().insert(std::make_pair(container_
, this));
907 void BrowserPlugin::EnableCompositing(bool enable
) {
908 if (compositing_enabled_
== enable
)
911 compositing_enabled_
= enable
;
913 // No need to keep the backing store and damage buffer around if we're now
915 backing_store_
.reset();
916 current_damage_buffer_
.reset();
917 if (!compositing_helper_
.get()) {
918 compositing_helper_
=
919 new BrowserPluginCompositingHelper(container_
,
920 browser_plugin_manager(),
922 render_view_routing_id_
);
925 if (paint_ack_received_
) {
926 // We're switching back to the software path. We create a new damage
927 // buffer that can accommodate the current size of the container.
928 BrowserPluginHostMsg_ResizeGuest_Params params
;
929 // Request a full repaint from the guest even if its size is not actually
931 PopulateResizeGuestParameters(¶ms
,
933 true /* needs_repaint */);
934 paint_ack_received_
= false;
935 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
936 render_view_routing_id_
,
941 compositing_helper_
->EnableCompositing(enable
);
942 compositing_helper_
->SetContentsOpaque(!GetAllowTransparencyAttribute());
945 void BrowserPlugin::destroy() {
946 // If the plugin was initialized then it has a valid |npp_| identifier, and
947 // the |container_| must clear references to the plugin's script objects.
948 DCHECK(!npp_
|| container_
);
950 container_
->clearScriptObjects();
952 // The BrowserPlugin's WebPluginContainer is deleted immediately after this
953 // call returns, so let's not keep a reference to it around.
954 g_plugin_container_map
.Get().erase(container_
);
956 if (compositing_helper_
.get())
957 compositing_helper_
->OnContainerDestroy();
958 // Will be a no-op if the mouse is not currently locked.
959 if (render_view_
.get())
960 render_view_
->mouse_lock_dispatcher()->OnLockTargetDestroyed(this);
961 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
964 NPObject
* BrowserPlugin::scriptableObject() {
968 NPObject
* browser_plugin_np_object(bindings_
->np_object());
969 // The object is expected to be retained before it is returned.
970 blink::WebBindings::retainObject(browser_plugin_np_object
);
971 return browser_plugin_np_object
;
974 NPP
BrowserPlugin::pluginNPP() {
978 bool BrowserPlugin::supportsKeyboardFocus() const {
982 bool BrowserPlugin::supportsEditCommands() const {
986 bool BrowserPlugin::supportsInputMethod() const {
990 bool BrowserPlugin::canProcessDrag() const {
994 void BrowserPlugin::paint(WebCanvas
* canvas
, const WebRect
& rect
) {
995 if (guest_crashed_
) {
996 if (!sad_guest_
) // Lazily initialize bitmap.
997 sad_guest_
= content::GetContentClient()->renderer()->
998 GetSadWebViewBitmap();
999 // content_shell does not have the sad plugin bitmap, so we'll paint black
1000 // instead to make it clear that something went wrong.
1002 PaintSadPlugin(canvas
, plugin_rect_
, *sad_guest_
);
1006 SkAutoCanvasRestore
auto_restore(canvas
, true);
1007 canvas
->translate(plugin_rect_
.x(), plugin_rect_
.y());
1008 SkRect image_data_rect
= SkRect::MakeXYWH(
1011 SkIntToScalar(plugin_rect_
.width()),
1012 SkIntToScalar(plugin_rect_
.height()));
1013 canvas
->clipRect(image_data_rect
);
1014 // Paint black or white in case we have nothing in our backing store or we
1015 // need to show a gutter.
1017 paint
.setStyle(SkPaint::kFill_Style
);
1018 paint
.setColor(guest_crashed_
? SK_ColorBLACK
: SK_ColorWHITE
);
1019 canvas
->drawRect(image_data_rect
, paint
);
1020 // Stay a solid color if we have never set a non-empty src, or we don't have a
1022 if (!backing_store_
.get() || !HasGuestInstanceID())
1024 float inverse_scale_factor
= 1.0f
/ backing_store_
->GetScaleFactor();
1025 canvas
->scale(inverse_scale_factor
, inverse_scale_factor
);
1026 canvas
->drawBitmap(backing_store_
->GetBitmap(), 0, 0);
1029 bool BrowserPlugin::InBounds(const gfx::Point
& position
) const {
1030 // Note that even for plugins that are rotated using rotate transformations,
1031 // we use the the |plugin_rect_| provided by updateGeometry, which means we
1032 // will be off if |position| is within the plugin rect but does not fall
1033 // within the actual plugin boundary. Not supporting such edge case is OK
1034 // since this function should not be used for making security-sensitive
1036 // This also does not take overlapping plugins into account.
1037 bool result
= position
.x() >= plugin_rect_
.x() &&
1038 position
.x() < plugin_rect_
.x() + plugin_rect_
.width() &&
1039 position
.y() >= plugin_rect_
.y() &&
1040 position
.y() < plugin_rect_
.y() + plugin_rect_
.height();
1044 gfx::Point
BrowserPlugin::ToLocalCoordinates(const gfx::Point
& point
) const {
1046 return container_
->windowToLocalPoint(blink::WebPoint(point
));
1047 return gfx::Point(point
.x() - plugin_rect_
.x(), point
.y() - plugin_rect_
.y());
1051 bool BrowserPlugin::ShouldForwardToBrowserPlugin(
1052 const IPC::Message
& message
) {
1053 switch (message
.type()) {
1054 case BrowserPluginMsg_AdvanceFocus::ID
:
1055 case BrowserPluginMsg_Attach_ACK::ID
:
1056 case BrowserPluginMsg_BuffersSwapped::ID
:
1057 case BrowserPluginMsg_CompositorFrameSwapped::ID
:
1058 case BrowserPluginMsg_CopyFromCompositingSurface::ID
:
1059 case BrowserPluginMsg_GuestContentWindowReady::ID
:
1060 case BrowserPluginMsg_GuestGone::ID
:
1061 case BrowserPluginMsg_SetCursor::ID
:
1062 case BrowserPluginMsg_SetMouseLock::ID
:
1063 case BrowserPluginMsg_ShouldAcceptTouchEvents::ID
:
1064 case BrowserPluginMsg_UpdatedName::ID
:
1065 case BrowserPluginMsg_UpdateRect::ID
:
1073 void BrowserPlugin::updateGeometry(
1074 const WebRect
& window_rect
,
1075 const WebRect
& clip_rect
,
1076 const WebVector
<WebRect
>& cut_outs_rects
,
1078 int old_width
= width();
1079 int old_height
= height();
1080 plugin_rect_
= window_rect
;
1084 // In AutoSize mode, guests don't care when the BrowserPlugin container is
1085 // resized. If |!paint_ack_received_|, then we are still waiting on a
1086 // previous resize to be ACK'ed and so we don't issue additional resizes
1087 // until the previous one is ACK'ed.
1088 // TODO(mthiesse): Assess the performance of calling GetAutoSizeAttribute() on
1090 if (!paint_ack_received_
||
1091 (old_width
== window_rect
.width
&& old_height
== window_rect
.height
) ||
1092 GetAutoSizeAttribute()) {
1093 // Let the browser know about the updated view rect.
1094 browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateGeometry(
1095 render_view_routing_id_
, guest_instance_id_
, plugin_rect_
));
1099 BrowserPluginHostMsg_ResizeGuest_Params params
;
1100 PopulateResizeGuestParameters(¶ms
, plugin_rect(), false);
1101 paint_ack_received_
= false;
1102 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
1103 render_view_routing_id_
,
1108 void BrowserPlugin::SwapDamageBuffers() {
1109 current_damage_buffer_
.reset(pending_damage_buffer_
.release());
1110 paint_ack_received_
= true;
1113 void BrowserPlugin::PopulateResizeGuestParameters(
1114 BrowserPluginHostMsg_ResizeGuest_Params
* params
,
1115 const gfx::Rect
& view_rect
,
1116 bool needs_repaint
) {
1117 params
->size_changed
= true;
1118 params
->view_rect
= view_rect
;
1119 params
->repaint
= needs_repaint
;
1120 params
->scale_factor
= GetDeviceScaleFactor();
1121 if (last_device_scale_factor_
!= params
->scale_factor
){
1122 params
->repaint
= true;
1123 last_device_scale_factor_
= params
->scale_factor
;
1126 // In HW compositing mode, we do not need a damage buffer.
1127 if (compositing_enabled_
)
1130 const size_t stride
= skia::PlatformCanvasStrideForWidth(view_rect
.width());
1131 // Make sure the size of the damage buffer is at least four bytes so that we
1132 // can fit in a magic word to verify that the memory is shared correctly.
1134 std::max(sizeof(unsigned int),
1135 static_cast<size_t>(view_rect
.height() *
1137 GetDeviceScaleFactor() *
1138 GetDeviceScaleFactor()));
1140 params
->damage_buffer_size
= size
;
1141 pending_damage_buffer_
.reset(
1142 CreateDamageBuffer(size
, ¶ms
->damage_buffer_handle
));
1143 if (!pending_damage_buffer_
)
1145 params
->damage_buffer_sequence_id
= ++damage_buffer_sequence_id_
;
1148 void BrowserPlugin::GetDamageBufferWithSizeParams(
1149 BrowserPluginHostMsg_AutoSize_Params
* auto_size_params
,
1150 BrowserPluginHostMsg_ResizeGuest_Params
* resize_guest_params
,
1151 bool needs_repaint
) {
1152 if (auto_size_params
) {
1153 PopulateAutoSizeParameters(auto_size_params
, GetAutoSizeAttribute());
1155 max_auto_size_
= gfx::Size();
1157 gfx::Size view_size
= (auto_size_params
&& auto_size_params
->enable
) ?
1158 auto_size_params
->max_size
: gfx::Size(width(), height());
1159 if (view_size
.IsEmpty())
1161 paint_ack_received_
= false;
1162 gfx::Rect view_rect
= gfx::Rect(plugin_rect_
.origin(), view_size
);
1163 PopulateResizeGuestParameters(resize_guest_params
, view_rect
, needs_repaint
);
1166 #if defined(OS_POSIX)
1167 base::SharedMemory
* BrowserPlugin::CreateDamageBuffer(
1169 base::SharedMemoryHandle
* damage_buffer_handle
) {
1170 scoped_ptr
<base::SharedMemory
> shared_buf(
1171 content::RenderThread::Get()->HostAllocateSharedMemoryBuffer(
1175 if (shared_buf
->Map(size
)) {
1176 // Insert the magic word.
1177 *static_cast<unsigned int*>(shared_buf
->memory()) = 0xdeadbeef;
1178 shared_buf
->ShareToProcess(base::GetCurrentProcessHandle(),
1179 damage_buffer_handle
);
1180 return shared_buf
.release();
1186 #elif defined(OS_WIN)
1187 base::SharedMemory
* BrowserPlugin::CreateDamageBuffer(
1189 base::SharedMemoryHandle
* damage_buffer_handle
) {
1190 scoped_ptr
<base::SharedMemory
> shared_buf(new base::SharedMemory());
1192 if (!shared_buf
->CreateAndMapAnonymous(size
)) {
1193 NOTREACHED() << "Buffer allocation failed";
1197 // Insert the magic word.
1198 *static_cast<unsigned int*>(shared_buf
->memory()) = 0xdeadbeef;
1199 if (shared_buf
->ShareToProcess(base::GetCurrentProcessHandle(),
1200 damage_buffer_handle
))
1201 return shared_buf
.release();
1207 void BrowserPlugin::updateFocus(bool focused
) {
1208 if (plugin_focused_
== focused
)
1211 bool old_guest_focus_state
= ShouldGuestBeFocused();
1212 plugin_focused_
= focused
;
1214 if (ShouldGuestBeFocused() != old_guest_focus_state
)
1215 UpdateGuestFocusState();
1218 void BrowserPlugin::updateVisibility(bool visible
) {
1219 if (visible_
== visible
)
1223 if (!HasGuestInstanceID())
1226 if (compositing_helper_
.get())
1227 compositing_helper_
->UpdateVisibility(visible
);
1229 browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetVisibility(
1230 render_view_routing_id_
,
1235 bool BrowserPlugin::acceptsInputEvents() {
1239 bool BrowserPlugin::handleInputEvent(const blink::WebInputEvent
& event
,
1240 blink::WebCursorInfo
& cursor_info
) {
1241 if (guest_crashed_
|| !HasGuestInstanceID())
1244 if (event
.type
== blink::WebInputEvent::ContextMenu
)
1247 const blink::WebInputEvent
* modified_event
= &event
;
1248 scoped_ptr
<blink::WebTouchEvent
> touch_event
;
1249 // WebKit gives BrowserPlugin a list of touches that are down, but the browser
1250 // process expects a list of all touches. We modify the TouchEnd event here to
1251 // match these expectations.
1252 if (event
.type
== blink::WebInputEvent::TouchEnd
) {
1253 const blink::WebTouchEvent
* orig_touch_event
=
1254 static_cast<const blink::WebTouchEvent
*>(&event
);
1255 touch_event
.reset(new blink::WebTouchEvent());
1256 memcpy(touch_event
.get(), orig_touch_event
, sizeof(blink::WebTouchEvent
));
1257 if (touch_event
->changedTouchesLength
> 0) {
1258 memcpy(&touch_event
->touches
[touch_event
->touchesLength
],
1259 &touch_event
->changedTouches
,
1260 touch_event
->changedTouchesLength
* sizeof(blink::WebTouchPoint
));
1262 touch_event
->touchesLength
+= touch_event
->changedTouchesLength
;
1263 modified_event
= touch_event
.get();
1266 if (blink::WebInputEvent::isKeyboardEventType(event
.type
) &&
1267 !edit_commands_
.empty()) {
1268 browser_plugin_manager()->Send(
1269 new BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent(
1270 render_view_routing_id_
,
1273 edit_commands_
.clear();
1276 browser_plugin_manager()->Send(
1277 new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_
,
1281 GetWebKitCursorInfo(cursor_
, &cursor_info
);
1285 bool BrowserPlugin::handleDragStatusUpdate(blink::WebDragStatus drag_status
,
1286 const blink::WebDragData
& drag_data
,
1287 blink::WebDragOperationsMask mask
,
1288 const blink::WebPoint
& position
,
1289 const blink::WebPoint
& screen
) {
1290 if (guest_crashed_
|| !HasGuestInstanceID())
1292 browser_plugin_manager()->Send(
1293 new BrowserPluginHostMsg_DragStatusUpdate(
1294 render_view_routing_id_
,
1297 DropDataBuilder::Build(drag_data
),
1303 void BrowserPlugin::didReceiveResponse(
1304 const blink::WebURLResponse
& response
) {
1307 void BrowserPlugin::didReceiveData(const char* data
, int data_length
) {
1310 void BrowserPlugin::didFinishLoading() {
1313 void BrowserPlugin::didFailLoading(const blink::WebURLError
& error
) {
1316 void BrowserPlugin::didFinishLoadingFrameRequest(const blink::WebURL
& url
,
1317 void* notify_data
) {
1320 void BrowserPlugin::didFailLoadingFrameRequest(
1321 const blink::WebURL
& url
,
1323 const blink::WebURLError
& error
) {
1326 bool BrowserPlugin::executeEditCommand(const blink::WebString
& name
) {
1327 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ExecuteEditCommand(
1328 render_view_routing_id_
,
1332 // BrowserPlugin swallows edit commands.
1336 bool BrowserPlugin::executeEditCommand(const blink::WebString
& name
,
1337 const blink::WebString
& value
) {
1338 edit_commands_
.push_back(EditCommand(name
.utf8(), value
.utf8()));
1339 // BrowserPlugin swallows edit commands.
1343 bool BrowserPlugin::setComposition(
1344 const blink::WebString
& text
,
1345 const blink::WebVector
<blink::WebCompositionUnderline
>& underlines
,
1348 if (!HasGuestInstanceID())
1350 std::vector
<blink::WebCompositionUnderline
> std_underlines
;
1351 for (size_t i
= 0; i
< underlines
.size(); ++i
) {
1352 std_underlines
.push_back(underlines
[i
]);
1354 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeSetComposition(
1355 render_view_routing_id_
,
1361 // TODO(kochi): This assumes the IPC handling always succeeds.
1365 bool BrowserPlugin::confirmComposition(
1366 const blink::WebString
& text
,
1367 blink::WebWidget::ConfirmCompositionBehavior selectionBehavior
) {
1368 if (!HasGuestInstanceID())
1370 bool keep_selection
= (selectionBehavior
== blink::WebWidget::KeepSelection
);
1371 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeConfirmComposition(
1372 render_view_routing_id_
,
1376 // TODO(kochi): This assumes the IPC handling always succeeds.
1380 void BrowserPlugin::extendSelectionAndDelete(int before
, int after
) {
1381 if (!HasGuestInstanceID())
1383 browser_plugin_manager()->Send(
1384 new BrowserPluginHostMsg_ExtendSelectionAndDelete(
1385 render_view_routing_id_
,
1391 void BrowserPlugin::OnLockMouseACK(bool succeeded
) {
1392 mouse_locked_
= succeeded
;
1393 browser_plugin_manager()->Send(new BrowserPluginHostMsg_LockMouse_ACK(
1394 render_view_routing_id_
,
1399 void BrowserPlugin::OnMouseLockLost() {
1400 mouse_locked_
= false;
1401 browser_plugin_manager()->Send(new BrowserPluginHostMsg_UnlockMouse_ACK(
1402 render_view_routing_id_
,
1403 guest_instance_id_
));
1406 bool BrowserPlugin::HandleMouseLockedInputEvent(
1407 const blink::WebMouseEvent
& event
) {
1408 browser_plugin_manager()->Send(
1409 new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_
,
1416 } // namespace content