OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "base/command_line.h" | |
6 #include "base/message_loop/message_loop.h" | |
7 #include "base/run_loop.h" | |
8 #include "base/strings/utf_string_conversions.h" | |
9 #include "chrome/browser/chromeos/profiles/profile_helper.h" | |
10 #include "chrome/browser/download/chrome_download_manager_delegate.h" | |
11 #include "chrome/browser/download/download_service.h" | |
12 #include "chrome/browser/download/download_service_factory.h" | |
13 #include "chrome/browser/profiles/profile.h" | |
14 #include "chrome/browser/signin/signin_manager_factory.h" | |
15 #include "chrome/browser/ui/browser.h" | |
16 #include "chrome/common/chrome_switches.h" | |
17 #include "chrome/grit/chromium_strings.h" | |
18 #include "chrome/grit/generated_resources.h" | |
19 #include "chrome/test/base/in_process_browser_test.h" | |
20 #include "chrome/test/base/ui_test_utils.h" | |
21 #include "chromeos/chromeos_switches.h" | |
22 #include "components/signin/core/browser/signin_manager_base.h" | |
23 #include "content/public/browser/browser_context.h" | |
24 #include "content/public/browser/download_item.h" | |
25 #include "content/public/browser/download_manager.h" | |
26 #include "grit/theme_resources.h" | |
27 #include "net/test/url_request/url_request_slow_download_job.h" | |
28 #include "ui/base/l10n/l10n_util.h" | |
29 #include "ui/message_center/message_center.h" | |
30 #include "ui/message_center/message_center_observer.h" | |
31 #include "url/gurl.h" | |
32 | |
33 namespace { | |
34 | |
35 enum { | |
36 DUMMY_ACCOUNT_INDEX = 0, | |
37 PRIMARY_ACCOUNT_INDEX = 1, | |
38 SECONDARY_ACCOUNT_INDEX_START = 2, | |
39 }; | |
40 | |
41 // Structure to describe an account info. | |
42 struct TestAccountInfo { | |
43 const char* const email; | |
44 const char* const gaia_id; | |
45 const char* const hash; | |
46 const char* const display_name; | |
47 }; | |
48 | |
49 // Accounts for multi profile test. | |
50 static const TestAccountInfo kTestAccounts[] = { | |
51 {"__dummy__@invalid.domain", "10000", "hashdummy", "Dummy Account"}, | |
52 {"alice@invalid.domain", "10001", "hashalice", "Alice"}, | |
53 {"bob@invalid.domain", "10002", "hashbobbo", "Bob"}, | |
54 {"charlie@invalid.domain", "10003", "hashcharl", "Charlie"}, | |
55 }; | |
56 | |
57 // Base class observing notification events. | |
58 class MessageCenterChangeObserver | |
59 : public message_center::MessageCenterObserver { | |
60 public: | |
61 MessageCenterChangeObserver() { | |
62 message_center::MessageCenter::Get()->AddObserver(this); | |
63 } | |
64 | |
65 ~MessageCenterChangeObserver() override { | |
66 message_center::MessageCenter::Get()->RemoveObserver(this); | |
67 } | |
68 | |
69 protected: | |
70 void RunLoop() { | |
71 base::MessageLoop::ScopedNestableTaskAllower allow( | |
72 base::MessageLoop::current()); | |
73 run_loop_.Run(); | |
74 } | |
75 | |
76 void QuitRunLoop() { | |
77 run_loop_.Quit(); | |
78 } | |
79 | |
80 private: | |
81 base::RunLoop run_loop_; | |
82 | |
83 DISALLOW_COPY_AND_ASSIGN(MessageCenterChangeObserver); | |
84 }; | |
85 | |
86 // Class observing of "ADD" notification events. | |
87 class NotificationAddObserver : public MessageCenterChangeObserver { | |
88 public: | |
89 NotificationAddObserver() : count_(1) { | |
90 MessageCenterChangeObserver(); | |
91 } | |
92 explicit NotificationAddObserver(int count) : count_(count) { | |
93 MessageCenterChangeObserver(); | |
94 } | |
95 ~NotificationAddObserver() override {} | |
96 | |
97 bool Wait() { | |
98 if (count_ <= 0) | |
99 return count_ == 0; | |
100 | |
101 waiting_ = true; | |
102 RunLoop(); | |
103 waiting_ = false; | |
104 return count_ == 0; | |
105 } | |
106 | |
107 // message_center::MessageCenterObserver: | |
108 void OnNotificationAdded(const std::string& notification_id) override { | |
109 count_--; | |
110 | |
111 if (notification_id_.empty()) | |
112 notification_id_ = notification_id; | |
113 | |
114 if (waiting_) | |
115 QuitRunLoop(); | |
116 } | |
117 | |
118 std::string notification_id() { return notification_id_; } | |
119 | |
120 private: | |
121 std::string notification_id_; | |
122 bool waiting_ = false; | |
123 int count_; | |
124 | |
125 DISALLOW_COPY_AND_ASSIGN(NotificationAddObserver); | |
126 }; | |
127 | |
128 // Class observing of "UPDATE" notification events. | |
129 class NotificationUpdateObserver : public MessageCenterChangeObserver { | |
130 public: | |
131 NotificationUpdateObserver() : waiting_(false) { | |
132 MessageCenterChangeObserver(); | |
Nico
2015/05/22 18:41:48
This is not how you call a superclass constructor.
| |
133 } | |
134 ~NotificationUpdateObserver() override {} | |
135 | |
136 std::string Wait() { | |
137 if (!notification_id_.empty()) | |
138 return notification_id_; | |
139 | |
140 waiting_ = true; | |
141 RunLoop(); | |
142 waiting_ = false; | |
143 return notification_id_; | |
144 } | |
145 | |
146 void OnNotificationUpdated(const std::string& notification_id) override { | |
147 if (notification_id_.empty()) { | |
148 notification_id_ = notification_id; | |
149 | |
150 if (waiting_) | |
151 QuitRunLoop(); | |
152 } | |
153 } | |
154 | |
155 private: | |
156 std::string notification_id_; | |
157 bool waiting_; | |
158 | |
159 DISALLOW_COPY_AND_ASSIGN(NotificationUpdateObserver); | |
160 }; | |
161 | |
162 class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate { | |
163 public: | |
164 explicit TestChromeDownloadManagerDelegate(Profile* profile) | |
165 : ChromeDownloadManagerDelegate(profile), opened_(false) {} | |
166 ~TestChromeDownloadManagerDelegate() override {} | |
167 | |
168 // ChromeDownloadManagerDelegate override: | |
169 void OpenDownload(content::DownloadItem* item) override { opened_ = true; } | |
170 | |
171 // Return if the download is opened. | |
172 bool opened() const { return opened_; } | |
173 | |
174 private: | |
175 bool opened_; | |
176 }; | |
177 | |
178 // Utility method to retrieve a message center. | |
179 message_center::MessageCenter* GetMessageCenter() { | |
180 return message_center::MessageCenter::Get(); | |
181 } | |
182 | |
183 // Utility method to retrieve a notification object by id. | |
184 message_center::Notification* GetNotification(const std::string& id) { | |
185 return GetMessageCenter()->FindVisibleNotificationById(id); | |
186 } | |
187 | |
188 } // anonnymous namespace | |
189 | |
190 // Base class for tests | |
191 class DownloadNotificationTestBase : public InProcessBrowserTest { | |
192 public: | |
193 ~DownloadNotificationTestBase() override {} | |
194 | |
195 void SetUpCommandLine(base::CommandLine* command_line) override { | |
196 // TODO(yoshiki): Remove this after the download notification launches. | |
197 command_line->AppendSwitch(switches::kEnableDownloadNotification); | |
198 } | |
199 | |
200 void SetUpOnMainThread() override { | |
201 content::BrowserThread::PostTask( | |
202 content::BrowserThread::IO, FROM_HERE, | |
203 base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler)); | |
204 } | |
205 | |
206 content::DownloadManager* GetDownloadManager(Browser* browser) { | |
207 return content::BrowserContext::GetDownloadManager(browser->profile()); | |
208 } | |
209 }; | |
210 | |
211 ////////////////////////////////////////////////// | |
212 // Test with a single profile | |
213 ////////////////////////////////////////////////// | |
214 | |
215 class DownloadNotificationTest : public DownloadNotificationTestBase { | |
216 public: | |
217 ~DownloadNotificationTest() override {} | |
218 | |
219 void SetUpOnMainThread() override { | |
220 Profile* profile = browser()->profile(); | |
221 | |
222 scoped_ptr<TestChromeDownloadManagerDelegate> test_delegate; | |
223 test_delegate.reset(new TestChromeDownloadManagerDelegate(profile)); | |
224 test_delegate->GetDownloadIdReceiverCallback().Run( | |
225 content::DownloadItem::kInvalidId + 1); | |
226 | |
227 DownloadServiceFactory::GetForBrowserContext(profile) | |
228 ->SetDownloadManagerDelegateForTesting(test_delegate.Pass()); | |
229 | |
230 DownloadNotificationTestBase::SetUpOnMainThread(); | |
231 } | |
232 | |
233 TestChromeDownloadManagerDelegate* GetDownloadManagerDelegate() const { | |
234 return static_cast<TestChromeDownloadManagerDelegate*>( | |
235 DownloadServiceFactory::GetForBrowserContext(browser()->profile()) | |
236 ->GetDownloadManagerDelegate()); | |
237 } | |
238 }; | |
239 | |
240 IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadFile) { | |
241 GURL url(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); | |
242 | |
243 // Starts a download. | |
244 NotificationAddObserver download_start_notification_observer; | |
245 ui_test_utils::NavigateToURL(browser(), url); | |
246 EXPECT_TRUE(download_start_notification_observer.Wait()); | |
247 | |
248 // Confirms that a notification is created. | |
249 std::string notification_id = | |
250 download_start_notification_observer.notification_id(); | |
251 EXPECT_FALSE(notification_id.empty()); | |
252 | |
253 // Confirms that a download is also started. | |
254 std::vector<content::DownloadItem*> downloads; | |
255 GetDownloadManager(browser())->GetAllDownloads(&downloads); | |
256 EXPECT_EQ(1u, downloads.size()); | |
257 content::DownloadItem* download = downloads[0]; | |
258 | |
259 EXPECT_EQ(l10n_util::GetStringFUTF16( | |
260 IDS_DOWNLOAD_STATUS_IN_PROGRESS_TITLE, | |
261 download->GetFileNameToReportUser().LossyDisplayName()), | |
262 GetNotification(notification_id)->title()); | |
263 EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, | |
264 GetNotification(notification_id)->type()); | |
265 | |
266 // Requests to complete the download. | |
267 ui_test_utils::NavigateToURL( | |
268 browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); | |
269 | |
270 // Waits for download completion. | |
271 while (download->GetState() != content::DownloadItem::COMPLETE) { | |
272 NotificationUpdateObserver download_change_notification_observer; | |
273 download_change_notification_observer.Wait(); | |
274 } | |
275 | |
276 EXPECT_EQ(l10n_util::GetStringFUTF16( | |
277 IDS_DOWNLOAD_STATUS_DOWNLOADED_TITLE, | |
278 download->GetFileNameToReportUser().LossyDisplayName()), | |
279 GetNotification(notification_id)->title()); | |
280 EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, | |
281 GetNotification(notification_id)->type()); | |
282 | |
283 // Try to open the downloaded item by clicking the notification. | |
284 EXPECT_FALSE(GetDownloadManagerDelegate()->opened()); | |
285 GetMessageCenter()->ClickOnNotification(notification_id); | |
286 EXPECT_TRUE(GetDownloadManagerDelegate()->opened()); | |
287 | |
288 EXPECT_FALSE(GetNotification(notification_id)); | |
289 } | |
290 | |
291 IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadMultipleFiles) { | |
292 GURL url1(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); | |
293 GURL url2(net::URLRequestSlowDownloadJob::kKnownSizeUrl); | |
294 | |
295 // Starts the 1st download. | |
296 NotificationAddObserver download_start_notification_observer1; | |
297 ui_test_utils::NavigateToURL(browser(), url1); | |
298 EXPECT_TRUE(download_start_notification_observer1.Wait()); | |
299 std::string notification_id1 = | |
300 download_start_notification_observer1.notification_id(); | |
301 EXPECT_FALSE(notification_id1.empty()); | |
302 | |
303 // Confirms that there is a download. | |
304 std::vector<content::DownloadItem*> downloads; | |
305 GetDownloadManager(browser())->GetAllDownloads(&downloads); | |
306 EXPECT_EQ(1u, downloads.size()); | |
307 content::DownloadItem* download1or2 = downloads[0]; | |
308 | |
309 // Starts the 2nd download. | |
310 NotificationAddObserver download_start_notification_observer2; | |
311 ui_test_utils::NavigateToURL(browser(), url2); | |
312 EXPECT_TRUE(download_start_notification_observer2.Wait()); | |
313 std::string notification_id2 = | |
314 download_start_notification_observer2.notification_id(); | |
315 EXPECT_FALSE(notification_id2.empty()); | |
316 | |
317 // Confirms that there are 2 downloads. | |
318 downloads.clear(); | |
319 GetDownloadManager(browser())->GetAllDownloads(&downloads); | |
320 content::DownloadItem* download1 = downloads[0]; | |
321 content::DownloadItem* download2 = downloads[1]; | |
322 EXPECT_EQ(2u, downloads.size()); | |
323 EXPECT_NE(download1, download2); | |
324 EXPECT_TRUE(download1 == download1or2 || download2 == download1or2); | |
325 | |
326 // Confirms the types of download notifications are correct. | |
327 EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, | |
328 GetNotification(notification_id1)->type()); | |
329 EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, | |
330 GetNotification(notification_id2)->type()); | |
331 | |
332 // Requests to complete the downloads. | |
333 ui_test_utils::NavigateToURL( | |
334 browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); | |
335 | |
336 // Waits for the completion of downloads. | |
337 while (download1->GetState() != content::DownloadItem::COMPLETE || | |
338 download2->GetState() != content::DownloadItem::COMPLETE) { | |
339 NotificationUpdateObserver download_change_notification_observer; | |
340 download_change_notification_observer.Wait(); | |
341 } | |
342 | |
343 // Confirms the types of download notifications are correct. | |
344 EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, | |
345 GetNotification(notification_id1)->type()); | |
346 EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, | |
347 GetNotification(notification_id2)->type()); | |
348 } | |
349 | |
350 ////////////////////////////////////////////////// | |
351 // Test with multi profiles | |
352 ////////////////////////////////////////////////// | |
353 | |
354 class MultiProfileDownloadNotificationTest | |
355 : public DownloadNotificationTestBase { | |
356 public: | |
357 ~MultiProfileDownloadNotificationTest() override {} | |
358 | |
359 void SetUpCommandLine(base::CommandLine* command_line) override { | |
360 DownloadNotificationTestBase::SetUpCommandLine(command_line); | |
361 | |
362 // Logs in to a dummy profile. | |
363 command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, | |
364 kTestAccounts[DUMMY_ACCOUNT_INDEX].email); | |
365 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, | |
366 kTestAccounts[DUMMY_ACCOUNT_INDEX].hash); | |
367 } | |
368 | |
369 // Logs in to the primary profile. | |
370 void SetUpOnMainThread() override { | |
371 const TestAccountInfo& info = kTestAccounts[PRIMARY_ACCOUNT_INDEX]; | |
372 | |
373 AddUser(info, true); | |
374 DownloadNotificationTestBase::SetUpOnMainThread(); | |
375 } | |
376 | |
377 // Loads all users to the current session and sets up necessary fields. | |
378 // This is used for preparing all accounts in PRE_ test setup, and for testing | |
379 // actual login behavior. | |
380 void AddAllUsers() { | |
381 for (size_t i = 0; i < arraysize(kTestAccounts); ++i) | |
382 AddUser(kTestAccounts[i], i >= SECONDARY_ACCOUNT_INDEX_START); | |
383 } | |
384 | |
385 Profile* GetProfileByIndex(int index) { | |
386 return chromeos::ProfileHelper::GetProfileByUserIdHash( | |
387 kTestAccounts[index].hash); | |
388 } | |
389 | |
390 // Adds a new user for testing to the current session. | |
391 void AddUser(const TestAccountInfo& info, bool log_in) { | |
392 user_manager::UserManager* const user_manager = | |
393 user_manager::UserManager::Get(); | |
394 if (log_in) | |
395 user_manager->UserLoggedIn(info.email, info.hash, false); | |
396 user_manager->SaveUserDisplayName(info.email, | |
397 base::UTF8ToUTF16(info.display_name)); | |
398 SigninManagerFactory::GetForProfile( | |
399 chromeos::ProfileHelper::GetProfileByUserIdHash(info.hash)) | |
400 ->SetAuthenticatedAccountInfo(info.gaia_id, info.email); | |
401 } | |
402 }; | |
403 | |
404 IN_PROC_BROWSER_TEST_F(MultiProfileDownloadNotificationTest, | |
405 PRE_DownloadMultipleFiles) { | |
406 AddAllUsers(); | |
407 } | |
408 | |
409 IN_PROC_BROWSER_TEST_F(MultiProfileDownloadNotificationTest, | |
410 DownloadMultipleFiles) { | |
411 AddAllUsers(); | |
412 | |
413 GURL url(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); | |
414 | |
415 Profile* profile1 = GetProfileByIndex(1); | |
416 Profile* profile2 = GetProfileByIndex(2); | |
417 Browser* browser1 = CreateBrowser(profile1); | |
418 Browser* browser2 = CreateBrowser(profile2); | |
419 EXPECT_NE(browser1, browser2); | |
420 | |
421 // First user starts a download. | |
422 NotificationAddObserver download_start_notification_observer1; | |
423 ui_test_utils::NavigateToURL(browser1, url); | |
424 download_start_notification_observer1.Wait(); | |
425 | |
426 // Confirms that the download is started. | |
427 std::vector<content::DownloadItem*> downloads; | |
428 GetDownloadManager(browser1)->GetAllDownloads(&downloads); | |
429 EXPECT_EQ(1u, downloads.size()); | |
430 content::DownloadItem* download1 = downloads[0]; | |
431 | |
432 // Confirms that a download notification is generated. | |
433 std::string notification_id1 = | |
434 download_start_notification_observer1.notification_id(); | |
435 EXPECT_FALSE(notification_id1.empty()); | |
436 | |
437 // Second user starts a download. | |
438 NotificationAddObserver download_start_notification_observer2; | |
439 ui_test_utils::NavigateToURL(browser2, url); | |
440 download_start_notification_observer2.Wait(); | |
441 std::string notification_id2 = | |
442 download_start_notification_observer2.notification_id(); | |
443 EXPECT_FALSE(notification_id2.empty()); | |
444 | |
445 // Confirms that the second user has only 1 download. | |
446 downloads.clear(); | |
447 GetDownloadManager(browser2)->GetAllDownloads(&downloads); | |
448 ASSERT_EQ(1u, downloads.size()); | |
449 | |
450 // Second user starts another download. | |
451 NotificationAddObserver download_start_notification_observer3; | |
452 ui_test_utils::NavigateToURL(browser2, url); | |
453 download_start_notification_observer3.Wait(); | |
454 std::string notification_id3 = | |
455 download_start_notification_observer3.notification_id(); | |
456 EXPECT_FALSE(notification_id3.empty()); | |
457 | |
458 // Confirms that the second user has 2 downloads. | |
459 downloads.clear(); | |
460 GetDownloadManager(browser2)->GetAllDownloads(&downloads); | |
461 ASSERT_EQ(2u, downloads.size()); | |
462 content::DownloadItem* download2 = downloads[0]; | |
463 content::DownloadItem* download3 = downloads[1]; | |
464 EXPECT_NE(download1, download2); | |
465 EXPECT_NE(download1, download3); | |
466 EXPECT_NE(download2, download3); | |
467 | |
468 // Confirms that the first user still has only 1 download. | |
469 downloads.clear(); | |
470 GetDownloadManager(browser1)->GetAllDownloads(&downloads); | |
471 ASSERT_EQ(1u, downloads.size()); | |
472 EXPECT_EQ(download1, downloads[0]); | |
473 | |
474 // Confirms the types of download notifications are correct. | |
475 EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, | |
476 GetNotification(notification_id1)->type()); | |
477 EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, | |
478 GetNotification(notification_id2)->type()); | |
479 EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, | |
480 GetNotification(notification_id3)->type()); | |
481 | |
482 // Requests to complete the downloads. | |
483 ui_test_utils::NavigateToURL( | |
484 browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); | |
485 | |
486 // Waits for the completion of downloads. | |
487 while (download1->GetState() != content::DownloadItem::COMPLETE || | |
488 download2->GetState() != content::DownloadItem::COMPLETE || | |
489 download3->GetState() != content::DownloadItem::COMPLETE) { | |
490 NotificationUpdateObserver download_change_notification_observer; | |
491 download_change_notification_observer.Wait(); | |
492 } | |
493 | |
494 // Confirms the types of download notifications are correct. | |
495 EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, | |
496 GetNotification(notification_id1)->type()); | |
497 EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, | |
498 GetNotification(notification_id2)->type()); | |
499 EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, | |
500 GetNotification(notification_id3)->type()); | |
501 } | |
OLD | NEW |