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

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

Powered by Google App Engine
This is Rietveld 408576698