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.
4
5 #include "content/renderer/browser_plugin/browser_plugin.h"
6
7 #include "base/command_line.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/common/browser_plugin/browser_plugin_constants.h"
12 #include "content/common/browser_plugin/browser_plugin_messages.h"
13 #include "content/common/view_messages.h"
14 #include "content/public/common/content_client.h"
15 #include "content/public/common/content_switches.h"
16 #include "content/public/renderer/browser_plugin_delegate.h"
17 #include "content/public/renderer/content_renderer_client.h"
18 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
19 #include "content/renderer/child_frame_compositing_helper.h"
20 #include "content/renderer/cursor_utils.h"
21 #include "content/renderer/drop_data_builder.h"
22 #include "content/renderer/render_thread_impl.h"
23 #include "content/renderer/sad_plugin.h"
24 #include "third_party/WebKit/public/platform/WebRect.h"
25 #include "third_party/WebKit/public/web/WebElement.h"
26 #include "third_party/WebKit/public/web/WebInputEvent.h"
27 #include "third_party/WebKit/public/web/WebPluginContainer.h"
28 #include "third_party/WebKit/public/web/WebView.h"
29 #include "third_party/skia/include/core/SkCanvas.h"
30 #include "ui/events/keycodes/keyboard_codes.h"
31
32 using blink::WebCanvas;
33 using blink::WebPluginContainer;
34 using blink::WebPoint;
35 using blink::WebRect;
36 using blink::WebURL;
37 using blink::WebVector;
38
39 namespace {
40 typedef std::map<blink::WebPluginContainer*, content::BrowserPlugin*>
41 PluginContainerMap;
42 static base::LazyInstance<PluginContainerMap> g_plugin_container_map =
43 LAZY_INSTANCE_INITIALIZER;
44 } // namespace
45
46 namespace content {
47
48 // static
GetFromNode(blink::WebNode & node)49 BrowserPlugin* BrowserPlugin::GetFromNode(blink::WebNode& node) {
50 blink::WebPluginContainer* container = node.pluginContainer();
51 if (!container)
52 return NULL;
53
54 PluginContainerMap* browser_plugins = g_plugin_container_map.Pointer();
55 PluginContainerMap::iterator it = browser_plugins->find(container);
56 return it == browser_plugins->end() ? NULL : it->second;
57 }
58
BrowserPlugin(RenderViewImpl * render_view,blink::WebFrame * frame,scoped_ptr<BrowserPluginDelegate> delegate)59 BrowserPlugin::BrowserPlugin(RenderViewImpl* render_view,
60 blink::WebFrame* frame,
61 scoped_ptr<BrowserPluginDelegate> delegate)
62 : attached_(false),
63 attach_pending_(false),
64 render_view_(render_view->AsWeakPtr()),
65 render_view_routing_id_(render_view->GetRoutingID()),
66 container_(NULL),
67 last_device_scale_factor_(GetDeviceScaleFactor()),
68 sad_guest_(NULL),
69 guest_crashed_(false),
70 plugin_focused_(false),
71 visible_(true),
72 mouse_locked_(false),
73 browser_plugin_manager_(render_view->GetBrowserPluginManager()),
74 browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
75 contents_opaque_(true),
76 delegate_(delegate.Pass()),
77 weak_ptr_factory_(this) {
78 browser_plugin_instance_id_ = browser_plugin_manager()->GetNextInstanceID();
79
80 if (delegate_)
81 delegate_->SetElementInstanceID(browser_plugin_instance_id_);
82 }
83
~BrowserPlugin()84 BrowserPlugin::~BrowserPlugin() {
85 browser_plugin_manager()->RemoveBrowserPlugin(browser_plugin_instance_id_);
86
87 if (!ready())
88 return;
89
90 browser_plugin_manager()->Send(
91 new BrowserPluginHostMsg_PluginDestroyed(render_view_routing_id_,
92 browser_plugin_instance_id_));
93 }
94
OnMessageReceived(const IPC::Message & message)95 bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
96 bool handled = true;
97 IPC_BEGIN_MESSAGE_MAP(BrowserPlugin, message)
98 IPC_MESSAGE_HANDLER(BrowserPluginMsg_Attach_ACK, OnAttachACK)
99 IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus, OnAdvanceFocus)
100 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginMsg_CompositorFrameSwapped,
101 OnCompositorFrameSwapped(message))
102 IPC_MESSAGE_HANDLER(BrowserPluginMsg_CopyFromCompositingSurface,
103 OnCopyFromCompositingSurface)
104 IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
105 IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetContentsOpaque, OnSetContentsOpaque)
106 IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
107 IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock)
108 IPC_MESSAGE_HANDLER(BrowserPluginMsg_ShouldAcceptTouchEvents,
109 OnShouldAcceptTouchEvents)
110 IPC_MESSAGE_UNHANDLED(handled = false)
111 IPC_END_MESSAGE_MAP()
112 return handled;
113 }
114
UpdateDOMAttribute(const std::string & attribute_name,const std::string & attribute_value)115 void BrowserPlugin::UpdateDOMAttribute(const std::string& attribute_name,
116 const std::string& attribute_value) {
117 if (!container())
118 return;
119
120 blink::WebElement element = container()->element();
121 blink::WebString web_attribute_name =
122 blink::WebString::fromUTF8(attribute_name);
123 element.setAttribute(web_attribute_name,
124 blink::WebString::fromUTF8(attribute_value));
125 }
126
Attach()127 void BrowserPlugin::Attach() {
128 if (ready()) {
129 attached_ = false;
130 guest_crashed_ = false;
131 EnableCompositing(false);
132 if (compositing_helper_.get()) {
133 compositing_helper_->OnContainerDestroy();
134 compositing_helper_ = NULL;
135 }
136 }
137
138 // TODO(fsamuel): Add support for reattachment.
139 BrowserPluginHostMsg_Attach_Params attach_params;
140 attach_params.focused = ShouldGuestBeFocused();
141 attach_params.visible = visible_;
142 attach_params.origin = plugin_rect().origin();
143 gfx::Size view_size(width(), height());
144 if (!view_size.IsEmpty()) {
145 PopulateResizeGuestParameters(view_size,
146 &attach_params.resize_guest_params);
147 }
148 browser_plugin_manager()->Send(new BrowserPluginHostMsg_Attach(
149 render_view_routing_id_,
150 browser_plugin_instance_id_,
151 attach_params));
152
153 attach_pending_ = true;
154 }
155
DidCommitCompositorFrame()156 void BrowserPlugin::DidCommitCompositorFrame() {
157 if (compositing_helper_.get())
158 compositing_helper_->DidCommitCompositorFrame();
159 }
160
OnAdvanceFocus(int browser_plugin_instance_id,bool reverse)161 void BrowserPlugin::OnAdvanceFocus(int browser_plugin_instance_id,
162 bool reverse) {
163 DCHECK(render_view_);
164 render_view_->GetWebView()->advanceFocus(reverse);
165 }
166
OnAttachACK(int browser_plugin_instance_id)167 void BrowserPlugin::OnAttachACK(int browser_plugin_instance_id) {
168 DCHECK(!attached());
169 attached_ = true;
170 attach_pending_ = false;
171 }
172
OnCompositorFrameSwapped(const IPC::Message & message)173 void BrowserPlugin::OnCompositorFrameSwapped(const IPC::Message& message) {
174 BrowserPluginMsg_CompositorFrameSwapped::Param param;
175 if (!BrowserPluginMsg_CompositorFrameSwapped::Read(&message, ¶m))
176 return;
177
178 // Note that there is no need to send ACK for this message.
179 // If the guest has updated pixels then it is no longer crashed.
180 guest_crashed_ = false;
181
182 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
183 param.b.frame.AssignTo(frame.get());
184
185 EnableCompositing(true);
186 compositing_helper_->OnCompositorFrameSwapped(frame.Pass(),
187 param.b.producing_route_id,
188 param.b.output_surface_id,
189 param.b.producing_host_id,
190 param.b.shared_memory_handle);
191 }
192
OnCopyFromCompositingSurface(int browser_plugin_instance_id,int request_id,gfx::Rect source_rect,gfx::Size dest_size)193 void BrowserPlugin::OnCopyFromCompositingSurface(int browser_plugin_instance_id,
194 int request_id,
195 gfx::Rect source_rect,
196 gfx::Size dest_size) {
197 if (!compositing_helper_.get()) {
198 browser_plugin_manager()->Send(
199 new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck(
200 render_view_routing_id_,
201 browser_plugin_instance_id_,
202 request_id,
203 SkBitmap()));
204 return;
205 }
206 compositing_helper_->CopyFromCompositingSurface(request_id, source_rect,
207 dest_size);
208 }
209
OnGuestGone(int browser_plugin_instance_id)210 void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) {
211 guest_crashed_ = true;
212
213 // Turn off compositing so we can display the sad graphic. Changes to
214 // compositing state will show up at a later time after a layout and commit.
215 EnableCompositing(false);
216
217 // Queue up showing the sad graphic to give content embedders an opportunity
218 // to fire their listeners and potentially overlay the webview with custom
219 // behavior. If the BrowserPlugin is destroyed in the meantime, then the
220 // task will not be executed.
221 base::MessageLoop::current()->PostTask(
222 FROM_HERE,
223 base::Bind(&BrowserPlugin::ShowSadGraphic,
224 weak_ptr_factory_.GetWeakPtr()));
225 }
226
OnSetContentsOpaque(int browser_plugin_instance_id,bool opaque)227 void BrowserPlugin::OnSetContentsOpaque(int browser_plugin_instance_id,
228 bool opaque) {
229 if (contents_opaque_ == opaque)
230 return;
231 contents_opaque_ = opaque;
232 if (compositing_helper_.get())
233 compositing_helper_->SetContentsOpaque(opaque);
234 }
235
OnSetCursor(int browser_plugin_instance_id,const WebCursor & cursor)236 void BrowserPlugin::OnSetCursor(int browser_plugin_instance_id,
237 const WebCursor& cursor) {
238 cursor_ = cursor;
239 }
240
OnSetMouseLock(int browser_plugin_instance_id,bool enable)241 void BrowserPlugin::OnSetMouseLock(int browser_plugin_instance_id,
242 bool enable) {
243 if (enable) {
244 if (mouse_locked_)
245 return;
246 render_view_->mouse_lock_dispatcher()->LockMouse(this);
247 } else {
248 if (!mouse_locked_) {
249 OnLockMouseACK(false);
250 return;
251 }
252 render_view_->mouse_lock_dispatcher()->UnlockMouse(this);
253 }
254 }
255
OnShouldAcceptTouchEvents(int browser_plugin_instance_id,bool accept)256 void BrowserPlugin::OnShouldAcceptTouchEvents(int browser_plugin_instance_id,
257 bool accept) {
258 if (container()) {
259 container()->requestTouchEventType(
260 accept ? WebPluginContainer::TouchEventRequestTypeRaw
261 : WebPluginContainer::TouchEventRequestTypeNone);
262 }
263 }
264
ShowSadGraphic()265 void BrowserPlugin::ShowSadGraphic() {
266 // If the BrowserPlugin is scheduled to be deleted, then container_ will be
267 // NULL so we shouldn't attempt to access it.
268 if (container_)
269 container_->invalidate();
270 }
271
GetDeviceScaleFactor() const272 float BrowserPlugin::GetDeviceScaleFactor() const {
273 if (!render_view_)
274 return 1.0f;
275 return render_view_->GetWebView()->deviceScaleFactor();
276 }
277
UpdateDeviceScaleFactor()278 void BrowserPlugin::UpdateDeviceScaleFactor() {
279 if (last_device_scale_factor_ == GetDeviceScaleFactor())
280 return;
281
282 BrowserPluginHostMsg_ResizeGuest_Params params;
283 PopulateResizeGuestParameters(plugin_size(), ¶ms);
284 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
285 render_view_routing_id_,
286 browser_plugin_instance_id_,
287 params));
288 }
289
UpdateGuestFocusState()290 void BrowserPlugin::UpdateGuestFocusState() {
291 if (!ready())
292 return;
293 bool should_be_focused = ShouldGuestBeFocused();
294 browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetFocus(
295 render_view_routing_id_,
296 browser_plugin_instance_id_,
297 should_be_focused));
298 }
299
ShouldGuestBeFocused() const300 bool BrowserPlugin::ShouldGuestBeFocused() const {
301 bool embedder_focused = false;
302 if (render_view_)
303 embedder_focused = render_view_->has_focus();
304 return plugin_focused_ && embedder_focused;
305 }
306
container() const307 WebPluginContainer* BrowserPlugin::container() const {
308 return container_;
309 }
310
initialize(WebPluginContainer * container)311 bool BrowserPlugin::initialize(WebPluginContainer* container) {
312 if (!container)
313 return false;
314
315 container_ = container;
316 container_->setWantsWheelEvents(true);
317
318 g_plugin_container_map.Get().insert(std::make_pair(container_, this));
319
320 // This is a way to notify observers of our attributes that this plugin is
321 // available in render tree.
322 // TODO(lazyboy): This should be done through the delegate instead. Perhaps
323 // by firing an event from there.
324 UpdateDOMAttribute("internalinstanceid",
325 base::IntToString(browser_plugin_instance_id_));
326
327 browser_plugin_manager()->AddBrowserPlugin(browser_plugin_instance_id_, this);
328 return true;
329 }
330
EnableCompositing(bool enable)331 void BrowserPlugin::EnableCompositing(bool enable) {
332 bool enabled = !!compositing_helper_.get();
333 if (enabled == enable)
334 return;
335
336 if (enable) {
337 DCHECK(!compositing_helper_.get());
338 if (!compositing_helper_.get()) {
339 compositing_helper_ = ChildFrameCompositingHelper::CreateForBrowserPlugin(
340 weak_ptr_factory_.GetWeakPtr());
341 }
342 }
343 compositing_helper_->EnableCompositing(enable);
344 compositing_helper_->SetContentsOpaque(contents_opaque_);
345
346 if (!enable) {
347 DCHECK(compositing_helper_.get());
348 compositing_helper_->OnContainerDestroy();
349 compositing_helper_ = NULL;
350 }
351 }
352
destroy()353 void BrowserPlugin::destroy() {
354 if (container_) {
355 //container_->clearScriptObjects();
356
357 // The BrowserPlugin's WebPluginContainer is deleted immediately after this
358 // call returns, so let's not keep a reference to it around.
359 g_plugin_container_map.Get().erase(container_);
360 }
361
362 if (compositing_helper_.get())
363 compositing_helper_->OnContainerDestroy();
364 container_ = NULL;
365 // Will be a no-op if the mouse is not currently locked.
366 if (render_view_)
367 render_view_->mouse_lock_dispatcher()->OnLockTargetDestroyed(this);
368 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
369 }
370
supportsKeyboardFocus() const371 bool BrowserPlugin::supportsKeyboardFocus() const {
372 return true;
373 }
374
supportsEditCommands() const375 bool BrowserPlugin::supportsEditCommands() const {
376 return true;
377 }
378
supportsInputMethod() const379 bool BrowserPlugin::supportsInputMethod() const {
380 return true;
381 }
382
canProcessDrag() const383 bool BrowserPlugin::canProcessDrag() const {
384 return true;
385 }
386
paint(WebCanvas * canvas,const WebRect & rect)387 void BrowserPlugin::paint(WebCanvas* canvas, const WebRect& rect) {
388 if (guest_crashed_) {
389 if (!sad_guest_) // Lazily initialize bitmap.
390 sad_guest_ = content::GetContentClient()->renderer()->
391 GetSadWebViewBitmap();
392 // content_shell does not have the sad plugin bitmap, so we'll paint black
393 // instead to make it clear that something went wrong.
394 if (sad_guest_) {
395 PaintSadPlugin(canvas, plugin_rect_, *sad_guest_);
396 return;
397 }
398 }
399 SkAutoCanvasRestore auto_restore(canvas, true);
400 canvas->translate(plugin_rect_.x(), plugin_rect_.y());
401 SkRect image_data_rect = SkRect::MakeXYWH(
402 SkIntToScalar(0),
403 SkIntToScalar(0),
404 SkIntToScalar(plugin_rect_.width()),
405 SkIntToScalar(plugin_rect_.height()));
406 canvas->clipRect(image_data_rect);
407 // Paint black or white in case we have nothing in our backing store or we
408 // need to show a gutter.
409 SkPaint paint;
410 paint.setStyle(SkPaint::kFill_Style);
411 paint.setColor(guest_crashed_ ? SK_ColorBLACK : SK_ColorWHITE);
412 canvas->drawRect(image_data_rect, paint);
413 }
414
415 // static
ShouldForwardToBrowserPlugin(const IPC::Message & message)416 bool BrowserPlugin::ShouldForwardToBrowserPlugin(
417 const IPC::Message& message) {
418 switch (message.type()) {
419 case BrowserPluginMsg_Attach_ACK::ID:
420 case BrowserPluginMsg_AdvanceFocus::ID:
421 case BrowserPluginMsg_CompositorFrameSwapped::ID:
422 case BrowserPluginMsg_CopyFromCompositingSurface::ID:
423 case BrowserPluginMsg_GuestGone::ID:
424 case BrowserPluginMsg_SetContentsOpaque::ID:
425 case BrowserPluginMsg_SetCursor::ID:
426 case BrowserPluginMsg_SetMouseLock::ID:
427 case BrowserPluginMsg_ShouldAcceptTouchEvents::ID:
428 return true;
429 default:
430 break;
431 }
432 return false;
433 }
434
updateGeometry(const WebRect & window_rect,const WebRect & clip_rect,const WebVector<WebRect> & cut_outs_rects,bool is_visible)435 void BrowserPlugin::updateGeometry(
436 const WebRect& window_rect,
437 const WebRect& clip_rect,
438 const WebVector<WebRect>& cut_outs_rects,
439 bool is_visible) {
440 int old_width = width();
441 int old_height = height();
442 plugin_rect_ = window_rect;
443 if (!attached())
444 return;
445
446 if (old_width == window_rect.width && old_height == window_rect.height) {
447 // Let the browser know about the updated view rect.
448 browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateGeometry(
449 render_view_routing_id_, browser_plugin_instance_id_, plugin_rect_));
450 return;
451 }
452
453 BrowserPluginHostMsg_ResizeGuest_Params params;
454 PopulateResizeGuestParameters(plugin_size(), ¶ms);
455 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
456 render_view_routing_id_,
457 browser_plugin_instance_id_,
458 params));
459 }
460
PopulateResizeGuestParameters(const gfx::Size & view_size,BrowserPluginHostMsg_ResizeGuest_Params * params)461 void BrowserPlugin::PopulateResizeGuestParameters(
462 const gfx::Size& view_size,
463 BrowserPluginHostMsg_ResizeGuest_Params* params) {
464 params->view_size = view_size;
465 params->scale_factor = GetDeviceScaleFactor();
466 if (last_device_scale_factor_ != params->scale_factor) {
467 last_device_scale_factor_ = params->scale_factor;
468 params->repaint = true;
469 }
470 }
471
updateFocus(bool focused)472 void BrowserPlugin::updateFocus(bool focused) {
473 plugin_focused_ = focused;
474 UpdateGuestFocusState();
475 }
476
updateVisibility(bool visible)477 void BrowserPlugin::updateVisibility(bool visible) {
478 if (visible_ == visible)
479 return;
480
481 visible_ = visible;
482 if (!ready())
483 return;
484
485 if (compositing_helper_.get())
486 compositing_helper_->UpdateVisibility(visible);
487
488 browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetVisibility(
489 render_view_routing_id_,
490 browser_plugin_instance_id_,
491 visible));
492 }
493
acceptsInputEvents()494 bool BrowserPlugin::acceptsInputEvents() {
495 return true;
496 }
497
handleInputEvent(const blink::WebInputEvent & event,blink::WebCursorInfo & cursor_info)498 bool BrowserPlugin::handleInputEvent(const blink::WebInputEvent& event,
499 blink::WebCursorInfo& cursor_info) {
500 if (guest_crashed_ || !ready())
501 return false;
502
503 if (event.type == blink::WebInputEvent::ContextMenu)
504 return true;
505
506 if (blink::WebInputEvent::isKeyboardEventType(event.type) &&
507 !edit_commands_.empty()) {
508 browser_plugin_manager()->Send(
509 new BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent(
510 render_view_routing_id_,
511 browser_plugin_instance_id_,
512 edit_commands_));
513 edit_commands_.clear();
514 }
515
516 browser_plugin_manager()->Send(
517 new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_,
518 browser_plugin_instance_id_,
519 plugin_rect_,
520 &event));
521 GetWebKitCursorInfo(cursor_, &cursor_info);
522 return true;
523 }
524
handleDragStatusUpdate(blink::WebDragStatus drag_status,const blink::WebDragData & drag_data,blink::WebDragOperationsMask mask,const blink::WebPoint & position,const blink::WebPoint & screen)525 bool BrowserPlugin::handleDragStatusUpdate(blink::WebDragStatus drag_status,
526 const blink::WebDragData& drag_data,
527 blink::WebDragOperationsMask mask,
528 const blink::WebPoint& position,
529 const blink::WebPoint& screen) {
530 if (guest_crashed_ || !ready())
531 return false;
532 browser_plugin_manager()->Send(
533 new BrowserPluginHostMsg_DragStatusUpdate(
534 render_view_routing_id_,
535 browser_plugin_instance_id_,
536 drag_status,
537 DropDataBuilder::Build(drag_data),
538 mask,
539 position));
540 return true;
541 }
542
didReceiveResponse(const blink::WebURLResponse & response)543 void BrowserPlugin::didReceiveResponse(
544 const blink::WebURLResponse& response) {
545 }
546
didReceiveData(const char * data,int data_length)547 void BrowserPlugin::didReceiveData(const char* data, int data_length) {
548 if (delegate_)
549 delegate_->DidReceiveData(data, data_length);
550 }
551
didFinishLoading()552 void BrowserPlugin::didFinishLoading() {
553 if (delegate_)
554 delegate_->DidFinishLoading();
555 }
556
didFailLoading(const blink::WebURLError & error)557 void BrowserPlugin::didFailLoading(const blink::WebURLError& error) {
558 }
559
didFinishLoadingFrameRequest(const blink::WebURL & url,void * notify_data)560 void BrowserPlugin::didFinishLoadingFrameRequest(const blink::WebURL& url,
561 void* notify_data) {
562 }
563
didFailLoadingFrameRequest(const blink::WebURL & url,void * notify_data,const blink::WebURLError & error)564 void BrowserPlugin::didFailLoadingFrameRequest(
565 const blink::WebURL& url,
566 void* notify_data,
567 const blink::WebURLError& error) {
568 }
569
executeEditCommand(const blink::WebString & name)570 bool BrowserPlugin::executeEditCommand(const blink::WebString& name) {
571 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ExecuteEditCommand(
572 render_view_routing_id_,
573 browser_plugin_instance_id_,
574 name.utf8()));
575
576 // BrowserPlugin swallows edit commands.
577 return true;
578 }
579
executeEditCommand(const blink::WebString & name,const blink::WebString & value)580 bool BrowserPlugin::executeEditCommand(const blink::WebString& name,
581 const blink::WebString& value) {
582 edit_commands_.push_back(EditCommand(name.utf8(), value.utf8()));
583 // BrowserPlugin swallows edit commands.
584 return true;
585 }
586
setComposition(const blink::WebString & text,const blink::WebVector<blink::WebCompositionUnderline> & underlines,int selectionStart,int selectionEnd)587 bool BrowserPlugin::setComposition(
588 const blink::WebString& text,
589 const blink::WebVector<blink::WebCompositionUnderline>& underlines,
590 int selectionStart,
591 int selectionEnd) {
592 if (!ready())
593 return false;
594 std::vector<blink::WebCompositionUnderline> std_underlines;
595 for (size_t i = 0; i < underlines.size(); ++i) {
596 std_underlines.push_back(underlines[i]);
597 }
598 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeSetComposition(
599 render_view_routing_id_,
600 browser_plugin_instance_id_,
601 text.utf8(),
602 std_underlines,
603 selectionStart,
604 selectionEnd));
605 // TODO(kochi): This assumes the IPC handling always succeeds.
606 return true;
607 }
608
confirmComposition(const blink::WebString & text,blink::WebWidget::ConfirmCompositionBehavior selectionBehavior)609 bool BrowserPlugin::confirmComposition(
610 const blink::WebString& text,
611 blink::WebWidget::ConfirmCompositionBehavior selectionBehavior) {
612 if (!ready())
613 return false;
614 bool keep_selection = (selectionBehavior == blink::WebWidget::KeepSelection);
615 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeConfirmComposition(
616 render_view_routing_id_,
617 browser_plugin_instance_id_,
618 text.utf8(),
619 keep_selection));
620 // TODO(kochi): This assumes the IPC handling always succeeds.
621 return true;
622 }
623
extendSelectionAndDelete(int before,int after)624 void BrowserPlugin::extendSelectionAndDelete(int before, int after) {
625 if (!ready())
626 return;
627 browser_plugin_manager()->Send(
628 new BrowserPluginHostMsg_ExtendSelectionAndDelete(
629 render_view_routing_id_,
630 browser_plugin_instance_id_,
631 before,
632 after));
633 }
634
OnLockMouseACK(bool succeeded)635 void BrowserPlugin::OnLockMouseACK(bool succeeded) {
636 mouse_locked_ = succeeded;
637 browser_plugin_manager()->Send(new BrowserPluginHostMsg_LockMouse_ACK(
638 render_view_routing_id_,
639 browser_plugin_instance_id_,
640 succeeded));
641 }
642
OnMouseLockLost()643 void BrowserPlugin::OnMouseLockLost() {
644 mouse_locked_ = false;
645 browser_plugin_manager()->Send(new BrowserPluginHostMsg_UnlockMouse_ACK(
646 render_view_routing_id_,
647 browser_plugin_instance_id_));
648 }
649
HandleMouseLockedInputEvent(const blink::WebMouseEvent & event)650 bool BrowserPlugin::HandleMouseLockedInputEvent(
651 const blink::WebMouseEvent& event) {
652 browser_plugin_manager()->Send(
653 new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_,
654 browser_plugin_instance_id_,
655 plugin_rect_,
656 &event));
657 return true;
658 }
659
660 } // namespace content
661