summaryrefslogtreecommitdiffstats
path: root/ceee/ie/plugin
diff options
context:
space:
mode:
authormad@google.com <mad@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-17 17:50:11 +0000
committermad@google.com <mad@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-17 17:50:11 +0000
commita66464ec0d01381ed75f8514076c75c8d30d9ddd (patch)
tree35160e2cd62c73ee9441e8cbbed53726472e24f2 /ceee/ie/plugin
parentf65e1af922ff4178abcc0566be137c23793bd9c3 (diff)
downloadchromium_src-a66464ec0d01381ed75f8514076c75c8d30d9ddd.zip
chromium_src-a66464ec0d01381ed75f8514076c75c8d30d9ddd.tar.gz
chromium_src-a66464ec0d01381ed75f8514076c75c8d30d9ddd.tar.bz2
Committing for Vadim:
http://codereview.chromium.org/4991002/ New unittests for infobar. BUG=None TEST=None git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66459 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ceee/ie/plugin')
-rw-r--r--ceee/ie/plugin/bho/executor_unittest.cc68
-rw-r--r--ceee/ie/plugin/bho/infobar_manager.cc65
-rw-r--r--ceee/ie/plugin/bho/infobar_manager.h26
-rw-r--r--ceee/ie/plugin/bho/infobar_manager_unittest.cc203
-rw-r--r--ceee/ie/plugin/bho/infobar_window.cc13
-rw-r--r--ceee/ie/plugin/bho/infobar_window.h15
-rw-r--r--ceee/ie/plugin/bho/infobar_window_unittest.cc181
7 files changed, 535 insertions, 36 deletions
diff --git a/ceee/ie/plugin/bho/executor_unittest.cc b/ceee/ie/plugin/bho/executor_unittest.cc
index d68f2d0..f18736d 100644
--- a/ceee/ie/plugin/bho/executor_unittest.cc
+++ b/ceee/ie/plugin/bho/executor_unittest.cc
@@ -19,6 +19,7 @@
#include "ceee/ie/common/ie_util.h"
#include "ceee/ie/common/mock_ie_tab_interfaces.h"
#include "ceee/ie/plugin/bho/executor.h"
+#include "ceee/ie/plugin/bho/infobar_manager.h"
#include "ceee/ie/testing/mock_broker_and_friends.h"
#include "ceee/ie/testing/mock_frame_event_handler_host.h"
#include "ceee/common/initializing_coclass.h"
@@ -80,6 +81,15 @@ class TestingMockExecutorCreatorTeardown
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, Teardown, HRESULT(long));
};
+class MockInfobarManager : public infobar_api::InfobarManager {
+ public:
+ MockInfobarManager() : InfobarManager(kGoodWindow) {}
+ MOCK_METHOD4(Show, HRESULT(infobar_api::InfobarType, int,
+ const std::wstring&, bool));
+ MOCK_METHOD1(Hide, HRESULT(infobar_api::InfobarType));
+ MOCK_METHOD0(HideAll, void());
+};
+
TEST(ExecutorCreator, ProperTearDownOnDestruction) {
StrictMock<TestingMockExecutorCreatorTeardown>* executor_creator = NULL;
CComPtr<ICeeeExecutorCreator> executor_creator_keeper;
@@ -315,6 +325,14 @@ class TestingExecutor
void set_id(HWND hwnd) {
hwnd_ = hwnd;
}
+ void InitializeInfobarManager(MockInfobarManager** manager) {
+ ASSERT_TRUE(manager != NULL);
+ *manager = new MockInfobarManager();
+ infobar_manager_.reset(*manager);
+ }
+ void TerminateInfobarManager() {
+ infobar_manager_.reset(NULL);
+ }
static BOOL MockEnumChildWindows(HWND, WNDENUMPROC, LPARAM p) {
std::vector<HWND>* tab_windows = reinterpret_cast<std::vector<HWND>*>(p);
*tab_windows = tab_windows_;
@@ -1083,6 +1101,54 @@ TEST_F(ExecutorTests, RegisterCookieStore) {
EXPECT_EQ(S_OK, executor_->CookieStoreIsRegistered());
}
-// TODO(vadimb@google.com): Add unit tests for infobar APIs.
+TEST_F(ExecutorTests, ShowInfobar) {
+ testing::LogDisabler no_dchecks;
+ CComBSTR url(L"/infobar/test.html");
+ CComBSTR empty_url(L"");
+ CComBSTR extension_id(L"abcdefjh");
+
+ // Calling when manager has not been initialized.
+ EXPECT_HRESULT_FAILED(executor_->ShowInfobar(url, NULL));
+
+ // Initializing the manager and calling it with different parameters.
+ MockInfobarManager* manager;
+ executor_->InitializeInfobarManager(&manager);
+
+ EXPECT_CALL(*manager, Show(infobar_api::TOP_INFOBAR, _,
+ std::wstring(url.m_str), true)).
+ WillOnce(Return(S_OK));
+ EXPECT_CALL(mock_window_utils_, GetTopLevelParent(_)).
+ WillRepeatedly(Return(kGoodWindow));
+ CeeeWindowHandle window_handle;
+
+ EXPECT_HRESULT_SUCCEEDED(executor_->ShowInfobar(url, &window_handle));
+ EXPECT_EQ(reinterpret_cast<CeeeWindowHandle>(kGoodWindow), window_handle);
+
+ EXPECT_CALL(*manager, HideAll()).Times(1);
+ EXPECT_HRESULT_SUCCEEDED(executor_->ShowInfobar(empty_url, &window_handle));
+ EXPECT_EQ(0, window_handle);
+
+ EXPECT_CALL(*manager, Show(infobar_api::TOP_INFOBAR, _,
+ std::wstring(url.m_str), true)).
+ WillOnce(Return(E_FAIL));
+ EXPECT_HRESULT_FAILED(executor_->ShowInfobar(url, &window_handle));
+ EXPECT_EQ(0, window_handle);
+
+ EXPECT_CALL(*manager, HideAll()).Times(1);
+ EXPECT_HRESULT_SUCCEEDED(executor_->OnTopFrameBeforeNavigate(url));
+
+ EXPECT_HRESULT_SUCCEEDED(executor_->SetExtensionId(extension_id));
+ std::wstring full_url(L"chrome-extension://");
+ full_url += extension_id.m_str;
+ full_url += url.m_str;
+ EXPECT_CALL(*manager, Show(infobar_api::TOP_INFOBAR, _, full_url, true)).
+ WillOnce(Return(S_OK));
+ EXPECT_HRESULT_SUCCEEDED(executor_->ShowInfobar(url, &window_handle));
+
+ // Have to destroy the manager before LogDisabler from this test goes out of
+ // scope.
+ EXPECT_CALL(user32_, IsWindow(NULL)).WillRepeatedly(Return(FALSE));
+ executor_->TerminateInfobarManager();
+}
} // namespace
diff --git a/ceee/ie/plugin/bho/infobar_manager.cc b/ceee/ie/plugin/bho/infobar_manager.cc
index 6b969f6..30ff9a9 100644
--- a/ceee/ie/plugin/bho/infobar_manager.cc
+++ b/ceee/ie/plugin/bho/infobar_manager.cc
@@ -31,7 +31,9 @@ namespace infobar_api {
// WM_NCCALCSIZE to resize its client area. It also handles WM_SIZE and WM_MOVE
// messages to make infobars consistent with IE content window's size and
// position.
-class InfobarManager::ContainerWindow : public CWindowImpl<ContainerWindow> {
+class InfobarManager::ContainerWindow
+ : public InfobarManager::ContainerWindowInterface,
+ public CWindowImpl<ContainerWindow> {
public:
ContainerWindow(HWND container, InfobarManager* manager)
: infobar_manager_(manager) {
@@ -44,10 +46,18 @@ class InfobarManager::ContainerWindow : public CWindowImpl<ContainerWindow> {
UnsubclassWindow();
}
- bool destroyed() const {
+ virtual bool IsDestroyed() const {
return destroyed_;
}
+ virtual HWND GetWindowHandle() const {
+ return IsWindow() ? m_hWnd : NULL;
+ }
+
+ virtual bool PostWindowsMessage(UINT msg, WPARAM wparam, LPARAM lparam) {
+ return PostMessage(msg, wparam, lparam) != 0;
+ }
+
BEGIN_MSG_MAP_EX(ContainerWindow)
MSG_WM_NCCALCSIZE(OnNcCalcSize)
MSG_WM_SIZE(OnSize)
@@ -135,17 +145,11 @@ class InfobarManager::ContainerWindow : public CWindowImpl<ContainerWindow> {
InfobarManager::InfobarManager(HWND tab_window)
: tab_window_(tab_window) {
- for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
- // Note that when InfobarManager is being initialized the IE has not created
- // the tab. Therefore we cannot find the container window here and have to
- // pass interface for a function that finds windows to be called later.
- infobars_[index].reset(
- InfobarWindow::CreateInfobar(static_cast<InfobarType>(index), this));
- }
}
HRESULT InfobarManager::Show(InfobarType type, int max_height,
const std::wstring& url, bool slide) {
+ LazyInitialize(type);
if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE ||
infobars_[type] == NULL) {
return E_INVALIDARG;
@@ -155,8 +159,7 @@ HRESULT InfobarManager::Show(InfobarType type, int max_height,
infobars_[type]->Navigate(url);
// Create the window if not created.
if (!infobars_[type]->IsWindow()) {
- infobars_[type]->Create(tab_window_, NULL, NULL,
- WS_CHILD | WS_CLIPCHILDREN);
+ infobars_[type]->InternalCreate(tab_window_, WS_CHILD | WS_CLIPCHILDREN);
}
if (!infobars_[type]->IsWindow())
return E_UNEXPECTED;
@@ -166,10 +169,12 @@ HRESULT InfobarManager::Show(InfobarType type, int max_height,
}
HRESULT InfobarManager::Hide(InfobarType type) {
- if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE ||
- infobars_[type] == NULL) {
+ if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE)
return E_INVALIDARG;
- }
+ // No lazy initialization here - if the infobar has not been created just
+ // return;
+ if (infobars_[type] == NULL)
+ return E_UNEXPECTED;
// There is a choice either to hide or to destroy the infobar window.
// This implementation destroys the infobar to save resources and stop all
// scripts that possibly still run in the window. If we want to just hide the
@@ -208,7 +213,7 @@ static BOOL CALLBACK FindContentParentWindowsProc(HWND hwnd, LPARAM lparam) {
}
HWND InfobarManager::GetContainerWindow() {
- if (container_window_ != NULL && container_window_->destroyed())
+ if (container_window_ != NULL && container_window_->IsDestroyed())
container_window_.reset(NULL);
if (container_window_ == NULL) {
@@ -221,12 +226,13 @@ HWND InfobarManager::GetContainerWindow() {
DCHECK(content_parent_window);
if (content_parent_window != NULL) {
container_window_.reset(
- new ContainerWindow(content_parent_window, this));
+ CreateContainerWindow(content_parent_window, this));
}
}
}
- DCHECK(container_window_ != NULL && container_window_->IsWindow());
- return container_window_->m_hWnd;
+ DCHECK(container_window_ != NULL &&
+ container_window_->GetWindowHandle() != NULL);
+ return container_window_->GetWindowHandle();
}
void InfobarManager::OnWindowClose(InfobarType type) {
@@ -234,8 +240,8 @@ void InfobarManager::OnWindowClose(InfobarType type) {
// infobar window right away as it may result on deleting the object that
// started this callback. So instead we post ourtselves the message.
if (container_window_ != NULL)
- container_window_->PostMessage(TM_DELAYED_CLOSE_INFOBAR,
- static_cast<WPARAM>(type), 0);
+ container_window_->PostWindowsMessage(TM_DELAYED_CLOSE_INFOBAR,
+ static_cast<WPARAM>(type), 0);
}
void InfobarManager::OnContainerWindowNcCalcSize(RECT* rect) {
@@ -267,4 +273,23 @@ void InfobarManager::OnContainerWindowDestroy() {
}
}
+void InfobarManager::LazyInitialize(InfobarType type) {
+ DCHECK(type >= FIRST_INFOBAR_TYPE && type < END_OF_INFOBAR_TYPE);
+ if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE)
+ return;
+
+ if (infobars_[type] != NULL)
+ return;
+
+ // Note that when InfobarManager is being initialized the IE has not created
+ // the tab. Therefore we cannot find the container window here and have to
+ // pass interface for a function that finds windows to be called later.
+ infobars_[type].reset(InfobarWindow::CreateInfobar(type, this));
+}
+
+InfobarManager::ContainerWindowInterface* InfobarManager::CreateContainerWindow(
+ HWND container, InfobarManager* manager) {
+ return new ContainerWindow(container, manager);
+}
+
} // namespace infobar_api
diff --git a/ceee/ie/plugin/bho/infobar_manager.h b/ceee/ie/plugin/bho/infobar_manager.h
index dead924..d09e3d9 100644
--- a/ceee/ie/plugin/bho/infobar_manager.h
+++ b/ceee/ie/plugin/bho/infobar_manager.h
@@ -24,12 +24,12 @@ class InfobarManager : public InfobarWindow::Delegate,
// Shows the infobar of the specified type and navigates it to the specified
// URL.
- HRESULT Show(InfobarType type, int max_height, const std::wstring& url,
- bool slide);
+ virtual HRESULT Show(InfobarType type, int max_height,
+ const std::wstring& url, bool slide);
// Hides the infobar of the specified type.
- HRESULT Hide(InfobarType type);
+ virtual HRESULT Hide(InfobarType type);
// Hides all infobars.
- void HideAll();
+ virtual void HideAll();
// Implementation of InfobarWindow::Delegate.
// Finds the handle of the container window.
@@ -37,14 +37,28 @@ class InfobarManager : public InfobarWindow::Delegate,
// Informs about window.close() event.
virtual void OnWindowClose(InfobarType type);
- private:
+ protected:
class ContainerWindow;
+ class ContainerWindowInterface {
+ public:
+ virtual ~ContainerWindowInterface() {}
+ virtual bool IsDestroyed() const = 0;
+ virtual HWND GetWindowHandle() const = 0;
+ virtual bool PostWindowsMessage(UINT msg, WPARAM wparam, LPARAM lparam) = 0;
+ };
+
+ // Lazy initialization of InfobarWindow object.
+ void LazyInitialize(InfobarType type);
+
+ // Creates container window. Separated for the unit testing.
+ virtual ContainerWindowInterface* CreateContainerWindow(
+ HWND container, InfobarManager* manager);
// The HWND of the tab window the infobars are associated with.
HWND tab_window_;
// Parent window for IE content window.
- scoped_ptr<ContainerWindow> container_window_;
+ scoped_ptr<ContainerWindowInterface> container_window_;
// Infobar windows.
scoped_ptr<InfobarWindow> infobars_[END_OF_INFOBAR_TYPE];
diff --git a/ceee/ie/plugin/bho/infobar_manager_unittest.cc b/ceee/ie/plugin/bho/infobar_manager_unittest.cc
new file mode 100644
index 0000000..610634e
--- /dev/null
+++ b/ceee/ie/plugin/bho/infobar_manager_unittest.cc
@@ -0,0 +1,203 @@
+// Copyright (c) 2010 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.
+//
+// Infobar manager implementation unit tests.
+
+// MockWin32 must not be included after atlwin, which is included by some
+// headers in here, so we need to put it at the top:
+#include "ceee/testing/utils/mock_win32.h" // NOLINT
+
+#include "ceee/ie/plugin/bho/infobar_manager.h"
+#include "ceee/ie/plugin/bho/infobar_window.h"
+#include "ceee/testing/utils/instance_count_mixin.h"
+#include "ceee/testing/utils/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "broker_lib.h" // NOLINT
+
+namespace {
+
+using testing::_;
+using testing::Invoke;
+using testing::InvokeWithoutArgs;
+using testing::NotNull;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+const HWND kGoodWindow = reinterpret_cast<HWND>(42);
+const HWND kParentWindow = reinterpret_cast<HWND>(77);
+const HWND kInfobarWindow = reinterpret_cast<HWND>(91);
+const wchar_t* kUrl1 = L"/infobar/test.html";
+const int kMaxHeight = 55;
+
+class MockInfobarDelegate : public infobar_api::InfobarWindow::Delegate {
+ public:
+ MOCK_METHOD0(GetContainerWindow, HWND());
+ MOCK_METHOD1(OnWindowClose, void(infobar_api::InfobarType));
+};
+
+class MockInfobarWindow : public infobar_api::InfobarWindow {
+ public:
+ MockInfobarWindow(infobar_api::InfobarType type, Delegate* delegate)
+ : infobar_api::InfobarWindow(type, delegate) {}
+ MOCK_METHOD2(InternalCreate, HWND(HWND, DWORD));
+ MOCK_METHOD2(Show, HRESULT(int, bool));
+ MOCK_METHOD0(Hide, HRESULT());
+ MOCK_METHOD1(Navigate, HRESULT(const std::wstring& url));
+ MOCK_METHOD0(Reset, void());
+
+ HWND SetInfobarHwnd() {
+ m_hWnd = kInfobarWindow;
+ return m_hWnd;
+ }
+};
+
+class TestingInfobarManager : public infobar_api::InfobarManager {
+ public:
+ class MockContainerWindow : public ContainerWindowInterface {
+ public:
+ // TODO(vadimb@google.com): Mock these two methods and test different
+ // behaviors when they return different values.
+ virtual bool IsDestroyed() const { return false; }
+ virtual HWND GetWindowHandle() const { return kParentWindow; }
+ MOCK_METHOD3(PostWindowsMessage, bool(UINT, WPARAM, LPARAM));
+ };
+
+ explicit TestingInfobarManager(HWND tab_window)
+ : infobar_api::InfobarManager(tab_window) {
+ }
+
+ MockInfobarWindow* GetInfobarWindow(infobar_api::InfobarType type) {
+ if (type < infobar_api::FIRST_INFOBAR_TYPE ||
+ type >= infobar_api::END_OF_INFOBAR_TYPE) {
+ return NULL;
+ }
+ return reinterpret_cast<MockInfobarWindow*>(infobars_[type].get());
+ }
+
+ void InitInfobarWindow(infobar_api::InfobarType type, Delegate* delegate) {
+ ASSERT_TRUE(type >= infobar_api::FIRST_INFOBAR_TYPE &&
+ type < infobar_api::END_OF_INFOBAR_TYPE);
+ ASSERT_TRUE(infobars_[type] == NULL);
+ infobars_[type].reset(new MockInfobarWindow(type, delegate));
+ }
+
+ virtual ContainerWindowInterface* CreateContainerWindow(
+ HWND container, InfobarManager* manager) {
+ return new MockContainerWindow;
+ }
+
+ void SetContainerWindow(ContainerWindowInterface* window) {
+ container_window_.reset(window);
+ }
+
+ void EmulateOnClose(infobar_api::InfobarType type) {
+ OnWindowClose(type);
+ OnContainerWindowDelayedCloseInfobar(type);
+ }
+};
+
+class InfobarManagerTests : public testing::Test {
+ public:
+ virtual void SetUp() {
+ infobar_delegate_.reset(new MockInfobarDelegate);
+ infobar_manager_.reset(new TestingInfobarManager(kGoodWindow));
+
+ EXPECT_CALL(user32_, IsWindow(kParentWindow)).WillRepeatedly(Return(TRUE));
+ EXPECT_CALL(user32_, IsWindow(kGoodWindow)).WillRepeatedly(Return(TRUE));
+ EXPECT_CALL(user32_, IsWindow(kInfobarWindow)).WillRepeatedly(Return(TRUE));
+ EXPECT_CALL(user32_, IsWindow(NULL)).WillRepeatedly(Return(FALSE));
+ EXPECT_CALL(user32_, GetParent(_)).WillRepeatedly(Return(kGoodWindow));
+
+ // Arbitrary number to return from GetWindowRect. Unique to make it easier
+ // to trace in the debugger or to add in future tests dependent on return
+ // values.
+ RECT window_rect = {131, 213, 831, 1013};
+ EXPECT_CALL(user32_, GetWindowRect(_, NotNull())).
+ WillRepeatedly(DoAll(SetArgumentPointee<1>(window_rect), Return(TRUE)));
+ }
+ virtual void TearDown() {
+ testing::LogDisabler no_dchecks;
+ infobar_manager_.reset(NULL);
+ infobar_delegate_.reset(NULL);
+
+ // Everything should have been relinquished.
+ ASSERT_EQ(0, testing::InstanceCountMixinBase::all_instance_count());
+}
+
+ protected:
+ static BOOL MockEnumChildWindows(HWND, WNDENUMPROC, LPARAM lparam) {
+ HWND* window_handle = reinterpret_cast<HWND*>(lparam);
+ if (window_handle)
+ *window_handle = kParentWindow;
+ return TRUE;
+ }
+
+ StrictMock<testing::MockUser32> user32_;
+ scoped_ptr<MockInfobarDelegate> infobar_delegate_;
+ scoped_ptr<TestingInfobarManager> infobar_manager_;
+};
+
+TEST_F(InfobarManagerTests, GetContainerWindow) {
+ EXPECT_CALL(user32_, EnumChildWindows(kGoodWindow, _, _)).
+ WillOnce(Invoke(MockEnumChildWindows));
+
+ ASSERT_EQ(kParentWindow, infobar_manager_->GetContainerWindow());
+ // Next time it should not call EnumChildWindows.
+ ASSERT_EQ(kParentWindow, infobar_manager_->GetContainerWindow());
+}
+
+TEST_F(InfobarManagerTests, ShowHide) {
+ infobar_manager_->InitInfobarWindow(infobar_api::TOP_INFOBAR,
+ infobar_delegate_.get());
+
+ // Test Show first.
+ MockInfobarWindow* infobar_window =
+ infobar_manager_->GetInfobarWindow(infobar_api::TOP_INFOBAR);
+ const std::wstring url(kUrl1);
+ EXPECT_CALL(*infobar_window, Navigate(url)).WillOnce(Return(S_OK));
+ EXPECT_CALL(*infobar_window, InternalCreate(kGoodWindow, _)).
+ WillOnce(WithoutArgs(Invoke(infobar_window,
+ &MockInfobarWindow::SetInfobarHwnd)));
+ EXPECT_CALL(*infobar_window, Show(kMaxHeight, false));
+ EXPECT_CALL(*infobar_delegate_, GetContainerWindow()).
+ WillRepeatedly(Return(kParentWindow));
+ EXPECT_CALL(user32_, SetWindowPos(_, _, _, _, _, _, _)).
+ WillRepeatedly(Return(TRUE));
+
+ EXPECT_HRESULT_SUCCEEDED(infobar_manager_->Show(infobar_api::TOP_INFOBAR,
+ kMaxHeight, kUrl1, false));
+
+ // Test Hide for this infobar two times. The second Hide should still be OK
+ // even though the infobar is already hidden.
+ EXPECT_CALL(*infobar_window, Reset()).Times(2);
+ EXPECT_HRESULT_SUCCEEDED(infobar_manager_->Hide(infobar_api::TOP_INFOBAR));
+ EXPECT_HRESULT_SUCCEEDED(infobar_manager_->Hide(infobar_api::TOP_INFOBAR));
+
+ // However Hide to non-existent infobar should result in an error.
+ EXPECT_HRESULT_FAILED(infobar_manager_->Hide(infobar_api::BOTTOM_INFOBAR));
+ EXPECT_HRESULT_FAILED(infobar_manager_->Hide(
+ static_cast<infobar_api::InfobarType>(55)));
+
+ // HideAll hides only the existing infobar.
+ EXPECT_CALL(*infobar_window, Reset());
+ infobar_manager_->HideAll();
+}
+
+TEST_F(InfobarManagerTests, OnClose) {
+ infobar_manager_->InitInfobarWindow(infobar_api::TOP_INFOBAR,
+ infobar_delegate_.get());
+ TestingInfobarManager::MockContainerWindow* container_window =
+ new TestingInfobarManager::MockContainerWindow;
+ infobar_manager_->SetContainerWindow(container_window);
+ EXPECT_CALL(*container_window, PostWindowsMessage(_, _, _));
+ MockInfobarWindow* infobar_window =
+ infobar_manager_->GetInfobarWindow(infobar_api::TOP_INFOBAR);
+ EXPECT_CALL(*infobar_window, Reset());
+ infobar_manager_->EmulateOnClose(infobar_api::TOP_INFOBAR);
+}
+
+} // namespace
diff --git a/ceee/ie/plugin/bho/infobar_window.cc b/ceee/ie/plugin/bho/infobar_window.cc
index f7c06c1..d484670 100644
--- a/ceee/ie/plugin/bho/infobar_window.cc
+++ b/ceee/ie/plugin/bho/infobar_window.cc
@@ -41,7 +41,8 @@ InfobarWindow::InfobarWindow(InfobarType type, Delegate* delegate)
show_(false),
target_height_(1),
current_height_(1),
- sliding_infobar_(false) {
+ sliding_infobar_(false),
+ timer_id_(0) {
DCHECK(delegate);
}
@@ -165,7 +166,7 @@ void InfobarWindow::StartUpdatingLayout(bool show, int max_height, bool slide) {
current_height_ = target_height_;
if (sliding_infobar_) {
- KillTimer(kInfobarSlidingTimerId);
+ KillTimer(timer_id_);
sliding_infobar_ = false;
}
} else {
@@ -174,7 +175,9 @@ void InfobarWindow::StartUpdatingLayout(bool show, int max_height, bool slide) {
current_height_ = CalculateNextHeight();
if (!sliding_infobar_) {
- SetTimer(kInfobarSlidingTimerId, kInfobarSlidingTimerIntervalMs, NULL);
+ // Set timer and store its id (it could be different from the passed one).
+ timer_id_ = SetTimer(kInfobarSlidingTimerId,
+ kInfobarSlidingTimerIntervalMs, NULL);
sliding_infobar_ = true;
}
}
@@ -258,12 +261,12 @@ HRESULT InfobarWindow::GetContentSize(SIZE* size) {
}
LRESULT InfobarWindow::OnTimer(UINT_PTR nIDEvent) {
- DCHECK(nIDEvent == kInfobarSlidingTimerId);
+ DCHECK(nIDEvent == timer_id_);
if (show_ && sliding_infobar_ && current_height_ != target_height_) {
current_height_ = CalculateNextHeight();
UpdateLayout();
} else if (sliding_infobar_) {
- KillTimer(kInfobarSlidingTimerId);
+ KillTimer(timer_id_);
sliding_infobar_ = false;
}
diff --git a/ceee/ie/plugin/bho/infobar_window.h b/ceee/ie/plugin/bho/infobar_window.h
index 6b373b06..9d8aa5c 100644
--- a/ceee/ie/plugin/bho/infobar_window.h
+++ b/ceee/ie/plugin/bho/infobar_window.h
@@ -55,13 +55,13 @@ class InfobarWindow : public InfobarBrowserWindow::Delegate,
// max_height if the content is too high; no limit if max_height is set to
// 0).
// slide indicates whether to show sliding effect.
- HRESULT Show(int max_height, bool slide);
+ virtual HRESULT Show(int max_height, bool slide);
// Hides the infobar.
- HRESULT Hide();
+ virtual HRESULT Hide();
// Navigates the HTML view of the infobar.
- HRESULT Navigate(const std::wstring& url);
+ virtual HRESULT Navigate(const std::wstring& url);
// Reserves space for the infobar when IE window recalculates its size.
void ReserveSpace(RECT* rect);
@@ -71,7 +71,11 @@ class InfobarWindow : public InfobarBrowserWindow::Delegate,
void UpdatePosition();
// Destroys the browser window.
- void Reset();
+ virtual void Reset();
+
+ virtual HWND InternalCreate(HWND parent_window, DWORD style) {
+ return Create(parent_window, NULL, NULL, style);
+ }
private:
BEGIN_MSG_MAP(InfobarWindow)
@@ -103,6 +107,9 @@ class InfobarWindow : public InfobarBrowserWindow::Delegate,
// Indicates whether the infobar is sliding.
bool sliding_infobar_;
+ // Timer id when sliding the infobar.
+ UINT_PTR timer_id_;
+
// The Chrome Frame host handling a Chrome Frame instance for us.
CComPtr<IInfobarBrowserWindow> chrome_frame_host_;
diff --git a/ceee/ie/plugin/bho/infobar_window_unittest.cc b/ceee/ie/plugin/bho/infobar_window_unittest.cc
new file mode 100644
index 0000000..378b09f
--- /dev/null
+++ b/ceee/ie/plugin/bho/infobar_window_unittest.cc
@@ -0,0 +1,181 @@
+// Copyright (c) 2010 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.
+//
+// Infobar window implementation unit tests.
+
+// MockWin32 must not be included after atlwin, which is included by some
+// headers in here, so we need to put it at the top:
+#include "ceee/testing/utils/mock_win32.h" // NOLINT
+
+#include "ceee/ie/plugin/bho/infobar_window.h"
+#include "ceee/testing/utils/instance_count_mixin.h"
+#include "ceee/testing/utils/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "broker_lib.h" // NOLINT
+
+namespace {
+
+using testing::_;
+using testing::NotNull;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrEq;
+using testing::StrictMock;
+
+const HWND kGoodWindow = reinterpret_cast<HWND>(42);
+const HWND kParentWindow = reinterpret_cast<HWND>(74);
+const wchar_t* kUrl1 = L"/infobar/test.html";
+const int kMaxHeight = 25;
+const UINT_PTR timer_id = 19;
+
+class MockInfobarBrowserWindow : public infobar_api::IInfobarBrowserWindow {
+ public:
+ MockInfobarBrowserWindow() : ref_count(0) {}
+ ~MockInfobarBrowserWindow() { EXPECT_EQ(0, ref_count); }
+ STDMETHOD_(ULONG, AddRef)() { return ++ref_count; }
+ STDMETHOD_(ULONG, Release)() { return --ref_count; }
+ STDMETHOD(QueryInterface)(REFIID, LPVOID*) { return S_OK; }
+
+ MOCK_METHOD1_WITH_CALLTYPE(__stdcall, CreateAndShowWindow, HRESULT(HWND));
+ MOCK_METHOD1_WITH_CALLTYPE(__stdcall, SetUrl, HRESULT(BSTR));
+ MOCK_METHOD2_WITH_CALLTYPE(__stdcall, SetWindowSize, HRESULT(int, int));
+ MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Teardown, HRESULT());
+
+ ULONG ref_count;
+};
+
+class MockInfobarWindowDelegate : public infobar_api::InfobarWindow::Delegate {
+ public:
+ MOCK_METHOD0(GetContainerWindow, HWND());
+ MOCK_METHOD1(OnWindowClose, void(infobar_api::InfobarType));
+};
+
+class TestingInfobarWindow : public infobar_api::InfobarWindow {
+ public:
+ TestingInfobarWindow(infobar_api::InfobarType type,
+ InfobarWindow::Delegate* delegate,
+ MockInfobarBrowserWindow* browser_window)
+ : infobar_api::InfobarWindow(type, delegate) {
+ chrome_frame_host_ = browser_window;
+ }
+};
+
+class InfobarWindowTests : public testing::Test {
+ public:
+ virtual void SetUp() {
+ infobar_window_delegate_.reset(new StrictMock<MockInfobarWindowDelegate>);
+ browser_window_.reset(new StrictMock<MockInfobarBrowserWindow>);
+ infobar_window_.reset(new StrictMock<TestingInfobarWindow>(
+ infobar_api::TOP_INFOBAR, infobar_window_delegate_.get(),
+ browser_window_.get()));
+ infobar_window_->m_hWnd = kGoodWindow;
+
+ EXPECT_CALL(*browser_window_, Teardown()).WillOnce(Return(S_OK));
+ EXPECT_CALL(*infobar_window_delegate_, GetContainerWindow()).
+ WillRepeatedly(Return(kParentWindow));
+
+ EXPECT_CALL(user32_, IsWindow(kGoodWindow)).WillRepeatedly(Return(TRUE));
+ EXPECT_CALL(user32_, IsWindow(kParentWindow)).WillRepeatedly(Return(TRUE));
+ EXPECT_CALL(user32_, IsWindow(NULL)).WillRepeatedly(Return(FALSE));
+ EXPECT_CALL(user32_, GetParent(_)).WillRepeatedly(Return(kParentWindow));
+
+ // Arbitrary number to return from GetWindowRect. Unique to make it easier
+ // to trace in the debugger or to add in future tests dependent on return
+ // values.
+ RECT window_rect = {131, 213, 831, 1013};
+ EXPECT_CALL(user32_, GetWindowRect(kParentWindow, NotNull())).
+ WillRepeatedly(DoAll(SetArgumentPointee<1>(window_rect), Return(TRUE)));
+ EXPECT_CALL(user32_, SetWindowPos(_, _, _, _, _, _, _)).
+ WillRepeatedly(Return(TRUE));
+ }
+ virtual void TearDown() {
+ testing::LogDisabler no_dchecks;
+ // Infobar window must be deleted before delegate as the destructor will
+ // call the delegate member functions.
+ infobar_window_.reset(NULL);
+ infobar_window_delegate_.reset(NULL);
+
+ // Everything should have been relinquished.
+ ASSERT_EQ(0, testing::InstanceCountMixinBase::all_instance_count());
+}
+
+ protected:
+ StrictMock<testing::MockUser32> user32_;
+ scoped_ptr<StrictMock<MockInfobarWindowDelegate>> infobar_window_delegate_;
+ scoped_ptr<StrictMock<TestingInfobarWindow>> infobar_window_;
+ scoped_ptr<StrictMock<MockInfobarBrowserWindow>> browser_window_;
+};
+
+TEST_F(InfobarWindowTests, ShowHide) {
+ // Show without previous Navigate should fail.
+ EXPECT_HRESULT_FAILED(infobar_window_->Show(kMaxHeight, false));
+
+ // Navigate, then Show.
+ EXPECT_CALL(*browser_window_, SetUrl(StrEq(kUrl1))).Times(1);
+ EXPECT_HRESULT_SUCCEEDED(infobar_window_->Navigate(std::wstring(kUrl1)));
+ EXPECT_HRESULT_SUCCEEDED(infobar_window_->Show(kMaxHeight, false));
+ EXPECT_EQ(kMaxHeight, infobar_window_->target_height_);
+ EXPECT_EQ(kMaxHeight, infobar_window_->current_height_);
+ EXPECT_TRUE(infobar_window_->show_);
+
+ EXPECT_HRESULT_SUCCEEDED(infobar_window_->Hide());
+ EXPECT_FALSE(infobar_window_->show_);
+}
+
+TEST_F(InfobarWindowTests, SlidingShow) {
+ EXPECT_CALL(*browser_window_, SetUrl(StrEq(kUrl1))).Times(1);
+ EXPECT_HRESULT_SUCCEEDED(infobar_window_->Navigate(std::wstring(kUrl1)));
+ EXPECT_CALL(user32_, SetTimer(kGoodWindow, _, _, _)).
+ WillRepeatedly(Return(timer_id));
+ EXPECT_HRESULT_SUCCEEDED(infobar_window_->Show(kMaxHeight, true));
+ EXPECT_EQ(kMaxHeight, infobar_window_->target_height_);
+ // With sliding enabled, the hight of the infobar should not be the target
+ // height immediately - it increases on each timer tick until reaches target.
+ EXPECT_LE(infobar_window_->current_height_, kMaxHeight);
+ EXPECT_TRUE(infobar_window_->show_);
+ EXPECT_TRUE(infobar_window_->sliding_infobar_);
+
+ // Call timer callback function until required.
+ EXPECT_CALL(user32_, KillTimer(kGoodWindow, timer_id)).WillOnce(Return(TRUE));
+ // Restrict the maximum number of times the loop can run so the test does not
+ // hang if infobar_window_->sliding_infobar_ is not set. Normally it should
+ // run just a few times (3 times if kMaxHeight is 25 and sliding step is 10).
+ for (int i = 0; infobar_window_->sliding_infobar_ && i < 100; ++i) {
+ infobar_window_->OnTimer(timer_id);
+ }
+ // Check that the loop is exited because of sliding_infobar_ condition and not
+ // the counter saturation.
+ EXPECT_FALSE(infobar_window_->sliding_infobar_);
+ EXPECT_EQ(kMaxHeight, infobar_window_->current_height_);
+ EXPECT_TRUE(infobar_window_->show_);
+}
+
+TEST_F(InfobarWindowTests, OnClose) {
+ EXPECT_CALL(*infobar_window_delegate_,
+ OnWindowClose(infobar_api::TOP_INFOBAR)).Times(1);
+
+ infobar_window_->OnBrowserWindowClose();
+}
+
+TEST_F(InfobarWindowTests, ReserveSpace) {
+ // Arbitrary number to return from GetWindowRect. Unique to make it easier
+ // to trace in the debugger.
+ CRect rect1(255, 311, 814, 1015);
+ CRect rect0 = rect1;
+ infobar_window_->ReserveSpace(&rect1);
+ EXPECT_EQ(rect0, rect1);
+
+ EXPECT_CALL(*browser_window_, SetUrl(StrEq(kUrl1))).Times(1);
+ EXPECT_HRESULT_SUCCEEDED(infobar_window_->Navigate(std::wstring(kUrl1)));
+ EXPECT_HRESULT_SUCCEEDED(infobar_window_->Show(kMaxHeight, false));
+ infobar_window_->ReserveSpace(&rect1);
+ EXPECT_EQ(rect0.left, rect1.left);
+ EXPECT_EQ(rect0.right, rect1.right);
+ EXPECT_EQ(rect0.top + kMaxHeight, rect1.top);
+ EXPECT_EQ(rect0.bottom, rect1.bottom);
+}
+
+} // namespace