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

Side by Side Diff: chrome/browser/download/download_extension_test.cc

Issue 9617010: Move chrome.downloads out of experimental to dev (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 8 years, 6 months 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
OLDNEW
(Empty)
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 <algorithm>
6
7 #include "base/file_util.h"
8 #include "base/scoped_temp_dir.h"
9 #include "base/stringprintf.h"
10 #include "chrome/browser/download/download_extension_api.h"
11 #include "chrome/browser/download/download_file_icon_extractor.h"
12 #include "chrome/browser/download/download_service.h"
13 #include "chrome/browser/download/download_service_factory.h"
14 #include "chrome/browser/download/download_test_observer.h"
15 #include "chrome/browser/extensions/extension_function_test_utils.h"
16 #include "chrome/browser/net/url_request_mock_util.h"
17 #include "chrome/browser/prefs/pref_service.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "chrome/test/base/ui_test_utils.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/download_manager.h"
25 #include "content/public/browser/download_persistent_store_info.h"
26 #include "content/test/net/url_request_slow_download_job.h"
27 #include "net/base/data_url.h"
28 #include "net/base/net_util.h"
29 #include "ui/gfx/codec/png_codec.h"
30
31 using content::BrowserContext;
32 using content::BrowserThread;
33 using content::DownloadItem;
34 using content::DownloadManager;
35 using content::DownloadPersistentStoreInfo;
36
37 namespace {
38
39 // Comparator that orders download items by their ID. Can be used with
40 // std::sort.
41 struct DownloadIdComparator {
42 bool operator() (DownloadItem* first, DownloadItem* second) {
43 return first->GetId() < second->GetId();
44 }
45 };
46
47 class DownloadExtensionTest : public InProcessBrowserTest {
48 protected:
49 // Used with CreateHistoryDownloads
50 struct HistoryDownloadInfo {
51 // Filename to use. CreateHistoryDownloads will append this filename to the
52 // temporary downloads directory specified by downloads_directory().
53 const FilePath::CharType* filename;
54
55 // State for the download. Note that IN_PROGRESS downloads will be created
56 // as CANCELLED.
57 DownloadItem::DownloadState state;
58
59 // Danger type for the download. Only use DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
60 // and DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT.
61 content::DownloadDangerType danger_type;
62 };
63
64 virtual Browser* current_browser() { return browser(); }
65
66 // InProcessBrowserTest
67 virtual void SetUpOnMainThread() OVERRIDE {
68 BrowserThread::PostTask(
69 BrowserThread::IO, FROM_HERE,
70 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
71 InProcessBrowserTest::SetUpOnMainThread();
72 CreateAndSetDownloadsDirectory();
73 current_browser()->profile()->GetPrefs()->SetBoolean(
74 prefs::kPromptForDownload, false);
75 GetDownloadManager()->RemoveAllDownloads();
76 }
77
78 virtual DownloadManager* GetDownloadManager() {
79 return BrowserContext::GetDownloadManager(current_browser()->profile());
80 }
81
82 // Creates a set of history downloads based on the provided |history_info|
83 // array. |count| is the number of elements in |history_info|. On success,
84 // |items| will contain |count| DownloadItems in the order that they were
85 // specified in |history_info|. Returns true on success and false otherwise.
86 bool CreateHistoryDownloads(const HistoryDownloadInfo* history_info,
87 size_t count,
88 DownloadManager::DownloadVector* items) {
89 DownloadIdComparator download_id_comparator;
90 base::Time current = base::Time::Now();
91 std::vector<DownloadPersistentStoreInfo> entries;
92 entries.reserve(count);
93 for (size_t i = 0; i < count; ++i) {
94 DownloadPersistentStoreInfo entry(
95 downloads_directory().Append(history_info[i].filename),
96 GURL(), GURL(), // URL, referrer
97 current, current, // start_time, end_time
98 1, 1, // received_bytes, total_bytes
99 history_info[i].state, // state
100 i + 1, // db_handle
101 false); // opened
102 entries.push_back(entry);
103 }
104 GetDownloadManager()->OnPersistentStoreQueryComplete(&entries);
105 GetDownloadManager()->GetAllDownloads(FilePath(), items);
106 EXPECT_EQ(count, items->size());
107 if (count != items->size())
108 return false;
109
110 // Order by ID so that they are in the order that we created them.
111 std::sort(items->begin(), items->end(), download_id_comparator);
112 // Set the danger type if necessary.
113 for (size_t i = 0; i < count; ++i) {
114 if (history_info[i].danger_type !=
115 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
116 EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT,
117 history_info[i].danger_type);
118 items->at(i)->OnContentCheckCompleted(history_info[i].danger_type);
119 }
120 }
121 return true;
122 }
123
124 void CreateSlowTestDownloads(
125 size_t count, DownloadManager::DownloadVector* items) {
126 for (size_t i = 0; i < count; ++i) {
127 scoped_ptr<DownloadTestObserver> observer(
128 CreateInProgressDownloadObserver(1));
129 GURL slow_download_url(URLRequestSlowDownloadJob::kUnknownSizeUrl);
130 ui_test_utils::NavigateToURLWithDisposition(
131 current_browser(), slow_download_url, CURRENT_TAB,
132 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
133 observer->WaitForFinished();
134 EXPECT_EQ(
135 1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
136 // We don't expect a select file dialog.
137 ASSERT_FALSE(observer->select_file_dialog_seen());
138 }
139 GetDownloadManager()->GetAllDownloads(FilePath(), items);
140 ASSERT_EQ(count, items->size());
141 }
142
143 DownloadItem* CreateSlowTestDownload() {
144 scoped_ptr<DownloadTestObserver> observer(
145 CreateInProgressDownloadObserver(1));
146 GURL slow_download_url(URLRequestSlowDownloadJob::kUnknownSizeUrl);
147 DownloadManager* manager = GetDownloadManager();
148
149 EXPECT_EQ(0, manager->InProgressCount());
150 if (manager->InProgressCount() != 0)
151 return NULL;
152
153 ui_test_utils::NavigateToURLWithDisposition(
154 current_browser(), slow_download_url, CURRENT_TAB,
155 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
156
157 observer->WaitForFinished();
158 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
159 // We don't expect a select file dialog.
160 if (observer->select_file_dialog_seen())
161 return NULL;
162
163 DownloadManager::DownloadVector items;
164 manager->GetAllDownloads(FilePath(), &items);
165
166 DownloadItem* new_item = NULL;
167 for (DownloadManager::DownloadVector::iterator iter = items.begin();
168 iter != items.end(); ++iter) {
169 if ((*iter)->GetState() == DownloadItem::IN_PROGRESS) {
170 // There should be only one IN_PROGRESS item.
171 EXPECT_EQ(NULL, new_item);
172 new_item = *iter;
173 }
174 }
175 return new_item;
176 }
177
178 void FinishPendingSlowDownloads() {
179 scoped_ptr<DownloadTestObserver> observer(
180 CreateDownloadObserver(1));
181 GURL finish_url(URLRequestSlowDownloadJob::kFinishDownloadUrl);
182 ui_test_utils::NavigateToURLWithDisposition(
183 current_browser(), finish_url, NEW_FOREGROUND_TAB,
184 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
185 observer->WaitForFinished();
186 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::COMPLETE));
187 }
188
189 DownloadTestObserver* CreateDownloadObserver(size_t download_count) {
190 return new DownloadTestObserverTerminal(
191 GetDownloadManager(), download_count, true,
192 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
193 }
194
195 DownloadTestObserver* CreateInProgressDownloadObserver(
196 size_t download_count) {
197 return new DownloadTestObserverInProgress(GetDownloadManager(),
198 download_count,
199 true);
200 }
201
202 extension_function_test_utils::RunFunctionFlags GetFlags() {
203 return current_browser()->profile()->IsOffTheRecord() ?
204 extension_function_test_utils::INCLUDE_INCOGNITO :
205 extension_function_test_utils::NONE;
206 }
207
208 // extension_function_test_utils::RunFunction*() only uses browser for its
209 // profile(), so pass it the on-record browser so that it always uses the
210 // on-record profile.
211
212 bool RunFunction(UIThreadExtensionFunction* function,
213 const std::string& args) {
214 // extension_function_test_utils::RunFunction() does not take
215 // ownership of |function|.
216 scoped_refptr<ExtensionFunction> function_owner(function);
217 return extension_function_test_utils::RunFunction(
218 function, args, browser(), GetFlags());
219 }
220
221 base::Value* RunFunctionAndReturnResult(UIThreadExtensionFunction* function,
222 const std::string& args) {
223 return extension_function_test_utils::RunFunctionAndReturnResult(
224 function, args, browser(), GetFlags());
225 }
226
227 std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
228 const std::string& args) {
229 return extension_function_test_utils::RunFunctionAndReturnError(
230 function, args, browser(), GetFlags());
231 }
232
233 bool RunFunctionAndReturnString(UIThreadExtensionFunction* function,
234 const std::string& args,
235 std::string* result_string) {
236 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(function, args));
237 EXPECT_TRUE(result.get());
238 return result.get() && result->GetAsString(result_string);
239 }
240
241 std::string DownloadItemIdAsArgList(const DownloadItem* download_item) {
242 return base::StringPrintf("[%d]", download_item->GetId());
243 }
244
245 // Checks if a data URL encoded image is a PNG of a given size.
246 void ExpectDataURLIsPNGWithSize(const std::string& url, int expected_size) {
247 std::string mime_type;
248 std::string charset;
249 std::string data;
250 EXPECT_FALSE(url.empty());
251 EXPECT_TRUE(net::DataURL::Parse(GURL(url), &mime_type, &charset, &data));
252 EXPECT_STREQ("image/png", mime_type.c_str());
253 EXPECT_FALSE(data.empty());
254
255 if (data.empty())
256 return;
257
258 int width = -1, height = -1;
259 std::vector<unsigned char> decoded_data;
260 EXPECT_TRUE(gfx::PNGCodec::Decode(
261 reinterpret_cast<const unsigned char*>(data.c_str()), data.length(),
262 gfx::PNGCodec::FORMAT_RGBA, &decoded_data,
263 &width, &height));
264 EXPECT_EQ(expected_size, width);
265 EXPECT_EQ(expected_size, height);
266 }
267
268 const FilePath& downloads_directory() {
269 return downloads_directory_.path();
270 }
271
272 private:
273 void CreateAndSetDownloadsDirectory() {
274 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
275 current_browser()->profile()->GetPrefs()->SetFilePath(
276 prefs::kDownloadDefaultDirectory,
277 downloads_directory_.path());
278 }
279
280 ScopedTempDir downloads_directory_;
281 };
282
283 class DownloadExtensionTestIncognito : public DownloadExtensionTest {
284 public:
285 virtual Browser* current_browser() OVERRIDE { return current_browser_; }
286
287 virtual void SetUpOnMainThread() OVERRIDE {
288 GoOnTheRecord();
289 DownloadExtensionTest::SetUpOnMainThread();
290 incognito_browser_ = CreateIncognitoBrowser();
291 GoOffTheRecord();
292 GetDownloadManager()->RemoveAllDownloads();
293 }
294
295 void GoOnTheRecord() { current_browser_ = browser(); }
296 void GoOffTheRecord() { current_browser_ = incognito_browser_; }
297
298 private:
299 Browser* incognito_browser_;
300 Browser* current_browser_;
301 };
302
303 class MockIconExtractorImpl : public DownloadFileIconExtractor {
304 public:
305 MockIconExtractorImpl(const FilePath& path, IconLoader::IconSize icon_size,
306 const std::string& response)
307 : expected_path_(path),
308 expected_icon_size_(icon_size),
309 response_(response) {
310 }
311 virtual ~MockIconExtractorImpl() {}
312
313 virtual bool ExtractIconURLForPath(const FilePath& path,
314 IconLoader::IconSize icon_size,
315 IconURLCallback callback) OVERRIDE {
316 EXPECT_STREQ(expected_path_.value().c_str(), path.value().c_str());
317 EXPECT_EQ(expected_icon_size_, icon_size);
318 if (expected_path_ == path &&
319 expected_icon_size_ == icon_size) {
320 callback_ = callback;
321 BrowserThread::PostTask(
322 BrowserThread::UI, FROM_HERE,
323 base::Bind(&MockIconExtractorImpl::RunCallback,
324 base::Unretained(this)));
325 return true;
326 } else {
327 return false;
328 }
329 }
330
331 private:
332 void RunCallback() {
333 callback_.Run(response_);
334 }
335
336 FilePath expected_path_;
337 IconLoader::IconSize expected_icon_size_;
338 std::string response_;
339 IconURLCallback callback_;
340 };
341
342 // Cancels the underlying DownloadItem when the ScopedCancellingItem goes out of
343 // scope. Like a scoped_ptr, but for DownloadItems.
344 class ScopedCancellingItem {
345 public:
346 explicit ScopedCancellingItem(DownloadItem* item) : item_(item) {}
347 ~ScopedCancellingItem() {
348 item_->Cancel(true);
349 }
350 DownloadItem* operator*() { return item_; }
351 DownloadItem* operator->() { return item_; }
352 DownloadItem* get() { return item_; }
353 private:
354 DownloadItem* item_;
355 DISALLOW_COPY_AND_ASSIGN(ScopedCancellingItem);
356 };
357
358 // Cancels all the underlying DownloadItems when the ScopedItemVectorCanceller
359 // goes out of scope. Generalization of ScopedCancellingItem to many
360 // DownloadItems.
361 class ScopedItemVectorCanceller {
362 public:
363 explicit ScopedItemVectorCanceller(DownloadManager::DownloadVector* items)
364 : items_(items) {
365 }
366 ~ScopedItemVectorCanceller() {
367 for (DownloadManager::DownloadVector::const_iterator item = items_->begin();
368 item != items_->end(); ++item) {
369 if ((*item)->IsInProgress())
370 (*item)->Cancel(true);
371 }
372 }
373
374 private:
375 DownloadManager::DownloadVector* items_;
376 DISALLOW_COPY_AND_ASSIGN(ScopedItemVectorCanceller);
377 };
378
379 } // namespace
380
381 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_PauseResumeCancel) {
382 DownloadItem* download_item = CreateSlowTestDownload();
383 ASSERT_TRUE(download_item);
384
385 // Call pause(). It should succeed and the download should be paused on
386 // return.
387 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(),
388 DownloadItemIdAsArgList(download_item)));
389 EXPECT_TRUE(download_item->IsPaused());
390
391 // Calling pause() twice shouldn't be an error.
392 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(),
393 DownloadItemIdAsArgList(download_item)));
394 EXPECT_TRUE(download_item->IsPaused());
395
396 // Now try resuming this download. It should succeed.
397 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(),
398 DownloadItemIdAsArgList(download_item)));
399 EXPECT_FALSE(download_item->IsPaused());
400
401 // Resume again. Resuming a download that wasn't paused is not an error.
402 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(),
403 DownloadItemIdAsArgList(download_item)));
404 EXPECT_FALSE(download_item->IsPaused());
405
406 // Pause again.
407 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(),
408 DownloadItemIdAsArgList(download_item)));
409 EXPECT_TRUE(download_item->IsPaused());
410
411 // And now cancel.
412 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(),
413 DownloadItemIdAsArgList(download_item)));
414 EXPECT_TRUE(download_item->IsCancelled());
415
416 // Cancel again. Shouldn't have any effect.
417 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(),
418 DownloadItemIdAsArgList(download_item)));
419 EXPECT_TRUE(download_item->IsCancelled());
420
421 // Calling paused on a non-active download yields kInvalidOperationError.
422 std::string error = RunFunctionAndReturnError(
423 new DownloadsPauseFunction(), DownloadItemIdAsArgList(download_item));
424 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
425 error.c_str());
426
427 // Calling resume on a non-active download yields kInvalidOperationError
428 error = RunFunctionAndReturnError(
429 new DownloadsResumeFunction(), DownloadItemIdAsArgList(download_item));
430 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
431 error.c_str());
432
433 // Calling pause()/resume()/cancel() with invalid download Ids is
434 // tested in the API test (DownloadsApiTest).
435 }
436
437 // Test downloads.getFileIcon() on in-progress, finished, cancelled and deleted
438 // download items.
439 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_FileIcon_Active) {
440 DownloadItem* download_item = CreateSlowTestDownload();
441 ASSERT_TRUE(download_item);
442
443 // Get the icon for the in-progress download. This call should succeed even
444 // if the file type isn't registered.
445 std::string args = base::StringPrintf("[%d, {}]", download_item->GetId());
446 std::string result_string;
447 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(),
448 args, &result_string));
449
450 // Note: We are checking if the result is a Data URL that has encoded
451 // image/png data for an icon of a specific size. Of these, only the icon size
452 // is specified in the API contract. The image type (image/png) and URL type
453 // (Data) are implementation details.
454
455 // The default size for icons returned by getFileIcon() is 32x32.
456 ExpectDataURLIsPNGWithSize(result_string, 32);
457
458 // Test whether the correct path is being pased into the icon extractor.
459 FilePath expected_path(download_item->GetTargetFilePath());
460 scoped_refptr<DownloadsGetFileIconFunction> function(
461 new DownloadsGetFileIconFunction());
462 function->SetIconExtractorForTesting(new MockIconExtractorImpl(
463 expected_path, IconLoader::NORMAL, "foo"));
464 EXPECT_TRUE(RunFunctionAndReturnString(function.release(), args,
465 &result_string));
466
467 // Now try a 16x16 icon.
468 args = base::StringPrintf("[%d, {\"size\": 16}]", download_item->GetId());
469 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(),
470 args, &result_string));
471 ExpectDataURLIsPNGWithSize(result_string, 16);
472
473 // Explicitly asking for 32x32 should give us a 32x32 icon.
474 args = base::StringPrintf("[%d, {\"size\": 32}]", download_item->GetId());
475 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(),
476 args, &result_string));
477 ExpectDataURLIsPNGWithSize(result_string, 32);
478
479 // Finish the download and try again.
480 FinishPendingSlowDownloads();
481 EXPECT_EQ(DownloadItem::COMPLETE, download_item->GetState());
482 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(),
483 args, &result_string));
484 ExpectDataURLIsPNGWithSize(result_string, 32);
485
486 // Check the path passed to the icon extractor post-completion.
487 function = new DownloadsGetFileIconFunction();
488 function->SetIconExtractorForTesting(new MockIconExtractorImpl(
489 expected_path, IconLoader::NORMAL, "foo"));
490 EXPECT_TRUE(RunFunctionAndReturnString(function.release(), args,
491 &result_string));
492
493 // Now create another download.
494 download_item = CreateSlowTestDownload();
495 ASSERT_TRUE(download_item);
496 expected_path = download_item->GetTargetFilePath();
497
498 // Cancel the download. As long as the download has a target path, we should
499 // be able to query the file icon.
500 download_item->Cancel(true);
501 // Let cleanup complete on the FILE thread.
502 ui_test_utils::RunAllPendingInMessageLoop(BrowserThread::FILE);
503 args = base::StringPrintf("[%d, {\"size\": 32}]", download_item->GetId());
504 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(),
505 args, &result_string));
506 ExpectDataURLIsPNGWithSize(result_string, 32);
507
508 // Check the path passed to the icon extractor post-cancellation.
509 function = new DownloadsGetFileIconFunction();
510 function->SetIconExtractorForTesting(new MockIconExtractorImpl(
511 expected_path, IconLoader::NORMAL, "foo"));
512 EXPECT_TRUE(RunFunctionAndReturnString(function.release(), args,
513 &result_string));
514
515 // Simulate an error during icon load by invoking the mock with an empty
516 // result string.
517 function = new DownloadsGetFileIconFunction();
518 function->SetIconExtractorForTesting(new MockIconExtractorImpl(
519 expected_path, IconLoader::NORMAL, ""));
520 std::string error = RunFunctionAndReturnError(function.release(), args);
521 EXPECT_STREQ(download_extension_errors::kIconNotFoundError,
522 error.c_str());
523
524 // Once the download item is deleted, we should return kInvalidOperationError.
525 download_item->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD);
526 error = RunFunctionAndReturnError(new DownloadsGetFileIconFunction(), args);
527 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
528 error.c_str());
529
530 // Asking for icons of other (invalid) sizes is tested in the API test
531 // (DownloadsApiTest).
532 }
533
534 // Test that we can acquire file icons for history downloads regardless of
535 // whether they exist or not. If the file doesn't exist we should receive a
536 // generic icon from the OS/toolkit that may or may not be specific to the file
537 // type.
538 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_FileIcon_History) {
539 const HistoryDownloadInfo kHistoryInfo[] = {
540 { FILE_PATH_LITERAL("real.txt"),
541 DownloadItem::COMPLETE,
542 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
543 { FILE_PATH_LITERAL("fake.txt"),
544 DownloadItem::COMPLETE,
545 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
546 };
547 DownloadManager::DownloadVector all_downloads;
548 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
549 &all_downloads));
550
551 FilePath real_path = all_downloads[0]->GetFullPath();
552 FilePath fake_path = all_downloads[1]->GetFullPath();
553
554 EXPECT_EQ(0, file_util::WriteFile(real_path, "", 0));
555 ASSERT_TRUE(file_util::PathExists(real_path));
556 ASSERT_FALSE(file_util::PathExists(fake_path));
557
558 for (DownloadManager::DownloadVector::iterator iter = all_downloads.begin();
559 iter != all_downloads.end();
560 ++iter) {
561 std::string args(base::StringPrintf("[%d, {\"size\": 32}]",
562 (*iter)->GetId()));
563 std::string result_string;
564 EXPECT_TRUE(RunFunctionAndReturnString(
565 new DownloadsGetFileIconFunction(), args, &result_string));
566 // Note: We are checking if the result is a Data URL that has encoded
567 // image/png data for an icon of a specific size. Of these, only the icon
568 // size is specified in the API contract. The image type (image/png) and URL
569 // type (Data) are implementation details.
570 ExpectDataURLIsPNGWithSize(result_string, 32);
571
572 // Use a MockIconExtractorImpl to test if the correct path is being passed
573 // into the DownloadFileIconExtractor.
574 scoped_refptr<DownloadsGetFileIconFunction> function(
575 new DownloadsGetFileIconFunction());
576 function->SetIconExtractorForTesting(new MockIconExtractorImpl(
577 (*iter)->GetFullPath(), IconLoader::NORMAL, "hello"));
578 EXPECT_TRUE(RunFunctionAndReturnString(function.release(), args,
579 &result_string));
580 EXPECT_STREQ("hello", result_string.c_str());
581 }
582
583 // The temporary files should be cleaned up when the ScopedTempDir is removed.
584 }
585
586 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchEmptyQuery) {
587 ScopedCancellingItem item(CreateSlowTestDownload());
588 ASSERT_TRUE(item.get());
589
590 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
591 new DownloadsSearchFunction(), "[{}]"));
592 ASSERT_TRUE(result.get());
593 base::ListValue* result_list = NULL;
594 ASSERT_TRUE(result->GetAsList(&result_list));
595 ASSERT_EQ(1UL, result_list->GetSize());
596 }
597
598 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
599 DownloadsApi_SearchFilenameRegex) {
600 const HistoryDownloadInfo kHistoryInfo[] = {
601 { FILE_PATH_LITERAL("foobar"),
602 DownloadItem::COMPLETE,
603 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
604 { FILE_PATH_LITERAL("baz"),
605 DownloadItem::COMPLETE,
606 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
607 };
608 DownloadManager::DownloadVector all_downloads;
609 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
610 &all_downloads));
611
612 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
613 new DownloadsSearchFunction(), "[{\"filenameRegex\": \"foobar\"}]"));
614 ASSERT_TRUE(result.get());
615 base::ListValue* result_list = NULL;
616 ASSERT_TRUE(result->GetAsList(&result_list));
617 ASSERT_EQ(1UL, result_list->GetSize());
618 base::DictionaryValue* item_value = NULL;
619 ASSERT_TRUE(result_list->GetDictionary(0, &item_value));
620 int item_id = -1;
621 ASSERT_TRUE(item_value->GetInteger("id", &item_id));
622 ASSERT_EQ(0, item_id);
623 }
624
625 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchId) {
626 DownloadManager::DownloadVector items;
627 CreateSlowTestDownloads(2, &items);
628 ScopedItemVectorCanceller delete_items(&items);
629
630 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
631 new DownloadsSearchFunction(), "[{\"id\": 0}]"));
632 ASSERT_TRUE(result.get());
633 base::ListValue* result_list = NULL;
634 ASSERT_TRUE(result->GetAsList(&result_list));
635 ASSERT_EQ(1UL, result_list->GetSize());
636 base::DictionaryValue* item_value = NULL;
637 ASSERT_TRUE(result_list->GetDictionary(0, &item_value));
638 int item_id = -1;
639 ASSERT_TRUE(item_value->GetInteger("id", &item_id));
640 ASSERT_EQ(0, item_id);
641 }
642
643 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
644 DownloadsApi_SearchIdAndFilename) {
645 DownloadManager::DownloadVector items;
646 CreateSlowTestDownloads(2, &items);
647 ScopedItemVectorCanceller delete_items(&items);
648
649 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
650 new DownloadsSearchFunction(), "[{\"id\": 0,\"filename\": \"foobar\"}]"));
651 ASSERT_TRUE(result.get());
652 base::ListValue* result_list = NULL;
653 ASSERT_TRUE(result->GetAsList(&result_list));
654 ASSERT_EQ(0UL, result_list->GetSize());
655 }
656
657 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchOrderBy) {
658 const HistoryDownloadInfo kHistoryInfo[] = {
659 { FILE_PATH_LITERAL("zzz"),
660 DownloadItem::COMPLETE,
661 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
662 { FILE_PATH_LITERAL("baz"),
663 DownloadItem::COMPLETE,
664 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
665 };
666 DownloadManager::DownloadVector items;
667 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
668 &items));
669
670 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
671 new DownloadsSearchFunction(), "[{\"orderBy\": \"filename\"}]"));
672 ASSERT_TRUE(result.get());
673 base::ListValue* result_list = NULL;
674 ASSERT_TRUE(result->GetAsList(&result_list));
675 ASSERT_EQ(2UL, result_list->GetSize());
676 base::DictionaryValue* item0_value = NULL;
677 base::DictionaryValue* item1_value = NULL;
678 ASSERT_TRUE(result_list->GetDictionary(0, &item0_value));
679 ASSERT_TRUE(result_list->GetDictionary(1, &item1_value));
680 std::string item0_name, item1_name;
681 ASSERT_TRUE(item0_value->GetString("filename", &item0_name));
682 ASSERT_TRUE(item1_value->GetString("filename", &item1_name));
683 ASSERT_GT(items[0]->GetFullPath().value(), items[1]->GetFullPath().value());
684 ASSERT_LT(item0_name, item1_name);
685 }
686
687 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchOrderByEmpty) {
688 const HistoryDownloadInfo kHistoryInfo[] = {
689 { FILE_PATH_LITERAL("zzz"),
690 DownloadItem::COMPLETE,
691 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
692 { FILE_PATH_LITERAL("baz"),
693 DownloadItem::COMPLETE,
694 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
695 };
696 DownloadManager::DownloadVector items;
697 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
698 &items));
699
700 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
701 new DownloadsSearchFunction(), "[{\"orderBy\": \"\"}]"));
702 ASSERT_TRUE(result.get());
703 base::ListValue* result_list = NULL;
704 ASSERT_TRUE(result->GetAsList(&result_list));
705 ASSERT_EQ(2UL, result_list->GetSize());
706 base::DictionaryValue* item0_value = NULL;
707 base::DictionaryValue* item1_value = NULL;
708 ASSERT_TRUE(result_list->GetDictionary(0, &item0_value));
709 ASSERT_TRUE(result_list->GetDictionary(1, &item1_value));
710 std::string item0_name, item1_name;
711 ASSERT_TRUE(item0_value->GetString("filename", &item0_name));
712 ASSERT_TRUE(item1_value->GetString("filename", &item1_name));
713 ASSERT_GT(items[0]->GetFullPath().value(), items[1]->GetFullPath().value());
714 ASSERT_GT(item0_name, item1_name);
715 }
716
717 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchDanger) {
718 const HistoryDownloadInfo kHistoryInfo[] = {
719 { FILE_PATH_LITERAL("zzz"),
720 DownloadItem::COMPLETE,
721 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT },
722 { FILE_PATH_LITERAL("baz"),
723 DownloadItem::COMPLETE,
724 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
725 };
726 DownloadManager::DownloadVector items;
727 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
728 &items));
729
730 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
731 new DownloadsSearchFunction(), "[{\"danger\": \"content\"}]"));
732 ASSERT_TRUE(result.get());
733 base::ListValue* result_list = NULL;
734 ASSERT_TRUE(result->GetAsList(&result_list));
735 ASSERT_EQ(1UL, result_list->GetSize());
736 }
737
738 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchState) {
739 DownloadManager::DownloadVector items;
740 CreateSlowTestDownloads(2, &items);
741 ScopedItemVectorCanceller delete_items(&items);
742
743 items[0]->Cancel(true);
744
745 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
746 new DownloadsSearchFunction(), "[{\"state\": \"in_progress\"}]"));
747 ASSERT_TRUE(result.get());
748 base::ListValue* result_list = NULL;
749 ASSERT_TRUE(result->GetAsList(&result_list));
750 ASSERT_EQ(1UL, result_list->GetSize());
751 }
752
753 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchLimit) {
754 DownloadManager::DownloadVector items;
755 CreateSlowTestDownloads(2, &items);
756 ScopedItemVectorCanceller delete_items(&items);
757
758 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
759 new DownloadsSearchFunction(), "[{\"limit\": 1}]"));
760 ASSERT_TRUE(result.get());
761 base::ListValue* result_list = NULL;
762 ASSERT_TRUE(result->GetAsList(&result_list));
763 ASSERT_EQ(1UL, result_list->GetSize());
764 }
765
766 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchInvalid) {
767 std::string error = RunFunctionAndReturnError(
768 new DownloadsSearchFunction(), "[{\"filenameRegex\": \"(\"}]");
769 EXPECT_STREQ(download_extension_errors::kInvalidFilterError,
770 error.c_str());
771 error = RunFunctionAndReturnError(
772 new DownloadsSearchFunction(), "[{\"danger\": \"goat\"}]");
773 EXPECT_STREQ(download_extension_errors::kInvalidDangerTypeError,
774 error.c_str());
775 error = RunFunctionAndReturnError(
776 new DownloadsSearchFunction(), "[{\"state\": \"goat\"}]");
777 EXPECT_STREQ(download_extension_errors::kInvalidStateError,
778 error.c_str());
779 error = RunFunctionAndReturnError(
780 new DownloadsSearchFunction(), "[{\"orderBy\": \"goat\"}]");
781 EXPECT_STREQ(download_extension_errors::kInvalidOrderByError,
782 error.c_str());
783 error = RunFunctionAndReturnError(
784 new DownloadsSearchFunction(), "[{\"limit\": -1}]");
785 EXPECT_STREQ(download_extension_errors::kInvalidQueryLimit,
786 error.c_str());
787 }
788
789 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchPlural) {
790 const HistoryDownloadInfo kHistoryInfo[] = {
791 { FILE_PATH_LITERAL("aaa"),
792 DownloadItem::CANCELLED,
793 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
794 { FILE_PATH_LITERAL("zzz"),
795 DownloadItem::COMPLETE,
796 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT },
797 { FILE_PATH_LITERAL("baz"),
798 DownloadItem::COMPLETE,
799 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT },
800 };
801 DownloadManager::DownloadVector items;
802 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
803 &items));
804
805 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
806 new DownloadsSearchFunction(), "[{"
807 "\"state\": \"complete\", "
808 "\"danger\": \"content\", "
809 "\"orderBy\": \"filename\", "
810 "\"limit\": 1}]"));
811 ASSERT_TRUE(result.get());
812 base::ListValue* result_list = NULL;
813 ASSERT_TRUE(result->GetAsList(&result_list));
814 ASSERT_EQ(1UL, result_list->GetSize());
815 base::DictionaryValue* item_value = NULL;
816 ASSERT_TRUE(result_list->GetDictionary(0, &item_value));
817 FilePath::StringType item_name;
818 ASSERT_TRUE(item_value->GetString("filename", &item_name));
819 ASSERT_EQ(items[2]->GetFullPath().value(), item_name);
820 }
821
822 IN_PROC_BROWSER_TEST_F(DownloadExtensionTestIncognito,
823 DownloadsApi_SearchIncognito) {
824 scoped_ptr<base::Value> result_value;
825 base::ListValue* result_list = NULL;
826 base::DictionaryValue* result_dict = NULL;
827 FilePath::StringType filename;
828 bool is_incognito = false;
829 std::string error;
830 std::string on_item_arg;
831 std::string off_item_arg;
832 std::string result_string;
833
834 // Set up one on-record item and one off-record item.
835
836 GoOnTheRecord();
837 DownloadItem* on_item = CreateSlowTestDownload();
838 ASSERT_TRUE(on_item);
839 ASSERT_FALSE(on_item->IsOtr());
840 on_item_arg = DownloadItemIdAsArgList(on_item);
841
842 GoOffTheRecord();
843 DownloadItem* off_item = CreateSlowTestDownload();
844 ASSERT_TRUE(off_item);
845 ASSERT_TRUE(off_item->IsOtr());
846 ASSERT_TRUE(on_item->GetFullPath() != off_item->GetFullPath());
847 off_item_arg = DownloadItemIdAsArgList(off_item);
848
849 // Extensions running in the incognito window should have access to both
850 // items because the Test extension is in spanning mode.
851 result_value.reset(RunFunctionAndReturnResult(
852 new DownloadsSearchFunction(), "[{}]"));
853 ASSERT_TRUE(result_value.get());
854 ASSERT_TRUE(result_value->GetAsList(&result_list));
855 ASSERT_EQ(2UL, result_list->GetSize());
856 ASSERT_TRUE(result_list->GetDictionary(0, &result_dict));
857 ASSERT_TRUE(result_dict->GetString("filename", &filename));
858 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito));
859 EXPECT_TRUE(on_item->GetFullPath() == FilePath(filename));
860 EXPECT_FALSE(is_incognito);
861 ASSERT_TRUE(result_list->GetDictionary(1, &result_dict));
862 ASSERT_TRUE(result_dict->GetString("filename", &filename));
863 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito));
864 EXPECT_TRUE(off_item->GetFullPath() == FilePath(filename));
865 EXPECT_TRUE(is_incognito);
866
867 // Extensions running in the on-record window should have access only to the
868 // on-record item.
869 GoOnTheRecord();
870 result_value.reset(RunFunctionAndReturnResult(
871 new DownloadsSearchFunction(), "[{}]"));
872 ASSERT_TRUE(result_value.get());
873 ASSERT_TRUE(result_value->GetAsList(&result_list));
874 ASSERT_EQ(1UL, result_list->GetSize());
875 ASSERT_TRUE(result_list->GetDictionary(0, &result_dict));
876 ASSERT_TRUE(result_dict->GetString("filename", &filename));
877 EXPECT_TRUE(on_item->GetFullPath() == FilePath(filename));
878 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito));
879 EXPECT_FALSE(is_incognito);
880
881 // Pausing/Resuming the off-record item while on the record should return an
882 // error. Cancelling "non-existent" downloads is not an error.
883 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), off_item_arg);
884 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
885 error.c_str());
886 error = RunFunctionAndReturnError(new DownloadsResumeFunction(),
887 off_item_arg);
888 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
889 error.c_str());
890 error = RunFunctionAndReturnError(
891 new DownloadsGetFileIconFunction(),
892 base::StringPrintf("[%d, {}]", off_item->GetId()));
893 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
894 error.c_str());
895
896 // TODO(benjhayden): Test incognito_split_mode() extension.
897 // TODO(benjhayden): Test download(), onCreated, onChanged, onErased.
898
899 GoOffTheRecord();
900
901 // Do the FileIcon test for both the on- and off-items while off the record.
902 // NOTE(benjhayden): This does not include the FileIcon test from history,
903 // just active downloads. This shouldn't be a problem.
904 EXPECT_TRUE(RunFunctionAndReturnString(
905 new DownloadsGetFileIconFunction(),
906 base::StringPrintf("[%d, {}]", on_item->GetId()), &result_string));
907 EXPECT_TRUE(RunFunctionAndReturnString(
908 new DownloadsGetFileIconFunction(),
909 base::StringPrintf("[%d, {}]", off_item->GetId()), &result_string));
910
911 // Do the pause/resume/cancel test for both the on- and off-items while off
912 // the record.
913 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg));
914 EXPECT_TRUE(on_item->IsPaused());
915 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg));
916 EXPECT_TRUE(on_item->IsPaused());
917 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), on_item_arg));
918 EXPECT_FALSE(on_item->IsPaused());
919 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), on_item_arg));
920 EXPECT_FALSE(on_item->IsPaused());
921 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg));
922 EXPECT_TRUE(on_item->IsPaused());
923 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), on_item_arg));
924 EXPECT_TRUE(on_item->IsCancelled());
925 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), on_item_arg));
926 EXPECT_TRUE(on_item->IsCancelled());
927 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), on_item_arg);
928 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
929 error.c_str());
930 error = RunFunctionAndReturnError(new DownloadsResumeFunction(), on_item_arg);
931 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
932 error.c_str());
933 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg));
934 EXPECT_TRUE(off_item->IsPaused());
935 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg));
936 EXPECT_TRUE(off_item->IsPaused());
937 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), off_item_arg));
938 EXPECT_FALSE(off_item->IsPaused());
939 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), off_item_arg));
940 EXPECT_FALSE(off_item->IsPaused());
941 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg));
942 EXPECT_TRUE(off_item->IsPaused());
943 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), off_item_arg));
944 EXPECT_TRUE(off_item->IsCancelled());
945 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), off_item_arg));
946 EXPECT_TRUE(off_item->IsCancelled());
947 error = RunFunctionAndReturnError(new DownloadsPauseFunction(),
948 off_item_arg);
949 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
950 error.c_str());
951 error = RunFunctionAndReturnError(new DownloadsResumeFunction(),
952 off_item_arg);
953 EXPECT_STREQ(download_extension_errors::kInvalidOperationError,
954 error.c_str());
955 }
OLDNEW
« no previous file with comments | « chrome/browser/download/download_extension_apitest.cc ('k') | chrome/browser/extensions/api/downloads/OWNERS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698