• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/native_web_contents_modal_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 class TestNativeWebContentsModalDialogManager
18     : public NativeWebContentsModalDialogManager {
19  public:
20   enum DialogState {
21     UNKNOWN,
22     NOT_SHOWN,
23     SHOWN,
24     HIDDEN,
25     CLOSED
26   };
27 
TestNativeWebContentsModalDialogManager(NativeWebContentsModalDialogManagerDelegate * delegate)28   explicit TestNativeWebContentsModalDialogManager(
29       NativeWebContentsModalDialogManagerDelegate* delegate)
30       : delegate_(delegate) {}
ManageDialog(NativeWebContentsModalDialog dialog)31   virtual void ManageDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
32     dialog_state_[dialog] = NOT_SHOWN;
33   }
ShowDialog(NativeWebContentsModalDialog dialog)34   virtual void ShowDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
35     dialog_state_[dialog] = SHOWN;
36   }
HideDialog(NativeWebContentsModalDialog dialog)37   virtual void HideDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
38     dialog_state_[dialog] = HIDDEN;
39   }
CloseDialog(NativeWebContentsModalDialog dialog)40   virtual void CloseDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
41     delegate_->WillClose(dialog);
42     dialog_state_[dialog] = CLOSED;
43   }
FocusDialog(NativeWebContentsModalDialog dialog)44   virtual void FocusDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
45   }
PulseDialog(NativeWebContentsModalDialog dialog)46   virtual void PulseDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
47   }
HostChanged(WebContentsModalDialogHost * new_host)48   virtual void HostChanged(WebContentsModalDialogHost* new_host) OVERRIDE {
49   }
50 
GetCloseCount() const51   int GetCloseCount() const {
52     int count = 0;
53     for (DialogStateMap::const_iterator it = dialog_state_.begin();
54          it != dialog_state_.end(); ++it) {
55       if (it->second == CLOSED)
56         count++;
57     }
58     return count;
59   }
60 
GetDialogState(NativeWebContentsModalDialog dialog) const61   DialogState GetDialogState(NativeWebContentsModalDialog dialog) const {
62     DialogStateMap::const_iterator loc = dialog_state_.find(dialog);
63     return loc == dialog_state_.end() ? UNKNOWN : loc->second;
64   }
65 
66  private:
67   typedef std::map<NativeWebContentsModalDialog, DialogState> DialogStateMap;
68 
69   NativeWebContentsModalDialogManagerDelegate* delegate_;
70   DialogStateMap dialog_state_;
71 
72   DISALLOW_COPY_AND_ASSIGN(TestNativeWebContentsModalDialogManager);
73 };
74 
75 class WebContentsModalDialogManagerTest
76     : public content::RenderViewHostTestHarness {
77  public:
WebContentsModalDialogManagerTest()78   WebContentsModalDialogManagerTest()
79       : next_dialog_id(1),
80         manager(NULL),
81         native_manager(NULL) {
82   }
83 
SetUp()84   virtual void SetUp() {
85     content::RenderViewHostTestHarness::SetUp();
86 
87     delegate.reset(new TestWebContentsModalDialogManagerDelegate);
88     WebContentsModalDialogManager::CreateForWebContents(web_contents());
89     manager = WebContentsModalDialogManager::FromWebContents(web_contents());
90     manager->SetDelegate(delegate.get());
91     test_api.reset(new WebContentsModalDialogManager::TestApi(manager));
92     native_manager = new TestNativeWebContentsModalDialogManager(manager);
93 
94     // |manager| owns |native_manager| as a result.
95     test_api->ResetNativeManager(native_manager);
96   }
97 
TearDown()98   virtual void TearDown() {
99     test_api.reset();
100     content::RenderViewHostTestHarness::TearDown();
101   }
102 
103  protected:
MakeFakeDialog()104   NativeWebContentsModalDialog MakeFakeDialog() {
105     // WebContentsModalDialogManager treats the NativeWebContentsModalDialog as
106     // an opaque type, so creating fake NativeWebContentsModalDialogs using
107     // reinterpret_cast is valid.
108     return reinterpret_cast<NativeWebContentsModalDialog>(next_dialog_id++);
109   }
110 
111   int next_dialog_id;
112   scoped_ptr<TestWebContentsModalDialogManagerDelegate> delegate;
113   WebContentsModalDialogManager* manager;
114   scoped_ptr<WebContentsModalDialogManager::TestApi> test_api;
115   TestNativeWebContentsModalDialogManager* native_manager;
116 
117   DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogManagerTest);
118 };
119 
120 NativeWebContentsModalDialogManager*
CreateNativeManager(NativeWebContentsModalDialogManagerDelegate * native_delegate)121 WebContentsModalDialogManager::CreateNativeManager(
122     NativeWebContentsModalDialogManagerDelegate* native_delegate) {
123   return new TestNativeWebContentsModalDialogManager(native_delegate);
124 }
125 
126 // Test that the dialog is shown immediately when the delegate indicates the web
127 // contents is visible.
TEST_F(WebContentsModalDialogManagerTest,WebContentsVisible)128 TEST_F(WebContentsModalDialogManagerTest, WebContentsVisible) {
129   // Dialog should be shown while WebContents is visible.
130   const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
131 
132   manager->ShowDialog(dialog1);
133 
134   EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
135             native_manager->GetDialogState(dialog1));
136   EXPECT_TRUE(manager->IsDialogActive());
137   EXPECT_TRUE(delegate->web_contents_blocked());
138 }
139 
140 // Test that the dialog is not shown immediately when the delegate indicates the
141 // web contents is not visible.
TEST_F(WebContentsModalDialogManagerTest,WebContentsNotVisible)142 TEST_F(WebContentsModalDialogManagerTest, WebContentsNotVisible) {
143   // Dialog should not be shown while WebContents is not visible.
144   delegate->set_web_contents_visible(false);
145 
146   const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
147 
148   manager->ShowDialog(dialog1);
149 
150   EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
151             native_manager->GetDialogState(dialog1));
152   EXPECT_TRUE(manager->IsDialogActive());
153   EXPECT_TRUE(delegate->web_contents_blocked());
154 }
155 
156 // Test that only the first of multiple dialogs is shown.
TEST_F(WebContentsModalDialogManagerTest,ShowDialogs)157 TEST_F(WebContentsModalDialogManagerTest, ShowDialogs) {
158   const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
159   const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
160   const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();
161 
162   manager->ShowDialog(dialog1);
163   manager->ShowDialog(dialog2);
164   manager->ShowDialog(dialog3);
165 
166   EXPECT_TRUE(delegate->web_contents_blocked());
167   EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
168             native_manager->GetDialogState(dialog1));
169   EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
170             native_manager->GetDialogState(dialog2));
171   EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
172             native_manager->GetDialogState(dialog3));
173 }
174 
175 // Test that the dialog is shown/hidden when the WebContents is shown/hidden.
TEST_F(WebContentsModalDialogManagerTest,VisibilityObservation)176 TEST_F(WebContentsModalDialogManagerTest, VisibilityObservation) {
177   const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
178 
179   manager->ShowDialog(dialog1);
180 
181   EXPECT_TRUE(manager->IsDialogActive());
182   EXPECT_TRUE(delegate->web_contents_blocked());
183   EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
184             native_manager->GetDialogState(dialog1));
185 
186   test_api->WebContentsWasHidden();
187 
188   EXPECT_TRUE(manager->IsDialogActive());
189   EXPECT_TRUE(delegate->web_contents_blocked());
190   EXPECT_EQ(TestNativeWebContentsModalDialogManager::HIDDEN,
191             native_manager->GetDialogState(dialog1));
192 
193   test_api->WebContentsWasShown();
194 
195   EXPECT_TRUE(manager->IsDialogActive());
196   EXPECT_TRUE(delegate->web_contents_blocked());
197   EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
198             native_manager->GetDialogState(dialog1));
199 }
200 
201 // Test that attaching an interstitial page closes dialogs configured to close.
TEST_F(WebContentsModalDialogManagerTest,InterstitialPage)202 TEST_F(WebContentsModalDialogManagerTest, InterstitialPage) {
203   const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
204   const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
205   const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();
206 
207   manager->ShowDialog(dialog1);
208   manager->ShowDialog(dialog2);
209   manager->ShowDialog(dialog3);
210 
211 #if defined(OS_WIN) || defined(USE_AURA)
212   manager->SetCloseOnInterstitialPage(dialog2, false);
213 #else
214   // TODO(wittman): Remove this section once Mac is changed to close on
215   // interstitial pages by default.
216   manager->SetCloseOnInterstitialPage(dialog1, true);
217   manager->SetCloseOnInterstitialPage(dialog3, true);
218 #endif
219 
220   test_api->DidAttachInterstitialPage();
221   EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
222             native_manager->GetDialogState(dialog1));
223   EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
224             native_manager->GetDialogState(dialog2));
225   EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
226             native_manager->GetDialogState(dialog3));
227 }
228 
229 
230 // Test that the first dialog is always shown, regardless of the order in which
231 // dialogs are closed.
TEST_F(WebContentsModalDialogManagerTest,CloseDialogs)232 TEST_F(WebContentsModalDialogManagerTest, CloseDialogs) {
233   // The front dialog is always shown regardless of dialog close order.
234   const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
235   const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
236   const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();
237   const NativeWebContentsModalDialog dialog4 = MakeFakeDialog();
238 
239   manager->ShowDialog(dialog1);
240   manager->ShowDialog(dialog2);
241   manager->ShowDialog(dialog3);
242   manager->ShowDialog(dialog4);
243 
244   native_manager->CloseDialog(dialog1);
245 
246   EXPECT_TRUE(manager->IsDialogActive());
247   EXPECT_TRUE(delegate->web_contents_blocked());
248   EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
249             native_manager->GetDialogState(dialog1));
250   EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
251             native_manager->GetDialogState(dialog2));
252   EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
253             native_manager->GetDialogState(dialog3));
254   EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
255             native_manager->GetDialogState(dialog4));
256 
257   native_manager->CloseDialog(dialog3);
258 
259   EXPECT_TRUE(manager->IsDialogActive());
260   EXPECT_TRUE(delegate->web_contents_blocked());
261   EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
262             native_manager->GetDialogState(dialog2));
263   EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
264             native_manager->GetDialogState(dialog3));
265   EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
266             native_manager->GetDialogState(dialog4));
267 
268   native_manager->CloseDialog(dialog2);
269 
270   EXPECT_TRUE(manager->IsDialogActive());
271   EXPECT_TRUE(delegate->web_contents_blocked());
272   EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
273             native_manager->GetDialogState(dialog2));
274   EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
275             native_manager->GetDialogState(dialog4));
276 
277   native_manager->CloseDialog(dialog4);
278 
279   EXPECT_FALSE(manager->IsDialogActive());
280   EXPECT_FALSE(delegate->web_contents_blocked());
281   EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
282             native_manager->GetDialogState(dialog4));
283 }
284 
285 // Test that CloseAllDialogs does what it says.
TEST_F(WebContentsModalDialogManagerTest,CloseAllDialogs)286 TEST_F(WebContentsModalDialogManagerTest, CloseAllDialogs) {
287   const int kWindowCount = 4;
288   for (int i = 0; i < kWindowCount; i++)
289     manager->ShowDialog(MakeFakeDialog());
290 
291   EXPECT_EQ(0, native_manager->GetCloseCount());
292 
293   test_api->CloseAllDialogs();
294   EXPECT_FALSE(delegate->web_contents_blocked());
295   EXPECT_FALSE(manager->IsDialogActive());
296   EXPECT_EQ(kWindowCount, native_manager->GetCloseCount());
297 }
298 
299 }  // namespace web_modal
300