Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: chrome_frame/test/ready_mode_unittest.cc

Issue 5747002: Implement a ReadyPromptContent that displays a prompt to accept, temporarily ... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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/scoped_ptr.h"
15 #include "base/win/registry.h"
16 #include "chrome_frame/infobars/infobar_content.h"
17 #include "chrome_frame/ready_mode/internal/installation_state.h"
18 #include "chrome_frame/ready_mode/internal/ready_mode_state.h"
19 #include "chrome_frame/ready_mode/internal/ready_prompt_content.h"
20 #include "chrome_frame/ready_mode/internal/ready_prompt_window.h"
21 #include "chrome_frame/ready_mode/internal/registry_ready_mode_state.h"
22 #include "chrome_frame/ready_mode/ready_mode_manager.h"
23 #include "chrome_frame/simple_resource_loader.h"
24 #include "chrome_frame/test/chrome_frame_test_utils.h"
25
26 namespace {
27
28 class SetResourceInstance {
29 public:
30 SetResourceInstance() {
31 SimpleResourceLoader* loader_instance = SimpleResourceLoader::instance();
32 DCHECK(loader_instance != NULL);
33 res_dll_ = loader_instance->GetResourceModuleHandle();
34 old_res_dll_ = ATL::_AtlBaseModule.SetResourceInstance(res_dll_);
35 }
36
37 ~SetResourceInstance() {
38 DCHECK_EQ(res_dll_, ATL::_AtlBaseModule.SetResourceInstance(old_res_dll_));
grt (UTC plus 2) 2010/12/11 03:12:06 Should EXPECT_EQ be used here (and above) so that
erikwright (departed) 2010/12/14 16:15:17 If this fails, all later tests would potentially b
39 }
40
41 private:
42 HMODULE res_dll_;
43 HMODULE old_res_dll_;
44 };
45
46 class SimpleWindow : public CWindowImpl<SimpleWindow,
47 CWindow,
48 CFrameWinTraits> {
49 public:
50 virtual ~SimpleWindow() {
51 if (IsWindow())
52 DestroyWindow();
53 }
54
55 static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM l_param) {
56 HWND* out = reinterpret_cast<HWND*>(l_param);
57 EXPECT_TRUE(out != NULL);
58
59 if (out == NULL)
60 return FALSE;
61
62 EXPECT_TRUE(*out == NULL || ::IsChild(*out, hwnd));
63
64 if (*out == NULL)
65 *out = hwnd;
66
67 return TRUE;
68 }
69
70 HWND GetZeroOrOneChildWindows() {
71 HWND child = NULL;
72 EnumChildWindows(m_hWnd, EnumChildProc, reinterpret_cast<LPARAM>(&child));
73 return child;
74 }
75
76 BEGIN_MSG_MAP(SimpleWindow)
77 END_MSG_MAP()
78 };
79
80 class MockInfobarContentFrame : public InfobarContent::Frame {
81 public:
82 // InfobarContent::Frame implementation
83 MOCK_METHOD0(GetFrameWindow, HWND(void));
84 MOCK_METHOD0(CloseInfobar, void(void));
85 }; // class Frame
86
87 class MockReadyModeState : public ReadyModeState {
88 public:
89 // ReadyModeState implementation
90 MOCK_METHOD0(TemporarilyDeclineChromeFrame, void(void));
91 MOCK_METHOD0(PermanentlyDeclineChromeFrame, void(void));
92 MOCK_METHOD0(AcceptChromeFrame, void(void));
93 };
94
95 ACTION_P(ReturnPointee, pointer) {
96 return *pointer;
97 }
98
99 ACTION_P2(SetPointeeTo, pointer, value) {
100 *pointer = value;
101 }
102
103 class MockInstallationState : public InstallationState {
104 public:
105 // InstallationState implementation
106 MOCK_METHOD0(IsProductInstalled, bool(void));
107 MOCK_METHOD0(IsProductRegistered, bool(void));
108 MOCK_METHOD0(InstallProduct, bool(void));
109 MOCK_METHOD0(UnregisterProduct, bool(void));
110 }; // MockInstallationState
111
112 class MockRegistryReadyModeStateObserver
113 : public RegistryReadyModeState::Observer {
114 public:
115 // RegistryReadyModeState::Observer implementation
116 MOCK_METHOD0(OnStateChange, void(void));
117 }; // class MockRegistryReadyModeStateObserver
118
119 } // namespace
120
121 class ReadyPromptTest : public testing::Test {
122 public:
123 ReadyPromptTest() {
124 hwnd_ = window_.Create(NULL);
125 DCHECK(hwnd_ != NULL);
126 window_.ShowWindow(SW_SHOW);
127 DCHECK(window_.IsWindowVisible());
128 EXPECT_CALL(frame_, GetFrameWindow()).Times(testing::AnyNumber())
129 .WillRepeatedly(testing::Return(hwnd_));
130 }
131
132 protected:
133 SimpleWindow window_;
134 HWND hwnd_;
135 MockInfobarContentFrame frame_;
136 SetResourceInstance set_resource_instance_;
137 };
138
139 class ReadyPromptWindowTest : public ReadyPromptTest {
140 public:
141 ReadyPromptWindowTest() {
142 // owned by ReadyPromptWindow
143 state_ = new MockReadyModeState();
144 ready_prompt_window_ = (new ReadyPromptWindow())->Initialize(&frame_,
145 state_);
146 }
147
148 void SetUp() {
149 ReadyPromptTest::SetUp();
150
151 ASSERT_TRUE(ready_prompt_window_ != NULL);
152 RECT position = {0, 0, 800, 39};
153 ASSERT_TRUE(ready_prompt_window_->SetWindowPos(HWND_TOP, &position,
154 SWP_SHOWWINDOW));
155 }
156
157 protected:
158 MockReadyModeState* state_;
159 base::WeakPtr<ReadyPromptWindow> ready_prompt_window_;
160 }; // class ReadyPromptWindowTest
161
162 class ReadyPromptWindowButtonTest : public ReadyPromptWindowTest {
163 public:
164 void TearDown() {
165 ASSERT_TRUE(ready_prompt_window_ != NULL);
166 ASSERT_TRUE(ready_prompt_window_->DestroyWindow());
167 ASSERT_TRUE(ready_prompt_window_ == NULL);
168 ASSERT_FALSE(message_loop_.WasTimedOut());
169
170 ReadyPromptWindowTest::TearDown();
171 }
172
173 protected:
174 struct ClickOnCaptionData {
175 const wchar_t* target_caption;
176 bool found;
177 }; // struct ClickOnCaptionData
178
179 static BOOL CALLBACK ClickOnCaptionProc(HWND hwnd, LPARAM l_param) {
180 wchar_t window_caption[256] = {0};
181 size_t buffer_length = arraysize(window_caption);
182
183 ClickOnCaptionData* data = reinterpret_cast<ClickOnCaptionData*>(l_param);
184 EXPECT_TRUE(data->target_caption != NULL);
185
186 if (data->target_caption == NULL)
187 return FALSE;
188
189 if (wcsnlen(data->target_caption, buffer_length + 1) == buffer_length + 1)
190 return FALSE;
191
192 if (::GetWindowText(hwnd, window_caption, buffer_length) ==
193 static_cast<int>(buffer_length)) {
194 return TRUE;
195 }
196
197 if (wcscmp(data->target_caption, window_caption) == 0) {
198 EXPECT_FALSE(data->found);
199
200 CRect client_rect;
201 EXPECT_TRUE(::GetClientRect(hwnd, client_rect));
202
203 CPoint center_point(client_rect.CenterPoint());
204 LPARAM coordinates = (center_point.y << 16) | center_point.x;
205
206 ::PostMessage(hwnd, WM_LBUTTONDOWN, 0, coordinates);
207 ::PostMessage(hwnd, WM_LBUTTONUP, 0, coordinates);
208
209 data->found = true;
210 }
211
212 return TRUE;
213 }
214
215 bool ClickOnCaption(const std::wstring& caption) {
216 ClickOnCaptionData data = {caption.c_str(), false};
217
218 ::EnumChildWindows(hwnd_, ClickOnCaptionProc,
219 reinterpret_cast<LPARAM>(&data));
220 return data.found;
221 }
222
223 void RunUntilCloseInfobar() {
224 EXPECT_CALL(frame_, CloseInfobar()).WillOnce(QUIT_LOOP(message_loop_));
225 ASSERT_NO_FATAL_FAILURE(message_loop_.RunFor(5)); // seconds
226 }
227
228 chrome_frame_test::TimedMsgLoop message_loop_;
229 };
230
231 TEST_F(ReadyPromptTest, ReadyPromptContentTest) {
232 // owned by ReadyPromptContent
233 MockReadyModeState* state = new MockReadyModeState();
234 scoped_ptr<ReadyPromptContent> content_(new ReadyPromptContent(state));
235
236 content_->InstallInFrame(&frame_);
237
238 // Ensure that, if a child is created, it is not visible yet.
239 HWND child_hwnd = window_.GetZeroOrOneChildWindows();
240 if (child_hwnd != NULL) {
241 CWindow child(child_hwnd);
242 RECT child_dimensions;
243 EXPECT_TRUE(child.GetClientRect(&child_dimensions));
244 EXPECT_FALSE(child.IsWindowVisible() && !::IsRectEmpty(&child_dimensions));
245 }
246
247 int desired_height = content_->GetDesiredSize(400, 0);
248 EXPECT_GT(desired_height, 0);
249 RECT dimensions = {10, 15, 410, 20};
250 content_->SetDimensions(dimensions);
251
252 child_hwnd = window_.GetZeroOrOneChildWindows();
253 EXPECT_TRUE(child_hwnd != NULL);
254
255 if (child_hwnd != NULL) {
256 CWindow child(child_hwnd);
257 EXPECT_TRUE(child.IsWindowVisible());
258 RECT child_dimensions;
259 EXPECT_TRUE(child.GetWindowRect(&child_dimensions));
260 EXPECT_TRUE(window_.ScreenToClient(&child_dimensions));
261 EXPECT_TRUE(::EqualRect(&child_dimensions, &dimensions));
262 }
263
264 // Being visible doesn't change the desired height
265 EXPECT_EQ(desired_height, content_->GetDesiredSize(400, 0));
266
267 content_.reset();
268
269 EXPECT_TRUE(window_.GetZeroOrOneChildWindows() == NULL);
270 }
271
272 TEST_F(ReadyPromptWindowTest, Destroy) {
273 // Should delete associated mocks, not invoke on ReadyModeState
274 ready_prompt_window_->DestroyWindow();
275 }
276
277 TEST_F(ReadyPromptWindowButtonTest, ClickYes) {
278 EXPECT_CALL(*state_, AcceptChromeFrame());
279 ASSERT_TRUE(ClickOnCaption(L"&Yes"));
280 RunUntilCloseInfobar();
281 }
282
283 TEST_F(ReadyPromptWindowButtonTest, ClickRemindMeLater) {
284 EXPECT_CALL(*state_, TemporarilyDeclineChromeFrame());
285 ASSERT_TRUE(ClickOnCaption(L"Remind me &Later"));
286 RunUntilCloseInfobar();
287 }
288
289 TEST_F(ReadyPromptWindowButtonTest, ClickNo) {
290 EXPECT_CALL(*state_, PermanentlyDeclineChromeFrame());
291 ASSERT_TRUE(ClickOnCaption(L"&No"));
292 RunUntilCloseInfobar();
293 }
294
295 class ReadyModeRegistryTest : public testing::Test {
296 public:
297 class TimeControlledRegistryReadyModeState : public RegistryReadyModeState {
298 public:
299 TimeControlledRegistryReadyModeState(
300 const std::wstring& key_name,
301 base::TimeDelta temporary_decline_duration,
302 InstallationState* installation_state,
303 Observer* observer)
304 : RegistryReadyModeState(key_name, temporary_decline_duration,
305 installation_state, observer),
306 now_(base::Time::Now()) {
307 }
308
309 base::Time now_;
310
311 protected:
312 virtual base::Time GetNow() {
313 return now_;
314 }
315 }; // class TimeControlledRegistryReadyModeState
316
317 ReadyModeRegistryTest()
318 : is_product_registered_(true),
319 is_product_installed_(false),
320 observer_(NULL),
321 installation_state_(NULL) {
322 }
323
324 virtual void SetUp() {
325 base::win::RegKey key;
326 ASSERT_TRUE(key.Create(HKEY_CURRENT_USER, kRootKey, KEY_ALL_ACCESS));
327 observer_ = new MockRegistryReadyModeStateObserver();
328 installation_state_ = new MockInstallationState();
329
330 EXPECT_CALL(*installation_state_, IsProductRegistered())
331 .Times(testing::AnyNumber())
332 .WillRepeatedly(ReturnPointee(&is_product_registered_));
333 EXPECT_CALL(*installation_state_, IsProductInstalled())
334 .Times(testing::AnyNumber())
335 .WillRepeatedly(ReturnPointee(&is_product_installed_));
336
337 ready_mode_state_.reset(new TimeControlledRegistryReadyModeState(
338 kRootKey,
339 base::TimeDelta::FromSeconds(kTemporaryDeclineDurationInSeconds),
340 installation_state_,
341 observer_));
342 }
343
344 virtual void TearDown() {
345 base::win::RegKey key;
346 EXPECT_TRUE(key.Open(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS));
347 EXPECT_TRUE(key.DeleteKey(kRootKey));
348 }
349
350 protected:
351 void AdjustClockBySeconds(int seconds) {
352 ready_mode_state_->now_ += base::TimeDelta::FromSeconds(seconds);
353 }
354
355 void ExpectUnregisterProductAndReturn(bool success) {
356 EXPECT_CALL(*installation_state_, UnregisterProduct())
357 .WillOnce(testing::DoAll(
358 SetPointeeTo(&is_product_registered_, !success),
359 testing::Return(success)));
360 }
361
362 void ExpectInstallProductAndReturn(bool success) {
363 EXPECT_CALL(*installation_state_, InstallProduct())
364 .WillOnce(testing::DoAll(SetPointeeTo(&is_product_installed_, success),
365 testing::Return(success)));
366 }
367
368 bool is_product_registered_;
369 bool is_product_installed_;
370 MockInstallationState* installation_state_;
371 MockRegistryReadyModeStateObserver* observer_;
372
373 scoped_ptr<TimeControlledRegistryReadyModeState> ready_mode_state_;
374 base::win::RegKey config_key;
375 static const wchar_t kRootKey[];
376 static const int kTemporaryDeclineDurationInSeconds;
377 };
378
379 const int ReadyModeRegistryTest::kTemporaryDeclineDurationInSeconds = 2;
380 const wchar_t ReadyModeRegistryTest::kRootKey[] = L"chrome_frame_unittests";
381
382 TEST_F(ReadyModeRegistryTest, CallNothing) {
383 // expect it to delete the two mocks... Google Mock fails if they are leaked.
384 }
385
386 TEST_F(ReadyModeRegistryTest, NotInstalledStatus) {
387 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
388 }
389
390 TEST_F(ReadyModeRegistryTest, NotRegisteredStatus) {
391 is_product_registered_ = false;
392 ASSERT_EQ(READY_MODE_PERMANENTLY_DECLINED, ready_mode_state_->GetStatus());
393 }
394
395 TEST_F(ReadyModeRegistryTest, InstalledStatus) {
396 is_product_installed_ = true;
397 ASSERT_EQ(READY_MODE_ACCEPTED, ready_mode_state_->GetStatus());
398 }
399
400 TEST_F(ReadyModeRegistryTest, TemporarilyDeclineChromeFrame) {
401 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
402
403 EXPECT_CALL(*observer_, OnStateChange());
404 ready_mode_state_->TemporarilyDeclineChromeFrame();
405
406 ASSERT_EQ(READY_MODE_TEMPORARILY_DECLINED, ready_mode_state_->GetStatus());
407
408 AdjustClockBySeconds(kTemporaryDeclineDurationInSeconds + 1);
409 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
410 }
411
412 TEST_F(ReadyModeRegistryTest, TemporarilyDeclineChromeFrameSetClockBack) {
413 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
414
415 EXPECT_CALL(*observer_, OnStateChange());
416 ready_mode_state_->TemporarilyDeclineChromeFrame();
417
418 ASSERT_EQ(READY_MODE_TEMPORARILY_DECLINED, ready_mode_state_->GetStatus());
419
420 AdjustClockBySeconds(kTemporaryDeclineDurationInSeconds + 1);
421 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
422 }
423
424 TEST_F(ReadyModeRegistryTest, PermanentlyDeclineChromeFrame) {
425 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
426
427 EXPECT_CALL(*observer_, OnStateChange());
428 ExpectUnregisterProductAndReturn(true);
429 ready_mode_state_->PermanentlyDeclineChromeFrame();
430
431 ASSERT_EQ(READY_MODE_PERMANENTLY_DECLINED, ready_mode_state_->GetStatus());
432 }
433
434 TEST_F(ReadyModeRegistryTest, PermanentlyDeclineChromeFrameFailUnregister) {
435 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
436
437 EXPECT_CALL(*observer_, OnStateChange());
438 ExpectUnregisterProductAndReturn(false);
439 ready_mode_state_->PermanentlyDeclineChromeFrame();
440
441 ASSERT_EQ(READY_MODE_PERMANENTLY_DECLINED, ready_mode_state_->GetStatus());
442 }
443
444 TEST_F(ReadyModeRegistryTest, AcceptChromeFrame) {
445 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
446
447 EXPECT_CALL(*observer_, OnStateChange());
448 ExpectInstallProductAndReturn(true);
449 ready_mode_state_->AcceptChromeFrame();
450
451 ASSERT_EQ(READY_MODE_ACCEPTED, ready_mode_state_->GetStatus());
452 }
453
454 // TODO(erikwright): What do we actually want to happen if the install fails?
455 // Stay in Ready Mode? Attempt to unregister (deactivate ready mode)?
456 //
457 // Which component is responsible for messaging the user? The installer? The
458 // InstallationState implementation? The ReadyModeState implementation?
459 TEST_F(ReadyModeRegistryTest, AcceptChromeFrameInstallFails) {
460 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
461
462 ExpectInstallProductAndReturn(false);
463 ready_mode_state_->AcceptChromeFrame();
464
465 ASSERT_EQ(READY_MODE_ACTIVE, ready_mode_state_->GetStatus());
466 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698