diff options
author | jdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-07 21:24:08 +0000 |
---|---|---|
committer | jdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-07 21:24:08 +0000 |
commit | b025568b97cd2c3f0e47ef456f463cd1fcdb0a0f (patch) | |
tree | f00e60e285595b3cbcefca94fb17d39ffefa3263 | |
parent | 9c34c413c27316bf196bf3d430b99722ea21755a (diff) | |
download | chromium_src-b025568b97cd2c3f0e47ef456f463cd1fcdb0a0f.zip chromium_src-b025568b97cd2c3f0e47ef456f463cd1fcdb0a0f.tar.gz chromium_src-b025568b97cd2c3f0e47ef456f463cd1fcdb0a0f.tar.bz2 |
Fix WebView compositor input handling
Recent changes to compositor input handling deprecated existing hooks for
Android WebView. This patch addresses these changes, allowing the browser
to perform synchronous, in-process input event handling when the UI and
compositor threads are merged. In particular, an InputHandlerManagerClient
allows the embedder to customize delivery of and response to InputEvents.
BUG=241641
Review URL: https://chromiumcodereview.appspot.com/15920002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@204933 0039d316-1c4b-4281-b951-d872f2087c98
22 files changed, 272 insertions, 166 deletions
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc index 9093c2b..846fa91 100644 --- a/content/browser/android/content_view_core_impl.cc +++ b/content/browser/android/content_view_core_impl.cc @@ -17,7 +17,6 @@ #include "content/browser/android/interstitial_page_delegate_android.h" #include "content/browser/android/load_url_params.h" #include "content/browser/android/media_player_manager_impl.h" -#include "content/browser/android/sync_input_event_filter.h" #include "content/browser/android/touch_point.h" #include "content/browser/renderer_host/compositor_impl_android.h" #include "content/browser/renderer_host/java/java_bound_object.h" @@ -688,14 +687,6 @@ float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const { / GetDpiScale(); } -InputEventAckState ContentViewCoreImpl::FilterInputEvent( - const WebKit::WebInputEvent& input_event) { - if (!input_event_filter_) - return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; - - return input_event_filter_->HandleInputEvent(input_event); -} - void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) { root_layer_->AddChild(layer); } diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h index c1e5c21..4581e69 100644 --- a/content/browser/android/content_view_core_impl.h +++ b/content/browser/android/content_view_core_impl.h @@ -33,7 +33,6 @@ class WindowAndroid; namespace content { class RenderWidgetHostViewAndroid; -class SyncInputEventFilter; // TODO(jrg): this is a shell. Upstream the rest. class ContentViewCoreImpl : public ContentViewCore, @@ -296,8 +295,6 @@ class ContentViewCoreImpl : public ContentViewCore, gfx::Size GetViewportSizeOffsetDip() const; float GetOverdrawBottomHeightDip() const; - InputEventAckState FilterInputEvent(const WebKit::WebInputEvent& input_event); - void AttachLayer(scoped_refptr<cc::Layer> layer); void RemoveLayer(scoped_refptr<cc::Layer> layer); void SetVSyncNotificationEnabled(bool enabled); @@ -361,9 +358,6 @@ class ContentViewCoreImpl : public ContentViewCore, std::vector<UpdateFrameInfoCallback> update_frame_info_callbacks_; - // Optional browser-side input event filtering. - scoped_ptr<SyncInputEventFilter> input_event_filter_; - DISALLOW_COPY_AND_ASSIGN(ContentViewCoreImpl); }; diff --git a/content/browser/android/in_process/DEPS b/content/browser/android/in_process/DEPS index 98af01f..a8ba3f4 100644 --- a/content/browser/android/in_process/DEPS +++ b/content/browser/android/in_process/DEPS @@ -1,6 +1,6 @@ include_rules = [ # Required for SynchronousCompositor (in --single-process mode only). "+content/public/renderer/android", - "+content/renderer/android", + "+content/renderer", # Include joth@chromium.org on the review for any additions to this file. ] diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc index 4b70c9b..ea72bc7 100644 --- a/content/browser/android/in_process/synchronous_compositor_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_impl.cc @@ -6,6 +6,7 @@ #include "base/lazy_instance.h" #include "base/message_loop.h" +#include "content/browser/android/in_process/synchronous_input_event_filter.h" #include "content/public/browser/android/synchronous_compositor_client.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" @@ -49,6 +50,17 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { new SynchronousCompositorOutputSurface(routing_id)); return output_surface.PassAs<cc::OutputSurface>(); } + + virtual InputHandlerManagerClient* GetInputHandlerManagerClient() OVERRIDE { + return synchronous_input_event_filter(); + } + + SynchronousInputEventFilter* synchronous_input_event_filter() { + return &synchronous_input_event_filter_; + } + + private: + SynchronousInputEventFilter synchronous_input_event_filter_; }; base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = @@ -59,10 +71,11 @@ base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl); // static -SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID( - int routing_id) { - RenderViewHost* rvh = RenderViewHost::FromID(GetInProcessRendererId(), - routing_id); +SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id, + int routing_id) { + if (g_factory == NULL) + return NULL; + RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_id); if (!rvh) return NULL; WebContents* contents = WebContents::FromRenderViewHost(rvh); @@ -71,6 +84,11 @@ SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID( return FromWebContents(contents); } +SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID( + int routing_id) { + return FromID(GetInProcessRendererId(), routing_id); +} + SynchronousCompositorImpl::SynchronousCompositorImpl(WebContents* contents) : compositor_client_(NULL), output_surface_(NULL), @@ -139,6 +157,13 @@ void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) { compositor_client_->SetContinuousInvalidate(enable); } +InputEventAckState SynchronousCompositorImpl::HandleInputEvent( + const WebKit::WebInputEvent& input_event) { + DCHECK(CalledOnValidThread()); + return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent( + routing_id_, input_event); +} + // Not using base::NonThreadSafe as we want to enforce a more exacting threading // requirement: SynchronousCompositorImpl() must only be used on the UI thread. bool SynchronousCompositorImpl::CalledOnValidThread() const { diff --git a/content/browser/android/in_process/synchronous_compositor_impl.h b/content/browser/android/in_process/synchronous_compositor_impl.h index 3659ca0..c6aced8 100644 --- a/content/browser/android/in_process/synchronous_compositor_impl.h +++ b/content/browser/android/in_process/synchronous_compositor_impl.h @@ -9,9 +9,14 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "content/browser/android/in_process/synchronous_compositor_output_surface.h" +#include "content/port/common/input_event_ack_state.h" #include "content/public/browser/android/synchronous_compositor.h" #include "content/public/browser/web_contents_user_data.h" +namespace WebKit { +class WebInputEvent; +} + namespace content { // The purpose of this class is to act as the intermediary between the various @@ -24,8 +29,14 @@ class SynchronousCompositorImpl public SynchronousCompositorOutputSurfaceDelegate, public WebContentsUserData<SynchronousCompositorImpl> { public: + // When used from browser code, use both |process_id| and |routing_id|. + static SynchronousCompositorImpl* FromID(int process_id, int routing_id); + // When handling upcalls from renderer code, use this version; the process id + // is implicitly that of the in-process renderer. static SynchronousCompositorImpl* FromRoutingID(int routing_id); + InputEventAckState HandleInputEvent(const WebKit::WebInputEvent& input_event); + // SynchronousCompositor virtual bool IsHwReady() OVERRIDE; virtual void SetClient(SynchronousCompositorClient* compositor_client) diff --git a/content/browser/android/in_process/synchronous_input_event_filter.cc b/content/browser/android/in_process/synchronous_input_event_filter.cc new file mode 100644 index 0000000..3e0c09a --- /dev/null +++ b/content/browser/android/in_process/synchronous_input_event_filter.cc @@ -0,0 +1,44 @@ +// Copyright 2013 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/browser/android/in_process/synchronous_input_event_filter.h" + +#include "content/public/browser/browser_thread.h" + +using WebKit::WebInputEvent; + +namespace content { + +SynchronousInputEventFilter::SynchronousInputEventFilter() { +} + +SynchronousInputEventFilter::~SynchronousInputEventFilter() { +} + +InputEventAckState SynchronousInputEventFilter::HandleInputEvent( + int routing_id, + const WebKit::WebInputEvent& input_event) { + // The handler will be empty both before renderer initialization and after + // renderer destruction. It's possible that this will be reached in such a + // state. While not good, it should also not be fatal. + if (handler_.is_null()) + return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; + + return handler_.Run(routing_id, &input_event); +} + +void SynchronousInputEventFilter::SetBoundHandler(const Handler& handler) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&SynchronousInputEventFilter::SetBoundHandlerOnUIThread, + base::Unretained(this), handler)); +} + +void SynchronousInputEventFilter::SetBoundHandlerOnUIThread( + const Handler& handler) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + handler_ = handler; +} + +} // namespace content diff --git a/content/browser/android/in_process/synchronous_input_event_filter.h b/content/browser/android/in_process/synchronous_input_event_filter.h new file mode 100644 index 0000000..75b5be1 --- /dev/null +++ b/content/browser/android/in_process/synchronous_input_event_filter.h @@ -0,0 +1,46 @@ +// Copyright 2013 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. + +#ifndef CONTENT_BROWSER_ANDOIRD_IN_PROCESS_SYNCHRONOUS_INPUT_EVENT_FILTER_H_ +#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_INPUT_EVENT_FILTER_H_ + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "content/port/common/input_event_ack_state.h" +#include "content/renderer/gpu/input_handler_manager_client.h" + +namespace WebKit { +class WebInputEvent; +} + +namespace content { + +// This class perform synchronous, in-process InputEvent handling. +// +// The provided |handler| process WebInputEvents synchronously on the merged +// UI and compositing thread. If the event goes unhandled, that is reflected in +// the InputEventAckState; no forwarding is performed. +class SynchronousInputEventFilter : public InputHandlerManagerClient { + public: + SynchronousInputEventFilter(); + virtual ~SynchronousInputEventFilter(); + + InputEventAckState HandleInputEvent(int routing_id, + const WebKit::WebInputEvent& input_event); + + // InputHandlerManagerClient implementation. + virtual void SetBoundHandler(const Handler& handler) OVERRIDE; + virtual void DidAddInputHandler(int routing_id) OVERRIDE {} + virtual void DidRemoveInputHandler(int routing_id) OVERRIDE {} + + private: + void SetBoundHandlerOnUIThread(const Handler& handler); + + Handler handler_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_INPUT_EVENT_FILTER_H_ diff --git a/content/browser/android/sync_input_event_filter.cc b/content/browser/android/sync_input_event_filter.cc deleted file mode 100644 index fb252c36..0000000 --- a/content/browser/android/sync_input_event_filter.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2013 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 "base/debug/trace_event.h" -#include "content/browser/android/sync_input_event_filter.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" - -using WebKit::WebInputEvent; - -namespace content { - -//------------------------------------------------------------------------------ - -SyncInputEventFilter::SyncInputEventFilter() { -} - -SyncInputEventFilter::~SyncInputEventFilter() { - DCHECK(thread_checker_.CalledOnValidThread()); -} - -InputEventAckState SyncInputEventFilter::HandleInputEvent( - const WebInputEvent& event) { - return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; -} - -void SyncInputEventFilter::ClearInputHandler() { - DCHECK(thread_checker_.CalledOnValidThread()); -} - -} // namespace content diff --git a/content/browser/android/sync_input_event_filter.h b/content/browser/android/sync_input_event_filter.h deleted file mode 100644 index e2ce90b..0000000 --- a/content/browser/android/sync_input_event_filter.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2013 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. - -#ifndef CONTENT_BROWSER_ANDROID_SYNC_INPUT_EVENT_FILTER_H_ -#define CONTENT_BROWSER_ANDROID_SYNC_INPUT_EVENT_FILTER_H_ - -#include "base/memory/scoped_ptr.h" -#include "base/threading/thread_checker.h" -#include "content/port/common/input_event_ack_state.h" - -namespace WebKit { -class WebInputEvent; -} - -namespace content { - -// Performs synchronous event filtering, to be used for browser-side, -// in-process event handling when the UI and compositor share threads. -// The filter is associated with at most one view, and one event handler. -class SyncInputEventFilter { - public: - - SyncInputEventFilter(); - ~SyncInputEventFilter(); - - InputEventAckState HandleInputEvent(const WebKit::WebInputEvent& input_event); - void ClearInputHandler(); - - private: - // Used to DCHECK that input_handler_ changes are made on the correct thread. - base::ThreadChecker thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(SyncInputEventFilter); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_ANDROID_SYNC_INPUT_EVENT_FILTER_H_ diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 408f753..88b4acf 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -19,6 +19,7 @@ #include "cc/output/compositor_frame.h" #include "cc/output/compositor_frame_ack.h" #include "content/browser/android/content_view_core_impl.h" +#include "content/browser/android/in_process/synchronous_compositor_impl.h" #include "content/browser/android/overscroll_glow.h" #include "content/browser/gpu/gpu_surface_tracker.h" #include "content/browser/renderer_host/compositor_impl_android.h" @@ -829,10 +830,14 @@ void RenderWidgetHostViewAndroid::UnhandledWheelEvent( InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent( const WebKit::WebInputEvent& input_event) { - if (!content_view_core_) - return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; - - return content_view_core_->FilterInputEvent(input_event); + if (host_) { + SynchronousCompositorImpl* compositor = + SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(), + host_->GetRoutingID()); + if (compositor) + return compositor->HandleInputEvent(input_event); + } + return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; } void RenderWidgetHostViewAndroid::OnAccessibilityNotifications( diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 41dc8d1..7f8c4c5 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -251,6 +251,8 @@ 'browser/android/in_process/synchronous_compositor_impl.h', 'browser/android/in_process/synchronous_compositor_output_surface.cc', 'browser/android/in_process/synchronous_compositor_output_surface.h', + 'browser/android/in_process/synchronous_input_event_filter.cc', + 'browser/android/in_process/synchronous_input_event_filter.h', 'browser/android/interstitial_page_delegate_android.cc', 'browser/android/interstitial_page_delegate_android.h', 'browser/android/load_url_params.cc', @@ -263,8 +265,6 @@ 'browser/android/overscroll_glow.cc', 'browser/android/surface_texture_peer_browser_impl.cc', 'browser/android/surface_texture_peer_browser_impl.h', - 'browser/android/sync_input_event_filter.h', - 'browser/android/sync_input_event_filter.cc', 'browser/android/touch_point.cc', 'browser/android/touch_point.h', 'browser/android/tracing_intent_handler.cc', diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index aca8515..07f946f 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -111,6 +111,7 @@ 'renderer/gpu/input_handler_proxy.h', 'renderer/gpu/input_handler_manager.cc', 'renderer/gpu/input_handler_manager.h', + 'renderer/gpu/input_handler_manager_client.h', 'renderer/gpu/input_handler_wrapper.cc', 'renderer/gpu/input_handler_wrapper.h', 'renderer/gpu/gpu_benchmarking_extension.cc', diff --git a/content/renderer/android/synchronous_compositor_factory.h b/content/renderer/android/synchronous_compositor_factory.h index 9c8fdce..06e7c36 100644 --- a/content/renderer/android/synchronous_compositor_factory.h +++ b/content/renderer/android/synchronous_compositor_factory.h @@ -18,6 +18,8 @@ class OutputSurface; namespace content { +class InputHandlerManagerClient; + // Decouples creation from usage of the parts needed for the synchonous // compositor rendering path. In practice this is only used in single // process mode (namely, for Android WebView) hence the implementation of @@ -34,6 +36,9 @@ class SynchronousCompositorFactory { virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface( int routing_id) = 0; + // The factory maintains ownership of the returned interface. + virtual InputHandlerManagerClient* GetInputHandlerManagerClient() = 0; + protected: SynchronousCompositorFactory() {} ~SynchronousCompositorFactory() {} diff --git a/content/renderer/gpu/input_event_filter.cc b/content/renderer/gpu/input_event_filter.cc index 9085c156..4032e8f 100644 --- a/content/renderer/gpu/input_event_filter.cc +++ b/content/renderer/gpu/input_event_filter.cc @@ -15,23 +15,25 @@ namespace content { InputEventFilter::InputEventFilter( IPC::Listener* main_listener, - const scoped_refptr<base::MessageLoopProxy>& target_loop, - const Handler& handler) + const scoped_refptr<base::MessageLoopProxy>& target_loop) : main_loop_(base::MessageLoopProxy::current()), main_listener_(main_listener), sender_(NULL), - target_loop_(target_loop), - handler_(handler) { - DCHECK(target_loop_.get()); - DCHECK(!handler_.is_null()); + target_loop_(target_loop) { + DCHECK(target_loop_); +} + +void InputEventFilter::SetBoundHandler(const Handler& handler) { + DCHECK(main_loop_->BelongsToCurrentThread()); + handler_ = handler; } -void InputEventFilter::AddRoute(int routing_id) { +void InputEventFilter::DidAddInputHandler(int routing_id) { base::AutoLock locked(routes_lock_); routes_.insert(routing_id); } -void InputEventFilter::RemoveRoute(int routing_id) { +void InputEventFilter::DidRemoveInputHandler(int routing_id) { base::AutoLock locked(routes_lock_); routes_.erase(routing_id); } @@ -93,6 +95,7 @@ void InputEventFilter::ForwardToMainListener(const IPC::Message& message) { } void InputEventFilter::ForwardToHandler(const IPC::Message& message) { + DCHECK(!handler_.is_null()); DCHECK(target_loop_->BelongsToCurrentThread()); if (message.type() != InputMsg_HandleInputEvent::ID) { diff --git a/content/renderer/gpu/input_event_filter.h b/content/renderer/gpu/input_event_filter.h index 693aefa..499003c 100644 --- a/content/renderer/gpu/input_event_filter.h +++ b/content/renderer/gpu/input_event_filter.h @@ -12,6 +12,7 @@ #include "base/synchronization/lock.h" #include "content/common/content_export.h" #include "content/port/common/input_event_ack_state.h" +#include "content/renderer/gpu/input_handler_manager_client.h" #include "ipc/ipc_channel_proxy.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" @@ -26,11 +27,11 @@ namespace content { class CONTENT_EXPORT InputEventFilter - : public IPC::ChannelProxy::MessageFilter { + : public InputHandlerManagerClient, + public IPC::ChannelProxy::MessageFilter { public: - typedef base::Callback<InputEventAckState( - int /*routing_id*/, - const WebKit::WebInputEvent*)> Handler; + InputEventFilter(IPC::Listener* main_listener, + const scoped_refptr<base::MessageLoopProxy>& target_loop); // The |handler| is invoked on the thread associated with |target_loop| to // handle input events matching the filtered routes. @@ -42,13 +43,9 @@ class CONTENT_EXPORT InputEventFilter // is left to the eventual handler to deliver the corresponding // InputHostMsg_HandleInputEvent_ACK. // - InputEventFilter(IPC::Listener* main_listener, - const scoped_refptr<base::MessageLoopProxy>& target_loop, - const Handler& handler); - - // Define the message routes to be filtered. - void AddRoute(int routing_id); - void RemoveRoute(int routing_id); + virtual void SetBoundHandler(const Handler& handler) OVERRIDE; + virtual void DidAddInputHandler(int routing_id) OVERRIDE; + virtual void DidRemoveInputHandler(int routing_id) OVERRIDE; // IPC::ChannelProxy::MessageFilter methods: virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE; diff --git a/content/renderer/gpu/input_event_filter_unittest.cc b/content/renderer/gpu/input_event_filter_unittest.cc index 7fbeafe..8f48f12 100644 --- a/content/renderer/gpu/input_event_filter_unittest.cc +++ b/content/renderer/gpu/input_event_filter_unittest.cc @@ -135,9 +135,11 @@ class InputEventFilterTest : public testing::Test { virtual void SetUp() OVERRIDE { filter_ = new InputEventFilter( &message_recorder_, - message_loop_.message_loop_proxy(), + message_loop_.message_loop_proxy()); + filter_->SetBoundHandler( base::Bind(&InputEventRecorder::HandleInputEvent, base::Unretained(&event_recorder_))); + event_recorder_.set_filter(filter_.get()); filter_->OnFilterAdded(&ipc_sink_); @@ -170,7 +172,7 @@ TEST_F(InputEventFilterTest, Basic) { EXPECT_EQ(0U, event_recorder_.record_count()); EXPECT_EQ(0U, message_recorder_.message_count()); - filter_->AddRoute(kTestRoutingID); + filter_->DidAddInputHandler(kTestRoutingID); AddEventsToFilter(filter_.get(), kEvents, arraysize(kEvents)); ASSERT_EQ(arraysize(kEvents), ipc_sink_.message_count()); @@ -245,7 +247,7 @@ TEST_F(InputEventFilterTest, Basic) { } TEST_F(InputEventFilterTest, PreserveRelativeOrder) { - filter_->AddRoute(kTestRoutingID); + filter_->DidAddInputHandler(kTestRoutingID); event_recorder_.set_send_to_widget(true); diff --git a/content/renderer/gpu/input_handler_manager.cc b/content/renderer/gpu/input_handler_manager.cc index 15c49cc..61617a9 100644 --- a/content/renderer/gpu/input_handler_manager.cc +++ b/content/renderer/gpu/input_handler_manager.cc @@ -8,8 +8,8 @@ #include "base/debug/trace_event.h" #include "cc/input/input_handler.h" #include "content/renderer/gpu/input_event_filter.h" +#include "content/renderer/gpu/input_handler_manager_client.h" #include "content/renderer/gpu/input_handler_wrapper.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebActiveWheelFlingParameters.h" using WebKit::WebInputEvent; @@ -34,38 +34,38 @@ InputEventAckState InputEventDispositionToAck( } // namespace InputHandlerManager::InputHandlerManager( - IPC::Listener* main_listener, - const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy) - : message_loop_proxy_(message_loop_proxy) { - filter_ = - new InputEventFilter(main_listener, - message_loop_proxy, - base::Bind(&InputHandlerManager::HandleInputEvent, + const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy, + InputHandlerManagerClient* client) + : message_loop_proxy_(message_loop_proxy), + client_(client) { + DCHECK(client_); + client_->SetBoundHandler(base::Bind(&InputHandlerManager::HandleInputEvent, base::Unretained(this))); } InputHandlerManager::~InputHandlerManager() { -} - -IPC::ChannelProxy::MessageFilter* -InputHandlerManager::GetMessageFilter() const { - return filter_.get(); + client_->SetBoundHandler(InputHandlerManagerClient::Handler()); } void InputHandlerManager::AddInputHandler( int routing_id, const base::WeakPtr<cc::InputHandler>& input_handler, const base::WeakPtr<RenderViewImpl>& render_view_impl) { - DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); - - message_loop_proxy_->PostTask( - FROM_HERE, - base::Bind(&InputHandlerManager::AddInputHandlerOnCompositorThread, - base::Unretained(this), - routing_id, - base::MessageLoopProxy::current(), - input_handler, - render_view_impl)); + if (message_loop_proxy_->BelongsToCurrentThread()) { + AddInputHandlerOnCompositorThread(routing_id, + base::MessageLoopProxy::current(), + input_handler, + render_view_impl); + } else { + message_loop_proxy_->PostTask( + FROM_HERE, + base::Bind(&InputHandlerManager::AddInputHandlerOnCompositorThread, + base::Unretained(this), + routing_id, + base::MessageLoopProxy::current(), + input_handler, + render_view_impl)); + } } void InputHandlerManager::AddInputHandlerOnCompositorThread( @@ -76,7 +76,7 @@ void InputHandlerManager::AddInputHandlerOnCompositorThread( DCHECK(message_loop_proxy_->BelongsToCurrentThread()); // The handler could be gone by this point if the compositor has shut down. - if (!input_handler.get()) + if (!input_handler) return; // The same handler may be registered for a route multiple times. @@ -84,7 +84,7 @@ void InputHandlerManager::AddInputHandlerOnCompositorThread( return; TRACE_EVENT0("InputHandlerManager::AddInputHandler", "AddingRoute"); - filter_->AddRoute(routing_id); + client_->DidAddInputHandler(routing_id); input_handlers_[routing_id] = make_scoped_refptr(new InputHandlerWrapper(this, routing_id, main_loop, input_handler, render_view_impl)); @@ -95,7 +95,7 @@ void InputHandlerManager::RemoveInputHandler(int routing_id) { TRACE_EVENT0("InputHandlerManager::RemoveInputHandler", "RemovingRoute"); - filter_->RemoveRoute(routing_id); + client_->DidRemoveInputHandler(routing_id); input_handlers_.erase(routing_id); } diff --git a/content/renderer/gpu/input_handler_manager.h b/content/renderer/gpu/input_handler_manager.h index 598e944..904db0d 100644 --- a/content/renderer/gpu/input_handler_manager.h +++ b/content/renderer/gpu/input_handler_manager.h @@ -7,10 +7,10 @@ #include <map> +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/port/common/input_event_ack_state.h" #include "content/renderer/render_view_impl.h" -#include "ipc/ipc_channel_proxy.h" namespace base { class MessageLoopProxy; @@ -26,26 +26,20 @@ class WebInputEvent; namespace content { -class InputEventFilter; class InputHandlerWrapper; +class InputHandlerManagerClient; // InputHandlerManager class manages InputHandlerProxy instances for // the WebViews in this renderer. class InputHandlerManager { public: - // |main_listener| refers to the central IPC message listener that lives on - // the main thread, where all incoming IPC messages are first handled. - // |message_loop_proxy| is the MessageLoopProxy of the compositor thread. - // The underlying MessageLoop must outlive this object. + // |message_loop_proxy| is the MessageLoopProxy of the compositor thread. Both + // the underlying MessageLoop and supplied |client| must outlive this object. InputHandlerManager( - IPC::Listener* main_listener, - const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy); + const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy, + InputHandlerManagerClient* client); ~InputHandlerManager(); - // This MessageFilter should be added to allow input events to be redirected - // to the compositor's thread. - IPC::ChannelProxy::MessageFilter* GetMessageFilter() const; - // Callable from the main thread only. void AddInputHandler( int routing_id, @@ -59,9 +53,6 @@ class InputHandlerManager { InputEventAckState HandleInputEvent(int routing_id, const WebKit::WebInputEvent* input_event); - // Called from the compositor's thread. - InputEventFilter* filter() { return filter_.get(); } - private: // Called from the compositor's thread. void AddInputHandlerOnCompositorThread( @@ -75,7 +66,7 @@ class InputHandlerManager { InputHandlerMap input_handlers_; scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; - scoped_refptr<InputEventFilter> filter_; + InputHandlerManagerClient* client_; }; } // namespace content diff --git a/content/renderer/gpu/input_handler_manager_client.h b/content/renderer/gpu/input_handler_manager_client.h new file mode 100644 index 0000000..deb7839 --- /dev/null +++ b/content/renderer/gpu/input_handler_manager_client.h @@ -0,0 +1,44 @@ +// Copyright 2013 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. + +#ifndef CONTENT_RENDERER_GPU_INPUT_HANDLER_MANAGER_CLIENT_H_ +#define CONTENT_RENDERER_GPU_INPUT_HANDLER_MANAGER_CLIENT_H_ + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "content/common/content_export.h" + +namespace WebKit { +class WebInputEvent; +} + +namespace content { + +class CONTENT_EXPORT InputHandlerManagerClient { + public: + virtual ~InputHandlerManagerClient() {} + + // The Manager will supply a |handler| when bound to the client. This is valid + // until the manager shuts down, at which point it supplies a null |handler|. + // The client should only makes calls to |handler| on the compositor thread. + typedef base::Callback<InputEventAckState( + int /*routing_id*/, const WebKit::WebInputEvent*)> Handler; + + // Called from the main thread. + virtual void SetBoundHandler(const Handler& handler) = 0; + + // Called from the compositor thread. + virtual void DidAddInputHandler(int routing_id) = 0; + virtual void DidRemoveInputHandler(int routing_id) = 0; + + protected: + InputHandlerManagerClient() {} + + private: + DISALLOW_COPY_AND_ASSIGN(InputHandlerManagerClient); +}; + +} // namespace content + +#endif // CONTENT_COMMON_GPU_INPUT_HANDLER_MANAGER_CLIENT_H_ diff --git a/content/renderer/gpu/input_handler_proxy.h b/content/renderer/gpu/input_handler_proxy.h index 5c857ee..3784771 100644 --- a/content/renderer/gpu/input_handler_proxy.h +++ b/content/renderer/gpu/input_handler_proxy.h @@ -10,7 +10,6 @@ #include "base/memory/scoped_ptr.h" #include "cc/input/input_handler.h" #include "content/common/content_export.h" -#include "content/port/common/input_event_ack_state.h" #include "third_party/WebKit/public/platform/WebGestureCurve.h" #include "third_party/WebKit/public/platform/WebGestureCurveTarget.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebActiveWheelFlingParameters.h" diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 2ed9c18..5bb608c 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -57,6 +57,7 @@ #include "content/renderer/gpu/compositor_output_surface.h" #include "content/renderer/gpu/gpu_benchmarking_extension.h" #include "content/renderer/gpu/input_handler_manager.h" +#include "content/renderer/gpu/input_event_filter.h" #include "content/renderer/media/audio_input_message_filter.h" #include "content/renderer/media/audio_message_filter.h" #include "content/renderer/media/audio_renderer_mixer_manager.h" @@ -456,9 +457,10 @@ void RenderThreadImpl::Shutdown() { } compositor_thread_.reset(); - if (input_handler_manager_) { - RemoveFilter(input_handler_manager_->GetMessageFilter()); - input_handler_manager_.reset(); + input_handler_manager_.reset(); + if (input_event_filter_) { + RemoveFilter(input_event_filter_.get()); + input_event_filter_ = NULL; } if (webkit_platform_support_) @@ -775,9 +777,22 @@ void RenderThreadImpl::EnsureWebKitInitialized() { false)); } + InputHandlerManagerClient* input_handler_manager_client = NULL; +#if defined(OS_ANDROID) + if (SynchronousCompositorFactory* factory = + SynchronousCompositorFactory::GetInstance()) { + input_handler_manager_client = factory->GetInputHandlerManagerClient(); + } +#endif + if (!input_handler_manager_client) { + input_event_filter_ = + new InputEventFilter(this, compositor_message_loop_proxy_); + AddFilter(input_event_filter_.get()); + input_handler_manager_client = input_event_filter_.get(); + } input_handler_manager_.reset( - new InputHandlerManager(this, compositor_message_loop_proxy_)); - AddFilter(input_handler_manager_->GetMessageFilter()); + new InputHandlerManager(compositor_message_loop_proxy_, + input_handler_manager_client)); } scoped_refptr<base::MessageLoopProxy> output_surface_loop; diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index cf48425..1d92af2 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -77,6 +77,7 @@ class DevToolsAgentFilter; class DomStorageDispatcher; class GpuChannelHost; class IndexedDBDispatcher; +class InputEventFilter; class InputHandlerManager; class MediaStreamCenter; class MediaStreamDependencyFactory; @@ -437,6 +438,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, // regardless of whether |compositor_thread_| is overriden. scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy_; + // May be null if unused by the |input_handler_manager_|. + scoped_refptr<InputEventFilter> input_event_filter_; scoped_ptr<InputHandlerManager> input_handler_manager_; scoped_refptr<IPC::ForwardingMessageFilter> compositor_output_surface_filter_; |