blob: 19e2c163a59affb17a8bda65c951f909143c5219 [file] [log] [blame]
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/browser_plugin/browser_plugin.h"
#include <stddef.h>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/browser_plugin_delegate.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/child_frame_compositing_helper.h"
#include "content/renderer/cursor_utils.h"
#include "content/renderer/drop_data_builder.h"
#include "content/renderer/mash_util.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/sad_plugin.h"
#include "third_party/WebKit/public/platform/WebCoalescedInputEvent.h"
#include "third_party/WebKit/public/platform/WebGestureEvent.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/events/keycodes/keyboard_codes.h"
#if defined(USE_AURA)
#include "content/renderer/mus/mus_embedded_frame.h"
#include "content/renderer/mus/renderer_window_tree_client.h"
#endif
using blink::WebPluginContainer;
using blink::WebPoint;
using blink::WebRect;
using blink::WebURL;
using blink::WebVector;
namespace {
using PluginContainerMap =
std::map<blink::WebPluginContainer*, content::BrowserPlugin*>;
static base::LazyInstance<PluginContainerMap>::DestructorAtExit
g_plugin_container_map = LAZY_INSTANCE_INITIALIZER;
} // namespace
namespace content {
// static
BrowserPlugin* BrowserPlugin::GetFromNode(blink::WebNode& node) {
blink::WebPluginContainer* container = node.PluginContainer();
if (!container)
return nullptr;
PluginContainerMap* browser_plugins = g_plugin_container_map.Pointer();
PluginContainerMap::iterator it = browser_plugins->find(container);
return it == browser_plugins->end() ? nullptr : it->second;
}
BrowserPlugin::BrowserPlugin(
RenderFrame* render_frame,
const base::WeakPtr<BrowserPluginDelegate>& delegate)
: attached_(false),
render_frame_routing_id_(render_frame->GetRoutingID()),
container_(nullptr),
guest_crashed_(false),
plugin_focused_(false),
visible_(true),
mouse_locked_(false),
ready_(false),
browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
delegate_(delegate),
task_runner_(render_frame->GetTaskRunner(blink::TaskType::kUnthrottled)),
weak_ptr_factory_(this) {
browser_plugin_instance_id_ =
BrowserPluginManager::Get()->GetNextInstanceID();
if (delegate_)
delegate_->SetElementInstanceID(browser_plugin_instance_id_);
enable_surface_synchronization_ = features::IsSurfaceSynchronizationEnabled();
}
BrowserPlugin::~BrowserPlugin() {
Detach();
if (delegate_) {
delegate_->DidDestroyElement();
delegate_.reset();
}
BrowserPluginManager::Get()->RemoveBrowserPlugin(browser_plugin_instance_id_);
}
bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(BrowserPlugin, message)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus, OnAdvanceFocus)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestReady, OnGuestReady)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_ResizeDueToAutoResize,
OnResizeDueToAutoResize)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock)
#if defined(USE_AURA)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMusEmbedToken, OnSetMusEmbedToken)
#endif
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetTooltipText, OnSetTooltipText)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_ShouldAcceptTouchEvents,
OnShouldAcceptTouchEvents)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetChildFrameSurface,
OnSetChildFrameSurface)
IPC_END_MESSAGE_MAP()
return handled;
}
void BrowserPlugin::OnSetChildFrameSurface(
int browser_plugin_instance_id,
const viz::SurfaceInfo& surface_info,
const viz::SurfaceSequence& sequence) {
if (!attached() || switches::IsMusHostingViz())
return;
if (!enable_surface_synchronization_) {
compositing_helper_->SetPrimarySurfaceId(surface_info.id(),
frame_rect().size());
}
compositing_helper_->SetFallbackSurfaceId(surface_info.id(),
frame_rect().size(), sequence);
}
void BrowserPlugin::SendSatisfySequence(const viz::SurfaceSequence& sequence) {
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_SatisfySequence(
render_frame_routing_id_, browser_plugin_instance_id_, sequence));
}
void BrowserPlugin::UpdateDOMAttribute(const std::string& attribute_name,
const base::string16& attribute_value) {
if (!Container())
return;
blink::WebElement element = Container()->GetElement();
element.SetAttribute(blink::WebString::FromUTF8(attribute_name),
blink::WebString::FromUTF16(attribute_value));
}
void BrowserPlugin::Attach() {
Detach();
BrowserPluginHostMsg_Attach_Params attach_params;
attach_params.focused = ShouldGuestBeFocused();
attach_params.visible = visible_;
attach_params.frame_rect = frame_rect();
attach_params.is_full_page_plugin = false;
if (Container()) {
blink::WebLocalFrame* frame = Container()->GetDocument().GetFrame();
attach_params.is_full_page_plugin =
frame->View()->MainFrame()->IsWebLocalFrame() &&
frame->View()
->MainFrame()
->ToWebLocalFrame()
->GetDocument()
.IsPluginDocument();
}
#if defined(USE_AURA)
if (pending_embed_token_) {
base::Optional<base::UnguessableToken> embed_token =
std::move(pending_embed_token_);
CreateMusWindowAndEmbed(*embed_token);
}
#endif
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_Attach(
render_frame_routing_id_,
browser_plugin_instance_id_,
attach_params));
attached_ = true;
// Post an update event to the associated accessibility object.
auto* render_frame =
RenderFrameImpl::FromRoutingID(render_frame_routing_id());
if (render_frame && render_frame->render_accessibility() && Container()) {
blink::WebElement element = Container()->GetElement();
blink::WebAXObject ax_element = blink::WebAXObject::FromWebNode(element);
if (!ax_element.IsDetached()) {
render_frame->render_accessibility()->HandleAXEvent(
ax_element,
ui::AX_EVENT_CHILDREN_CHANGED);
}
}
sent_resize_params_ = base::nullopt;
WasResized();
}
void BrowserPlugin::Detach() {
if (!attached())
return;
attached_ = false;
guest_crashed_ = false;
compositing_helper_->OnContainerDestroy();
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_Detach(browser_plugin_instance_id_));
}
#if defined(USE_AURA)
void BrowserPlugin::CreateMusWindowAndEmbed(
const base::UnguessableToken& embed_token) {
RenderFrameImpl* render_frame =
RenderFrameImpl::FromRoutingID(render_frame_routing_id_);
if (!render_frame) {
pending_embed_token_ = embed_token;
return;
}
RendererWindowTreeClient* renderer_window_tree_client =
RendererWindowTreeClient::Get(
render_frame->GetRenderWidget()->routing_id());
DCHECK(renderer_window_tree_client);
mus_embedded_frame_ =
renderer_window_tree_client->CreateMusEmbeddedFrame(this, embed_token);
if (attached() && local_surface_id_.is_valid()) {
mus_embedded_frame_->SetWindowBounds(local_surface_id_,
FrameRectInPixels());
}
}
#endif
void BrowserPlugin::WasResized() {
bool size_changed = !sent_resize_params_ ||
sent_resize_params_->frame_rect.size() !=
pending_resize_params_.frame_rect.size() ||
sent_resize_params_->sequence_number !=
pending_resize_params_.sequence_number;
bool synchronized_params_changed =
!sent_resize_params_ || size_changed ||
sent_resize_params_->screen_info != pending_resize_params_.screen_info;
if (synchronized_params_changed)
local_surface_id_ = parent_local_surface_id_allocator_.GenerateId();
if (enable_surface_synchronization_ && frame_sink_id_.is_valid()) {
compositing_helper_->SetPrimarySurfaceId(
viz::SurfaceId(frame_sink_id_, local_surface_id_), frame_rect().size());
}
bool position_changed =
!sent_resize_params_ || sent_resize_params_->frame_rect.origin() !=
pending_resize_params_.frame_rect.origin();
bool resize_params_changed = synchronized_params_changed || position_changed;
if (resize_params_changed && attached()) {
// Let the browser know about the updated view rect.
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_UpdateResizeParams(
browser_plugin_instance_id_, frame_rect(), screen_info(),
auto_size_sequence_number(), local_surface_id_));
}
if (delegate_ && size_changed)
delegate_->DidResizeElement(frame_rect().size());
if (resize_params_changed && attached())
sent_resize_params_ = pending_resize_params_;
#if defined(USE_AURA)
if (IsRunningWithMus() && mus_embedded_frame_) {
mus_embedded_frame_->SetWindowBounds(local_surface_id_,
FrameRectInPixels());
}
#endif
}
void BrowserPlugin::OnAdvanceFocus(int browser_plugin_instance_id,
bool reverse) {
auto* render_frame =
RenderFrameImpl::FromRoutingID(render_frame_routing_id());
auto* render_view = render_frame ? render_frame->GetRenderView() : nullptr;
if (!render_view)
return;
render_view->GetWebView()->AdvanceFocus(reverse);
}
void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) {
guest_crashed_ = true;
compositing_helper_->ChildFrameGone();
}
void BrowserPlugin::OnGuestReady(int browser_plugin_instance_id,
const viz::FrameSinkId& frame_sink_id) {
guest_crashed_ = false;
frame_sink_id_ = frame_sink_id;
sent_resize_params_ = base::nullopt;
WasResized();
}
void BrowserPlugin::OnResizeDueToAutoResize(int browser_plugin_instance_id,
uint64_t sequence_number) {
pending_resize_params_.sequence_number = sequence_number;
WasResized();
}
void BrowserPlugin::OnSetCursor(int browser_plugin_instance_id,
const WebCursor& cursor) {
cursor_ = cursor;
}
void BrowserPlugin::OnSetMouseLock(int browser_plugin_instance_id,
bool enable) {
auto* render_frame =
RenderFrameImpl::FromRoutingID(render_frame_routing_id());
auto* render_view = static_cast<RenderViewImpl*>(
render_frame ? render_frame->GetRenderView() : nullptr);
if (enable) {
if (mouse_locked_ || !render_view)
return;
render_view->mouse_lock_dispatcher()->LockMouse(this);
} else {
if (!mouse_locked_) {
OnLockMouseACK(false);
return;
}
if (!render_view)
return;
render_view->mouse_lock_dispatcher()->UnlockMouse(this);
}
}
#if defined(USE_AURA)
void BrowserPlugin::OnSetMusEmbedToken(
int instance_id,
const base::UnguessableToken& embed_token) {
DCHECK(switches::IsMusHostingViz());
if (!attached_) {
pending_embed_token_ = embed_token;
} else {
pending_embed_token_.reset();
CreateMusWindowAndEmbed(embed_token);
}
}
#endif
void BrowserPlugin::OnSetTooltipText(int instance_id,
const base::string16& tooltip_text) {
// Show tooltip text by setting the BrowserPlugin's |title| attribute.
UpdateDOMAttribute("title", tooltip_text);
}
void BrowserPlugin::OnShouldAcceptTouchEvents(int browser_plugin_instance_id,
bool accept) {
if (Container()) {
Container()->RequestTouchEventType(
accept ? WebPluginContainer::kTouchEventRequestTypeRaw
: WebPluginContainer::kTouchEventRequestTypeNone);
}
}
gfx::Rect BrowserPlugin::FrameRectInPixels() const {
const float device_scale_factor = GetDeviceScaleFactor();
return gfx::Rect(
gfx::ScaleToFlooredPoint(frame_rect().origin(), device_scale_factor),
gfx::ScaleToCeiledSize(frame_rect().size(), device_scale_factor));
}
float BrowserPlugin::GetDeviceScaleFactor() const {
return embedding_render_widget_->GetOriginalDeviceScaleFactor();
}
void BrowserPlugin::UpdateInternalInstanceId() {
// This is a way to notify observers of our attributes that this plugin is
// available in render tree.
// TODO(lazyboy): This should be done through the delegate instead. Perhaps
// by firing an event from there.
UpdateDOMAttribute(
"internalinstanceid",
base::UTF8ToUTF16(base::IntToString(browser_plugin_instance_id_)));
}
void BrowserPlugin::UpdateGuestFocusState(blink::WebFocusType focus_type) {
if (!attached())
return;
bool should_be_focused = ShouldGuestBeFocused();
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_SetFocus(
browser_plugin_instance_id_,
should_be_focused,
focus_type));
}
void BrowserPlugin::ScreenInfoChanged(const ScreenInfo& screen_info) {
pending_resize_params_.screen_info = screen_info;
WasResized();
}
bool BrowserPlugin::ShouldGuestBeFocused() const {
bool embedder_focused = false;
auto* render_frame =
RenderFrameImpl::FromRoutingID(render_frame_routing_id());
auto* render_view = static_cast<RenderViewImpl*>(
render_frame ? render_frame->GetRenderView() : nullptr);
if (render_view)
embedder_focused = render_view->has_focus();
return plugin_focused_ && embedder_focused;
}
WebPluginContainer* BrowserPlugin::Container() const {
return container_;
}
bool BrowserPlugin::Initialize(WebPluginContainer* container) {
DCHECK(container);
DCHECK_EQ(this, container->Plugin());
container_ = container;
container_->SetWantsWheelEvents(true);
g_plugin_container_map.Get().insert(std::make_pair(container_, this));
BrowserPluginManager::Get()->AddBrowserPlugin(
browser_plugin_instance_id_, this);
// Defer attach call so that if there's any pending browser plugin
// destruction, then it can progress first.
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&BrowserPlugin::UpdateInternalInstanceId,
weak_ptr_factory_.GetWeakPtr()));
compositing_helper_.reset(ChildFrameCompositingHelper::CreateForBrowserPlugin(
weak_ptr_factory_.GetWeakPtr()));
embedding_render_widget_ =
RenderFrameImpl::FromWebFrame(container_->GetDocument().GetFrame())
->GetRenderWidget();
pending_resize_params_.screen_info = embedding_render_widget_->screen_info();
embedding_render_widget_->RegisterBrowserPlugin(this);
return true;
}
void BrowserPlugin::Destroy() {
if (embedding_render_widget_) {
embedding_render_widget_->UnregisterBrowserPlugin(this);
embedding_render_widget_ = nullptr;
}
if (container_) {
// The BrowserPlugin's WebPluginContainer is deleted immediately after this
// call returns, so let's not keep a reference to it around.
g_plugin_container_map.Get().erase(container_);
}
container_ = nullptr;
// Will be a no-op if the mouse is not currently locked.
auto* render_frame =
RenderFrameImpl::FromRoutingID(render_frame_routing_id());
auto* render_view = static_cast<RenderViewImpl*>(
render_frame ? render_frame->GetRenderView() : nullptr);
if (render_view)
render_view->mouse_lock_dispatcher()->OnLockTargetDestroyed(this);
task_runner_->DeleteSoon(FROM_HERE, this);
}
v8::Local<v8::Object> BrowserPlugin::V8ScriptableObject(v8::Isolate* isolate) {
if (!delegate_)
return v8::Local<v8::Object>();
return delegate_->V8ScriptableObject(isolate);
}
bool BrowserPlugin::SupportsKeyboardFocus() const {
return visible_;
}
bool BrowserPlugin::SupportsEditCommands() const {
return true;
}
bool BrowserPlugin::SupportsInputMethod() const {
return true;
}
bool BrowserPlugin::CanProcessDrag() const {
return true;
}
// static
bool BrowserPlugin::ShouldForwardToBrowserPlugin(
const IPC::Message& message) {
return IPC_MESSAGE_CLASS(message) == BrowserPluginMsgStart;
}
void BrowserPlugin::UpdateGeometry(const WebRect& plugin_rect_in_viewport,
const WebRect& clip_rect,
const WebRect& unobscured_rect,
bool is_visible) {
// Convert the plugin_rect_in_viewport to window coordinates, which is css.
WebRect rect_in_css(plugin_rect_in_viewport);
// We will use the local root's RenderWidget to convert coordinates to Window.
// If this local root belongs to an OOPIF, on the browser side we will have to
// consider the displacement of the child frame in root window.
embedding_render_widget_->ConvertViewportToWindow(&rect_in_css);
gfx::Rect frame_rect = rect_in_css;
if (!ready_) {
if (delegate_)
delegate_->Ready();
ready_ = true;
}
pending_resize_params_.frame_rect = frame_rect;
pending_resize_params_.screen_info = embedding_render_widget_->screen_info();
WasResized();
}
void BrowserPlugin::UpdateFocus(bool focused, blink::WebFocusType focus_type) {
plugin_focused_ = focused;
UpdateGuestFocusState(focus_type);
}
void BrowserPlugin::UpdateVisibility(bool visible) {
if (visible_ == visible)
return;
visible_ = visible;
if (!attached())
return;
compositing_helper_->UpdateVisibility(visible);
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_SetVisibility(
browser_plugin_instance_id_,
visible));
}
blink::WebInputEventResult BrowserPlugin::HandleInputEvent(
const blink::WebCoalescedInputEvent& coalesced_event,
blink::WebCursorInfo& cursor_info) {
const blink::WebInputEvent& event = coalesced_event.Event();
if (guest_crashed_ || !attached())
return blink::WebInputEventResult::kNotHandled;
DCHECK(!blink::WebInputEvent::IsTouchEventType(event.GetType()));
// With direct event routing turned on, BrowserPlugin should almost never
// see wheel events any more. The two exceptions are (1) scroll bubbling, and
// (2) synthetic mouse wheels generated by touchpad GesturePinch events on
// Mac, which always go to the mainframe and thus may hit BrowserPlugin if
// it's in a top-level embedder. In both cases we should indicate the event
// as not handled (for GesturePinch on Mac, indicating the event has been
// handled leads to touchpad pinch not working).
if (event.GetType() == blink::WebInputEvent::kMouseWheel)
return blink::WebInputEventResult::kNotHandled;
if (blink::WebInputEvent::IsGestureEventType(event.GetType())) {
auto gesture_event = static_cast<const blink::WebGestureEvent&>(event);
DCHECK(blink::WebInputEvent::kGestureTapDown == event.GetType() ||
gesture_event.resending_plugin_id == browser_plugin_instance_id_);
// We shouldn't be forwarding GestureEvents to the Guest anymore. Indicate
// we handled this only if it's a non-resent event.
return gesture_event.resending_plugin_id == browser_plugin_instance_id_
? blink::WebInputEventResult::kNotHandled
: blink::WebInputEventResult::kHandledApplication;
}
if (event.GetType() == blink::WebInputEvent::kContextMenu)
return blink::WebInputEventResult::kHandledSuppressed;
if (blink::WebInputEvent::IsKeyboardEventType(event.GetType()) &&
!edit_commands_.empty()) {
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent(
browser_plugin_instance_id_,
edit_commands_));
edit_commands_.clear();
}
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_HandleInputEvent(browser_plugin_instance_id_,
&event));
GetWebCursorInfo(cursor_, &cursor_info);
// Although we forward this event to the guest, we don't report it as consumed
// since other targets of this event in Blink never get that chance either.
if (event.GetType() == blink::WebInputEvent::kGestureFlingStart)
return blink::WebInputEventResult::kNotHandled;
return blink::WebInputEventResult::kHandledApplication;
}
bool BrowserPlugin::HandleDragStatusUpdate(blink::WebDragStatus drag_status,
const blink::WebDragData& drag_data,
blink::WebDragOperationsMask mask,
const blink::WebFloatPoint& position,
const blink::WebFloatPoint& screen) {
if (guest_crashed_ || !attached())
return false;
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_DragStatusUpdate(
browser_plugin_instance_id_,
drag_status,
DropDataBuilder::Build(drag_data),
mask,
position));
return true;
}
void BrowserPlugin::DidReceiveResponse(const blink::WebURLResponse& response) {}
void BrowserPlugin::DidReceiveData(const char* data, int data_length) {
if (delegate_)
delegate_->PluginDidReceiveData(data, data_length);
}
void BrowserPlugin::DidFinishLoading() {
if (delegate_)
delegate_->PluginDidFinishLoading();
}
void BrowserPlugin::DidFailLoading(const blink::WebURLError& error) {}
bool BrowserPlugin::ExecuteEditCommand(const blink::WebString& name) {
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_ExecuteEditCommand(
browser_plugin_instance_id_, name.Utf8()));
// BrowserPlugin swallows edit commands.
return true;
}
bool BrowserPlugin::ExecuteEditCommand(const blink::WebString& name,
const blink::WebString& value) {
edit_commands_.push_back(EditCommand(name.Utf8(), value.Utf8()));
// BrowserPlugin swallows edit commands.
return true;
}
bool BrowserPlugin::SetComposition(
const blink::WebString& text,
const blink::WebVector<blink::WebImeTextSpan>& ime_text_spans,
const blink::WebRange& replacementRange,
int selectionStart,
int selectionEnd) {
if (!attached())
return false;
BrowserPluginHostMsg_SetComposition_Params params;
params.text = text.Utf16();
for (size_t i = 0; i < ime_text_spans.size(); ++i) {
params.ime_text_spans.push_back(ime_text_spans[i]);
}
params.replacement_range =
replacementRange.IsNull()
? gfx::Range::InvalidRange()
: gfx::Range(static_cast<uint32_t>(replacementRange.StartOffset()),
static_cast<uint32_t>(replacementRange.EndOffset()));
params.selection_start = selectionStart;
params.selection_end = selectionEnd;
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_ImeSetComposition(
browser_plugin_instance_id_, params));
// TODO(kochi): This assumes the IPC handling always succeeds.
return true;
}
bool BrowserPlugin::CommitText(
const blink::WebString& text,
const blink::WebVector<blink::WebImeTextSpan>& ime_text_spans,
const blink::WebRange& replacementRange,
int relative_cursor_pos) {
if (!attached())
return false;
std::vector<blink::WebImeTextSpan> std_ime_text_spans;
for (size_t i = 0; i < ime_text_spans.size(); ++i) {
std_ime_text_spans.push_back(ime_text_spans[i]);
}
gfx::Range replacement_range =
replacementRange.IsNull()
? gfx::Range::InvalidRange()
: gfx::Range(static_cast<uint32_t>(replacementRange.StartOffset()),
static_cast<uint32_t>(replacementRange.EndOffset()));
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_ImeCommitText(
browser_plugin_instance_id_, text.Utf16(), std_ime_text_spans,
replacement_range, relative_cursor_pos));
// TODO(kochi): This assumes the IPC handling always succeeds.
return true;
}
bool BrowserPlugin::FinishComposingText(
blink::WebInputMethodController::ConfirmCompositionBehavior
selection_behavior) {
if (!attached())
return false;
bool keep_selection =
(selection_behavior == blink::WebInputMethodController::kKeepSelection);
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_ImeFinishComposingText(
browser_plugin_instance_id_, keep_selection));
// TODO(kochi): This assumes the IPC handling always succeeds.
return true;
}
void BrowserPlugin::ExtendSelectionAndDelete(int before, int after) {
if (!attached())
return;
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_ExtendSelectionAndDelete(
browser_plugin_instance_id_,
before,
after));
}
void BrowserPlugin::OnLockMouseACK(bool succeeded) {
mouse_locked_ = succeeded;
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_LockMouse_ACK(
browser_plugin_instance_id_,
succeeded));
}
void BrowserPlugin::OnMouseLockLost() {
mouse_locked_ = false;
BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_UnlockMouse_ACK(
browser_plugin_instance_id_));
}
bool BrowserPlugin::HandleMouseLockedInputEvent(
const blink::WebMouseEvent& event) {
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_HandleInputEvent(browser_plugin_instance_id_,
&event));
return true;
}
#if defined(USE_AURA)
void BrowserPlugin::OnMusEmbeddedFrameSurfaceChanged(
const viz::SurfaceInfo& surface_info) {
if (!attached_)
return;
compositing_helper_->SetFallbackSurfaceId(
surface_info.id(), frame_rect().size(), viz::SurfaceSequence());
}
void BrowserPlugin::OnMusEmbeddedFrameSinkIdAllocated(
const viz::FrameSinkId& frame_sink_id) {
// RendererWindowTreeClient should only call this when mus is hosting viz.
DCHECK(switches::IsMusHostingViz());
OnGuestReady(browser_plugin_instance_id_, frame_sink_id);
}
#endif
} // namespace content