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