Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / components / web_modal / web_contents_modal_dialog_manager_unittest.cc
1 // Copyright (c) 2012 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 "components/web_modal/web_contents_modal_dialog_manager.h"
6
7 #include <map>
8
9 #include "base/memory/scoped_ptr.h"
10 #include "components/web_modal/single_web_contents_dialog_manager.h"
11 #include "components/web_modal/test_web_contents_modal_dialog_manager_delegate.h"
12 #include "content/public/test/test_renderer_host.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace web_modal {
16
17 // Tracks persistent state changes of the native WC-modal dialog manager.
18 class NativeManagerTracker {
19  public:
20   enum DialogState {
21     UNKNOWN,
22     NOT_SHOWN,
23     SHOWN,
24     HIDDEN,
25     CLOSED
26   };
27
28   NativeManagerTracker() : state_(UNKNOWN), was_shown_(false) {}
29
30   void SetState(DialogState state) {
31     state_ = state;
32     if (state_ == SHOWN)
33       was_shown_ = true;
34   }
35
36   DialogState state_;
37   bool was_shown_;
38 };
39
40 NativeManagerTracker unused_tracker;
41
42 class TestNativeWebContentsModalDialogManager
43     : public SingleWebContentsDialogManager {
44  public:
45   TestNativeWebContentsModalDialogManager(
46       NativeWebContentsModalDialog dialog,
47       SingleWebContentsDialogManagerDelegate* delegate,
48       NativeManagerTracker* tracker)
49       : delegate_(delegate),
50         dialog_(dialog),
51         tracker_(tracker) {
52     if (tracker_)
53       tracker_->SetState(NativeManagerTracker::NOT_SHOWN);
54   }
55
56   virtual void Show() OVERRIDE {
57     if (tracker_)
58       tracker_->SetState(NativeManagerTracker::SHOWN);
59   }
60   virtual void Hide() OVERRIDE {
61     if (tracker_)
62       tracker_->SetState(NativeManagerTracker::HIDDEN);
63   }
64   virtual void Close() OVERRIDE {
65     if (tracker_)
66       tracker_->SetState(NativeManagerTracker::CLOSED);
67     delegate_->WillClose(dialog_);
68   }
69   virtual void Focus() OVERRIDE {
70   }
71   virtual void Pulse() OVERRIDE {
72   }
73   virtual void HostChanged(WebContentsModalDialogHost* new_host) OVERRIDE {
74   }
75   virtual NativeWebContentsModalDialog dialog() OVERRIDE {
76       return dialog_;
77   }
78
79   void StopTracking() {
80     tracker_ = NULL;
81   }
82
83  private:
84   SingleWebContentsDialogManagerDelegate* delegate_;
85   NativeWebContentsModalDialog dialog_;
86   NativeManagerTracker* tracker_;
87
88   DISALLOW_COPY_AND_ASSIGN(TestNativeWebContentsModalDialogManager);
89 };
90
91 class WebContentsModalDialogManagerTest
92     : public content::RenderViewHostTestHarness {
93  public:
94   WebContentsModalDialogManagerTest()
95       : next_dialog_id(1),
96         manager(NULL) {
97   }
98
99   virtual void SetUp() {
100     content::RenderViewHostTestHarness::SetUp();
101
102     delegate.reset(new TestWebContentsModalDialogManagerDelegate);
103     WebContentsModalDialogManager::CreateForWebContents(web_contents());
104     manager = WebContentsModalDialogManager::FromWebContents(web_contents());
105     manager->SetDelegate(delegate.get());
106     test_api.reset(new WebContentsModalDialogManager::TestApi(manager));
107   }
108
109   virtual void TearDown() {
110     test_api.reset();
111     content::RenderViewHostTestHarness::TearDown();
112   }
113
114  protected:
115   NativeWebContentsModalDialog MakeFakeDialog() {
116     // WebContentsModalDialogManager treats the NativeWebContentsModalDialog as
117     // an opaque type, so creating fake NativeWebContentsModalDialogs using
118     // reinterpret_cast is valid.
119     return reinterpret_cast<NativeWebContentsModalDialog>(next_dialog_id++);
120   }
121
122   int next_dialog_id;
123   scoped_ptr<TestWebContentsModalDialogManagerDelegate> delegate;
124   WebContentsModalDialogManager* manager;
125   scoped_ptr<WebContentsModalDialogManager::TestApi> test_api;
126
127   DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogManagerTest);
128 };
129
130 SingleWebContentsDialogManager*
131 WebContentsModalDialogManager::CreateNativeWebModalManager(
132     NativeWebContentsModalDialog dialog,
133     SingleWebContentsDialogManagerDelegate* native_delegate) {
134   NOTREACHED();
135   return new TestNativeWebContentsModalDialogManager(
136       dialog,
137       native_delegate,
138       &unused_tracker);
139 }
140
141 // Test that the dialog is shown immediately when the delegate indicates the web
142 // contents is visible.
143 TEST_F(WebContentsModalDialogManagerTest, WebContentsVisible) {
144   // Dialog should be shown while WebContents is visible.
145   const NativeWebContentsModalDialog dialog = MakeFakeDialog();
146
147   NativeManagerTracker tracker;
148   TestNativeWebContentsModalDialogManager* native_manager =
149       new TestNativeWebContentsModalDialogManager(dialog, manager, &tracker);
150   manager->ShowDialogWithManager(dialog,
151       scoped_ptr<SingleWebContentsDialogManager>(native_manager).Pass());
152
153   EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
154   EXPECT_TRUE(manager->IsDialogActive());
155   EXPECT_TRUE(delegate->web_contents_blocked());
156   EXPECT_TRUE(tracker.was_shown_);
157
158   native_manager->StopTracking();
159 }
160
161 // Test that the dialog is not shown immediately when the delegate indicates the
162 // web contents is not visible.
163 TEST_F(WebContentsModalDialogManagerTest, WebContentsNotVisible) {
164   // Dialog should not be shown while WebContents is not visible.
165   delegate->set_web_contents_visible(false);
166
167   const NativeWebContentsModalDialog dialog = MakeFakeDialog();
168
169   NativeManagerTracker tracker;
170   TestNativeWebContentsModalDialogManager* native_manager =
171       new TestNativeWebContentsModalDialogManager(dialog, manager, &tracker);
172   manager->ShowDialogWithManager(dialog,
173       scoped_ptr<SingleWebContentsDialogManager>(native_manager).Pass());
174
175   EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker.state_);
176   EXPECT_TRUE(manager->IsDialogActive());
177   EXPECT_TRUE(delegate->web_contents_blocked());
178   EXPECT_FALSE(tracker.was_shown_);
179
180   native_manager->StopTracking();
181 }
182
183 // Test that only the first of multiple dialogs is shown.
184 TEST_F(WebContentsModalDialogManagerTest, ShowDialogs) {
185   const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
186   const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
187   const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();
188
189   NativeManagerTracker tracker1;
190   NativeManagerTracker tracker2;
191   NativeManagerTracker tracker3;
192   TestNativeWebContentsModalDialogManager* native_manager1 =
193       new TestNativeWebContentsModalDialogManager(dialog1, manager, &tracker1);
194   TestNativeWebContentsModalDialogManager* native_manager2 =
195       new TestNativeWebContentsModalDialogManager(dialog2, manager, &tracker2);
196   TestNativeWebContentsModalDialogManager* native_manager3 =
197       new TestNativeWebContentsModalDialogManager(dialog3, manager, &tracker3);
198   manager->ShowDialogWithManager(dialog1,
199       scoped_ptr<SingleWebContentsDialogManager>(native_manager1).Pass());
200   manager->ShowDialogWithManager(dialog2,
201       scoped_ptr<SingleWebContentsDialogManager>(native_manager2).Pass());
202   manager->ShowDialogWithManager(dialog3,
203       scoped_ptr<SingleWebContentsDialogManager>(native_manager3).Pass());
204
205   EXPECT_TRUE(delegate->web_contents_blocked());
206   EXPECT_EQ(NativeManagerTracker::SHOWN, tracker1.state_);
207   EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker2.state_);
208   EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker3.state_);
209
210   native_manager1->StopTracking();
211   native_manager2->StopTracking();
212   native_manager3->StopTracking();
213 }
214
215 // Test that the dialog is shown/hidden when the WebContents is shown/hidden.
216 TEST_F(WebContentsModalDialogManagerTest, VisibilityObservation) {
217   const NativeWebContentsModalDialog dialog = MakeFakeDialog();
218
219   NativeManagerTracker tracker;
220   TestNativeWebContentsModalDialogManager* native_manager =
221       new TestNativeWebContentsModalDialogManager(dialog, manager, &tracker);
222   manager->ShowDialogWithManager(dialog,
223       scoped_ptr<SingleWebContentsDialogManager>(native_manager).Pass());
224
225   EXPECT_TRUE(manager->IsDialogActive());
226   EXPECT_TRUE(delegate->web_contents_blocked());
227   EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
228
229   test_api->WebContentsWasHidden();
230
231   EXPECT_TRUE(manager->IsDialogActive());
232   EXPECT_TRUE(delegate->web_contents_blocked());
233   EXPECT_EQ(NativeManagerTracker::HIDDEN, tracker.state_);
234
235   test_api->WebContentsWasShown();
236
237   EXPECT_TRUE(manager->IsDialogActive());
238   EXPECT_TRUE(delegate->web_contents_blocked());
239   EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
240
241   native_manager->StopTracking();
242 }
243
244 // Test that attaching an interstitial page closes dialogs configured to close.
245 TEST_F(WebContentsModalDialogManagerTest, InterstitialPage) {
246   const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
247   const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
248   const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();
249
250   NativeManagerTracker tracker1;
251   NativeManagerTracker tracker2;
252   NativeManagerTracker tracker3;
253   TestNativeWebContentsModalDialogManager* native_manager1 =
254       new TestNativeWebContentsModalDialogManager(dialog1, manager, &tracker1);
255   TestNativeWebContentsModalDialogManager* native_manager2 =
256       new TestNativeWebContentsModalDialogManager(dialog2, manager, &tracker2);
257   TestNativeWebContentsModalDialogManager* native_manager3 =
258       new TestNativeWebContentsModalDialogManager(dialog3, manager, &tracker3);
259   manager->ShowDialogWithManager(dialog1,
260       scoped_ptr<SingleWebContentsDialogManager>(native_manager1).Pass());
261   manager->ShowDialogWithManager(dialog2,
262       scoped_ptr<SingleWebContentsDialogManager>(native_manager2).Pass());
263   manager->ShowDialogWithManager(dialog3,
264       scoped_ptr<SingleWebContentsDialogManager>(native_manager3).Pass());
265
266 #if defined(OS_WIN) || defined(USE_AURA)
267   manager->SetCloseOnInterstitialPage(dialog2, false);
268 #else
269   // TODO(wittman): Remove this section once Mac is changed to close on
270   // interstitial pages by default.
271   manager->SetCloseOnInterstitialPage(dialog1, true);
272   manager->SetCloseOnInterstitialPage(dialog3, true);
273 #endif
274
275   test_api->DidAttachInterstitialPage();
276
277   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
278   EXPECT_EQ(NativeManagerTracker::SHOWN, tracker2.state_);
279   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
280   EXPECT_TRUE(tracker1.was_shown_);
281   EXPECT_TRUE(tracker2.was_shown_);
282   EXPECT_FALSE(tracker3.was_shown_);
283
284   native_manager2->StopTracking();
285 }
286
287
288 // Test that the first dialog is always shown, regardless of the order in which
289 // dialogs are closed.
290 TEST_F(WebContentsModalDialogManagerTest, CloseDialogs) {
291   // The front dialog is always shown regardless of dialog close order.
292   const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
293   const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
294   const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();
295   const NativeWebContentsModalDialog dialog4 = MakeFakeDialog();
296
297   NativeManagerTracker tracker1;
298   NativeManagerTracker tracker2;
299   NativeManagerTracker tracker3;
300   NativeManagerTracker tracker4;
301   TestNativeWebContentsModalDialogManager* native_manager1 =
302       new TestNativeWebContentsModalDialogManager(dialog1, manager, &tracker1);
303   TestNativeWebContentsModalDialogManager* native_manager2 =
304       new TestNativeWebContentsModalDialogManager(dialog2, manager, &tracker2);
305   TestNativeWebContentsModalDialogManager* native_manager3 =
306       new TestNativeWebContentsModalDialogManager(dialog3, manager, &tracker3);
307   TestNativeWebContentsModalDialogManager* native_manager4 =
308       new TestNativeWebContentsModalDialogManager(dialog4, manager, &tracker4);
309   manager->ShowDialogWithManager(dialog1,
310       scoped_ptr<SingleWebContentsDialogManager>(native_manager1).Pass());
311   manager->ShowDialogWithManager(dialog2,
312       scoped_ptr<SingleWebContentsDialogManager>(native_manager2).Pass());
313   manager->ShowDialogWithManager(dialog3,
314       scoped_ptr<SingleWebContentsDialogManager>(native_manager3).Pass());
315   manager->ShowDialogWithManager(dialog4,
316       scoped_ptr<SingleWebContentsDialogManager>(native_manager4).Pass());
317
318   native_manager1->Close();
319
320   EXPECT_TRUE(manager->IsDialogActive());
321   EXPECT_TRUE(delegate->web_contents_blocked());
322   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
323   EXPECT_EQ(NativeManagerTracker::SHOWN, tracker2.state_);
324   EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker3.state_);
325   EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker4.state_);
326
327   native_manager3->Close();
328
329   EXPECT_TRUE(manager->IsDialogActive());
330   EXPECT_TRUE(delegate->web_contents_blocked());
331   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
332   EXPECT_EQ(NativeManagerTracker::SHOWN, tracker2.state_);
333   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
334   EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker4.state_);
335   EXPECT_FALSE(tracker3.was_shown_);
336
337   native_manager2->Close();
338
339   EXPECT_TRUE(manager->IsDialogActive());
340   EXPECT_TRUE(delegate->web_contents_blocked());
341   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
342   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker2.state_);
343   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
344   EXPECT_EQ(NativeManagerTracker::SHOWN, tracker4.state_);
345   EXPECT_FALSE(tracker3.was_shown_);
346
347   native_manager4->Close();
348
349   EXPECT_FALSE(manager->IsDialogActive());
350   EXPECT_FALSE(delegate->web_contents_blocked());
351   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
352   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker2.state_);
353   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
354   EXPECT_EQ(NativeManagerTracker::CLOSED, tracker4.state_);
355   EXPECT_TRUE(tracker1.was_shown_);
356   EXPECT_TRUE(tracker2.was_shown_);
357   EXPECT_FALSE(tracker3.was_shown_);
358   EXPECT_TRUE(tracker4.was_shown_);
359 }
360
361 // Test that CloseAllDialogs does what it says.
362 TEST_F(WebContentsModalDialogManagerTest, CloseAllDialogs) {
363   const int kWindowCount = 4;
364   NativeManagerTracker trackers[kWindowCount];
365   TestNativeWebContentsModalDialogManager* native_managers[kWindowCount];
366   for (int i = 0; i < kWindowCount; i++) {
367     const NativeWebContentsModalDialog dialog = MakeFakeDialog();
368     native_managers[i] =
369         new TestNativeWebContentsModalDialogManager(
370             dialog, manager, &(trackers[i]));
371     manager->ShowDialogWithManager(dialog,
372     scoped_ptr<SingleWebContentsDialogManager>(
373         native_managers[i]).Pass());
374   }
375
376   for (int i = 0; i < kWindowCount; i++)
377     EXPECT_NE(NativeManagerTracker::CLOSED, trackers[i].state_);
378
379   test_api->CloseAllDialogs();
380
381   EXPECT_FALSE(delegate->web_contents_blocked());
382   EXPECT_FALSE(manager->IsDialogActive());
383   for (int i = 0; i < kWindowCount; i++)
384     EXPECT_EQ(NativeManagerTracker::CLOSED, trackers[i].state_);
385 }
386
387 }  // namespace web_modal