blob: 7095498a4b8c7c393d91ebec6d9aac41918c4bb3 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include <map>
#include "base/memory/scoped_ptr.h"
#include "components/web_modal/native_web_contents_modal_dialog_manager.h"
#include "components/web_modal/test_web_contents_modal_dialog_manager_delegate.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace web_modal {
class TestNativeWebContentsModalDialogManager
: public NativeWebContentsModalDialogManager {
public:
enum DialogState {
UNKNOWN,
NOT_SHOWN,
SHOWN,
HIDDEN,
CLOSED
};
explicit TestNativeWebContentsModalDialogManager(
NativeWebContentsModalDialogManagerDelegate* 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);
dialog_state_[dialog] = CLOSED;
}
virtual void FocusDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
}
virtual void PulseDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
}
virtual void HostChanged(WebContentsModalDialogHost* new_host) OVERRIDE {
}
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:
typedef std::map<NativeWebContentsModalDialog, DialogState> DialogStateMap;
NativeWebContentsModalDialogManagerDelegate* delegate_;
DialogStateMap dialog_state_;
DISALLOW_COPY_AND_ASSIGN(TestNativeWebContentsModalDialogManager);
};
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 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->IsDialogActive());
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->IsDialogActive());
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 that the dialog is shown/hidden when the WebContents is shown/hidden.
TEST_F(WebContentsModalDialogManagerTest, VisibilityObservation) {
const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
manager->ShowDialog(dialog1);
EXPECT_TRUE(manager->IsDialogActive());
EXPECT_TRUE(delegate->web_contents_blocked());
EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
native_manager->GetDialogState(dialog1));
test_api->WebContentsWasHidden();
EXPECT_TRUE(manager->IsDialogActive());
EXPECT_TRUE(delegate->web_contents_blocked());
EXPECT_EQ(TestNativeWebContentsModalDialogManager::HIDDEN,
native_manager->GetDialogState(dialog1));
test_api->WebContentsWasShown();
EXPECT_TRUE(manager->IsDialogActive());
EXPECT_TRUE(delegate->web_contents_blocked());
EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
native_manager->GetDialogState(dialog1));
}
// Test that attaching an interstitial WebUI page closes dialogs configured to
// close on interstitial WebUI.
TEST_F(WebContentsModalDialogManagerTest, InterstitialWebUI) {
const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();
manager->ShowDialog(dialog1);
manager->ShowDialog(dialog2);
manager->ShowDialog(dialog3);
manager->SetCloseOnInterstitialWebUI(dialog1, true);
manager->SetCloseOnInterstitialWebUI(dialog3, true);
test_api->DidAttachInterstitialPage();
EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
native_manager->GetDialogState(dialog1));
EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
native_manager->GetDialogState(dialog2));
EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
native_manager->GetDialogState(dialog3));
}
// 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->IsDialogActive());
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->IsDialogActive());
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->IsDialogActive());
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->IsDialogActive());
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++)
manager->ShowDialog(MakeFakeDialog());
EXPECT_EQ(0, native_manager->GetCloseCount());
test_api->CloseAllDialogs();
EXPECT_FALSE(delegate->web_contents_blocked());
EXPECT_FALSE(manager->IsDialogActive());
EXPECT_EQ(kWindowCount, native_manager->GetCloseCount());
}
} // namespace web_modal