• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 "ui/events/event_rewriter.h"
6 
7 #include <list>
8 #include <map>
9 #include <set>
10 #include <utility>
11 
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/events/test/test_event_processor.h"
14 
15 namespace ui {
16 
17 namespace {
18 
19 // To test the handling of |EventRewriter|s through |EventSource|,
20 // we rewrite and test event types.
21 class TestEvent : public Event {
22  public:
TestEvent(EventType type)23   explicit TestEvent(EventType type)
24       : Event(type, base::TimeDelta(), 0), unique_id_(next_unique_id_++) {}
~TestEvent()25   virtual ~TestEvent() {}
unique_id() const26   int unique_id() const { return unique_id_; }
27 
28  private:
29   static int next_unique_id_;
30   int unique_id_;
31 };
32 
33 int TestEvent::next_unique_id_ = 0;
34 
35 // TestEventRewriteProcessor is set up with a sequence of event types,
36 // and fails if the events received via OnEventFromSource() do not match
37 // this sequence. These expected event types are consumed on receipt.
38 class TestEventRewriteProcessor : public test::TestEventProcessor {
39  public:
TestEventRewriteProcessor()40   TestEventRewriteProcessor() {}
~TestEventRewriteProcessor()41   virtual ~TestEventRewriteProcessor() { CheckAllReceived(); }
42 
AddExpectedEvent(EventType type)43   void AddExpectedEvent(EventType type) { expected_events_.push_back(type); }
44   // Test that all expected events have been received.
CheckAllReceived()45   void CheckAllReceived() { EXPECT_TRUE(expected_events_.empty()); }
46 
47   // EventProcessor:
OnEventFromSource(Event * event)48   virtual EventDispatchDetails OnEventFromSource(Event* event) OVERRIDE {
49     EXPECT_FALSE(expected_events_.empty());
50     EXPECT_EQ(expected_events_.front(), event->type());
51     expected_events_.pop_front();
52     return EventDispatchDetails();
53   }
54 
55  private:
56   std::list<EventType> expected_events_;
57   DISALLOW_COPY_AND_ASSIGN(TestEventRewriteProcessor);
58 };
59 
60 // Trivial EventSource that does nothing but send events.
61 class TestEventRewriteSource : public EventSource {
62  public:
TestEventRewriteSource(EventProcessor * processor)63   explicit TestEventRewriteSource(EventProcessor* processor)
64       : processor_(processor) {}
GetEventProcessor()65   virtual EventProcessor* GetEventProcessor() OVERRIDE { return processor_; }
Send(EventType type)66   void Send(EventType type) {
67     scoped_ptr<Event> event(new TestEvent(type));
68     (void)SendEventToProcessor(event.get());
69   }
70 
71  private:
72   EventProcessor* processor_;
73 };
74 
75 // This EventRewriter always returns the same status, and if rewriting, the
76 // same event type; it is used to test simple rewriting, and rewriter addition,
77 // removal, and sequencing. Consequently EVENT_REWRITE_DISPATCH_ANOTHER is not
78 // supported here (calls to NextDispatchEvent() would continue indefinitely).
79 class TestConstantEventRewriter : public EventRewriter {
80  public:
TestConstantEventRewriter(EventRewriteStatus status,EventType type)81   TestConstantEventRewriter(EventRewriteStatus status, EventType type)
82       : status_(status), type_(type) {
83     CHECK_NE(EVENT_REWRITE_DISPATCH_ANOTHER, status);
84   }
85 
RewriteEvent(const Event & event,scoped_ptr<Event> * rewritten_event)86   virtual EventRewriteStatus RewriteEvent(const Event& event,
87                                           scoped_ptr<Event>* rewritten_event)
88       OVERRIDE {
89     if (status_ == EVENT_REWRITE_REWRITTEN)
90       rewritten_event->reset(new TestEvent(type_));
91     return status_;
92   }
NextDispatchEvent(const Event & last_event,scoped_ptr<Event> * new_event)93   virtual EventRewriteStatus NextDispatchEvent(const Event& last_event,
94                                                scoped_ptr<Event>* new_event)
95       OVERRIDE {
96     NOTREACHED();
97     return status_;
98   }
99 
100  private:
101   EventRewriteStatus status_;
102   EventType type_;
103 };
104 
105 // This EventRewriter runs a simple state machine; it is used to test
106 // EVENT_REWRITE_DISPATCH_ANOTHER.
107 class TestStateMachineEventRewriter : public EventRewriter {
108  public:
TestStateMachineEventRewriter()109   TestStateMachineEventRewriter() : last_rewritten_event_(0), state_(0) {}
AddRule(int from_state,EventType from_type,int to_state,EventType to_type,EventRewriteStatus to_status)110   void AddRule(int from_state, EventType from_type,
111                int to_state, EventType to_type, EventRewriteStatus to_status) {
112     RewriteResult r = {to_state, to_type, to_status};
113     rules_.insert(std::pair<RewriteCase, RewriteResult>(
114         RewriteCase(from_state, from_type), r));
115   }
RewriteEvent(const Event & event,scoped_ptr<Event> * rewritten_event)116   virtual EventRewriteStatus RewriteEvent(const Event& event,
117                                           scoped_ptr<Event>* rewritten_event)
118       OVERRIDE {
119     RewriteRules::iterator find =
120         rules_.find(RewriteCase(state_, event.type()));
121     if (find == rules_.end())
122       return EVENT_REWRITE_CONTINUE;
123     if ((find->second.status == EVENT_REWRITE_REWRITTEN) ||
124         (find->second.status == EVENT_REWRITE_DISPATCH_ANOTHER)) {
125       last_rewritten_event_ = new TestEvent(find->second.type);
126       rewritten_event->reset(last_rewritten_event_);
127     } else {
128       last_rewritten_event_ = 0;
129     }
130     state_ = find->second.state;
131     return find->second.status;
132   }
NextDispatchEvent(const Event & last_event,scoped_ptr<Event> * new_event)133   virtual EventRewriteStatus NextDispatchEvent(const Event& last_event,
134                                                scoped_ptr<Event>* new_event)
135       OVERRIDE {
136     EXPECT_TRUE(last_rewritten_event_);
137     const TestEvent* arg_last = static_cast<const TestEvent*>(&last_event);
138     EXPECT_EQ(last_rewritten_event_->unique_id(), arg_last->unique_id());
139     const TestEvent* arg_new = static_cast<const TestEvent*>(new_event->get());
140     EXPECT_FALSE(arg_new && arg_last->unique_id() == arg_new->unique_id());
141     return RewriteEvent(last_event, new_event);
142   }
143 
144  private:
145   typedef std::pair<int, EventType> RewriteCase;
146   struct RewriteResult {
147     int state;
148     EventType type;
149     EventRewriteStatus status;
150   };
151   typedef std::map<RewriteCase, RewriteResult> RewriteRules;
152   RewriteRules rules_;
153   TestEvent* last_rewritten_event_;
154   int state_;
155 };
156 
157 }  // namespace
158 
TEST(EventRewriterTest,EventRewriting)159 TEST(EventRewriterTest, EventRewriting) {
160   // TestEventRewriter r0 always rewrites events to ET_CANCEL_MODE;
161   // it is placed at the beginning of the chain and later removed,
162   // to verify that rewriter removal works.
163   TestConstantEventRewriter r0(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
164 
165   // TestEventRewriter r1 always returns EVENT_REWRITE_CONTINUE;
166   // it is placed at the beginning of the chain to verify that a
167   // later rewriter sees the events.
168   TestConstantEventRewriter r1(EVENT_REWRITE_CONTINUE, ET_UNKNOWN);
169 
170   // TestEventRewriter r2 has a state machine, primarily to test
171   // |EVENT_REWRITE_DISPATCH_ANOTHER|.
172   TestStateMachineEventRewriter r2;
173 
174   // TestEventRewriter r3 always rewrites events to ET_CANCEL_MODE;
175   // it is placed at the end of the chain to verify that previously
176   // rewritten events are not passed further down the chain.
177   TestConstantEventRewriter r3(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
178 
179   TestEventRewriteProcessor p;
180   TestEventRewriteSource s(&p);
181   s.AddEventRewriter(&r0);
182   s.AddEventRewriter(&r1);
183   s.AddEventRewriter(&r2);
184 
185   // These events should be rewritten by r0 to ET_CANCEL_MODE.
186   p.AddExpectedEvent(ET_CANCEL_MODE);
187   s.Send(ET_MOUSE_DRAGGED);
188   p.AddExpectedEvent(ET_CANCEL_MODE);
189   s.Send(ET_MOUSE_PRESSED);
190   p.CheckAllReceived();
191 
192   // Remove r0, and verify that it's gone and that events make it through.
193   s.AddEventRewriter(&r3);
194   s.RemoveEventRewriter(&r0);
195   r2.AddRule(0, ET_SCROLL_FLING_START,
196              0, ET_SCROLL_FLING_CANCEL, EVENT_REWRITE_REWRITTEN);
197   p.AddExpectedEvent(ET_SCROLL_FLING_CANCEL);
198   s.Send(ET_SCROLL_FLING_START);
199   p.CheckAllReceived();
200   s.RemoveEventRewriter(&r3);
201 
202   // Verify EVENT_REWRITE_DISPATCH_ANOTHER using a state machine
203   // (that happens to be analogous to sticky keys).
204   r2.AddRule(0, ET_KEY_PRESSED,
205              1, ET_KEY_PRESSED, EVENT_REWRITE_CONTINUE);
206   r2.AddRule(1, ET_MOUSE_PRESSED,
207              0, ET_MOUSE_PRESSED, EVENT_REWRITE_CONTINUE);
208   r2.AddRule(1, ET_KEY_RELEASED,
209              2, ET_KEY_RELEASED, EVENT_REWRITE_DISCARD);
210   r2.AddRule(2, ET_MOUSE_RELEASED,
211              3, ET_MOUSE_RELEASED, EVENT_REWRITE_DISPATCH_ANOTHER);
212   r2.AddRule(3, ET_MOUSE_RELEASED,
213              0, ET_KEY_RELEASED, EVENT_REWRITE_REWRITTEN);
214   p.AddExpectedEvent(ET_KEY_PRESSED);
215   s.Send(ET_KEY_PRESSED);
216   s.Send(ET_KEY_RELEASED);
217   p.AddExpectedEvent(ET_MOUSE_PRESSED);
218   s.Send(ET_MOUSE_PRESSED);
219 
220   // Removing rewriters r1 and r3 shouldn't affect r2.
221   s.RemoveEventRewriter(&r1);
222   s.RemoveEventRewriter(&r3);
223 
224   // Continue with the state-based rewriting.
225   p.AddExpectedEvent(ET_MOUSE_RELEASED);
226   p.AddExpectedEvent(ET_KEY_RELEASED);
227   s.Send(ET_MOUSE_RELEASED);
228   p.CheckAllReceived();
229 }
230 
231 }  // namespace ui
232