- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / web_contents / aura / window_slider_unittest.cc
1 // Copyright (c) 2013 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/browser/web_contents/aura/window_slider.h"
6
7 #include "base/bind.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "ui/aura/root_window.h"
10 #include "ui/aura/test/aura_test_base.h"
11 #include "ui/aura/test/event_generator.h"
12 #include "ui/aura/test/test_window_delegate.h"
13 #include "ui/aura/window.h"
14 #include "ui/base/hit_test.h"
15
16 namespace content {
17
18 void DispatchEventDuringScrollCallback(aura::RootWindow* root_window,
19                                        ui::Event* event,
20                                        ui::EventType type,
21                                        const gfx::Vector2dF& delta) {
22   if (type != ui::ET_GESTURE_SCROLL_UPDATE)
23     return;
24   aura::RootWindowHostDelegate* delegate =
25       root_window->AsRootWindowHostDelegate();
26   if (event->IsMouseEvent())
27     delegate->OnHostMouseEvent(static_cast<ui::MouseEvent*>(event));
28   else if (event->IsKeyEvent())
29     delegate->OnHostKeyEvent(static_cast<ui::KeyEvent*>(event));
30 }
31
32 void ChangeSliderOwnerDuringScrollCallback(scoped_ptr<aura::Window>* window,
33                                            WindowSlider* slider,
34                                            ui::EventType type,
35                                            const gfx::Vector2dF& delta) {
36   if (type != ui::ET_GESTURE_SCROLL_UPDATE)
37     return;
38   aura::Window* new_window = new aura::Window(NULL);
39   new_window->Init(ui::LAYER_TEXTURED);
40   new_window->Show();
41   slider->ChangeOwner(new_window);
42   (*window)->parent()->AddChild(new_window);
43   window->reset(new_window);
44 }
45
46 // The window delegate does not receive any events.
47 class NoEventWindowDelegate : public aura::test::TestWindowDelegate {
48  public:
49   NoEventWindowDelegate() {
50   }
51   virtual ~NoEventWindowDelegate() {}
52
53  private:
54   // Overridden from aura::WindowDelegate:
55   virtual bool HasHitTestMask() const OVERRIDE { return true; }
56
57   DISALLOW_COPY_AND_ASSIGN(NoEventWindowDelegate);
58 };
59
60 class WindowSliderDelegateTest : public WindowSlider::Delegate {
61  public:
62   WindowSliderDelegateTest()
63       : can_create_layer_(true),
64         created_back_layer_(false),
65         created_front_layer_(false),
66         slide_completed_(false),
67         slide_aborted_(false),
68         slider_destroyed_(false) {
69   }
70   virtual ~WindowSliderDelegateTest() {}
71
72   void Reset() {
73     can_create_layer_ = true;
74     created_back_layer_ = false;
75     created_front_layer_ = false;
76     slide_completed_ = false;
77     slide_aborted_ = false;
78     slider_destroyed_ = false;
79   }
80
81   void SetCanCreateLayer(bool can_create_layer) {
82     can_create_layer_ = can_create_layer;
83   }
84
85   bool created_back_layer() const { return created_back_layer_; }
86   bool created_front_layer() const { return created_front_layer_; }
87   bool slide_completed() const { return slide_completed_; }
88   bool slide_aborted() const { return slide_aborted_; }
89   bool slider_destroyed() const { return slider_destroyed_; }
90
91  protected:
92   ui::Layer* CreateLayerForTest() {
93     CHECK(can_create_layer_);
94     ui::Layer* layer = new ui::Layer(ui::LAYER_SOLID_COLOR);
95     layer->SetColor(SK_ColorRED);
96     return layer;
97   }
98
99   // Overridden from WindowSlider::Delegate:
100   virtual ui::Layer* CreateBackLayer() OVERRIDE {
101     if (!can_create_layer_)
102       return NULL;
103     created_back_layer_ = true;
104     return CreateLayerForTest();
105   }
106
107   virtual ui::Layer* CreateFrontLayer() OVERRIDE {
108     if (!can_create_layer_)
109       return NULL;
110     created_front_layer_ = true;
111     return CreateLayerForTest();
112   }
113
114   virtual void OnWindowSlideComplete() OVERRIDE {
115     slide_completed_ = true;
116   }
117
118   virtual void OnWindowSlideAborted() OVERRIDE {
119     slide_aborted_ = true;
120   }
121
122   virtual void OnWindowSliderDestroyed() OVERRIDE {
123     slider_destroyed_ = true;
124   }
125
126  private:
127   bool can_create_layer_;
128   bool created_back_layer_;
129   bool created_front_layer_;
130   bool slide_completed_;
131   bool slide_aborted_;
132   bool slider_destroyed_;
133
134   DISALLOW_COPY_AND_ASSIGN(WindowSliderDelegateTest);
135 };
136
137 // This delegate destroys the owner window when the slider is destroyed.
138 class WindowSliderDeleteOwnerOnDestroy : public WindowSliderDelegateTest {
139  public:
140   explicit WindowSliderDeleteOwnerOnDestroy(aura::Window* owner)
141       : owner_(owner) {
142   }
143   virtual ~WindowSliderDeleteOwnerOnDestroy() {}
144
145  private:
146   // Overridden from WindowSlider::Delegate:
147   virtual void OnWindowSliderDestroyed() OVERRIDE {
148     WindowSliderDelegateTest::OnWindowSliderDestroyed();
149     delete owner_;
150   }
151
152   aura::Window* owner_;
153   DISALLOW_COPY_AND_ASSIGN(WindowSliderDeleteOwnerOnDestroy);
154 };
155
156 // This delegate destroyes the owner window when a slide is completed.
157 class WindowSliderDeleteOwnerOnComplete : public WindowSliderDelegateTest {
158  public:
159   explicit WindowSliderDeleteOwnerOnComplete(aura::Window* owner)
160       : owner_(owner) {
161   }
162   virtual ~WindowSliderDeleteOwnerOnComplete() {}
163
164  private:
165   // Overridden from WindowSlider::Delegate:
166   virtual void OnWindowSlideComplete() OVERRIDE {
167     WindowSliderDelegateTest::OnWindowSlideComplete();
168     delete owner_;
169   }
170
171   aura::Window* owner_;
172   DISALLOW_COPY_AND_ASSIGN(WindowSliderDeleteOwnerOnComplete);
173 };
174
175 typedef aura::test::AuraTestBase WindowSliderTest;
176
177 TEST_F(WindowSliderTest, WindowSlideUsingGesture) {
178   scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
179   window->SetBounds(gfx::Rect(0, 0, 400, 400));
180   WindowSliderDelegateTest slider_delegate;
181
182   aura::test::EventGenerator generator(root_window());
183
184   // Generate a horizontal overscroll.
185   WindowSlider* slider =
186       new WindowSlider(&slider_delegate, root_window(), window.get());
187   generator.GestureScrollSequence(gfx::Point(10, 10),
188                                   gfx::Point(160, 10),
189                                   base::TimeDelta::FromMilliseconds(10),
190                                   10);
191   EXPECT_TRUE(slider_delegate.created_back_layer());
192   EXPECT_TRUE(slider_delegate.slide_completed());
193   EXPECT_FALSE(slider_delegate.created_front_layer());
194   EXPECT_FALSE(slider_delegate.slide_aborted());
195   EXPECT_FALSE(slider_delegate.slider_destroyed());
196   EXPECT_FALSE(slider->IsSlideInProgress());
197   slider_delegate.Reset();
198   window->SetTransform(gfx::Transform());
199
200   // Generat a horizontal overscroll in the reverse direction.
201   generator.GestureScrollSequence(gfx::Point(160, 10),
202                                   gfx::Point(10, 10),
203                                   base::TimeDelta::FromMilliseconds(10),
204                                   10);
205   EXPECT_TRUE(slider_delegate.created_front_layer());
206   EXPECT_TRUE(slider_delegate.slide_completed());
207   EXPECT_FALSE(slider_delegate.created_back_layer());
208   EXPECT_FALSE(slider_delegate.slide_aborted());
209   EXPECT_FALSE(slider_delegate.slider_destroyed());
210   EXPECT_FALSE(slider->IsSlideInProgress());
211   slider_delegate.Reset();
212
213   // Generate a vertical overscroll.
214   generator.GestureScrollSequence(gfx::Point(10, 10),
215                                   gfx::Point(10, 80),
216                                   base::TimeDelta::FromMilliseconds(10),
217                                   10);
218   EXPECT_FALSE(slider_delegate.created_back_layer());
219   EXPECT_FALSE(slider_delegate.slide_completed());
220   EXPECT_FALSE(slider_delegate.created_front_layer());
221   EXPECT_FALSE(slider_delegate.slide_aborted());
222   EXPECT_FALSE(slider->IsSlideInProgress());
223   slider_delegate.Reset();
224
225   // Generate a horizontal scroll that starts overscroll, but doesn't scroll
226   // enough to complete it.
227   generator.GestureScrollSequence(gfx::Point(10, 10),
228                                   gfx::Point(60, 10),
229                                   base::TimeDelta::FromMilliseconds(10),
230                                   10);
231   EXPECT_TRUE(slider_delegate.created_back_layer());
232   EXPECT_TRUE(slider_delegate.slide_aborted());
233   EXPECT_FALSE(slider_delegate.created_front_layer());
234   EXPECT_FALSE(slider_delegate.slide_completed());
235   EXPECT_FALSE(slider_delegate.slider_destroyed());
236   EXPECT_FALSE(slider->IsSlideInProgress());
237   slider_delegate.Reset();
238
239   // Destroy the window. This should destroy the slider.
240   window.reset();
241   EXPECT_TRUE(slider_delegate.slider_destroyed());
242 }
243
244 // Tests that the window slide is cancelled when a different type of event
245 // happens.
246 TEST_F(WindowSliderTest, WindowSlideIsCancelledOnEvent) {
247   scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
248   WindowSliderDelegateTest slider_delegate;
249
250   ui::Event* events[] = {
251     new ui::MouseEvent(ui::ET_MOUSE_MOVED,
252                        gfx::Point(55, 10),
253                        gfx::Point(55, 10),
254                        0),
255     new ui::KeyEvent(ui::ET_KEY_PRESSED,
256                      ui::VKEY_A,
257                      0,
258                      true),
259     NULL
260   };
261
262   new WindowSlider(&slider_delegate, root_window(), window.get());
263   for (int i = 0; events[i]; ++i) {
264     // Generate a horizontal overscroll.
265     aura::test::EventGenerator generator(root_window());
266     generator.GestureScrollSequenceWithCallback(
267         gfx::Point(10, 10),
268         gfx::Point(80, 10),
269         base::TimeDelta::FromMilliseconds(10),
270         1,
271         base::Bind(&DispatchEventDuringScrollCallback,
272                    root_window(),
273                    base::Owned(events[i])));
274     EXPECT_TRUE(slider_delegate.created_back_layer());
275     EXPECT_TRUE(slider_delegate.slide_aborted());
276     EXPECT_FALSE(slider_delegate.created_front_layer());
277     EXPECT_FALSE(slider_delegate.slide_completed());
278     EXPECT_FALSE(slider_delegate.slider_destroyed());
279     slider_delegate.Reset();
280   }
281   window.reset();
282   EXPECT_TRUE(slider_delegate.slider_destroyed());
283 }
284
285 // Tests that the slide works correctly when the owner of the window changes
286 // during the duration of the slide.
287 TEST_F(WindowSliderTest, OwnerWindowChangesDuringWindowSlide) {
288   scoped_ptr<aura::Window> parent(CreateNormalWindow(0, root_window(), NULL));
289
290   NoEventWindowDelegate window_delegate;
291   window_delegate.set_window_component(HTNOWHERE);
292   scoped_ptr<aura::Window> window(CreateNormalWindow(1, parent.get(),
293                                                      &window_delegate));
294
295   WindowSliderDelegateTest slider_delegate;
296   scoped_ptr<WindowSlider> slider(
297       new WindowSlider(&slider_delegate, parent.get(), window.get()));
298
299   // Generate a horizontal scroll, and change the owner in the middle of the
300   // scroll.
301   aura::test::EventGenerator generator(root_window());
302   aura::Window* old_window = window.get();
303   generator.GestureScrollSequenceWithCallback(
304       gfx::Point(10, 10),
305       gfx::Point(80, 10),
306       base::TimeDelta::FromMilliseconds(10),
307       1,
308       base::Bind(&ChangeSliderOwnerDuringScrollCallback,
309                  base::Unretained(&window),
310                  slider.get()));
311   aura::Window* new_window = window.get();
312   EXPECT_NE(old_window, new_window);
313
314   EXPECT_TRUE(slider_delegate.created_back_layer());
315   EXPECT_TRUE(slider_delegate.slide_completed());
316   EXPECT_FALSE(slider_delegate.created_front_layer());
317   EXPECT_FALSE(slider_delegate.slide_aborted());
318   EXPECT_FALSE(slider_delegate.slider_destroyed());
319 }
320
321 TEST_F(WindowSliderTest, NoSlideWhenLayerCantBeCreated) {
322   scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
323   window->SetBounds(gfx::Rect(0, 0, 400, 400));
324   WindowSliderDelegateTest slider_delegate;
325   slider_delegate.SetCanCreateLayer(false);
326
327   aura::test::EventGenerator generator(root_window());
328
329   // Generate a horizontal overscroll.
330   scoped_ptr<WindowSlider> slider(
331       new WindowSlider(&slider_delegate, root_window(), window.get()));
332   generator.GestureScrollSequence(gfx::Point(10, 10),
333                                   gfx::Point(160, 10),
334                                   base::TimeDelta::FromMilliseconds(10),
335                                   10);
336   EXPECT_FALSE(slider_delegate.created_back_layer());
337   EXPECT_FALSE(slider_delegate.slide_completed());
338   EXPECT_FALSE(slider_delegate.created_front_layer());
339   EXPECT_FALSE(slider_delegate.slide_aborted());
340   EXPECT_FALSE(slider_delegate.slider_destroyed());
341   window->SetTransform(gfx::Transform());
342
343   slider_delegate.SetCanCreateLayer(true);
344   generator.GestureScrollSequence(gfx::Point(10, 10),
345                                   gfx::Point(160, 10),
346                                   base::TimeDelta::FromMilliseconds(10),
347                                   10);
348   EXPECT_TRUE(slider_delegate.created_back_layer());
349   EXPECT_TRUE(slider_delegate.slide_completed());
350   EXPECT_FALSE(slider_delegate.created_front_layer());
351   EXPECT_FALSE(slider_delegate.slide_aborted());
352   EXPECT_FALSE(slider_delegate.slider_destroyed());
353 }
354
355 // Tests that the owner window can be destroyed from |OnWindowSliderDestroyed()|
356 // delegate callback without causing a crash.
357 TEST_F(WindowSliderTest, OwnerIsDestroyedOnSliderDestroy) {
358   size_t child_windows = root_window()->children().size();
359   aura::Window* window = CreateNormalWindow(0, root_window(), NULL);
360   window->SetBounds(gfx::Rect(0, 0, 400, 400));
361   EXPECT_EQ(child_windows + 1, root_window()->children().size());
362
363   WindowSliderDeleteOwnerOnDestroy slider_delegate(window);
364   aura::test::EventGenerator generator(root_window());
365
366   // Generate a horizontal overscroll.
367   scoped_ptr<WindowSlider> slider(
368       new WindowSlider(&slider_delegate, root_window(), window));
369   generator.GestureScrollSequence(gfx::Point(10, 10),
370                                   gfx::Point(160, 10),
371                                   base::TimeDelta::FromMilliseconds(10),
372                                   10);
373   EXPECT_TRUE(slider_delegate.created_back_layer());
374   EXPECT_TRUE(slider_delegate.slide_completed());
375   EXPECT_FALSE(slider_delegate.created_front_layer());
376   EXPECT_FALSE(slider_delegate.slide_aborted());
377   EXPECT_FALSE(slider_delegate.slider_destroyed());
378
379   slider.reset();
380   // Destroying the slider would have destroyed |window| too. So |window| should
381   // not need to be destroyed here.
382   EXPECT_EQ(child_windows, root_window()->children().size());
383 }
384
385 // Tests that the owner window can be destroyed from |OnWindowSlideComplete()|
386 // delegate callback without causing a crash.
387 TEST_F(WindowSliderTest, OwnerIsDestroyedOnSlideComplete) {
388   size_t child_windows = root_window()->children().size();
389   aura::Window* window = CreateNormalWindow(0, root_window(), NULL);
390   window->SetBounds(gfx::Rect(0, 0, 400, 400));
391   EXPECT_EQ(child_windows + 1, root_window()->children().size());
392
393   WindowSliderDeleteOwnerOnComplete slider_delegate(window);
394   aura::test::EventGenerator generator(root_window());
395
396   // Generate a horizontal overscroll.
397   new WindowSlider(&slider_delegate, root_window(), window);
398   generator.GestureScrollSequence(gfx::Point(10, 10),
399                                   gfx::Point(160, 10),
400                                   base::TimeDelta::FromMilliseconds(10),
401                                   10);
402   EXPECT_TRUE(slider_delegate.created_back_layer());
403   EXPECT_TRUE(slider_delegate.slide_completed());
404   EXPECT_FALSE(slider_delegate.created_front_layer());
405   EXPECT_FALSE(slider_delegate.slide_aborted());
406   EXPECT_TRUE(slider_delegate.slider_destroyed());
407
408   // Destroying the slider would have destroyed |window| too. So |window| should
409   // not need to be destroyed here.
410   EXPECT_EQ(child_windows, root_window()->children().size());
411 }
412
413 }  // namespace content