Index: content/renderer/pepper_plugin_delegate_impl.cc |
diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc |
index 1bb13eefc8dfab4c78398712dc96c88470ec8bc1..999b1f53ef918505550060919e0097bfda2c3d33 100644 |
--- a/content/renderer/pepper_plugin_delegate_impl.cc |
+++ b/content/renderer/pepper_plugin_delegate_impl.cc |
@@ -52,8 +52,10 @@ |
#include "ppapi/proxy/host_dispatcher.h" |
#include "ppapi/proxy/ppapi_messages.h" |
#include "ppapi/shared_impl/ppapi_preferences.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserCompletion.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserParams.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
@@ -650,10 +652,15 @@ PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderView* render_view) |
has_saved_context_menu_action_(false), |
saved_context_menu_action_(0), |
id_generator_(0), |
- is_pepper_plugin_focused_(false) { |
+ is_pepper_plugin_focused_(false), |
+ mouse_lock_owner_(NULL), |
+ mouse_locked_(false), |
+ pending_lock_request_(false), |
+ pending_unlock_request_(false) { |
} |
PepperPluginDelegateImpl::~PepperPluginDelegateImpl() { |
+ DCHECK(!mouse_lock_owner_); |
} |
scoped_refptr<webkit::ppapi::PluginModule> |
@@ -837,6 +844,8 @@ void PepperPluginDelegateImpl::PluginCrashed( |
webkit::ppapi::PluginInstance* instance) { |
subscribed_to_policy_updates_.erase(instance); |
render_view_->PluginCrashed(instance->module()->path()); |
+ |
+ UnlockMouse(instance); |
} |
void PepperPluginDelegateImpl::InstanceCreated( |
@@ -851,6 +860,14 @@ void PepperPluginDelegateImpl::InstanceDeleted( |
webkit::ppapi::PluginInstance* instance) { |
active_instances_.erase(instance); |
subscribed_to_policy_updates_.erase(instance); |
+ |
+ if (mouse_lock_owner_ && mouse_lock_owner_ == instance) { |
+ // UnlockMouse() will determine whether a ViewHostMsg_UnlockMouse needs to |
+ // be sent, and set internal state properly. We only need to forget about |
+ // the current |mouse_lock_owner_|. |
+ UnlockMouse(mouse_lock_owner_); |
+ mouse_lock_owner_ = NULL; |
+ } |
} |
SkBitmap* PepperPluginDelegateImpl::GetSadPluginBitmap() { |
@@ -1011,7 +1028,7 @@ void PepperPluginDelegateImpl::OnAsyncFileOpened( |
void PepperPluginDelegateImpl::OnSetFocus(bool has_focus) { |
for (std::set<webkit::ppapi::PluginInstance*>::iterator i = |
- active_instances_.begin(); |
+ active_instances_.begin(); |
i != active_instances_.end(); ++i) |
(*i)->SetContentAreaFocus(has_focus); |
} |
@@ -1020,6 +1037,64 @@ bool PepperPluginDelegateImpl::IsPluginFocused() const { |
return is_pepper_plugin_focused_; |
} |
+void PepperPluginDelegateImpl::OnLockMouseACK(bool succeeded) { |
+ DCHECK(!mouse_locked_ && pending_lock_request_); |
+ |
+ mouse_locked_ = succeeded; |
+ pending_lock_request_ = false; |
+ if (pending_unlock_request_ && !succeeded) { |
+ // We have sent an unlock request after the lock request. However, since |
+ // the lock request has failed, the unlock request will be ignored by the |
+ // browser side and there won't be any response to it. |
+ pending_unlock_request_ = false; |
+ } |
+ // If the PluginInstance has been deleted, |mouse_lock_owner_| can be NULL. |
+ if (mouse_lock_owner_) { |
+ webkit::ppapi::PluginInstance* last_mouse_lock_owner = mouse_lock_owner_; |
+ if (!succeeded) { |
+ // Reset |mouse_lock_owner_| to NULL before calling OnLockMouseACK(), so |
+ // that if OnLockMouseACK() results in calls to any mouse lock method |
+ // (e.g., LockMouse()), the method will see consistent internal state. |
+ mouse_lock_owner_ = NULL; |
+ } |
+ |
+ last_mouse_lock_owner->OnLockMouseACK(succeeded ? PP_OK : PP_ERROR_FAILED); |
+ } |
+} |
+ |
+void PepperPluginDelegateImpl::OnMouseLockLost() { |
+ DCHECK(mouse_locked_ && !pending_lock_request_); |
+ |
+ mouse_locked_ = false; |
+ pending_unlock_request_ = false; |
+ // If the PluginInstance has been deleted, |mouse_lock_owner_| can be NULL. |
+ if (mouse_lock_owner_) { |
+ // Reset |mouse_lock_owner_| to NULL before calling OnMouseLockLost(), so |
+ // that if OnMouseLockLost() results in calls to any mouse lock method |
+ // (e.g., LockMouse()), the method will see consistent internal state. |
+ webkit::ppapi::PluginInstance* last_mouse_lock_owner = mouse_lock_owner_; |
+ mouse_lock_owner_ = NULL; |
+ |
+ last_mouse_lock_owner->OnMouseLockLost(); |
+ } |
+} |
+ |
+bool PepperPluginDelegateImpl::DispatchLockedMouseEvent( |
+ const WebKit::WebMouseEvent& event) { |
+ if (mouse_locked_) { |
+ if (mouse_lock_owner_) { |
+ // |cursor_info| is ignored since it is hidden when the mouse is locked. |
+ WebKit::WebCursorInfo cursor_info; |
+ mouse_lock_owner_->HandleInputEvent(event, &cursor_info); |
+ } |
+ |
+ // If the mouse is locked, only the current owner of the mouse lock can |
+ // process mouse events. |
+ return true; |
+ } |
+ return false; |
+} |
+ |
bool PepperPluginDelegateImpl::OpenFileSystem( |
const GURL& url, |
fileapi::FileSystemType type, |
@@ -1474,6 +1549,58 @@ ppapi::Preferences PepperPluginDelegateImpl::GetPreferences() { |
return ppapi::Preferences(render_view_->webkit_preferences()); |
} |
+void PepperPluginDelegateImpl::LockMouse( |
+ webkit::ppapi::PluginInstance* instance) { |
+ DCHECK(instance); |
+ if (!MouseLockedOrPending()) { |
+ DCHECK(!mouse_lock_owner_); |
+ pending_lock_request_ = true; |
+ mouse_lock_owner_ = instance; |
+ |
+ render_view_->Send( |
+ new ViewHostMsg_LockMouse(render_view_->routing_id())); |
+ } else if (instance != mouse_lock_owner_) { |
+ // Another plugin instance is using mouse lock. Fail immediately. |
+ instance->OnLockMouseACK(PP_ERROR_FAILED); |
+ } else { |
+ if (mouse_locked_) { |
+ instance->OnLockMouseACK(PP_OK); |
+ } else if (pending_lock_request_) { |
+ instance->OnLockMouseACK(PP_ERROR_INPROGRESS); |
+ } else { |
+ // The only case left here is |
+ // !mouse_locked_ && !pending_lock_request_ && pending_unlock_request_, |
+ // which is not possible. |
+ NOTREACHED(); |
+ instance->OnLockMouseACK(PP_ERROR_FAILED); |
+ } |
+ } |
+} |
+ |
+void PepperPluginDelegateImpl::UnlockMouse( |
+ webkit::ppapi::PluginInstance* instance) { |
+ DCHECK(instance); |
+ |
+ // If no one is using mouse lock or the user is not |instance|, ignore |
+ // the unlock request. |
+ if (MouseLockedOrPending() && mouse_lock_owner_ == instance) { |
+ if (mouse_locked_ || pending_lock_request_) { |
+ DCHECK(!mouse_locked_ || !pending_lock_request_); |
+ if (!pending_unlock_request_) { |
+ pending_unlock_request_ = true; |
+ |
+ render_view_->Send( |
+ new ViewHostMsg_UnlockMouse(render_view_->routing_id())); |
+ } |
+ } else { |
+ // The only case left here is |
+ // !mouse_locked_ && !pending_lock_request_ && pending_unlock_request_, |
+ // which is not possible. |
+ NOTREACHED(); |
+ } |
+ } |
+} |
+ |
int PepperPluginDelegateImpl::GetRoutingId() const { |
return render_view_->routing_id(); |
} |