diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/web_modal/web_contents_modal_dialog_manager.h | 4 | ||||
-rw-r--r-- | components/web_modal/web_contents_modal_dialog_manager_unittest.cc | 305 |
2 files changed, 271 insertions, 38 deletions
diff --git a/components/web_modal/web_contents_modal_dialog_manager.h b/components/web_modal/web_contents_modal_dialog_manager.h index 09115f0..5502c09 100644 --- a/components/web_modal/web_contents_modal_dialog_manager.h +++ b/components/web_modal/web_contents_modal_dialog_manager.h @@ -38,7 +38,9 @@ class WebContentsModalDialogManager // WillClose() when it is being destroyed. void ShowDialog(NativeWebContentsModalDialog dialog); - // Returns true if a dialog is currently being shown. + // Returns true if any dialogs are active and not closed. + // TODO(wittman): Give this a better name, since it can return true if no + // dialogs are displayed. bool IsShowingDialog() const; // Focus the topmost modal dialog. IsShowingDialog() must be true when diff --git a/components/web_modal/web_contents_modal_dialog_manager_unittest.cc b/components/web_modal/web_contents_modal_dialog_manager_unittest.cc index 42c46bc..837824e 100644 --- a/components/web_modal/web_contents_modal_dialog_manager_unittest.cc +++ b/components/web_modal/web_contents_modal_dialog_manager_unittest.cc @@ -2,37 +2,47 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <map> + +#include "base/memory/scoped_ptr.h" #include "components/web_modal/native_web_contents_modal_dialog_manager.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" +#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" +#include "content/public/browser/notification_details.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_source.h" +#include "content/public/browser/notification_types.h" #include "content/public/test/test_renderer_host.h" #include "testing/gtest/include/gtest/gtest.h" namespace web_modal { -class WebContentsModalDialogManagerTest - : public content::RenderViewHostTestHarness { - public: - virtual void SetUp() { - content::RenderViewHostTestHarness::SetUp(); - WebContentsModalDialogManager::CreateForWebContents(web_contents()); - } -}; - -class NativeWebContentsModalDialogManagerCloseTest +class TestNativeWebContentsModalDialogManager : public NativeWebContentsModalDialogManager { public: - explicit NativeWebContentsModalDialogManagerCloseTest( + enum DialogState { + UNKNOWN, + NOT_SHOWN, + SHOWN, + HIDDEN, + CLOSED + }; + + explicit TestNativeWebContentsModalDialogManager( NativeWebContentsModalDialogManagerDelegate* delegate) - : close_count_(0), delegate_(delegate) {} + : delegate_(delegate) {} virtual void ManageDialog(NativeWebContentsModalDialog dialog) OVERRIDE { + dialog_state_[dialog] = NOT_SHOWN; } virtual void ShowDialog(NativeWebContentsModalDialog dialog) OVERRIDE { + dialog_state_[dialog] = SHOWN; } virtual void HideDialog(NativeWebContentsModalDialog dialog) OVERRIDE { + dialog_state_[dialog] = HIDDEN; } virtual void CloseDialog(NativeWebContentsModalDialog dialog) OVERRIDE { delegate_->WillClose(dialog); - ++close_count_; + dialog_state_[dialog] = CLOSED; } virtual void FocusDialog(NativeWebContentsModalDialog dialog) OVERRIDE { } @@ -41,46 +51,267 @@ class NativeWebContentsModalDialogManagerCloseTest virtual void HostChanged(WebContentsModalDialogHost* new_host) OVERRIDE { } - int close_count() const { return close_count_; } + int GetCloseCount() const { + int count = 0; + for (DialogStateMap::const_iterator it = dialog_state_.begin(); + it != dialog_state_.end(); ++it) { + if (it->second == CLOSED) + count++; + } + return count; + } + + DialogState GetDialogState(NativeWebContentsModalDialog dialog) const { + DialogStateMap::const_iterator loc = dialog_state_.find(dialog); + return loc == dialog_state_.end() ? UNKNOWN : loc->second; + } private: - int close_count_; + typedef std::map<NativeWebContentsModalDialog, DialogState> DialogStateMap; + NativeWebContentsModalDialogManagerDelegate* delegate_; + DialogStateMap dialog_state_; + + DISALLOW_COPY_AND_ASSIGN(TestNativeWebContentsModalDialogManager); +}; + +class TestWebContentsModalDialogManagerDelegate + : public WebContentsModalDialogManagerDelegate { + public: + TestWebContentsModalDialogManagerDelegate() + : web_contents_visible_(true), + web_contents_blocked_(false) { + } + + // WebContentsModalDialogManagerDelegate overrides + virtual void SetWebContentsBlocked(content::WebContents* web_contents, + bool blocked) OVERRIDE { + web_contents_blocked_ = blocked; + } - DISALLOW_COPY_AND_ASSIGN(NativeWebContentsModalDialogManagerCloseTest); + virtual WebContentsModalDialogHost* GetWebContentsModalDialogHost() OVERRIDE { + return NULL; + } + + virtual bool IsWebContentsVisible( + content::WebContents* web_contents) OVERRIDE { + return web_contents_visible_; + } + + void set_web_contents_visible(bool visible) { + web_contents_visible_ = visible; + } + + bool web_contents_blocked() const { return web_contents_blocked_; } + + private: + bool web_contents_visible_; + bool web_contents_blocked_; + + DISALLOW_COPY_AND_ASSIGN(TestWebContentsModalDialogManagerDelegate); +}; + +class WebContentsModalDialogManagerTest + : public content::RenderViewHostTestHarness { + public: + WebContentsModalDialogManagerTest() + : next_dialog_id(1), + manager(NULL), + native_manager(NULL) { + } + + virtual void SetUp() { + content::RenderViewHostTestHarness::SetUp(); + + delegate.reset(new TestWebContentsModalDialogManagerDelegate); + WebContentsModalDialogManager::CreateForWebContents(web_contents()); + manager = WebContentsModalDialogManager::FromWebContents(web_contents()); + manager->SetDelegate(delegate.get()); + test_api.reset(new WebContentsModalDialogManager::TestApi(manager)); + native_manager = new TestNativeWebContentsModalDialogManager(manager); + + // |manager| owns |native_manager| as a result. + test_api->ResetNativeManager(native_manager); + } + + virtual void TearDown() { + test_api.reset(); + content::RenderViewHostTestHarness::TearDown(); + } + + protected: + NativeWebContentsModalDialog MakeFakeDialog() { + // WebContentsModalDialogManager treats the NativeWebContentsModalDialog as + // an opaque type, so creating fake NativeWebContentsModalDialogs using + // reinterpret_cast is valid. + return reinterpret_cast<NativeWebContentsModalDialog>(next_dialog_id++); + } + + int next_dialog_id; + scoped_ptr<TestWebContentsModalDialogManagerDelegate> delegate; + WebContentsModalDialogManager* manager; + scoped_ptr<WebContentsModalDialogManager::TestApi> test_api; + TestNativeWebContentsModalDialogManager* native_manager; + + DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogManagerTest); }; NativeWebContentsModalDialogManager* WebContentsModalDialogManager::CreateNativeManager( NativeWebContentsModalDialogManagerDelegate* native_delegate) { - return new NativeWebContentsModalDialogManagerCloseTest(native_delegate); + return new TestNativeWebContentsModalDialogManager(native_delegate); +} + +// Test that the dialog is shown immediately when the delegate indicates the web +// contents is visible. +TEST_F(WebContentsModalDialogManagerTest, WebContentsVisible) { + // Dialog should be shown while WebContents is visible. + const NativeWebContentsModalDialog dialog1 = MakeFakeDialog(); + + manager->ShowDialog(dialog1); + + EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN, + native_manager->GetDialogState(dialog1)); + EXPECT_TRUE(manager->IsShowingDialog()); + EXPECT_TRUE(delegate->web_contents_blocked()); +} + +// Test that the dialog is not shown immediately when the delegate indicates the +// web contents is not visible. +TEST_F(WebContentsModalDialogManagerTest, WebContentsNotVisible) { + // Dialog should not be shown while WebContents is not visible. + delegate->set_web_contents_visible(false); + + const NativeWebContentsModalDialog dialog1 = MakeFakeDialog(); + + manager->ShowDialog(dialog1); + + EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN, + native_manager->GetDialogState(dialog1)); + EXPECT_TRUE(manager->IsShowingDialog()); + EXPECT_TRUE(delegate->web_contents_blocked()); +} + +// Test that only the first of multiple dialogs is shown. +TEST_F(WebContentsModalDialogManagerTest, ShowDialogs) { + const NativeWebContentsModalDialog dialog1 = MakeFakeDialog(); + const NativeWebContentsModalDialog dialog2 = MakeFakeDialog(); + const NativeWebContentsModalDialog dialog3 = MakeFakeDialog(); + + manager->ShowDialog(dialog1); + manager->ShowDialog(dialog2); + manager->ShowDialog(dialog3); + + EXPECT_TRUE(delegate->web_contents_blocked()); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN, + native_manager->GetDialogState(dialog1)); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN, + native_manager->GetDialogState(dialog2)); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN, + native_manager->GetDialogState(dialog3)); } -TEST_F(WebContentsModalDialogManagerTest, WebContentsModalDialogs) { - WebContentsModalDialogManager* web_contents_modal_dialog_manager = - WebContentsModalDialogManager::FromWebContents(web_contents()); - WebContentsModalDialogManager::TestApi test_api( - web_contents_modal_dialog_manager); +// Test that the dialog is shown/hidden on +// NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED. +TEST_F(WebContentsModalDialogManagerTest, VisibilityObservation) { + const NativeWebContentsModalDialog dialog1 = MakeFakeDialog(); + bool web_contents_visible = true; - NativeWebContentsModalDialogManagerCloseTest* native_manager = - new NativeWebContentsModalDialogManagerCloseTest( - web_contents_modal_dialog_manager); + manager->ShowDialog(dialog1); - // |web_contents_modal_dialog_manager| owns |native_manager| as a result. - test_api.ResetNativeManager(native_manager); + EXPECT_TRUE(manager->IsShowingDialog()); + EXPECT_TRUE(delegate->web_contents_blocked()); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN, + native_manager->GetDialogState(dialog1)); + web_contents_visible = false; + manager->Observe(content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, + content::NotificationService::AllSources(), + content::Details<bool>(&web_contents_visible)); + + EXPECT_TRUE(manager->IsShowingDialog()); + EXPECT_TRUE(delegate->web_contents_blocked()); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::HIDDEN, + native_manager->GetDialogState(dialog1)); + + web_contents_visible = true; + manager->Observe(content::NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, + content::NotificationService::AllSources(), + content::Details<bool>(&web_contents_visible)); + + EXPECT_TRUE(manager->IsShowingDialog()); + EXPECT_TRUE(delegate->web_contents_blocked()); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN, + native_manager->GetDialogState(dialog1)); +} + +// Test that the first dialog is always shown, regardless of the order in which +// dialogs are closed. +TEST_F(WebContentsModalDialogManagerTest, CloseDialogs) { + // The front dialog is always shown regardless of dialog close order. + const NativeWebContentsModalDialog dialog1 = MakeFakeDialog(); + const NativeWebContentsModalDialog dialog2 = MakeFakeDialog(); + const NativeWebContentsModalDialog dialog3 = MakeFakeDialog(); + const NativeWebContentsModalDialog dialog4 = MakeFakeDialog(); + + manager->ShowDialog(dialog1); + manager->ShowDialog(dialog2); + manager->ShowDialog(dialog3); + manager->ShowDialog(dialog4); + + native_manager->CloseDialog(dialog1); + + EXPECT_TRUE(manager->IsShowingDialog()); + EXPECT_TRUE(delegate->web_contents_blocked()); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED, + native_manager->GetDialogState(dialog1)); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN, + native_manager->GetDialogState(dialog2)); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN, + native_manager->GetDialogState(dialog3)); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN, + native_manager->GetDialogState(dialog4)); + + native_manager->CloseDialog(dialog3); + + EXPECT_TRUE(manager->IsShowingDialog()); + EXPECT_TRUE(delegate->web_contents_blocked()); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN, + native_manager->GetDialogState(dialog2)); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED, + native_manager->GetDialogState(dialog3)); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN, + native_manager->GetDialogState(dialog4)); + + native_manager->CloseDialog(dialog2); + + EXPECT_TRUE(manager->IsShowingDialog()); + EXPECT_TRUE(delegate->web_contents_blocked()); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED, + native_manager->GetDialogState(dialog2)); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN, + native_manager->GetDialogState(dialog4)); + + native_manager->CloseDialog(dialog4); + + EXPECT_FALSE(manager->IsShowingDialog()); + EXPECT_FALSE(delegate->web_contents_blocked()); + EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED, + native_manager->GetDialogState(dialog4)); +} + +// Test that CloseAllDialogs does what it says. +TEST_F(WebContentsModalDialogManagerTest, CloseAllDialogs) { const int kWindowCount = 4; - for (int i = 0; i < kWindowCount; i++) { - // WebContentsModalDialogManager treats the NativeWebContentsModalDialog as - // an opaque type, so creating fake NativeWebContentsModalDialogs using - // reinterpret_cast is valid. - web_contents_modal_dialog_manager->ShowDialog( - reinterpret_cast<NativeWebContentsModalDialog>(i)); - } - EXPECT_EQ(0, native_manager->close_count()); + for (int i = 0; i < kWindowCount; i++) + manager->ShowDialog(MakeFakeDialog()); + + EXPECT_EQ(0, native_manager->GetCloseCount()); - test_api.CloseAllDialogs(); - EXPECT_EQ(kWindowCount, native_manager->close_count()); + test_api->CloseAllDialogs(); + EXPECT_FALSE(delegate->web_contents_blocked()); + EXPECT_FALSE(manager->IsShowingDialog()); + EXPECT_EQ(kWindowCount, native_manager->GetCloseCount()); } } // namespace web_modal |