Home | History | Annotate | Download | only in test
      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 <atlbase.h>
      6 #include <atlapp.h>
      7 #include <atlmisc.h>
      8 #include <atlwin.h>
      9 
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "testing/gmock/include/gmock/gmock.h"
     12 
     13 #include "base/logging.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/win/registry.h"
     16 #include "chrome_frame/infobars/infobar_content.h"
     17 #include "chrome_frame/ready_mode/internal/ready_mode_state.h"
     18 #include "chrome_frame/ready_mode/internal/ready_prompt_content.h"
     19 #include "chrome_frame/ready_mode/internal/ready_prompt_window.h"
     20 #include "chrome_frame/ready_mode/internal/registry_ready_mode_state.h"
     21 #include "chrome_frame/ready_mode/internal/url_launcher.h"
     22 #include "chrome_frame/simple_resource_loader.h"
     23 #include "chrome_frame/test/chrome_frame_test_utils.h"
     24 
     25 namespace {
     26 
     27 class SetResourceInstance {
     28  public:
     29   SetResourceInstance() : res_dll_(NULL), old_res_dll_(NULL) {
     30     SimpleResourceLoader* loader_instance = SimpleResourceLoader::GetInstance();
     31     EXPECT_TRUE(loader_instance != NULL);
     32     if (loader_instance != NULL) {
     33       res_dll_ = loader_instance->GetResourceModuleHandle();
     34       EXPECT_TRUE(res_dll_ != NULL);
     35       if (res_dll_ != NULL) {
     36         old_res_dll_ = ATL::_AtlBaseModule.SetResourceInstance(res_dll_);
     37       }
     38     }
     39   }
     40 
     41   ~SetResourceInstance() {
     42     if (old_res_dll_ != NULL) {
     43       CHECK_EQ(res_dll_, ATL::_AtlBaseModule.SetResourceInstance(old_res_dll_));
     44     }
     45   }
     46 
     47  private:
     48   HMODULE res_dll_;
     49   HMODULE old_res_dll_;
     50 };  // class SetResourceInstance
     51 
     52 class SimpleWindow : public CWindowImpl<SimpleWindow,
     53                                         CWindow,
     54                                         CFrameWinTraits> {
     55  public:
     56   virtual ~SimpleWindow() {
     57     if (IsWindow())
     58       DestroyWindow();
     59   }
     60 
     61   static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM l_param) {
     62     HWND* out = reinterpret_cast<HWND*>(l_param);
     63     EXPECT_TRUE(out != NULL);
     64 
     65     if (out == NULL)
     66       return FALSE;
     67 
     68     EXPECT_TRUE(*out == NULL || ::IsChild(*out, hwnd));
     69 
     70     if (*out == NULL)
     71       *out = hwnd;
     72 
     73     return TRUE;
     74   }
     75 
     76   HWND GetZeroOrOneChildWindows() {
     77     HWND child = NULL;
     78     EnumChildWindows(m_hWnd, EnumChildProc, reinterpret_cast<LPARAM>(&child));
     79     return child;
     80   }
     81 
     82   BEGIN_MSG_MAP(SimpleWindow)
     83   END_MSG_MAP()
     84 };  // class SimpleWindow
     85 
     86 class MockInfobarContentFrame : public InfobarContent::Frame {
     87  public:
     88   // InfobarContent::Frame implementation
     89   MOCK_METHOD0(GetFrameWindow, HWND(void));
     90   MOCK_METHOD0(CloseInfobar, void(void));
     91 };  // class Frame
     92 
     93 class MockReadyModeState : public ReadyModeState {
     94  public:
     95   // ReadyModeState implementation
     96   MOCK_METHOD0(TemporarilyDeclineChromeFrame, void(void));
     97   MOCK_METHOD0(PermanentlyDeclineChromeFrame, void(void));
     98   MOCK_METHOD0(AcceptChromeFrame, void(void));
     99 };  // class MockReadyModeState
    100 
    101 class MockUrlLauncher : public UrlLauncher {
    102  public:
    103   // UrlLauncher implementation
    104   MOCK_METHOD1(LaunchUrl, void(const std::wstring& url));
    105 };  // class MockUrlLauncher
    106 
    107 }  // namespace
    108 
    109 class ReadyPromptTest : public testing::Test {
    110  public:
    111   ReadyPromptTest() : hwnd_(NULL) {}
    112 
    113   void SetUp() {
    114     hwnd_ = window_.Create(NULL);
    115     EXPECT_TRUE(hwnd_ != NULL);
    116     window_.ShowWindow(SW_SHOW);
    117     EXPECT_TRUE(window_.IsWindowVisible());
    118     EXPECT_CALL(frame_, GetFrameWindow()).Times(testing::AnyNumber())
    119         .WillRepeatedly(testing::Return(hwnd_));
    120   }
    121 
    122  protected:
    123   SimpleWindow window_;
    124   HWND hwnd_;
    125   MockInfobarContentFrame frame_;
    126   SetResourceInstance set_resource_instance_;
    127 };  // class ReadyPromptTest
    128 
    129 class ReadyPromptWindowTest : public ReadyPromptTest {
    130  public:
    131   void SetUp() {
    132     ReadyPromptTest::SetUp();
    133 
    134     // owned by ReadyPromptWindow
    135     state_ = new MockReadyModeState();
    136     url_launcher_ = new MockUrlLauncher();
    137 
    138     ready_prompt_window_ = ReadyPromptWindow::CreateInstance(
    139         &frame_, state_, url_launcher_);
    140 
    141     ASSERT_TRUE(ready_prompt_window_ != NULL);
    142     RECT position = {0, 0, 800, 39};
    143     ASSERT_TRUE(ready_prompt_window_->SetWindowPos(HWND_TOP, &position,
    144                                                    SWP_SHOWWINDOW));
    145   }
    146 
    147  protected:
    148   MockReadyModeState* state_;
    149   MockUrlLauncher* url_launcher_;
    150   base::WeakPtr<ReadyPromptWindow> ready_prompt_window_;
    151 };  // class ReadyPromptWindowTest
    152 
    153 class ReadyPromptWindowButtonTest : public ReadyPromptWindowTest {
    154  public:
    155   void TearDown() {
    156     ASSERT_TRUE(ready_prompt_window_ != NULL);
    157     ASSERT_TRUE(ready_prompt_window_->DestroyWindow());
    158     ASSERT_TRUE(ready_prompt_window_ == NULL);
    159     ASSERT_FALSE(message_loop_.WasTimedOut());
    160 
    161     ReadyPromptWindowTest::TearDown();
    162   }
    163 
    164  protected:
    165   struct ClickOnCaptionData {
    166     const wchar_t* target_caption;
    167     bool found;
    168   };  // struct ClickOnCaptionData
    169 
    170   static BOOL CALLBACK ClickOnCaptionProc(HWND hwnd, LPARAM l_param) {
    171     wchar_t window_caption[256] = {0};
    172     size_t buffer_length = arraysize(window_caption);
    173 
    174     ClickOnCaptionData* data = reinterpret_cast<ClickOnCaptionData*>(l_param);
    175     EXPECT_TRUE(data->target_caption != NULL);
    176 
    177     if (data->target_caption == NULL)
    178       return FALSE;
    179 
    180     if (wcsnlen(data->target_caption, buffer_length + 1) == buffer_length + 1)
    181       return FALSE;
    182 
    183     if (::GetWindowText(hwnd, window_caption, buffer_length) ==
    184         static_cast<int>(buffer_length)) {
    185       return TRUE;
    186     }
    187 
    188     if (wcscmp(data->target_caption, window_caption) == 0) {
    189       EXPECT_FALSE(data->found);
    190 
    191       CRect client_rect;
    192       EXPECT_TRUE(::GetClientRect(hwnd, client_rect));
    193 
    194       CPoint center_point(client_rect.CenterPoint());
    195       LPARAM coordinates = (center_point.y << 16) | center_point.x;
    196 
    197       ::PostMessage(hwnd, WM_LBUTTONDOWN, 0, coordinates);
    198       ::PostMessage(hwnd, WM_LBUTTONUP, 0, coordinates);
    199 
    200       data->found = true;
    201     }
    202 
    203     return TRUE;
    204   }
    205 
    206   bool ClickOnCaption(const std::wstring& caption) {
    207     ClickOnCaptionData data = {caption.c_str(), false};
    208 
    209     ::EnumChildWindows(hwnd_, ClickOnCaptionProc,
    210                        reinterpret_cast<LPARAM>(&data));
    211     return data.found;
    212   }
    213 
    214   void RunUntilCloseInfobar() {
    215     EXPECT_CALL(frame_, CloseInfobar()).WillOnce(QUIT_LOOP(message_loop_));
    216     ASSERT_NO_FATAL_FAILURE(message_loop_.RunFor(
    217         base::TimeDelta::FromSeconds(5)));
    218   }
    219 
    220   chrome_frame_test::TimedMsgLoop message_loop_;
    221 };  // class ReadyPromptWindowButtonTest
    222 
    223 TEST_F(ReadyPromptTest, ReadyPromptContentTest) {
    224   // owned by ReadyPromptContent
    225   MockReadyModeState* state = new MockReadyModeState();
    226   MockUrlLauncher* url_launcher = new MockUrlLauncher();
    227 
    228   scoped_ptr<ReadyPromptContent> content_(new ReadyPromptContent(state,
    229                                                                  url_launcher));
    230 
    231   content_->InstallInFrame(&frame_);
    232 
    233   // Ensure that, if a child is created, it is not visible yet.
    234   HWND child_hwnd = window_.GetZeroOrOneChildWindows();
    235   if (child_hwnd != NULL) {
    236     CWindow child(child_hwnd);
    237     RECT child_dimensions;
    238     EXPECT_TRUE(child.GetClientRect(&child_dimensions));
    239     EXPECT_FALSE(child.IsWindowVisible() && !::IsRectEmpty(&child_dimensions));
    240   }
    241 
    242   int desired_height = content_->GetDesiredSize(400, 0);
    243   EXPECT_GT(desired_height, 0);
    244   RECT dimensions = {10, 15, 410, 20};
    245   content_->SetDimensions(dimensions);
    246 
    247   child_hwnd = window_.GetZeroOrOneChildWindows();
    248   EXPECT_TRUE(child_hwnd != NULL);
    249 
    250   if (child_hwnd != NULL) {
    251     CWindow child(child_hwnd);
    252     EXPECT_TRUE(child.IsWindowVisible());
    253     RECT child_dimensions;
    254     EXPECT_TRUE(child.GetWindowRect(&child_dimensions));
    255     EXPECT_TRUE(window_.ScreenToClient(&child_dimensions));
    256     EXPECT_TRUE(::EqualRect(&child_dimensions, &dimensions));
    257   }
    258 
    259   // Being visible doesn't change the desired height
    260   EXPECT_EQ(desired_height, content_->GetDesiredSize(400, 0));
    261 
    262   content_.reset();
    263 
    264   EXPECT_TRUE(window_.GetZeroOrOneChildWindows() == NULL);
    265 }
    266 
    267 TEST_F(ReadyPromptWindowTest, Destroy) {
    268   // Should delete associated mocks, not invoke on ReadyModeState
    269   ready_prompt_window_->DestroyWindow();
    270 }
    271 
    272 TEST_F(ReadyPromptWindowButtonTest, ClickEnable) {
    273   EXPECT_CALL(*state_, AcceptChromeFrame());
    274   ASSERT_TRUE(ClickOnCaption(L"Enable"));
    275   RunUntilCloseInfobar();
    276 }
    277 
    278 TEST_F(ReadyPromptWindowButtonTest, ClickIgnore) {
    279   EXPECT_CALL(*state_, PermanentlyDeclineChromeFrame());
    280   ASSERT_TRUE(ClickOnCaption(L"Ignore"));
    281   RunUntilCloseInfobar();
    282 }
    283 
    284 // TODO(erikwright): test WebBrowserAdapter
    285 // TODO(erikwright): an integration test of ReadyMode::Configure with a mock
    286 //                   IWebBrowser2?
    287