Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / api / downloads / downloads_api_browsertest.cc
blobaa0a6c3def4277ecf9439db20127013cf7622532
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.
5 // Disable everything on windows only. http://crbug.com/306144
6 #ifndef OS_WIN
8 #include <algorithm>
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/json/json_reader.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/stl_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "chrome/browser/download/download_file_icon_extractor.h"
19 #include "chrome/browser/download/download_service.h"
20 #include "chrome/browser/download/download_service_factory.h"
21 #include "chrome/browser/download/download_test_file_activity_observer.h"
22 #include "chrome/browser/extensions/api/downloads/downloads_api.h"
23 #include "chrome/browser/extensions/browser_action_test_util.h"
24 #include "chrome/browser/extensions/extension_apitest.h"
25 #include "chrome/browser/extensions/extension_function_test_utils.h"
26 #include "chrome/browser/net/url_request_mock_util.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/ui/browser.h"
29 #include "chrome/browser/ui/browser_tabstrip.h"
30 #include "chrome/common/pref_names.h"
31 #include "chrome/test/base/in_process_browser_test.h"
32 #include "chrome/test/base/ui_test_utils.h"
33 #include "content/public/browser/browser_context.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "content/public/browser/download_item.h"
36 #include "content/public/browser/download_manager.h"
37 #include "content/public/browser/notification_service.h"
38 #include "content/public/browser/storage_partition.h"
39 #include "content/public/browser/web_contents.h"
40 #include "content/public/common/content_switches.h"
41 #include "content/public/test/download_test_observer.h"
42 #include "extensions/browser/event_router.h"
43 #include "extensions/browser/notification_types.h"
44 #include "net/base/data_url.h"
45 #include "net/base/net_util.h"
46 #include "net/test/url_request/url_request_slow_download_job.h"
47 #include "net/url_request/url_request.h"
48 #include "net/url_request/url_request_context.h"
49 #include "net/url_request/url_request_job.h"
50 #include "net/url_request/url_request_job_factory.h"
51 #include "net/url_request/url_request_job_factory_impl.h"
52 #include "storage/browser/fileapi/file_system_context.h"
53 #include "storage/browser/fileapi/file_system_operation_runner.h"
54 #include "storage/browser/fileapi/file_system_url.h"
55 #include "ui/base/page_transition_types.h"
57 using content::BrowserContext;
58 using content::BrowserThread;
59 using content::DownloadItem;
60 using content::DownloadManager;
62 namespace errors = download_extension_errors;
64 namespace extensions {
65 namespace downloads = api::downloads;
67 namespace {
69 // Comparator that orders download items by their ID. Can be used with
70 // std::sort.
71 struct DownloadIdComparator {
72 bool operator() (DownloadItem* first, DownloadItem* second) {
73 return first->GetId() < second->GetId();
77 class DownloadsEventsListener : public content::NotificationObserver {
78 public:
79 DownloadsEventsListener()
80 : waiting_(false) {
81 registrar_.Add(this,
82 extensions::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT,
83 content::NotificationService::AllSources());
86 ~DownloadsEventsListener() override {
87 registrar_.Remove(this,
88 extensions::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT,
89 content::NotificationService::AllSources());
90 STLDeleteElements(&events_);
93 void ClearEvents() {
94 STLDeleteElements(&events_);
97 class Event {
98 public:
99 Event(Profile* profile,
100 const std::string& event_name,
101 const std::string& json_args,
102 base::Time caught)
103 : profile_(profile),
104 event_name_(event_name),
105 json_args_(json_args),
106 args_(base::JSONReader::DeprecatedRead(json_args)),
107 caught_(caught) {}
109 const base::Time& caught() { return caught_; }
111 bool Satisfies(const Event& other) const {
112 return other.SatisfiedBy(*this);
115 bool SatisfiedBy(const Event& other) const {
116 if ((profile_ != other.profile_) ||
117 (event_name_ != other.event_name_))
118 return false;
119 if (((event_name_ == downloads::OnDeterminingFilename::kEventName) ||
120 (event_name_ == downloads::OnCreated::kEventName) ||
121 (event_name_ == downloads::OnChanged::kEventName)) &&
122 args_.get() && other.args_.get()) {
123 base::ListValue* left_list = NULL;
124 base::DictionaryValue* left_dict = NULL;
125 base::ListValue* right_list = NULL;
126 base::DictionaryValue* right_dict = NULL;
127 if (!args_->GetAsList(&left_list) ||
128 !other.args_->GetAsList(&right_list) ||
129 !left_list->GetDictionary(0, &left_dict) ||
130 !right_list->GetDictionary(0, &right_dict))
131 return false;
132 for (base::DictionaryValue::Iterator iter(*left_dict);
133 !iter.IsAtEnd(); iter.Advance()) {
134 base::Value* right_value = NULL;
135 if (!right_dict->HasKey(iter.key()) ||
136 (right_dict->Get(iter.key(), &right_value) &&
137 !iter.value().Equals(right_value))) {
138 return false;
141 return true;
142 } else if ((event_name_ == downloads::OnErased::kEventName) &&
143 args_.get() && other.args_.get()) {
144 int my_id = -1, other_id = -1;
145 return (args_->GetAsInteger(&my_id) &&
146 other.args_->GetAsInteger(&other_id) &&
147 my_id == other_id);
149 return json_args_ == other.json_args_;
152 std::string Debug() {
153 return base::StringPrintf("Event(%p, %s, %s, %f)",
154 profile_,
155 event_name_.c_str(),
156 json_args_.c_str(),
157 caught_.ToJsTime());
160 private:
161 Profile* profile_;
162 std::string event_name_;
163 std::string json_args_;
164 scoped_ptr<base::Value> args_;
165 base::Time caught_;
167 DISALLOW_COPY_AND_ASSIGN(Event);
170 typedef ExtensionDownloadsEventRouter::DownloadsNotificationSource
171 DownloadsNotificationSource;
173 void Observe(int type,
174 const content::NotificationSource& source,
175 const content::NotificationDetails& details) override {
176 switch (type) {
177 case extensions::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT: {
178 DownloadsNotificationSource* dns =
179 content::Source<DownloadsNotificationSource>(source).ptr();
180 Event* new_event = new Event(
181 dns->profile, dns->event_name,
182 *content::Details<std::string>(details).ptr(), base::Time::Now());
183 events_.push_back(new_event);
184 if (waiting_ &&
185 waiting_for_.get() &&
186 new_event->Satisfies(*waiting_for_)) {
187 waiting_ = false;
188 base::MessageLoopForUI::current()->Quit();
190 break;
192 default:
193 NOTREACHED();
197 bool WaitFor(Profile* profile,
198 const std::string& event_name,
199 const std::string& json_args) {
200 waiting_for_.reset(new Event(profile, event_name, json_args, base::Time()));
201 for (std::deque<Event*>::const_iterator iter = events_.begin();
202 iter != events_.end(); ++iter) {
203 if ((*iter)->Satisfies(*waiting_for_.get())) {
204 return true;
207 waiting_ = true;
208 content::RunMessageLoop();
209 bool success = !waiting_;
210 if (waiting_) {
211 // Print the events that were caught since the last WaitFor() call to help
212 // find the erroneous event.
213 // TODO(benjhayden) Fuzzy-match and highlight the erroneous event.
214 for (std::deque<Event*>::const_iterator iter = events_.begin();
215 iter != events_.end(); ++iter) {
216 if ((*iter)->caught() > last_wait_) {
217 LOG(INFO) << "Caught " << (*iter)->Debug();
220 if (waiting_for_.get()) {
221 LOG(INFO) << "Timed out waiting for " << waiting_for_->Debug();
223 waiting_ = false;
225 waiting_for_.reset();
226 last_wait_ = base::Time::Now();
227 return success;
230 private:
231 bool waiting_;
232 base::Time last_wait_;
233 scoped_ptr<Event> waiting_for_;
234 content::NotificationRegistrar registrar_;
235 std::deque<Event*> events_;
237 DISALLOW_COPY_AND_ASSIGN(DownloadsEventsListener);
240 class DownloadExtensionTest : public ExtensionApiTest {
241 public:
242 DownloadExtensionTest()
243 : extension_(NULL),
244 incognito_browser_(NULL),
245 current_browser_(NULL) {
248 protected:
249 // Used with CreateHistoryDownloads
250 struct HistoryDownloadInfo {
251 // Filename to use. CreateHistoryDownloads will append this filename to the
252 // temporary downloads directory specified by downloads_directory().
253 const base::FilePath::CharType* filename;
255 // State for the download. Note that IN_PROGRESS downloads will be created
256 // as CANCELLED.
257 DownloadItem::DownloadState state;
259 // Danger type for the download. Only use DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
260 // and DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT.
261 content::DownloadDangerType danger_type;
264 void LoadExtension(const char* name) {
265 // Store the created Extension object so that we can attach it to
266 // ExtensionFunctions. Also load the extension in incognito profiles for
267 // testing incognito.
268 extension_ = LoadExtensionIncognito(test_data_dir_.AppendASCII(name));
269 CHECK(extension_);
270 content::WebContents* tab = chrome::AddSelectedTabWithURL(
271 current_browser(),
272 extension_->GetResourceURL("empty.html"),
273 ui::PAGE_TRANSITION_LINK);
274 EventRouter::Get(current_browser()->profile())
275 ->AddEventListener(downloads::OnCreated::kEventName,
276 tab->GetRenderProcessHost(),
277 GetExtensionId());
278 EventRouter::Get(current_browser()->profile())
279 ->AddEventListener(downloads::OnChanged::kEventName,
280 tab->GetRenderProcessHost(),
281 GetExtensionId());
282 EventRouter::Get(current_browser()->profile())
283 ->AddEventListener(downloads::OnErased::kEventName,
284 tab->GetRenderProcessHost(),
285 GetExtensionId());
288 content::RenderProcessHost* AddFilenameDeterminer() {
289 ExtensionDownloadsEventRouter::SetDetermineFilenameTimeoutSecondsForTesting(
291 content::WebContents* tab = chrome::AddSelectedTabWithURL(
292 current_browser(),
293 extension_->GetResourceURL("empty.html"),
294 ui::PAGE_TRANSITION_LINK);
295 EventRouter::Get(current_browser()->profile())
296 ->AddEventListener(downloads::OnDeterminingFilename::kEventName,
297 tab->GetRenderProcessHost(),
298 GetExtensionId());
299 return tab->GetRenderProcessHost();
302 void RemoveFilenameDeterminer(content::RenderProcessHost* host) {
303 EventRouter::Get(current_browser()->profile())->RemoveEventListener(
304 downloads::OnDeterminingFilename::kEventName, host, GetExtensionId());
307 Browser* current_browser() { return current_browser_; }
309 // InProcessBrowserTest
310 void SetUpOnMainThread() override {
311 ExtensionApiTest::SetUpOnMainThread();
312 BrowserThread::PostTask(
313 BrowserThread::IO, FROM_HERE,
314 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
315 InProcessBrowserTest::SetUpOnMainThread();
316 GoOnTheRecord();
317 CreateAndSetDownloadsDirectory();
318 current_browser()->profile()->GetPrefs()->SetBoolean(
319 prefs::kPromptForDownload, false);
320 GetOnRecordManager()->RemoveAllDownloads();
321 events_listener_.reset(new DownloadsEventsListener());
322 // Disable file chooser for current profile.
323 DownloadTestFileActivityObserver observer(current_browser()->profile());
324 observer.EnableFileChooser(false);
327 void GoOnTheRecord() { current_browser_ = browser(); }
329 void GoOffTheRecord() {
330 if (!incognito_browser_) {
331 incognito_browser_ = CreateIncognitoBrowser();
332 GetOffRecordManager()->RemoveAllDownloads();
333 // Disable file chooser for incognito profile.
334 DownloadTestFileActivityObserver observer(incognito_browser_->profile());
335 observer.EnableFileChooser(false);
337 current_browser_ = incognito_browser_;
340 bool WaitFor(const std::string& event_name, const std::string& json_args) {
341 return events_listener_->WaitFor(
342 current_browser()->profile(), event_name, json_args);
345 bool WaitForInterruption(
346 DownloadItem* item,
347 content::DownloadInterruptReason expected_error,
348 const std::string& on_created_event) {
349 if (!WaitFor(downloads::OnCreated::kEventName, on_created_event))
350 return false;
351 // Now, onCreated is always fired before interruption.
352 return WaitFor(
353 downloads::OnChanged::kEventName,
354 base::StringPrintf(
355 "[{\"id\": %d,"
356 " \"error\": {\"current\": \"%s\"},"
357 " \"state\": {"
358 " \"previous\": \"in_progress\","
359 " \"current\": \"interrupted\"}}]",
360 item->GetId(),
361 content::DownloadInterruptReasonToString(expected_error).c_str()));
364 void ClearEvents() {
365 events_listener_->ClearEvents();
368 std::string GetExtensionURL() {
369 return extension_->url().spec();
371 std::string GetExtensionId() {
372 return extension_->id();
375 std::string GetFilename(const char* path) {
376 std::string result =
377 downloads_directory_.path().AppendASCII(path).AsUTF8Unsafe();
378 #if defined(OS_WIN)
379 for (std::string::size_type next = result.find("\\");
380 next != std::string::npos;
381 next = result.find("\\", next)) {
382 result.replace(next, 1, "\\\\");
383 next += 2;
385 #endif
386 return result;
389 DownloadManager* GetOnRecordManager() {
390 return BrowserContext::GetDownloadManager(browser()->profile());
392 DownloadManager* GetOffRecordManager() {
393 return BrowserContext::GetDownloadManager(
394 browser()->profile()->GetOffTheRecordProfile());
396 DownloadManager* GetCurrentManager() {
397 return (current_browser_ == incognito_browser_) ?
398 GetOffRecordManager() : GetOnRecordManager();
401 // Creates a set of history downloads based on the provided |history_info|
402 // array. |count| is the number of elements in |history_info|. On success,
403 // |items| will contain |count| DownloadItems in the order that they were
404 // specified in |history_info|. Returns true on success and false otherwise.
405 bool CreateHistoryDownloads(const HistoryDownloadInfo* history_info,
406 size_t count,
407 DownloadManager::DownloadVector* items) {
408 DownloadIdComparator download_id_comparator;
409 base::Time current = base::Time::Now();
410 items->clear();
411 GetOnRecordManager()->GetAllDownloads(items);
412 CHECK_EQ(0, static_cast<int>(items->size()));
413 std::vector<GURL> url_chain;
414 url_chain.push_back(GURL());
415 for (size_t i = 0; i < count; ++i) {
416 DownloadItem* item = GetOnRecordManager()->CreateDownloadItem(
417 content::DownloadItem::kInvalidId + 1 + i,
418 downloads_directory().Append(history_info[i].filename),
419 downloads_directory().Append(history_info[i].filename),
420 url_chain, GURL(), // URL Chain, referrer
421 std::string(), std::string(), // mime_type, original_mime_type
422 current, current, // start_time, end_time
423 std::string(), std::string(), // etag, last_modified
424 1, 1, // received_bytes, total_bytes
425 history_info[i].state, // state
426 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
427 content::DOWNLOAD_INTERRUPT_REASON_NONE,
428 false); // opened
429 items->push_back(item);
432 // Order by ID so that they are in the order that we created them.
433 std::sort(items->begin(), items->end(), download_id_comparator);
434 // Set the danger type if necessary.
435 for (size_t i = 0; i < count; ++i) {
436 if (history_info[i].danger_type !=
437 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
438 EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT,
439 history_info[i].danger_type);
440 items->at(i)->OnContentCheckCompleted(history_info[i].danger_type);
443 return true;
446 void CreateSlowTestDownloads(
447 size_t count, DownloadManager::DownloadVector* items) {
448 for (size_t i = 0; i < count; ++i) {
449 scoped_ptr<content::DownloadTestObserver> observer(
450 CreateInProgressDownloadObserver(1));
451 GURL slow_download_url(net::URLRequestSlowDownloadJob::kUnknownSizeUrl);
452 ui_test_utils::NavigateToURL(current_browser(), slow_download_url);
453 observer->WaitForFinished();
454 EXPECT_EQ(
455 1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
457 GetCurrentManager()->GetAllDownloads(items);
458 ASSERT_EQ(count, items->size());
461 DownloadItem* CreateSlowTestDownload() {
462 scoped_ptr<content::DownloadTestObserver> observer(
463 CreateInProgressDownloadObserver(1));
464 GURL slow_download_url(net::URLRequestSlowDownloadJob::kUnknownSizeUrl);
465 DownloadManager* manager = GetCurrentManager();
467 EXPECT_EQ(0, manager->NonMaliciousInProgressCount());
468 EXPECT_EQ(0, manager->InProgressCount());
469 if (manager->InProgressCount() != 0)
470 return NULL;
472 ui_test_utils::NavigateToURL(current_browser(), slow_download_url);
474 observer->WaitForFinished();
475 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
477 DownloadManager::DownloadVector items;
478 manager->GetAllDownloads(&items);
480 DownloadItem* new_item = NULL;
481 for (DownloadManager::DownloadVector::iterator iter = items.begin();
482 iter != items.end(); ++iter) {
483 if ((*iter)->GetState() == DownloadItem::IN_PROGRESS) {
484 // There should be only one IN_PROGRESS item.
485 EXPECT_EQ(NULL, new_item);
486 new_item = *iter;
489 return new_item;
492 void FinishPendingSlowDownloads() {
493 scoped_ptr<content::DownloadTestObserver> observer(
494 CreateDownloadObserver(1));
495 GURL finish_url(net::URLRequestSlowDownloadJob::kFinishDownloadUrl);
496 ui_test_utils::NavigateToURLWithDisposition(
497 current_browser(), finish_url, NEW_FOREGROUND_TAB,
498 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
499 observer->WaitForFinished();
500 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::COMPLETE));
503 content::DownloadTestObserver* CreateDownloadObserver(size_t download_count) {
504 return new content::DownloadTestObserverTerminal(
505 GetCurrentManager(), download_count,
506 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
509 content::DownloadTestObserver* CreateInProgressDownloadObserver(
510 size_t download_count) {
511 return new content::DownloadTestObserverInProgress(
512 GetCurrentManager(), download_count);
515 bool RunFunction(UIThreadExtensionFunction* function,
516 const std::string& args) {
517 scoped_refptr<UIThreadExtensionFunction> delete_function(function);
518 SetUpExtensionFunction(function);
519 bool result = extension_function_test_utils::RunFunction(
520 function, args, browser(), GetFlags());
521 if (!result) {
522 LOG(ERROR) << function->GetError();
524 return result;
527 extension_function_test_utils::RunFunctionFlags GetFlags() {
528 return current_browser()->profile()->IsOffTheRecord() ?
529 extension_function_test_utils::INCLUDE_INCOGNITO :
530 extension_function_test_utils::NONE;
533 // extension_function_test_utils::RunFunction*() only uses browser for its
534 // profile(), so pass it the on-record browser so that it always uses the
535 // on-record profile to match real-life behavior.
537 base::Value* RunFunctionAndReturnResult(
538 scoped_refptr<UIThreadExtensionFunction> function,
539 const std::string& args) {
540 SetUpExtensionFunction(function.get());
541 return extension_function_test_utils::RunFunctionAndReturnSingleResult(
542 function.get(), args, browser(), GetFlags());
545 std::string RunFunctionAndReturnError(
546 scoped_refptr<UIThreadExtensionFunction> function,
547 const std::string& args) {
548 SetUpExtensionFunction(function.get());
549 return extension_function_test_utils::RunFunctionAndReturnError(
550 function.get(), args, browser(), GetFlags());
553 bool RunFunctionAndReturnString(
554 scoped_refptr<UIThreadExtensionFunction> function,
555 const std::string& args,
556 std::string* result_string) {
557 SetUpExtensionFunction(function.get());
558 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(function, args));
559 EXPECT_TRUE(result.get());
560 return result.get() && result->GetAsString(result_string);
563 std::string DownloadItemIdAsArgList(const DownloadItem* download_item) {
564 return base::StringPrintf("[%d]", download_item->GetId());
567 const base::FilePath& downloads_directory() {
568 return downloads_directory_.path();
571 DownloadsEventsListener* events_listener() { return events_listener_.get(); }
573 private:
574 void SetUpExtensionFunction(UIThreadExtensionFunction* function) {
575 if (extension_) {
576 // Recreate the tab each time for insulation.
577 content::WebContents* tab = chrome::AddSelectedTabWithURL(
578 current_browser(),
579 extension_->GetResourceURL("empty.html"),
580 ui::PAGE_TRANSITION_LINK);
581 function->set_extension(extension_);
582 function->SetRenderFrameHost(tab->GetMainFrame());
586 void CreateAndSetDownloadsDirectory() {
587 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
588 current_browser()->profile()->GetPrefs()->SetFilePath(
589 prefs::kDownloadDefaultDirectory,
590 downloads_directory_.path());
593 base::ScopedTempDir downloads_directory_;
594 const Extension* extension_;
595 Browser* incognito_browser_;
596 Browser* current_browser_;
597 scoped_ptr<DownloadsEventsListener> events_listener_;
599 DISALLOW_COPY_AND_ASSIGN(DownloadExtensionTest);
602 class MockIconExtractorImpl : public DownloadFileIconExtractor {
603 public:
604 MockIconExtractorImpl(const base::FilePath& path,
605 IconLoader::IconSize icon_size,
606 const std::string& response)
607 : expected_path_(path),
608 expected_icon_size_(icon_size),
609 response_(response) {
611 ~MockIconExtractorImpl() override {}
613 bool ExtractIconURLForPath(const base::FilePath& path,
614 float scale,
615 IconLoader::IconSize icon_size,
616 IconURLCallback callback) override {
617 EXPECT_STREQ(expected_path_.value().c_str(), path.value().c_str());
618 EXPECT_EQ(expected_icon_size_, icon_size);
619 if (expected_path_ == path &&
620 expected_icon_size_ == icon_size) {
621 callback_ = callback;
622 BrowserThread::PostTask(
623 BrowserThread::UI, FROM_HERE,
624 base::Bind(&MockIconExtractorImpl::RunCallback,
625 base::Unretained(this)));
626 return true;
627 } else {
628 return false;
632 private:
633 void RunCallback() {
634 callback_.Run(response_);
635 // Drop the reference on extension function to avoid memory leaks.
636 callback_ = IconURLCallback();
639 base::FilePath expected_path_;
640 IconLoader::IconSize expected_icon_size_;
641 std::string response_;
642 IconURLCallback callback_;
645 bool ItemNotInProgress(DownloadItem* item) {
646 return item->GetState() != DownloadItem::IN_PROGRESS;
649 // Cancels the underlying DownloadItem when the ScopedCancellingItem goes out of
650 // scope. Like a scoped_ptr, but for DownloadItems.
651 class ScopedCancellingItem {
652 public:
653 explicit ScopedCancellingItem(DownloadItem* item) : item_(item) {}
654 ~ScopedCancellingItem() {
655 item_->Cancel(true);
656 content::DownloadUpdatedObserver observer(
657 item_, base::Bind(&ItemNotInProgress));
658 observer.WaitForEvent();
660 DownloadItem* get() { return item_; }
661 private:
662 DownloadItem* item_;
663 DISALLOW_COPY_AND_ASSIGN(ScopedCancellingItem);
666 // Cancels all the underlying DownloadItems when the ScopedItemVectorCanceller
667 // goes out of scope. Generalization of ScopedCancellingItem to many
668 // DownloadItems.
669 class ScopedItemVectorCanceller {
670 public:
671 explicit ScopedItemVectorCanceller(DownloadManager::DownloadVector* items)
672 : items_(items) {
674 ~ScopedItemVectorCanceller() {
675 for (DownloadManager::DownloadVector::const_iterator item = items_->begin();
676 item != items_->end(); ++item) {
677 if ((*item)->GetState() == DownloadItem::IN_PROGRESS)
678 (*item)->Cancel(true);
679 content::DownloadUpdatedObserver observer(
680 (*item), base::Bind(&ItemNotInProgress));
681 observer.WaitForEvent();
685 private:
686 DownloadManager::DownloadVector* items_;
687 DISALLOW_COPY_AND_ASSIGN(ScopedItemVectorCanceller);
690 // Writes an HTML5 file so that it can be downloaded.
691 class HTML5FileWriter {
692 public:
693 static bool CreateFileForTesting(storage::FileSystemContext* context,
694 const storage::FileSystemURL& path,
695 const char* data,
696 int length) {
697 // Create a temp file.
698 base::FilePath temp_file;
699 if (!base::CreateTemporaryFile(&temp_file) ||
700 base::WriteFile(temp_file, data, length) != length) {
701 return false;
703 // Invoke the fileapi to copy it into the sandboxed filesystem.
704 bool result = false;
705 base::WaitableEvent done_event(true, false);
706 BrowserThread::PostTask(
707 BrowserThread::IO, FROM_HERE,
708 base::Bind(&CreateFileForTestingOnIOThread,
709 base::Unretained(context),
710 path, temp_file,
711 base::Unretained(&result),
712 base::Unretained(&done_event)));
713 // Wait for that to finish.
714 done_event.Wait();
715 base::DeleteFile(temp_file, false);
716 return result;
719 private:
720 static void CopyInCompletion(bool* result,
721 base::WaitableEvent* done_event,
722 base::File::Error error) {
723 DCHECK_CURRENTLY_ON(BrowserThread::IO);
724 *result = error == base::File::FILE_OK;
725 done_event->Signal();
728 static void CreateFileForTestingOnIOThread(
729 storage::FileSystemContext* context,
730 const storage::FileSystemURL& path,
731 const base::FilePath& temp_file,
732 bool* result,
733 base::WaitableEvent* done_event) {
734 DCHECK_CURRENTLY_ON(BrowserThread::IO);
735 context->operation_runner()->CopyInForeignFile(
736 temp_file, path,
737 base::Bind(&CopyInCompletion,
738 base::Unretained(result),
739 base::Unretained(done_event)));
743 // TODO(benjhayden) Merge this with the other TestObservers.
744 class JustInProgressDownloadObserver
745 : public content::DownloadTestObserverInProgress {
746 public:
747 JustInProgressDownloadObserver(
748 DownloadManager* download_manager, size_t wait_count)
749 : content::DownloadTestObserverInProgress(download_manager, wait_count) {
752 ~JustInProgressDownloadObserver() override {}
754 private:
755 bool IsDownloadInFinalState(DownloadItem* item) override {
756 return item->GetState() == DownloadItem::IN_PROGRESS;
759 DISALLOW_COPY_AND_ASSIGN(JustInProgressDownloadObserver);
762 bool ItemIsInterrupted(DownloadItem* item) {
763 return item->GetState() == DownloadItem::INTERRUPTED;
766 content::DownloadInterruptReason InterruptReasonExtensionToContent(
767 downloads::InterruptReason error) {
768 switch (error) {
769 case downloads::INTERRUPT_REASON_NONE:
770 return content::DOWNLOAD_INTERRUPT_REASON_NONE;
771 #define INTERRUPT_REASON(name, value) \
772 case downloads::INTERRUPT_REASON_##name: \
773 return content::DOWNLOAD_INTERRUPT_REASON_##name;
774 #include "content/public/browser/download_interrupt_reason_values.h"
775 #undef INTERRUPT_REASON
777 NOTREACHED();
778 return content::DOWNLOAD_INTERRUPT_REASON_NONE;
781 downloads::InterruptReason InterruptReasonContentToExtension(
782 content::DownloadInterruptReason error) {
783 switch (error) {
784 case content::DOWNLOAD_INTERRUPT_REASON_NONE:
785 return downloads::INTERRUPT_REASON_NONE;
786 #define INTERRUPT_REASON(name, value) \
787 case content::DOWNLOAD_INTERRUPT_REASON_##name: \
788 return downloads::INTERRUPT_REASON_##name;
789 #include "content/public/browser/download_interrupt_reason_values.h"
790 #undef INTERRUPT_REASON
792 NOTREACHED();
793 return downloads::INTERRUPT_REASON_NONE;
796 } // namespace
798 #if defined(OS_CHROMEOS)
799 // http://crbug.com/396510
800 #define MAYBE_DownloadExtensionTest_Open DISABLED_DownloadExtensionTest_Open
801 #else
802 #define MAYBE_DownloadExtensionTest_Open DownloadExtensionTest_Open
803 #endif
804 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
805 MAYBE_DownloadExtensionTest_Open) {
806 LoadExtension("downloads_split");
807 DownloadsOpenFunction* open_function = new DownloadsOpenFunction();
808 open_function->set_user_gesture(true);
809 EXPECT_STREQ(errors::kInvalidId,
810 RunFunctionAndReturnError(
811 open_function,
812 "[-42]").c_str());
814 DownloadItem* download_item = CreateSlowTestDownload();
815 ASSERT_TRUE(download_item);
816 EXPECT_FALSE(download_item->GetOpened());
817 EXPECT_FALSE(download_item->GetOpenWhenComplete());
818 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
819 base::StringPrintf(
820 "[{\"danger\": \"safe\","
821 " \"incognito\": false,"
822 " \"mime\": \"application/octet-stream\","
823 " \"paused\": false,"
824 " \"url\": \"%s\"}]",
825 download_item->GetURL().spec().c_str())));
826 open_function = new DownloadsOpenFunction();
827 open_function->set_user_gesture(true);
828 EXPECT_STREQ(errors::kNotComplete,
829 RunFunctionAndReturnError(
830 open_function,
831 DownloadItemIdAsArgList(download_item)).c_str());
833 FinishPendingSlowDownloads();
834 EXPECT_FALSE(download_item->GetOpened());
836 open_function = new DownloadsOpenFunction();
837 EXPECT_STREQ(errors::kUserGesture,
838 RunFunctionAndReturnError(
839 open_function,
840 DownloadItemIdAsArgList(download_item)).c_str());
841 EXPECT_FALSE(download_item->GetOpened());
843 open_function = new DownloadsOpenFunction();
844 open_function->set_user_gesture(true);
845 EXPECT_TRUE(RunFunction(open_function,
846 DownloadItemIdAsArgList(download_item)));
847 EXPECT_TRUE(download_item->GetOpened());
850 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
851 DownloadExtensionTest_PauseResumeCancelErase) {
852 DownloadItem* download_item = CreateSlowTestDownload();
853 ASSERT_TRUE(download_item);
854 std::string error;
856 // Call pause(). It should succeed and the download should be paused on
857 // return.
858 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(),
859 DownloadItemIdAsArgList(download_item)));
860 EXPECT_TRUE(download_item->IsPaused());
862 // Calling removeFile on a non-active download yields kNotComplete
863 // and should not crash. http://crbug.com/319984
864 error = RunFunctionAndReturnError(new DownloadsRemoveFileFunction(),
865 DownloadItemIdAsArgList(download_item));
866 EXPECT_STREQ(errors::kNotComplete, error.c_str());
868 // Calling pause() twice shouldn't be an error.
869 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(),
870 DownloadItemIdAsArgList(download_item)));
871 EXPECT_TRUE(download_item->IsPaused());
873 // Now try resuming this download. It should succeed.
874 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(),
875 DownloadItemIdAsArgList(download_item)));
876 EXPECT_FALSE(download_item->IsPaused());
878 // Resume again. Resuming a download that wasn't paused is not an error.
879 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(),
880 DownloadItemIdAsArgList(download_item)));
881 EXPECT_FALSE(download_item->IsPaused());
883 // Pause again.
884 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(),
885 DownloadItemIdAsArgList(download_item)));
886 EXPECT_TRUE(download_item->IsPaused());
888 // And now cancel.
889 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(),
890 DownloadItemIdAsArgList(download_item)));
891 EXPECT_EQ(DownloadItem::CANCELLED, download_item->GetState());
893 // Cancel again. Shouldn't have any effect.
894 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(),
895 DownloadItemIdAsArgList(download_item)));
896 EXPECT_EQ(DownloadItem::CANCELLED, download_item->GetState());
898 // Calling paused on a non-active download yields kNotInProgress.
899 error = RunFunctionAndReturnError(
900 new DownloadsPauseFunction(), DownloadItemIdAsArgList(download_item));
901 EXPECT_STREQ(errors::kNotInProgress, error.c_str());
903 // Calling resume on a non-active download yields kNotResumable
904 error = RunFunctionAndReturnError(
905 new DownloadsResumeFunction(), DownloadItemIdAsArgList(download_item));
906 EXPECT_STREQ(errors::kNotResumable, error.c_str());
908 // Calling pause on a non-existent download yields kInvalidId.
909 error = RunFunctionAndReturnError(
910 new DownloadsPauseFunction(), "[-42]");
911 EXPECT_STREQ(errors::kInvalidId, error.c_str());
913 // Calling resume on a non-existent download yields kInvalidId
914 error = RunFunctionAndReturnError(
915 new DownloadsResumeFunction(), "[-42]");
916 EXPECT_STREQ(errors::kInvalidId, error.c_str());
918 // Calling removeFile on a non-existent download yields kInvalidId.
919 error = RunFunctionAndReturnError(
920 new DownloadsRemoveFileFunction(), "[-42]");
921 EXPECT_STREQ(errors::kInvalidId, error.c_str());
923 int id = download_item->GetId();
924 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
925 new DownloadsEraseFunction(),
926 base::StringPrintf("[{\"id\": %d}]", id)));
927 DownloadManager::DownloadVector items;
928 GetCurrentManager()->GetAllDownloads(&items);
929 EXPECT_EQ(0UL, items.size());
930 ASSERT_TRUE(result);
931 download_item = NULL;
932 base::ListValue* result_list = NULL;
933 ASSERT_TRUE(result->GetAsList(&result_list));
934 ASSERT_EQ(1UL, result_list->GetSize());
935 int element = -1;
936 ASSERT_TRUE(result_list->GetInteger(0, &element));
937 EXPECT_EQ(id, element);
940 scoped_refptr<UIThreadExtensionFunction> MockedGetFileIconFunction(
941 const base::FilePath& expected_path,
942 IconLoader::IconSize icon_size,
943 const std::string& response) {
944 scoped_refptr<DownloadsGetFileIconFunction> function(
945 new DownloadsGetFileIconFunction());
946 function->SetIconExtractorForTesting(new MockIconExtractorImpl(
947 expected_path, icon_size, response));
948 return function;
951 // Test downloads.getFileIcon() on in-progress, finished, cancelled and deleted
952 // download items.
953 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
954 DownloadExtensionTest_FileIcon_Active) {
955 DownloadItem* download_item = CreateSlowTestDownload();
956 ASSERT_TRUE(download_item);
957 ASSERT_FALSE(download_item->GetTargetFilePath().empty());
958 std::string args32(base::StringPrintf("[%d, {\"size\": 32}]",
959 download_item->GetId()));
960 std::string result_string;
962 // Get the icon for the in-progress download. This call should succeed even
963 // if the file type isn't registered.
964 // Test whether the correct path is being pased into the icon extractor.
965 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
966 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
967 base::StringPrintf("[%d, {}]", download_item->GetId()), &result_string));
969 // Now try a 16x16 icon.
970 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
971 download_item->GetTargetFilePath(), IconLoader::SMALL, "foo"),
972 base::StringPrintf("[%d, {\"size\": 16}]", download_item->GetId()),
973 &result_string));
975 // Explicitly asking for 32x32 should give us a 32x32 icon.
976 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
977 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
978 args32, &result_string));
980 // Finish the download and try again.
981 FinishPendingSlowDownloads();
982 EXPECT_EQ(DownloadItem::COMPLETE, download_item->GetState());
983 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
984 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
985 args32, &result_string));
987 // Check the path passed to the icon extractor post-completion.
988 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
989 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
990 args32, &result_string));
992 // Now create another download.
993 download_item = CreateSlowTestDownload();
994 ASSERT_TRUE(download_item);
995 ASSERT_FALSE(download_item->GetTargetFilePath().empty());
996 args32 = base::StringPrintf("[%d, {\"size\": 32}]", download_item->GetId());
998 // Cancel the download. As long as the download has a target path, we should
999 // be able to query the file icon.
1000 download_item->Cancel(true);
1001 ASSERT_FALSE(download_item->GetTargetFilePath().empty());
1002 // Let cleanup complete on the FILE thread.
1003 content::RunAllPendingInMessageLoop(BrowserThread::FILE);
1004 // Check the path passed to the icon extractor post-cancellation.
1005 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
1006 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
1007 args32,
1008 &result_string));
1010 // Simulate an error during icon load by invoking the mock with an empty
1011 // result string.
1012 std::string error = RunFunctionAndReturnError(
1013 MockedGetFileIconFunction(download_item->GetTargetFilePath(),
1014 IconLoader::NORMAL,
1015 std::string()),
1016 args32);
1017 EXPECT_STREQ(errors::kIconNotFound, error.c_str());
1019 // Once the download item is deleted, we should return kInvalidId.
1020 int id = download_item->GetId();
1021 download_item->Remove();
1022 download_item = NULL;
1023 EXPECT_EQ(static_cast<DownloadItem*>(NULL),
1024 GetCurrentManager()->GetDownload(id));
1025 error = RunFunctionAndReturnError(new DownloadsGetFileIconFunction(), args32);
1026 EXPECT_STREQ(errors::kInvalidId,
1027 error.c_str());
1030 // Test that we can acquire file icons for history downloads regardless of
1031 // whether they exist or not. If the file doesn't exist we should receive a
1032 // generic icon from the OS/toolkit that may or may not be specific to the file
1033 // type.
1034 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1035 DownloadExtensionTest_FileIcon_History) {
1036 const HistoryDownloadInfo kHistoryInfo[] = {
1037 { FILE_PATH_LITERAL("real.txt"),
1038 DownloadItem::COMPLETE,
1039 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1040 { FILE_PATH_LITERAL("fake.txt"),
1041 DownloadItem::COMPLETE,
1042 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1044 DownloadManager::DownloadVector all_downloads;
1045 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1046 &all_downloads));
1048 base::FilePath real_path = all_downloads[0]->GetTargetFilePath();
1049 base::FilePath fake_path = all_downloads[1]->GetTargetFilePath();
1051 EXPECT_EQ(0, base::WriteFile(real_path, "", 0));
1052 ASSERT_TRUE(base::PathExists(real_path));
1053 ASSERT_FALSE(base::PathExists(fake_path));
1055 for (DownloadManager::DownloadVector::iterator iter = all_downloads.begin();
1056 iter != all_downloads.end();
1057 ++iter) {
1058 std::string result_string;
1059 // Use a MockIconExtractorImpl to test if the correct path is being passed
1060 // into the DownloadFileIconExtractor.
1061 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
1062 (*iter)->GetTargetFilePath(), IconLoader::NORMAL, "hello"),
1063 base::StringPrintf("[%d, {\"size\": 32}]", (*iter)->GetId()),
1064 &result_string));
1065 EXPECT_STREQ("hello", result_string.c_str());
1069 // Test passing the empty query to search().
1070 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1071 DownloadExtensionTest_SearchEmptyQuery) {
1072 ScopedCancellingItem item(CreateSlowTestDownload());
1073 ASSERT_TRUE(item.get());
1075 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1076 new DownloadsSearchFunction(), "[{}]"));
1077 ASSERT_TRUE(result.get());
1078 base::ListValue* result_list = NULL;
1079 ASSERT_TRUE(result->GetAsList(&result_list));
1080 ASSERT_EQ(1UL, result_list->GetSize());
1083 // Test the |filenameRegex| parameter for search().
1084 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1085 DownloadExtensionTest_SearchFilenameRegex) {
1086 const HistoryDownloadInfo kHistoryInfo[] = {
1087 { FILE_PATH_LITERAL("foobar"),
1088 DownloadItem::COMPLETE,
1089 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1090 { FILE_PATH_LITERAL("baz"),
1091 DownloadItem::COMPLETE,
1092 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1094 DownloadManager::DownloadVector all_downloads;
1095 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1096 &all_downloads));
1098 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1099 new DownloadsSearchFunction(), "[{\"filenameRegex\": \"foobar\"}]"));
1100 ASSERT_TRUE(result.get());
1101 base::ListValue* result_list = NULL;
1102 ASSERT_TRUE(result->GetAsList(&result_list));
1103 ASSERT_EQ(1UL, result_list->GetSize());
1104 base::DictionaryValue* item_value = NULL;
1105 ASSERT_TRUE(result_list->GetDictionary(0, &item_value));
1106 int item_id = -1;
1107 ASSERT_TRUE(item_value->GetInteger("id", &item_id));
1108 ASSERT_EQ(all_downloads[0]->GetId(), static_cast<uint32>(item_id));
1111 // Test the |id| parameter for search().
1112 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadExtensionTest_SearchId) {
1113 DownloadManager::DownloadVector items;
1114 CreateSlowTestDownloads(2, &items);
1115 ScopedItemVectorCanceller delete_items(&items);
1117 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1118 new DownloadsSearchFunction(), base::StringPrintf(
1119 "[{\"id\": %u}]", items[0]->GetId())));
1120 ASSERT_TRUE(result.get());
1121 base::ListValue* result_list = NULL;
1122 ASSERT_TRUE(result->GetAsList(&result_list));
1123 ASSERT_EQ(1UL, result_list->GetSize());
1124 base::DictionaryValue* item_value = NULL;
1125 ASSERT_TRUE(result_list->GetDictionary(0, &item_value));
1126 int item_id = -1;
1127 ASSERT_TRUE(item_value->GetInteger("id", &item_id));
1128 ASSERT_EQ(items[0]->GetId(), static_cast<uint32>(item_id));
1131 // Test specifying both the |id| and |filename| parameters for search().
1132 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1133 DownloadExtensionTest_SearchIdAndFilename) {
1134 DownloadManager::DownloadVector items;
1135 CreateSlowTestDownloads(2, &items);
1136 ScopedItemVectorCanceller delete_items(&items);
1138 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1139 new DownloadsSearchFunction(),
1140 "[{\"id\": 0, \"filename\": \"foobar\"}]"));
1141 ASSERT_TRUE(result.get());
1142 base::ListValue* result_list = NULL;
1143 ASSERT_TRUE(result->GetAsList(&result_list));
1144 ASSERT_EQ(0UL, result_list->GetSize());
1147 // Test a single |orderBy| parameter for search().
1148 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1149 DownloadExtensionTest_SearchOrderBy) {
1150 const HistoryDownloadInfo kHistoryInfo[] = {
1151 { FILE_PATH_LITERAL("zzz"),
1152 DownloadItem::COMPLETE,
1153 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1154 { FILE_PATH_LITERAL("baz"),
1155 DownloadItem::COMPLETE,
1156 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1158 DownloadManager::DownloadVector items;
1159 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1160 &items));
1162 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1163 new DownloadsSearchFunction(), "[{\"orderBy\": [\"filename\"]}]"));
1164 ASSERT_TRUE(result.get());
1165 base::ListValue* result_list = NULL;
1166 ASSERT_TRUE(result->GetAsList(&result_list));
1167 ASSERT_EQ(2UL, result_list->GetSize());
1168 base::DictionaryValue* item0_value = NULL;
1169 base::DictionaryValue* item1_value = NULL;
1170 ASSERT_TRUE(result_list->GetDictionary(0, &item0_value));
1171 ASSERT_TRUE(result_list->GetDictionary(1, &item1_value));
1172 std::string item0_name, item1_name;
1173 ASSERT_TRUE(item0_value->GetString("filename", &item0_name));
1174 ASSERT_TRUE(item1_value->GetString("filename", &item1_name));
1175 ASSERT_GT(items[0]->GetTargetFilePath().value(),
1176 items[1]->GetTargetFilePath().value());
1177 ASSERT_LT(item0_name, item1_name);
1180 // Test specifying an empty |orderBy| parameter for search().
1181 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1182 DownloadExtensionTest_SearchOrderByEmpty) {
1183 const HistoryDownloadInfo kHistoryInfo[] = {
1184 { FILE_PATH_LITERAL("zzz"),
1185 DownloadItem::COMPLETE,
1186 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1187 { FILE_PATH_LITERAL("baz"),
1188 DownloadItem::COMPLETE,
1189 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1191 DownloadManager::DownloadVector items;
1192 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1193 &items));
1195 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1196 new DownloadsSearchFunction(), "[{\"orderBy\": []}]"));
1197 ASSERT_TRUE(result.get());
1198 base::ListValue* result_list = NULL;
1199 ASSERT_TRUE(result->GetAsList(&result_list));
1200 ASSERT_EQ(2UL, result_list->GetSize());
1201 base::DictionaryValue* item0_value = NULL;
1202 base::DictionaryValue* item1_value = NULL;
1203 ASSERT_TRUE(result_list->GetDictionary(0, &item0_value));
1204 ASSERT_TRUE(result_list->GetDictionary(1, &item1_value));
1205 std::string item0_name, item1_name;
1206 ASSERT_TRUE(item0_value->GetString("filename", &item0_name));
1207 ASSERT_TRUE(item1_value->GetString("filename", &item1_name));
1208 ASSERT_GT(items[0]->GetTargetFilePath().value(),
1209 items[1]->GetTargetFilePath().value());
1210 // The order of results when orderBy is empty is unspecified. When there are
1211 // no sorters, DownloadQuery does not call sort(), so the order of the results
1212 // depends on the order of the items in base::hash_map<uint32,...>
1213 // DownloadManagerImpl::downloads_, which is unspecified and differs between
1214 // libc++ and libstdc++. http://crbug.com/365334
1217 // Test the |danger| option for search().
1218 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1219 DownloadExtensionTest_SearchDanger) {
1220 const HistoryDownloadInfo kHistoryInfo[] = {
1221 { FILE_PATH_LITERAL("zzz"),
1222 DownloadItem::COMPLETE,
1223 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT },
1224 { FILE_PATH_LITERAL("baz"),
1225 DownloadItem::COMPLETE,
1226 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1228 DownloadManager::DownloadVector items;
1229 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1230 &items));
1232 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1233 new DownloadsSearchFunction(), "[{\"danger\": \"content\"}]"));
1234 ASSERT_TRUE(result.get());
1235 base::ListValue* result_list = NULL;
1236 ASSERT_TRUE(result->GetAsList(&result_list));
1237 ASSERT_EQ(1UL, result_list->GetSize());
1240 // Test the |state| option for search().
1241 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1242 DownloadExtensionTest_SearchState) {
1243 DownloadManager::DownloadVector items;
1244 CreateSlowTestDownloads(2, &items);
1245 ScopedItemVectorCanceller delete_items(&items);
1247 items[0]->Cancel(true);
1249 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1250 new DownloadsSearchFunction(), "[{\"state\": \"in_progress\"}]"));
1251 ASSERT_TRUE(result.get());
1252 base::ListValue* result_list = NULL;
1253 ASSERT_TRUE(result->GetAsList(&result_list));
1254 ASSERT_EQ(1UL, result_list->GetSize());
1257 // Test the |limit| option for search().
1258 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1259 DownloadExtensionTest_SearchLimit) {
1260 DownloadManager::DownloadVector items;
1261 CreateSlowTestDownloads(2, &items);
1262 ScopedItemVectorCanceller delete_items(&items);
1264 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1265 new DownloadsSearchFunction(), "[{\"limit\": 1}]"));
1266 ASSERT_TRUE(result.get());
1267 base::ListValue* result_list = NULL;
1268 ASSERT_TRUE(result->GetAsList(&result_list));
1269 ASSERT_EQ(1UL, result_list->GetSize());
1272 // Test invalid search parameters.
1273 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1274 DownloadExtensionTest_SearchInvalid) {
1275 std::string error = RunFunctionAndReturnError(
1276 new DownloadsSearchFunction(), "[{\"filenameRegex\": \"(\"}]");
1277 EXPECT_STREQ(errors::kInvalidFilter,
1278 error.c_str());
1279 error = RunFunctionAndReturnError(
1280 new DownloadsSearchFunction(), "[{\"orderBy\": [\"goat\"]}]");
1281 EXPECT_STREQ(errors::kInvalidOrderBy,
1282 error.c_str());
1283 error = RunFunctionAndReturnError(
1284 new DownloadsSearchFunction(), "[{\"limit\": -1}]");
1285 EXPECT_STREQ(errors::kInvalidQueryLimit,
1286 error.c_str());
1289 // Test searching using multiple conditions through multiple downloads.
1290 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1291 DownloadExtensionTest_SearchPlural) {
1292 const HistoryDownloadInfo kHistoryInfo[] = {
1293 { FILE_PATH_LITERAL("aaa"),
1294 DownloadItem::CANCELLED,
1295 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1296 { FILE_PATH_LITERAL("zzz"),
1297 DownloadItem::COMPLETE,
1298 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT },
1299 { FILE_PATH_LITERAL("baz"),
1300 DownloadItem::COMPLETE,
1301 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT },
1303 DownloadManager::DownloadVector items;
1304 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1305 &items));
1307 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1308 new DownloadsSearchFunction(), "[{"
1309 "\"state\": \"complete\", "
1310 "\"danger\": \"content\", "
1311 "\"orderBy\": [\"filename\"], "
1312 "\"limit\": 1}]"));
1313 ASSERT_TRUE(result.get());
1314 base::ListValue* result_list = NULL;
1315 ASSERT_TRUE(result->GetAsList(&result_list));
1316 ASSERT_EQ(1UL, result_list->GetSize());
1317 base::DictionaryValue* item_value = NULL;
1318 ASSERT_TRUE(result_list->GetDictionary(0, &item_value));
1319 base::FilePath::StringType item_name;
1320 ASSERT_TRUE(item_value->GetString("filename", &item_name));
1321 ASSERT_EQ(items[2]->GetTargetFilePath().value(), item_name);
1324 // Test that incognito downloads are only visible in incognito contexts, and
1325 // test that on-record downloads are visible in both incognito and on-record
1326 // contexts, for DownloadsSearchFunction, DownloadsPauseFunction,
1327 // DownloadsResumeFunction, and DownloadsCancelFunction.
1328 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1329 DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) {
1330 scoped_ptr<base::Value> result_value;
1331 base::ListValue* result_list = NULL;
1332 base::DictionaryValue* result_dict = NULL;
1333 base::FilePath::StringType filename;
1334 bool is_incognito = false;
1335 std::string error;
1336 std::string on_item_arg;
1337 std::string off_item_arg;
1338 std::string result_string;
1340 // Set up one on-record item and one off-record item.
1341 // Set up the off-record item first because otherwise there are mysteriously 3
1342 // items total instead of 2.
1343 // TODO(benjhayden): Figure out where the third item comes from.
1344 GoOffTheRecord();
1345 DownloadItem* off_item = CreateSlowTestDownload();
1346 ASSERT_TRUE(off_item);
1347 off_item_arg = DownloadItemIdAsArgList(off_item);
1349 GoOnTheRecord();
1350 DownloadItem* on_item = CreateSlowTestDownload();
1351 ASSERT_TRUE(on_item);
1352 on_item_arg = DownloadItemIdAsArgList(on_item);
1353 ASSERT_TRUE(on_item->GetTargetFilePath() != off_item->GetTargetFilePath());
1355 // Extensions running in the incognito window should have access to both
1356 // items because the Test extension is in spanning mode.
1357 GoOffTheRecord();
1358 result_value.reset(RunFunctionAndReturnResult(
1359 new DownloadsSearchFunction(), "[{}]"));
1360 ASSERT_TRUE(result_value.get());
1361 ASSERT_TRUE(result_value->GetAsList(&result_list));
1362 ASSERT_EQ(2UL, result_list->GetSize());
1363 ASSERT_TRUE(result_list->GetDictionary(0, &result_dict));
1364 ASSERT_TRUE(result_dict->GetString("filename", &filename));
1365 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito));
1366 EXPECT_TRUE(on_item->GetTargetFilePath() == base::FilePath(filename));
1367 EXPECT_FALSE(is_incognito);
1368 ASSERT_TRUE(result_list->GetDictionary(1, &result_dict));
1369 ASSERT_TRUE(result_dict->GetString("filename", &filename));
1370 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito));
1371 EXPECT_TRUE(off_item->GetTargetFilePath() == base::FilePath(filename));
1372 EXPECT_TRUE(is_incognito);
1374 // Extensions running in the on-record window should have access only to the
1375 // on-record item.
1376 GoOnTheRecord();
1377 result_value.reset(RunFunctionAndReturnResult(
1378 new DownloadsSearchFunction(), "[{}]"));
1379 ASSERT_TRUE(result_value.get());
1380 ASSERT_TRUE(result_value->GetAsList(&result_list));
1381 ASSERT_EQ(1UL, result_list->GetSize());
1382 ASSERT_TRUE(result_list->GetDictionary(0, &result_dict));
1383 ASSERT_TRUE(result_dict->GetString("filename", &filename));
1384 EXPECT_TRUE(on_item->GetTargetFilePath() == base::FilePath(filename));
1385 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito));
1386 EXPECT_FALSE(is_incognito);
1388 // Pausing/Resuming the off-record item while on the record should return an
1389 // error. Cancelling "non-existent" downloads is not an error.
1390 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), off_item_arg);
1391 EXPECT_STREQ(errors::kInvalidId,
1392 error.c_str());
1393 error = RunFunctionAndReturnError(new DownloadsResumeFunction(),
1394 off_item_arg);
1395 EXPECT_STREQ(errors::kInvalidId,
1396 error.c_str());
1397 error = RunFunctionAndReturnError(
1398 new DownloadsGetFileIconFunction(),
1399 base::StringPrintf("[%d, {}]", off_item->GetId()));
1400 EXPECT_STREQ(errors::kInvalidId,
1401 error.c_str());
1403 GoOffTheRecord();
1405 // Do the FileIcon test for both the on- and off-items while off the record.
1406 // NOTE(benjhayden): This does not include the FileIcon test from history,
1407 // just active downloads. This shouldn't be a problem.
1408 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
1409 on_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
1410 base::StringPrintf("[%d, {}]", on_item->GetId()), &result_string));
1411 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
1412 off_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
1413 base::StringPrintf("[%d, {}]", off_item->GetId()), &result_string));
1415 // Do the pause/resume/cancel test for both the on- and off-items while off
1416 // the record.
1417 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg));
1418 EXPECT_TRUE(on_item->IsPaused());
1419 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg));
1420 EXPECT_TRUE(on_item->IsPaused());
1421 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), on_item_arg));
1422 EXPECT_FALSE(on_item->IsPaused());
1423 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), on_item_arg));
1424 EXPECT_FALSE(on_item->IsPaused());
1425 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg));
1426 EXPECT_TRUE(on_item->IsPaused());
1427 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), on_item_arg));
1428 EXPECT_EQ(DownloadItem::CANCELLED, on_item->GetState());
1429 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), on_item_arg));
1430 EXPECT_EQ(DownloadItem::CANCELLED, on_item->GetState());
1431 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), on_item_arg);
1432 EXPECT_STREQ(errors::kNotInProgress, error.c_str());
1433 error = RunFunctionAndReturnError(new DownloadsResumeFunction(), on_item_arg);
1434 EXPECT_STREQ(errors::kNotResumable, error.c_str());
1435 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg));
1436 EXPECT_TRUE(off_item->IsPaused());
1437 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg));
1438 EXPECT_TRUE(off_item->IsPaused());
1439 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), off_item_arg));
1440 EXPECT_FALSE(off_item->IsPaused());
1441 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), off_item_arg));
1442 EXPECT_FALSE(off_item->IsPaused());
1443 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg));
1444 EXPECT_TRUE(off_item->IsPaused());
1445 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), off_item_arg));
1446 EXPECT_EQ(DownloadItem::CANCELLED, off_item->GetState());
1447 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), off_item_arg));
1448 EXPECT_EQ(DownloadItem::CANCELLED, off_item->GetState());
1449 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), off_item_arg);
1450 EXPECT_STREQ(errors::kNotInProgress, error.c_str());
1451 error = RunFunctionAndReturnError(new DownloadsResumeFunction(),
1452 off_item_arg);
1453 EXPECT_STREQ(errors::kNotResumable, error.c_str());
1456 // Test that we can start a download and that the correct sequence of events is
1457 // fired for it.
1458 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1459 DownloadExtensionTest_Download_Basic) {
1460 LoadExtension("downloads_split");
1461 ASSERT_TRUE(StartEmbeddedTestServer());
1462 ASSERT_TRUE(test_server()->Start());
1463 std::string download_url = test_server()->GetURL("slow?0").spec();
1464 GoOnTheRecord();
1466 // Start downloading a file.
1467 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1468 new DownloadsDownloadFunction(), base::StringPrintf(
1469 "[{\"url\": \"%s\"}]", download_url.c_str())));
1470 ASSERT_TRUE(result.get());
1471 int result_id = -1;
1472 ASSERT_TRUE(result->GetAsInteger(&result_id));
1473 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1474 ASSERT_TRUE(item);
1475 ScopedCancellingItem canceller(item);
1476 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1478 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
1479 base::StringPrintf(
1480 "[{\"danger\": \"safe\","
1481 " \"incognito\": false,"
1482 " \"mime\": \"text/plain\","
1483 " \"paused\": false,"
1484 " \"url\": \"%s\"}]",
1485 download_url.c_str())));
1486 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1487 base::StringPrintf(
1488 "[{\"id\": %d,"
1489 " \"filename\": {"
1490 " \"previous\": \"\","
1491 " \"current\": \"%s\"}}]",
1492 result_id,
1493 GetFilename("slow.txt").c_str())));
1494 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1495 base::StringPrintf(
1496 "[{\"id\": %d,"
1497 " \"state\": {"
1498 " \"previous\": \"in_progress\","
1499 " \"current\": \"complete\"}}]",
1500 result_id)));
1503 // Test that we can start a download from an incognito context, and that the
1504 // download knows that it's incognito.
1505 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1506 DownloadExtensionTest_Download_Incognito) {
1507 LoadExtension("downloads_split");
1508 ASSERT_TRUE(StartEmbeddedTestServer());
1509 ASSERT_TRUE(test_server()->Start());
1510 GoOffTheRecord();
1511 std::string download_url = test_server()->GetURL("slow?0").spec();
1513 // Start downloading a file.
1514 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1515 new DownloadsDownloadFunction(), base::StringPrintf(
1516 "[{\"url\": \"%s\"}]", download_url.c_str())));
1517 ASSERT_TRUE(result.get());
1518 int result_id = -1;
1519 ASSERT_TRUE(result->GetAsInteger(&result_id));
1520 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1521 ASSERT_TRUE(item);
1522 ScopedCancellingItem canceller(item);
1523 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1525 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
1526 base::StringPrintf(
1527 "[{\"danger\": \"safe\","
1528 " \"incognito\": true,"
1529 " \"mime\": \"text/plain\","
1530 " \"paused\": false,"
1531 " \"url\": \"%s\"}]",
1532 download_url.c_str())));
1533 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1534 base::StringPrintf(
1535 "[{\"id\":%d,"
1536 " \"filename\": {"
1537 " \"previous\": \"\","
1538 " \"current\": \"%s\"}}]",
1539 result_id,
1540 GetFilename("slow.txt").c_str())));
1541 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1542 base::StringPrintf(
1543 "[{\"id\":%d,"
1544 " \"state\": {"
1545 " \"current\": \"complete\","
1546 " \"previous\": \"in_progress\"}}]",
1547 result_id)));
1550 #if defined(OS_WIN)
1551 // This test is very flaky on Win. http://crbug.com/248438
1552 #define MAYBE_DownloadExtensionTest_Download_UnsafeHeaders \
1553 DISABLED_DownloadExtensionTest_Download_UnsafeHeaders
1554 #else
1555 #define MAYBE_DownloadExtensionTest_Download_UnsafeHeaders \
1556 DownloadExtensionTest_Download_UnsafeHeaders
1557 #endif
1559 // Test that we disallow certain headers case-insensitively.
1560 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1561 MAYBE_DownloadExtensionTest_Download_UnsafeHeaders) {
1562 LoadExtension("downloads_split");
1563 ASSERT_TRUE(StartEmbeddedTestServer());
1564 ASSERT_TRUE(test_server()->Start());
1565 GoOnTheRecord();
1567 static const char* const kUnsafeHeaders[] = {
1568 "Accept-chArsEt",
1569 "accept-eNcoding",
1570 "coNNection",
1571 "coNteNt-leNgth",
1572 "cooKIE",
1573 "cOOkie2",
1574 "coNteNt-traNsfer-eNcodiNg",
1575 "dAtE",
1576 "ExpEcT",
1577 "hOsT",
1578 "kEEp-aLivE",
1579 "rEfErEr",
1580 "tE",
1581 "trAilER",
1582 "trANsfer-eNcodiNg",
1583 "upGRAde",
1584 "usER-agENt",
1585 "viA",
1586 "pRoxY-",
1587 "sEc-",
1588 "pRoxY-probably-not-evil",
1589 "sEc-probably-not-evil",
1590 "oRiGiN",
1591 "Access-Control-Request-Headers",
1592 "Access-Control-Request-Method",
1595 for (size_t index = 0; index < arraysize(kUnsafeHeaders); ++index) {
1596 std::string download_url = test_server()->GetURL("slow?0").spec();
1597 EXPECT_STREQ(errors::kInvalidHeaderUnsafe,
1598 RunFunctionAndReturnError(new DownloadsDownloadFunction(),
1599 base::StringPrintf(
1600 "[{\"url\": \"%s\","
1601 " \"filename\": \"unsafe-header-%d.txt\","
1602 " \"headers\": [{"
1603 " \"name\": \"%s\","
1604 " \"value\": \"unsafe\"}]}]",
1605 download_url.c_str(),
1606 static_cast<int>(index),
1607 kUnsafeHeaders[index])).c_str());
1611 // Tests that invalid header names and values are rejected.
1612 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1613 DownloadExtensionTest_Download_InvalidHeaders) {
1614 LoadExtension("downloads_split");
1615 ASSERT_TRUE(StartEmbeddedTestServer());
1616 ASSERT_TRUE(test_server()->Start());
1617 GoOnTheRecord();
1618 std::string download_url = test_server()->GetURL("slow?0").spec();
1619 EXPECT_STREQ(errors::kInvalidHeaderName,
1620 RunFunctionAndReturnError(new DownloadsDownloadFunction(),
1621 base::StringPrintf(
1622 "[{\"url\": \"%s\","
1623 " \"filename\": \"unsafe-header-crlf.txt\","
1624 " \"headers\": [{"
1625 " \"name\": \"Header\\r\\nSec-Spoof: Hey\\r\\nX-Split:X\","
1626 " \"value\": \"unsafe\"}]}]",
1627 download_url.c_str())).c_str());
1629 EXPECT_STREQ(errors::kInvalidHeaderValue,
1630 RunFunctionAndReturnError(new DownloadsDownloadFunction(),
1631 base::StringPrintf(
1632 "[{\"url\": \"%s\","
1633 " \"filename\": \"unsafe-header-crlf.txt\","
1634 " \"headers\": [{"
1635 " \"name\": \"Invalid-value\","
1636 " \"value\": \"hey\\r\\nSec-Spoof: Hey\"}]}]",
1637 download_url.c_str())).c_str());
1640 #if defined(OS_WIN)
1641 #define MAYBE_DownloadExtensionTest_Download_Subdirectory\
1642 DISABLED_DownloadExtensionTest_Download_Subdirectory
1643 #else
1644 #define MAYBE_DownloadExtensionTest_Download_Subdirectory\
1645 DownloadExtensionTest_Download_Subdirectory
1646 #endif
1647 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1648 MAYBE_DownloadExtensionTest_Download_Subdirectory) {
1649 LoadExtension("downloads_split");
1650 ASSERT_TRUE(StartEmbeddedTestServer());
1651 ASSERT_TRUE(test_server()->Start());
1652 std::string download_url = test_server()->GetURL("slow?0").spec();
1653 GoOnTheRecord();
1655 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1656 new DownloadsDownloadFunction(), base::StringPrintf(
1657 "[{\"url\": \"%s\","
1658 " \"filename\": \"sub/dir/ect/ory.txt\"}]",
1659 download_url.c_str())));
1660 ASSERT_TRUE(result.get());
1661 int result_id = -1;
1662 ASSERT_TRUE(result->GetAsInteger(&result_id));
1663 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1664 ASSERT_TRUE(item);
1665 ScopedCancellingItem canceller(item);
1666 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1668 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
1669 base::StringPrintf(
1670 "[{\"danger\": \"safe\","
1671 " \"incognito\": false,"
1672 " \"mime\": \"text/plain\","
1673 " \"paused\": false,"
1674 " \"url\": \"%s\"}]",
1675 download_url.c_str())));
1676 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1677 base::StringPrintf(
1678 "[{\"id\": %d,"
1679 " \"filename\": {"
1680 " \"previous\": \"\","
1681 " \"current\": \"%s\"}}]",
1682 result_id,
1683 GetFilename("sub/dir/ect/ory.txt").c_str())));
1684 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1685 base::StringPrintf(
1686 "[{\"id\": %d,"
1687 " \"state\": {"
1688 " \"previous\": \"in_progress\","
1689 " \"current\": \"complete\"}}]",
1690 result_id)));
1693 // Test that invalid filenames are disallowed.
1694 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1695 DownloadExtensionTest_Download_InvalidFilename) {
1696 LoadExtension("downloads_split");
1697 ASSERT_TRUE(StartEmbeddedTestServer());
1698 ASSERT_TRUE(test_server()->Start());
1699 std::string download_url = test_server()->GetURL("slow?0").spec();
1700 GoOnTheRecord();
1702 EXPECT_STREQ(errors::kInvalidFilename,
1703 RunFunctionAndReturnError(new DownloadsDownloadFunction(),
1704 base::StringPrintf(
1705 "[{\"url\": \"%s\","
1706 " \"filename\": \"../../../../../etc/passwd\"}]",
1707 download_url.c_str())).c_str());
1710 // flaky on mac: crbug.com/392288
1711 #if defined(OS_MACOSX)
1712 #define MAYBE_DownloadExtensionTest_Download_InvalidURLs \
1713 DISABLED_DownloadExtensionTest_Download_InvalidURLs
1714 #else
1715 #define MAYBE_DownloadExtensionTest_Download_InvalidURLs \
1716 DownloadExtensionTest_Download_InvalidURLs
1717 #endif
1719 // Test that downloading invalid URLs immediately returns kInvalidURLError.
1720 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1721 MAYBE_DownloadExtensionTest_Download_InvalidURLs) {
1722 LoadExtension("downloads_split");
1723 GoOnTheRecord();
1725 static const char* const kInvalidURLs[] = {
1726 "foo bar",
1727 "../hello",
1728 "/hello",
1729 "http://",
1730 "#frag",
1731 "foo/bar.html#frag",
1732 "google.com/",
1735 for (size_t index = 0; index < arraysize(kInvalidURLs); ++index) {
1736 EXPECT_STREQ(errors::kInvalidURL,
1737 RunFunctionAndReturnError(new DownloadsDownloadFunction(),
1738 base::StringPrintf(
1739 "[{\"url\": \"%s\"}]", kInvalidURLs[index])).c_str())
1740 << kInvalidURLs[index];
1743 EXPECT_STREQ("NETWORK_INVALID_REQUEST", RunFunctionAndReturnError(
1744 new DownloadsDownloadFunction(),
1745 "[{\"url\": \"javascript:document.write(\\\"hello\\\");\"}]").c_str());
1746 EXPECT_STREQ("NETWORK_INVALID_REQUEST", RunFunctionAndReturnError(
1747 new DownloadsDownloadFunction(),
1748 "[{\"url\": \"javascript:return false;\"}]").c_str());
1749 EXPECT_STREQ("NETWORK_FAILED", RunFunctionAndReturnError(
1750 new DownloadsDownloadFunction(),
1751 "[{\"url\": \"ftp://example.com/example.txt\"}]").c_str());
1754 // TODO(benjhayden): Set up a test ftp server, add ftp://localhost* to
1755 // permissions, test downloading from ftp.
1757 // Valid URLs plus fragments are still valid URLs.
1758 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1759 DownloadExtensionTest_Download_URLFragment) {
1760 LoadExtension("downloads_split");
1761 ASSERT_TRUE(StartEmbeddedTestServer());
1762 ASSERT_TRUE(test_server()->Start());
1763 std::string download_url = test_server()->GetURL("slow?0#fragment").spec();
1764 GoOnTheRecord();
1766 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1767 new DownloadsDownloadFunction(), base::StringPrintf(
1768 "[{\"url\": \"%s\"}]", download_url.c_str())));
1769 ASSERT_TRUE(result.get());
1770 int result_id = -1;
1771 ASSERT_TRUE(result->GetAsInteger(&result_id));
1772 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1773 ASSERT_TRUE(item);
1774 ScopedCancellingItem canceller(item);
1775 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1777 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
1778 base::StringPrintf(
1779 "[{\"danger\": \"safe\","
1780 " \"incognito\": false,"
1781 " \"mime\": \"text/plain\","
1782 " \"paused\": false,"
1783 " \"url\": \"%s\"}]",
1784 download_url.c_str())));
1785 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1786 base::StringPrintf(
1787 "[{\"id\": %d,"
1788 " \"filename\": {"
1789 " \"previous\": \"\","
1790 " \"current\": \"%s\"}}]",
1791 result_id,
1792 GetFilename("slow.txt").c_str())));
1793 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1794 base::StringPrintf(
1795 "[{\"id\": %d,"
1796 " \"state\": {"
1797 " \"previous\": \"in_progress\","
1798 " \"current\": \"complete\"}}]",
1799 result_id)));
1802 // conflictAction may be specified without filename.
1803 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1804 DownloadExtensionTest_Download_ConflictAction) {
1805 static char kFilename[] = "download.txt";
1806 LoadExtension("downloads_split");
1807 std::string download_url = "data:text/plain,hello";
1808 GoOnTheRecord();
1810 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1811 new DownloadsDownloadFunction(), base::StringPrintf(
1812 "[{\"url\": \"%s\"}]", download_url.c_str())));
1813 ASSERT_TRUE(result.get());
1814 int result_id = -1;
1815 ASSERT_TRUE(result->GetAsInteger(&result_id));
1816 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1817 ASSERT_TRUE(item);
1818 ScopedCancellingItem canceller(item);
1819 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1821 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
1822 base::StringPrintf(
1823 "[{\"danger\": \"safe\","
1824 " \"incognito\": false,"
1825 " \"mime\": \"text/plain\","
1826 " \"paused\": false,"
1827 " \"url\": \"%s\"}]",
1828 download_url.c_str())));
1829 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1830 base::StringPrintf(
1831 "[{\"id\": %d,"
1832 " \"filename\": {"
1833 " \"previous\": \"\","
1834 " \"current\": \"%s\"}}]",
1835 result_id,
1836 GetFilename(kFilename).c_str())));
1837 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1838 base::StringPrintf(
1839 "[{\"id\": %d,"
1840 " \"state\": {"
1841 " \"previous\": \"in_progress\","
1842 " \"current\": \"complete\"}}]",
1843 result_id)));
1845 result.reset(RunFunctionAndReturnResult(
1846 new DownloadsDownloadFunction(), base::StringPrintf(
1847 "[{\"url\": \"%s\", \"conflictAction\": \"overwrite\"}]",
1848 download_url.c_str())));
1849 ASSERT_TRUE(result.get());
1850 result_id = -1;
1851 ASSERT_TRUE(result->GetAsInteger(&result_id));
1852 item = GetCurrentManager()->GetDownload(result_id);
1853 ASSERT_TRUE(item);
1854 ScopedCancellingItem canceller2(item);
1855 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1857 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
1858 base::StringPrintf(
1859 "[{\"danger\": \"safe\","
1860 " \"incognito\": false,"
1861 " \"mime\": \"text/plain\","
1862 " \"paused\": false,"
1863 " \"url\": \"%s\"}]",
1864 download_url.c_str())));
1865 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1866 base::StringPrintf(
1867 "[{\"id\": %d,"
1868 " \"filename\": {"
1869 " \"previous\": \"\","
1870 " \"current\": \"%s\"}}]",
1871 result_id,
1872 GetFilename(kFilename).c_str())));
1873 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1874 base::StringPrintf(
1875 "[{\"id\": %d,"
1876 " \"state\": {"
1877 " \"previous\": \"in_progress\","
1878 " \"current\": \"complete\"}}]",
1879 result_id)));
1882 // Valid data URLs are valid URLs.
1883 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1884 DownloadExtensionTest_Download_DataURL) {
1885 LoadExtension("downloads_split");
1886 std::string download_url = "data:text/plain,hello";
1887 GoOnTheRecord();
1889 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1890 new DownloadsDownloadFunction(), base::StringPrintf(
1891 "[{\"url\": \"%s\","
1892 " \"filename\": \"data.txt\"}]", download_url.c_str())));
1893 ASSERT_TRUE(result.get());
1894 int result_id = -1;
1895 ASSERT_TRUE(result->GetAsInteger(&result_id));
1896 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1897 ASSERT_TRUE(item);
1898 ScopedCancellingItem canceller(item);
1899 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1901 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
1902 base::StringPrintf(
1903 "[{\"danger\": \"safe\","
1904 " \"incognito\": false,"
1905 " \"mime\": \"text/plain\","
1906 " \"paused\": false,"
1907 " \"url\": \"%s\"}]",
1908 download_url.c_str())));
1909 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1910 base::StringPrintf(
1911 "[{\"id\": %d,"
1912 " \"filename\": {"
1913 " \"previous\": \"\","
1914 " \"current\": \"%s\"}}]",
1915 result_id,
1916 GetFilename("data.txt").c_str())));
1917 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1918 base::StringPrintf(
1919 "[{\"id\": %d,"
1920 " \"state\": {"
1921 " \"previous\": \"in_progress\","
1922 " \"current\": \"complete\"}}]",
1923 result_id)));
1926 // Valid file URLs are valid URLs.
1927 #if defined(OS_WIN)
1928 // Disabled due to crbug.com/175711
1929 #define MAYBE_DownloadExtensionTest_Download_File \
1930 DISABLED_DownloadExtensionTest_Download_File
1931 #else
1932 #define MAYBE_DownloadExtensionTest_Download_File \
1933 DownloadExtensionTest_Download_File
1934 #endif
1935 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1936 MAYBE_DownloadExtensionTest_Download_File) {
1937 GoOnTheRecord();
1938 LoadExtension("downloads_split");
1939 std::string download_url = "file:///";
1940 #if defined(OS_WIN)
1941 download_url += "C:/";
1942 #endif
1944 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1945 new DownloadsDownloadFunction(), base::StringPrintf(
1946 "[{\"url\": \"%s\","
1947 " \"filename\": \"file.txt\"}]", download_url.c_str())));
1948 ASSERT_TRUE(result.get());
1949 int result_id = -1;
1950 ASSERT_TRUE(result->GetAsInteger(&result_id));
1951 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1952 ASSERT_TRUE(item);
1953 ScopedCancellingItem canceller(item);
1954 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1956 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
1957 base::StringPrintf(
1958 "[{\"danger\": \"safe\","
1959 " \"incognito\": false,"
1960 " \"mime\": \"text/html\","
1961 " \"paused\": false,"
1962 " \"url\": \"%s\"}]",
1963 download_url.c_str())));
1964 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1965 base::StringPrintf(
1966 "[{\"id\": %d,"
1967 " \"filename\": {"
1968 " \"previous\": \"\","
1969 " \"current\": \"%s\"}}]",
1970 result_id,
1971 GetFilename("file.txt").c_str())));
1972 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
1973 base::StringPrintf(
1974 "[{\"id\": %d,"
1975 " \"state\": {"
1976 " \"previous\": \"in_progress\","
1977 " \"current\": \"complete\"}}]",
1978 result_id)));
1981 // Test that auth-basic-succeed would fail if the resource requires the
1982 // Authorization header and chrome fails to propagate it back to the server.
1983 // This tests both that testserver.py does not succeed when it should fail as
1984 // well as how the downloads extension API exposes the failure to extensions.
1985 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1986 DownloadExtensionTest_Download_AuthBasic_Fail) {
1987 LoadExtension("downloads_split");
1988 ASSERT_TRUE(StartEmbeddedTestServer());
1989 ASSERT_TRUE(test_server()->Start());
1990 std::string download_url = test_server()->GetURL("auth-basic").spec();
1991 GoOnTheRecord();
1993 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1994 new DownloadsDownloadFunction(), base::StringPrintf(
1995 "[{\"url\": \"%s\","
1996 " \"filename\": \"auth-basic-fail.txt\"}]",
1997 download_url.c_str())));
1998 ASSERT_TRUE(result.get());
1999 int result_id = -1;
2000 ASSERT_TRUE(result->GetAsInteger(&result_id));
2001 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2002 ASSERT_TRUE(item);
2003 ScopedCancellingItem canceller(item);
2004 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2006 ASSERT_TRUE(WaitForInterruption(
2007 item,
2008 content::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED,
2009 base::StringPrintf("[{\"danger\": \"safe\","
2010 " \"incognito\": false,"
2011 " \"mime\": \"text/html\","
2012 " \"paused\": false,"
2013 " \"url\": \"%s\"}]",
2014 download_url.c_str())));
2017 // Test that DownloadsDownloadFunction propagates |headers| to the URLRequest.
2018 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2019 DownloadExtensionTest_Download_Headers) {
2020 LoadExtension("downloads_split");
2021 ASSERT_TRUE(StartEmbeddedTestServer());
2022 ASSERT_TRUE(test_server()->Start());
2023 std::string download_url = test_server()->GetURL("files/downloads/"
2024 "a_zip_file.zip?expected_headers=Foo:bar&expected_headers=Qx:yo").spec();
2025 GoOnTheRecord();
2027 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2028 new DownloadsDownloadFunction(), base::StringPrintf(
2029 "[{\"url\": \"%s\","
2030 " \"filename\": \"headers-succeed.txt\","
2031 " \"headers\": ["
2032 " {\"name\": \"Foo\", \"value\": \"bar\"},"
2033 " {\"name\": \"Qx\", \"value\":\"yo\"}]}]",
2034 download_url.c_str())));
2035 ASSERT_TRUE(result.get());
2036 int result_id = -1;
2037 ASSERT_TRUE(result->GetAsInteger(&result_id));
2038 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2039 ASSERT_TRUE(item);
2040 ScopedCancellingItem canceller(item);
2041 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2043 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2044 base::StringPrintf(
2045 "[{\"danger\": \"safe\","
2046 " \"incognito\": false,"
2047 " \"mime\": \"application/octet-stream\","
2048 " \"paused\": false,"
2049 " \"url\": \"%s\"}]",
2050 download_url.c_str())));
2051 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2052 base::StringPrintf(
2053 "[{\"id\": %d,"
2054 " \"filename\": {"
2055 " \"previous\": \"\","
2056 " \"current\": \"%s\"}}]",
2057 result_id,
2058 GetFilename("headers-succeed.txt").c_str())));
2059 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2060 base::StringPrintf(
2061 "[{\"id\": %d,"
2062 " \"state\": {"
2063 " \"previous\": \"in_progress\","
2064 " \"current\": \"complete\"}}]",
2065 result_id)));
2068 // Test that headers-succeed would fail if the resource requires the headers and
2069 // chrome fails to propagate them back to the server. This tests both that
2070 // testserver.py does not succeed when it should fail as well as how the
2071 // downloads extension api exposes the failure to extensions.
2072 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2073 DownloadExtensionTest_Download_Headers_Fail) {
2074 LoadExtension("downloads_split");
2075 ASSERT_TRUE(StartEmbeddedTestServer());
2076 ASSERT_TRUE(test_server()->Start());
2077 std::string download_url = test_server()->GetURL("files/downloads/"
2078 "a_zip_file.zip?expected_headers=Foo:bar&expected_headers=Qx:yo").spec();
2079 GoOnTheRecord();
2081 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2082 new DownloadsDownloadFunction(), base::StringPrintf(
2083 "[{\"url\": \"%s\","
2084 " \"filename\": \"headers-fail.txt\"}]",
2085 download_url.c_str())));
2086 ASSERT_TRUE(result.get());
2087 int result_id = -1;
2088 ASSERT_TRUE(result->GetAsInteger(&result_id));
2089 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2090 ASSERT_TRUE(item);
2091 ScopedCancellingItem canceller(item);
2092 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2094 ASSERT_TRUE(WaitForInterruption(
2095 item,
2096 content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
2097 base::StringPrintf("[{\"danger\": \"safe\","
2098 " \"incognito\": false,"
2099 " \"bytesReceived\": 0.0,"
2100 " \"fileSize\": 0.0,"
2101 " \"mime\": \"\","
2102 " \"paused\": false,"
2103 " \"url\": \"%s\"}]",
2104 download_url.c_str())));
2107 // Test that DownloadsDownloadFunction propagates the Authorization header
2108 // correctly.
2109 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2110 DownloadExtensionTest_Download_AuthBasic) {
2111 LoadExtension("downloads_split");
2112 ASSERT_TRUE(StartEmbeddedTestServer());
2113 ASSERT_TRUE(test_server()->Start());
2114 std::string download_url = test_server()->GetURL("auth-basic").spec();
2115 // This is just base64 of 'username:secret'.
2116 static const char kAuthorization[] = "dXNlcm5hbWU6c2VjcmV0";
2117 GoOnTheRecord();
2119 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2120 new DownloadsDownloadFunction(), base::StringPrintf(
2121 "[{\"url\": \"%s\","
2122 " \"filename\": \"auth-basic-succeed.txt\","
2123 " \"headers\": [{"
2124 " \"name\": \"Authorization\","
2125 " \"value\": \"Basic %s\"}]}]",
2126 download_url.c_str(), kAuthorization)));
2127 ASSERT_TRUE(result.get());
2128 int result_id = -1;
2129 ASSERT_TRUE(result->GetAsInteger(&result_id));
2130 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2131 ASSERT_TRUE(item);
2132 ScopedCancellingItem canceller(item);
2133 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2135 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2136 base::StringPrintf(
2137 "[{\"danger\": \"safe\","
2138 " \"incognito\": false,"
2139 " \"bytesReceived\": 0.0,"
2140 " \"fileSize\": 0.0,"
2141 " \"mime\": \"text/html\","
2142 " \"paused\": false,"
2143 " \"url\": \"%s\"}]",
2144 download_url.c_str())));
2145 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2146 base::StringPrintf(
2147 "[{\"id\": %d,"
2148 " \"state\": {"
2149 " \"previous\": \"in_progress\","
2150 " \"current\": \"complete\"}}]",
2151 result_id)));
2154 // Test that DownloadsDownloadFunction propagates the |method| and |body|
2155 // parameters to the URLRequest.
2156 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2157 DownloadExtensionTest_Download_Post) {
2158 LoadExtension("downloads_split");
2159 ASSERT_TRUE(StartEmbeddedTestServer());
2160 ASSERT_TRUE(test_server()->Start());
2161 std::string download_url = test_server()->GetURL("files/post/downloads/"
2162 "a_zip_file.zip?expected_body=BODY").spec();
2163 GoOnTheRecord();
2165 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2166 new DownloadsDownloadFunction(), base::StringPrintf(
2167 "[{\"url\": \"%s\","
2168 " \"filename\": \"post-succeed.txt\","
2169 " \"method\": \"POST\","
2170 " \"body\": \"BODY\"}]",
2171 download_url.c_str())));
2172 ASSERT_TRUE(result.get());
2173 int result_id = -1;
2174 ASSERT_TRUE(result->GetAsInteger(&result_id));
2175 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2176 ASSERT_TRUE(item);
2177 ScopedCancellingItem canceller(item);
2178 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2180 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2181 base::StringPrintf(
2182 "[{\"danger\": \"safe\","
2183 " \"incognito\": false,"
2184 " \"mime\": \"application/octet-stream\","
2185 " \"paused\": false,"
2186 " \"url\": \"%s\"}]",
2187 download_url.c_str())));
2188 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2189 base::StringPrintf(
2190 "[{\"id\": %d,"
2191 " \"filename\": {"
2192 " \"previous\": \"\","
2193 " \"current\": \"%s\"}}]",
2194 result_id,
2195 GetFilename("post-succeed.txt").c_str())));
2196 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2197 base::StringPrintf(
2198 "[{\"id\": %d,"
2199 " \"state\": {"
2200 " \"previous\": \"in_progress\","
2201 " \"current\": \"complete\"}}]",
2202 result_id)));
2205 // Test that downloadPostSuccess would fail if the resource requires the POST
2206 // method, and chrome fails to propagate the |method| parameter back to the
2207 // server. This tests both that testserver.py does not succeed when it should
2208 // fail, and this tests how the downloads extension api exposes the failure to
2209 // extensions.
2210 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2211 DownloadExtensionTest_Download_Post_Get) {
2212 LoadExtension("downloads_split");
2213 ASSERT_TRUE(StartEmbeddedTestServer());
2214 ASSERT_TRUE(test_server()->Start());
2215 std::string download_url = test_server()->GetURL("files/post/downloads/"
2216 "a_zip_file.zip?expected_body=BODY").spec();
2217 GoOnTheRecord();
2219 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2220 new DownloadsDownloadFunction(), base::StringPrintf(
2221 "[{\"url\": \"%s\","
2222 " \"body\": \"BODY\","
2223 " \"filename\": \"post-get.txt\"}]",
2224 download_url.c_str())));
2225 ASSERT_TRUE(result.get());
2226 int result_id = -1;
2227 ASSERT_TRUE(result->GetAsInteger(&result_id));
2228 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2229 ASSERT_TRUE(item);
2230 ScopedCancellingItem canceller(item);
2231 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2233 ASSERT_TRUE(WaitForInterruption(
2234 item,
2235 content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
2236 base::StringPrintf("[{\"danger\": \"safe\","
2237 " \"incognito\": false,"
2238 " \"mime\": \"\","
2239 " \"paused\": false,"
2240 " \"id\": %d,"
2241 " \"url\": \"%s\"}]",
2242 result_id,
2243 download_url.c_str())));
2246 // Test that downloadPostSuccess would fail if the resource requires the POST
2247 // method, and chrome fails to propagate the |body| parameter back to the
2248 // server. This tests both that testserver.py does not succeed when it should
2249 // fail, and this tests how the downloads extension api exposes the failure to
2250 // extensions.
2251 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2252 DownloadExtensionTest_Download_Post_NoBody) {
2253 LoadExtension("downloads_split");
2254 ASSERT_TRUE(StartEmbeddedTestServer());
2255 ASSERT_TRUE(test_server()->Start());
2256 std::string download_url = test_server()->GetURL("files/post/downloads/"
2257 "a_zip_file.zip?expected_body=BODY").spec();
2258 GoOnTheRecord();
2260 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2261 new DownloadsDownloadFunction(), base::StringPrintf(
2262 "[{\"url\": \"%s\","
2263 " \"method\": \"POST\","
2264 " \"filename\": \"post-nobody.txt\"}]",
2265 download_url.c_str())));
2266 ASSERT_TRUE(result.get());
2267 int result_id = -1;
2268 ASSERT_TRUE(result->GetAsInteger(&result_id));
2269 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2270 ASSERT_TRUE(item);
2271 ScopedCancellingItem canceller(item);
2272 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2274 ASSERT_TRUE(WaitForInterruption(
2275 item,
2276 content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
2277 base::StringPrintf("[{\"danger\": \"safe\","
2278 " \"incognito\": false,"
2279 " \"mime\": \"\","
2280 " \"paused\": false,"
2281 " \"id\": %d,"
2282 " \"url\": \"%s\"}]",
2283 result_id,
2284 download_url.c_str())));
2287 // Test that cancel()ing an in-progress download causes its state to transition
2288 // to interrupted, and test that that state transition is detectable by an
2289 // onChanged event listener. TODO(benjhayden): Test other sources of
2290 // interruptions such as server death.
2291 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2292 DownloadExtensionTest_Download_Cancel) {
2293 LoadExtension("downloads_split");
2294 ASSERT_TRUE(StartEmbeddedTestServer());
2295 ASSERT_TRUE(test_server()->Start());
2296 std::string download_url = test_server()->GetURL(
2297 "download-known-size").spec();
2298 GoOnTheRecord();
2300 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2301 new DownloadsDownloadFunction(), base::StringPrintf(
2302 "[{\"url\": \"%s\"}]", download_url.c_str())));
2303 ASSERT_TRUE(result.get());
2304 int result_id = -1;
2305 ASSERT_TRUE(result->GetAsInteger(&result_id));
2306 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2307 ASSERT_TRUE(item);
2308 ScopedCancellingItem canceller(item);
2309 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2311 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2312 base::StringPrintf(
2313 "[{\"danger\": \"safe\","
2314 " \"incognito\": false,"
2315 " \"mime\": \"application/octet-stream\","
2316 " \"paused\": false,"
2317 " \"id\": %d,"
2318 " \"url\": \"%s\"}]",
2319 result_id,
2320 download_url.c_str())));
2321 item->Cancel(true);
2322 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2323 base::StringPrintf(
2324 "[{\"id\": %d,"
2325 " \"error\": {\"current\":\"USER_CANCELED\"},"
2326 " \"state\": {"
2327 " \"previous\": \"in_progress\","
2328 " \"current\": \"interrupted\"}}]",
2329 result_id)));
2332 // flaky on mac: crbug.com/392288
2333 #if defined(OS_MACOSX)
2334 #define MAYBE_DownloadExtensionTest_Download_FileSystemURL \
2335 DISABLED_DownloadExtensionTest_Download_FileSystemURL
2336 #else
2337 #define MAYBE_DownloadExtensionTest_Download_FileSystemURL \
2338 DownloadExtensionTest_Download_FileSystemURL
2339 #endif
2341 // Test downloading filesystem: URLs.
2342 // NOTE: chrome disallows creating HTML5 FileSystem Files in incognito.
2343 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2344 MAYBE_DownloadExtensionTest_Download_FileSystemURL) {
2345 static const char kPayloadData[] = "on the record\ndata";
2346 GoOnTheRecord();
2347 LoadExtension("downloads_split");
2349 const std::string download_url = "filesystem:" + GetExtensionURL() +
2350 "temporary/on_record.txt";
2352 // Setup a file in the filesystem which we can download.
2353 ASSERT_TRUE(HTML5FileWriter::CreateFileForTesting(
2354 BrowserContext::GetDefaultStoragePartition(browser()->profile())
2355 ->GetFileSystemContext(),
2356 storage::FileSystemURL::CreateForTest(GURL(download_url)),
2357 kPayloadData,
2358 strlen(kPayloadData)));
2360 // Now download it.
2361 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2362 new DownloadsDownloadFunction(), base::StringPrintf(
2363 "[{\"url\": \"%s\"}]", download_url.c_str())));
2364 ASSERT_TRUE(result.get());
2365 int result_id = -1;
2366 ASSERT_TRUE(result->GetAsInteger(&result_id));
2368 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2369 ASSERT_TRUE(item);
2370 ScopedCancellingItem canceller(item);
2371 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2373 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2374 base::StringPrintf(
2375 "[{\"danger\": \"safe\","
2376 " \"incognito\": false,"
2377 " \"mime\": \"text/plain\","
2378 " \"paused\": false,"
2379 " \"url\": \"%s\"}]",
2380 download_url.c_str())));
2381 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2382 base::StringPrintf(
2383 "[{\"id\": %d,"
2384 " \"filename\": {"
2385 " \"previous\": \"\","
2386 " \"current\": \"%s\"}}]",
2387 result_id,
2388 GetFilename("on_record.txt").c_str())));
2389 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2390 base::StringPrintf(
2391 "[{\"id\": %d,"
2392 " \"state\": {"
2393 " \"previous\": \"in_progress\","
2394 " \"current\": \"complete\"}}]",
2395 result_id)));
2396 std::string disk_data;
2397 EXPECT_TRUE(base::ReadFileToString(item->GetTargetFilePath(), &disk_data));
2398 EXPECT_STREQ(kPayloadData, disk_data.c_str());
2401 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2402 DownloadExtensionTest_OnDeterminingFilename_NoChange) {
2403 GoOnTheRecord();
2404 LoadExtension("downloads_split");
2405 AddFilenameDeterminer();
2406 ASSERT_TRUE(StartEmbeddedTestServer());
2407 ASSERT_TRUE(test_server()->Start());
2408 std::string download_url = test_server()->GetURL("slow?0").spec();
2410 // Start downloading a file.
2411 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2412 new DownloadsDownloadFunction(), base::StringPrintf(
2413 "[{\"url\": \"%s\"}]", download_url.c_str())));
2414 ASSERT_TRUE(result.get());
2415 int result_id = -1;
2416 ASSERT_TRUE(result->GetAsInteger(&result_id));
2417 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2418 ASSERT_TRUE(item);
2419 ScopedCancellingItem canceller(item);
2420 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2422 // Wait for the onCreated and onDeterminingFilename events.
2423 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2424 base::StringPrintf(
2425 "[{\"danger\": \"safe\","
2426 " \"incognito\": false,"
2427 " \"id\": %d,"
2428 " \"mime\": \"text/plain\","
2429 " \"paused\": false,"
2430 " \"url\": \"%s\"}]",
2431 result_id,
2432 download_url.c_str())));
2433 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
2434 base::StringPrintf(
2435 "[{\"id\": %d,"
2436 " \"filename\":\"slow.txt\"}]",
2437 result_id)));
2438 ASSERT_TRUE(item->GetTargetFilePath().empty());
2439 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
2441 // Respond to the onDeterminingFilename.
2442 std::string error;
2443 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
2444 browser()->profile(),
2445 false,
2446 GetExtensionId(),
2447 result_id,
2448 base::FilePath(),
2449 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
2450 &error));
2451 EXPECT_EQ("", error);
2453 // The download should complete successfully.
2454 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2455 base::StringPrintf(
2456 "[{\"id\": %d,"
2457 " \"filename\": {"
2458 " \"previous\": \"\","
2459 " \"current\": \"%s\"}}]",
2460 result_id,
2461 GetFilename("slow.txt").c_str())));
2462 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2463 base::StringPrintf(
2464 "[{\"id\": %d,"
2465 " \"state\": {"
2466 " \"previous\": \"in_progress\","
2467 " \"current\": \"complete\"}}]",
2468 result_id)));
2471 // Disabled due to cross-platform flakes; http://crbug.com/370531.
2472 IN_PROC_BROWSER_TEST_F(
2473 DownloadExtensionTest,
2474 DISABLED_DownloadExtensionTest_OnDeterminingFilename_Timeout) {
2475 GoOnTheRecord();
2476 LoadExtension("downloads_split");
2477 AddFilenameDeterminer();
2478 ASSERT_TRUE(StartEmbeddedTestServer());
2479 ASSERT_TRUE(test_server()->Start());
2480 std::string download_url = test_server()->GetURL("slow?0").spec();
2482 ExtensionDownloadsEventRouter::SetDetermineFilenameTimeoutSecondsForTesting(
2485 // Start downloading a file.
2486 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2487 new DownloadsDownloadFunction(), base::StringPrintf(
2488 "[{\"url\": \"%s\"}]", download_url.c_str())));
2489 ASSERT_TRUE(result.get());
2490 int result_id = -1;
2491 ASSERT_TRUE(result->GetAsInteger(&result_id));
2492 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2493 ASSERT_TRUE(item);
2494 ScopedCancellingItem canceller(item);
2495 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2497 // Wait for the onCreated and onDeterminingFilename events.
2498 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2499 base::StringPrintf("[{\"danger\": \"safe\","
2500 " \"incognito\": false,"
2501 " \"id\": %d,"
2502 " \"mime\": \"text/plain\","
2503 " \"paused\": false,"
2504 " \"url\": \"%s\"}]",
2505 result_id,
2506 download_url.c_str())));
2507 ASSERT_TRUE(WaitFor(
2508 downloads::OnDeterminingFilename::kEventName,
2509 base::StringPrintf("[{\"id\": %d,"
2510 " \"filename\":\"slow.txt\"}]",
2511 result_id)));
2512 ASSERT_TRUE(item->GetTargetFilePath().empty());
2513 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
2515 // Do not respond to the onDeterminingFilename.
2517 // The download should complete successfully.
2518 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2519 base::StringPrintf("[{\"id\": %d,"
2520 " \"filename\": {"
2521 " \"previous\": \"\","
2522 " \"current\": \"%s\"}}]",
2523 result_id,
2524 GetFilename("slow.txt").c_str())));
2525 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2526 base::StringPrintf("[{\"id\": %d,"
2527 " \"state\": {"
2528 " \"previous\": \"in_progress\","
2529 " \"current\": \"complete\"}}]",
2530 result_id)));
2533 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2534 DownloadExtensionTest_OnDeterminingFilename_Twice) {
2535 GoOnTheRecord();
2536 LoadExtension("downloads_split");
2537 AddFilenameDeterminer();
2538 ASSERT_TRUE(StartEmbeddedTestServer());
2539 ASSERT_TRUE(test_server()->Start());
2540 std::string download_url = test_server()->GetURL("slow?0").spec();
2542 // Start downloading a file.
2543 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2544 new DownloadsDownloadFunction(), base::StringPrintf(
2545 "[{\"url\": \"%s\"}]", download_url.c_str())));
2546 ASSERT_TRUE(result.get());
2547 int result_id = -1;
2548 ASSERT_TRUE(result->GetAsInteger(&result_id));
2549 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2550 ASSERT_TRUE(item);
2551 ScopedCancellingItem canceller(item);
2552 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2554 // Wait for the onCreated and onDeterminingFilename events.
2555 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2556 base::StringPrintf("[{\"danger\": \"safe\","
2557 " \"incognito\": false,"
2558 " \"id\": %d,"
2559 " \"mime\": \"text/plain\","
2560 " \"paused\": false,"
2561 " \"url\": \"%s\"}]",
2562 result_id,
2563 download_url.c_str())));
2564 ASSERT_TRUE(WaitFor(
2565 downloads::OnDeterminingFilename::kEventName,
2566 base::StringPrintf("[{\"id\": %d,"
2567 " \"filename\":\"slow.txt\"}]",
2568 result_id)));
2569 ASSERT_TRUE(item->GetTargetFilePath().empty());
2570 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
2572 // Respond to the onDeterminingFilename.
2573 std::string error;
2574 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
2575 browser()->profile(),
2576 false,
2577 GetExtensionId(),
2578 result_id,
2579 base::FilePath(),
2580 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
2581 &error));
2582 EXPECT_EQ("", error);
2584 // Calling DetermineFilename again should return an error instead of calling
2585 // DownloadTargetDeterminer.
2586 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2587 browser()->profile(),
2588 false,
2589 GetExtensionId(),
2590 result_id,
2591 base::FilePath(FILE_PATH_LITERAL("different")),
2592 downloads::FILENAME_CONFLICT_ACTION_OVERWRITE,
2593 &error));
2594 EXPECT_EQ(errors::kTooManyListeners, error);
2596 // The download should complete successfully.
2597 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2598 base::StringPrintf("[{\"id\": %d,"
2599 " \"filename\": {"
2600 " \"previous\": \"\","
2601 " \"current\": \"%s\"}}]",
2602 result_id,
2603 GetFilename("slow.txt").c_str())));
2604 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2605 base::StringPrintf("[{\"id\": %d,"
2606 " \"state\": {"
2607 " \"previous\": \"in_progress\","
2608 " \"current\": \"complete\"}}]",
2609 result_id)));
2612 IN_PROC_BROWSER_TEST_F(
2613 DownloadExtensionTest,
2614 DownloadExtensionTest_OnDeterminingFilename_DangerousOverride) {
2615 GoOnTheRecord();
2616 LoadExtension("downloads_split");
2617 AddFilenameDeterminer();
2618 ASSERT_TRUE(StartEmbeddedTestServer());
2619 ASSERT_TRUE(test_server()->Start());
2620 std::string download_url = test_server()->GetURL("slow?0").spec();
2622 // Start downloading a file.
2623 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2624 new DownloadsDownloadFunction(), base::StringPrintf(
2625 "[{\"url\": \"%s\"}]", download_url.c_str())));
2626 ASSERT_TRUE(result.get());
2627 int result_id = -1;
2628 ASSERT_TRUE(result->GetAsInteger(&result_id));
2629 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2630 ASSERT_TRUE(item);
2631 ScopedCancellingItem canceller(item);
2632 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2634 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2635 base::StringPrintf(
2636 "[{\"danger\": \"safe\","
2637 " \"incognito\": false,"
2638 " \"id\": %d,"
2639 " \"mime\": \"text/plain\","
2640 " \"paused\": false,"
2641 " \"url\": \"%s\"}]",
2642 result_id,
2643 download_url.c_str())));
2644 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
2645 base::StringPrintf(
2646 "[{\"id\": %d,"
2647 " \"filename\":\"slow.txt\"}]",
2648 result_id)));
2649 ASSERT_TRUE(item->GetTargetFilePath().empty());
2650 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
2652 // Respond to the onDeterminingFilename.
2653 std::string error;
2654 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
2655 browser()->profile(),
2656 false,
2657 GetExtensionId(),
2658 result_id,
2659 base::FilePath(FILE_PATH_LITERAL("overridden.swf")),
2660 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
2661 &error));
2662 EXPECT_EQ("", error);
2664 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2665 base::StringPrintf(
2666 "[{\"id\": %d,"
2667 " \"danger\": {"
2668 " \"previous\":\"safe\","
2669 " \"current\":\"file\"}}]",
2670 result_id)));
2672 item->ValidateDangerousDownload();
2673 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2674 base::StringPrintf(
2675 "[{\"id\": %d,"
2676 " \"danger\": {"
2677 " \"previous\":\"file\","
2678 " \"current\":\"accepted\"}}]",
2679 result_id)));
2680 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2681 base::StringPrintf(
2682 "[{\"id\": %d,"
2683 " \"state\": {"
2684 " \"previous\": \"in_progress\","
2685 " \"current\": \"complete\"}}]",
2686 result_id)));
2687 EXPECT_EQ(downloads_directory().AppendASCII("overridden.swf"),
2688 item->GetTargetFilePath());
2691 IN_PROC_BROWSER_TEST_F(
2692 DownloadExtensionTest,
2693 DownloadExtensionTest_OnDeterminingFilename_ReferencesParentInvalid) {
2694 GoOnTheRecord();
2695 LoadExtension("downloads_split");
2696 AddFilenameDeterminer();
2697 ASSERT_TRUE(StartEmbeddedTestServer());
2698 ASSERT_TRUE(test_server()->Start());
2699 std::string download_url = test_server()->GetURL("slow?0").spec();
2701 // Start downloading a file.
2702 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2703 new DownloadsDownloadFunction(), base::StringPrintf(
2704 "[{\"url\": \"%s\"}]", download_url.c_str())));
2705 ASSERT_TRUE(result.get());
2706 int result_id = -1;
2707 ASSERT_TRUE(result->GetAsInteger(&result_id));
2708 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2709 ASSERT_TRUE(item);
2710 ScopedCancellingItem canceller(item);
2711 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2713 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2714 base::StringPrintf(
2715 "[{\"danger\": \"safe\","
2716 " \"incognito\": false,"
2717 " \"id\": %d,"
2718 " \"mime\": \"text/plain\","
2719 " \"paused\": false,"
2720 " \"url\": \"%s\"}]",
2721 result_id,
2722 download_url.c_str())));
2723 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
2724 base::StringPrintf(
2725 "[{\"id\": %d,"
2726 " \"filename\":\"slow.txt\"}]",
2727 result_id)));
2728 ASSERT_TRUE(item->GetTargetFilePath().empty());
2729 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
2731 // Respond to the onDeterminingFilename.
2732 std::string error;
2733 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2734 browser()->profile(),
2735 false,
2736 GetExtensionId(),
2737 result_id,
2738 base::FilePath(FILE_PATH_LITERAL("sneaky/../../sneaky.txt")),
2739 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
2740 &error));
2741 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
2742 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2743 base::StringPrintf(
2744 "[{\"id\": %d,"
2745 " \"filename\": {"
2746 " \"previous\": \"\","
2747 " \"current\": \"%s\"}}]",
2748 result_id,
2749 GetFilename("slow.txt").c_str())));
2750 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2751 base::StringPrintf(
2752 "[{\"id\": %d,"
2753 " \"state\": {"
2754 " \"previous\": \"in_progress\","
2755 " \"current\": \"complete\"}}]",
2756 result_id)));
2759 IN_PROC_BROWSER_TEST_F(
2760 DownloadExtensionTest,
2761 DownloadExtensionTest_OnDeterminingFilename_IllegalFilename) {
2762 GoOnTheRecord();
2763 LoadExtension("downloads_split");
2764 AddFilenameDeterminer();
2765 ASSERT_TRUE(StartEmbeddedTestServer());
2766 ASSERT_TRUE(test_server()->Start());
2767 std::string download_url = test_server()->GetURL("slow?0").spec();
2769 // Start downloading a file.
2770 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2771 new DownloadsDownloadFunction(), base::StringPrintf(
2772 "[{\"url\": \"%s\"}]", download_url.c_str())));
2773 ASSERT_TRUE(result.get());
2774 int result_id = -1;
2775 ASSERT_TRUE(result->GetAsInteger(&result_id));
2776 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2777 ASSERT_TRUE(item);
2778 ScopedCancellingItem canceller(item);
2779 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2781 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2782 base::StringPrintf(
2783 "[{\"danger\": \"safe\","
2784 " \"incognito\": false,"
2785 " \"id\": %d,"
2786 " \"mime\": \"text/plain\","
2787 " \"paused\": false,"
2788 " \"url\": \"%s\"}]",
2789 result_id,
2790 download_url.c_str())));
2791 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
2792 base::StringPrintf(
2793 "[{\"id\": %d,"
2794 " \"filename\":\"slow.txt\"}]",
2795 result_id)));
2796 ASSERT_TRUE(item->GetTargetFilePath().empty());
2797 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
2799 // Respond to the onDeterminingFilename.
2800 std::string error;
2801 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2802 browser()->profile(),
2803 false,
2804 GetExtensionId(),
2805 result_id,
2806 base::FilePath(FILE_PATH_LITERAL("<")),
2807 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
2808 &error));
2809 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
2810 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2811 base::StringPrintf(
2812 "[{\"id\": %d,"
2813 " \"filename\": {"
2814 " \"previous\": \"\","
2815 " \"current\": \"%s\"}}]",
2816 result_id,
2817 GetFilename("slow.txt").c_str())));
2818 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2819 base::StringPrintf(
2820 "[{\"id\": %d,"
2821 " \"state\": {"
2822 " \"previous\": \"in_progress\","
2823 " \"current\": \"complete\"}}]",
2824 result_id)));
2827 IN_PROC_BROWSER_TEST_F(
2828 DownloadExtensionTest,
2829 DownloadExtensionTest_OnDeterminingFilename_IllegalFilenameExtension) {
2830 GoOnTheRecord();
2831 LoadExtension("downloads_split");
2832 AddFilenameDeterminer();
2833 ASSERT_TRUE(StartEmbeddedTestServer());
2834 ASSERT_TRUE(test_server()->Start());
2835 std::string download_url = test_server()->GetURL("slow?0").spec();
2837 // Start downloading a file.
2838 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2839 new DownloadsDownloadFunction(), base::StringPrintf(
2840 "[{\"url\": \"%s\"}]", download_url.c_str())));
2841 ASSERT_TRUE(result.get());
2842 int result_id = -1;
2843 ASSERT_TRUE(result->GetAsInteger(&result_id));
2844 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2845 ASSERT_TRUE(item);
2846 ScopedCancellingItem canceller(item);
2847 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2849 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2850 base::StringPrintf(
2851 "[{\"danger\": \"safe\","
2852 " \"incognito\": false,"
2853 " \"id\": %d,"
2854 " \"mime\": \"text/plain\","
2855 " \"paused\": false,"
2856 " \"url\": \"%s\"}]",
2857 result_id,
2858 download_url.c_str())));
2859 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
2860 base::StringPrintf(
2861 "[{\"id\": %d,"
2862 " \"filename\":\"slow.txt\"}]",
2863 result_id)));
2864 ASSERT_TRUE(item->GetTargetFilePath().empty());
2865 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
2867 // Respond to the onDeterminingFilename.
2868 std::string error;
2869 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2870 browser()->profile(),
2871 false,
2872 GetExtensionId(),
2873 result_id,
2874 base::FilePath(FILE_PATH_LITERAL(
2875 "My Computer.{20D04FE0-3AEA-1069-A2D8-08002B30309D}/foo")),
2876 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
2877 &error));
2878 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
2879 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2880 base::StringPrintf(
2881 "[{\"id\": %d,"
2882 " \"filename\": {"
2883 " \"previous\": \"\","
2884 " \"current\": \"%s\"}}]",
2885 result_id,
2886 GetFilename("slow.txt").c_str())));
2887 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2888 base::StringPrintf(
2889 "[{\"id\": %d,"
2890 " \"state\": {"
2891 " \"previous\": \"in_progress\","
2892 " \"current\": \"complete\"}}]",
2893 result_id)));
2895 #if defined(OS_WIN)
2896 #define MAYBE_DownloadExtensionTest_OnDeterminingFilename_ReservedFilename\
2897 DISABLED_DownloadExtensionTest_OnDeterminingFilename_ReservedFilename
2898 #else
2899 #define MAYBE_DownloadExtensionTest_OnDeterminingFilename_ReservedFilename\
2900 DownloadExtensionTest_OnDeterminingFilename_ReservedFilename
2901 #endif
2902 IN_PROC_BROWSER_TEST_F(
2903 DownloadExtensionTest,
2904 MAYBE_DownloadExtensionTest_OnDeterminingFilename_ReservedFilename) {
2905 GoOnTheRecord();
2906 LoadExtension("downloads_split");
2907 AddFilenameDeterminer();
2908 ASSERT_TRUE(StartEmbeddedTestServer());
2909 ASSERT_TRUE(test_server()->Start());
2910 std::string download_url = test_server()->GetURL("slow?0").spec();
2912 // Start downloading a file.
2913 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2914 new DownloadsDownloadFunction(), base::StringPrintf(
2915 "[{\"url\": \"%s\"}]", download_url.c_str())));
2916 ASSERT_TRUE(result.get());
2917 int result_id = -1;
2918 ASSERT_TRUE(result->GetAsInteger(&result_id));
2919 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2920 ASSERT_TRUE(item);
2921 ScopedCancellingItem canceller(item);
2922 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2924 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2925 base::StringPrintf(
2926 "[{\"danger\": \"safe\","
2927 " \"incognito\": false,"
2928 " \"id\": %d,"
2929 " \"mime\": \"text/plain\","
2930 " \"paused\": false,"
2931 " \"url\": \"%s\"}]",
2932 result_id,
2933 download_url.c_str())));
2934 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
2935 base::StringPrintf(
2936 "[{\"id\": %d,"
2937 " \"filename\":\"slow.txt\"}]",
2938 result_id)));
2939 ASSERT_TRUE(item->GetTargetFilePath().empty());
2940 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
2942 // Respond to the onDeterminingFilename.
2943 std::string error;
2944 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2945 browser()->profile(),
2946 false,
2947 GetExtensionId(),
2948 result_id,
2949 base::FilePath(FILE_PATH_LITERAL("con.foo")),
2950 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
2951 &error));
2952 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
2953 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2954 base::StringPrintf(
2955 "[{\"id\": %d,"
2956 " \"filename\": {"
2957 " \"previous\": \"\","
2958 " \"current\": \"%s\"}}]",
2959 result_id,
2960 GetFilename("slow.txt").c_str())));
2961 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
2962 base::StringPrintf(
2963 "[{\"id\": %d,"
2964 " \"state\": {"
2965 " \"previous\": \"in_progress\","
2966 " \"current\": \"complete\"}}]",
2967 result_id)));
2970 IN_PROC_BROWSER_TEST_F(
2971 DownloadExtensionTest,
2972 DownloadExtensionTest_OnDeterminingFilename_CurDirInvalid) {
2973 GoOnTheRecord();
2974 LoadExtension("downloads_split");
2975 AddFilenameDeterminer();
2976 ASSERT_TRUE(StartEmbeddedTestServer());
2977 ASSERT_TRUE(test_server()->Start());
2978 std::string download_url = test_server()->GetURL("slow?0").spec();
2980 // Start downloading a file.
2981 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2982 new DownloadsDownloadFunction(), base::StringPrintf(
2983 "[{\"url\": \"%s\"}]", download_url.c_str())));
2984 ASSERT_TRUE(result.get());
2985 int result_id = -1;
2986 ASSERT_TRUE(result->GetAsInteger(&result_id));
2987 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2988 ASSERT_TRUE(item);
2989 ScopedCancellingItem canceller(item);
2990 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2992 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
2993 base::StringPrintf(
2994 "[{\"danger\": \"safe\","
2995 " \"incognito\": false,"
2996 " \"id\": %d,"
2997 " \"mime\": \"text/plain\","
2998 " \"paused\": false,"
2999 " \"url\": \"%s\"}]",
3000 result_id,
3001 download_url.c_str())));
3002 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3003 base::StringPrintf(
3004 "[{\"id\": %d,"
3005 " \"filename\":\"slow.txt\"}]",
3006 result_id)));
3007 ASSERT_TRUE(item->GetTargetFilePath().empty());
3008 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3010 // Respond to the onDeterminingFilename.
3011 std::string error;
3012 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
3013 browser()->profile(),
3014 false,
3015 GetExtensionId(),
3016 result_id,
3017 base::FilePath(FILE_PATH_LITERAL(".")),
3018 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3019 &error));
3020 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
3021 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3022 base::StringPrintf(
3023 "[{\"id\": %d,"
3024 " \"filename\": {"
3025 " \"previous\": \"\","
3026 " \"current\": \"%s\"}}]",
3027 result_id,
3028 GetFilename("slow.txt").c_str())));
3029 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3030 base::StringPrintf(
3031 "[{\"id\": %d,"
3032 " \"state\": {"
3033 " \"previous\": \"in_progress\","
3034 " \"current\": \"complete\"}}]",
3035 result_id)));
3038 IN_PROC_BROWSER_TEST_F(
3039 DownloadExtensionTest,
3040 DownloadExtensionTest_OnDeterminingFilename_ParentDirInvalid) {
3041 ASSERT_TRUE(StartEmbeddedTestServer());
3042 ASSERT_TRUE(test_server()->Start());
3043 GoOnTheRecord();
3044 LoadExtension("downloads_split");
3045 AddFilenameDeterminer();
3046 std::string download_url = test_server()->GetURL("slow?0").spec();
3048 // Start downloading a file.
3049 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3050 new DownloadsDownloadFunction(), base::StringPrintf(
3051 "[{\"url\": \"%s\"}]", download_url.c_str())));
3052 ASSERT_TRUE(result.get());
3053 int result_id = -1;
3054 ASSERT_TRUE(result->GetAsInteger(&result_id));
3055 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3056 ASSERT_TRUE(item);
3057 ScopedCancellingItem canceller(item);
3058 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3060 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3061 base::StringPrintf(
3062 "[{\"danger\": \"safe\","
3063 " \"incognito\": false,"
3064 " \"id\": %d,"
3065 " \"mime\": \"text/plain\","
3066 " \"paused\": false,"
3067 " \"url\": \"%s\"}]",
3068 result_id,
3069 download_url.c_str())));
3070 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3071 base::StringPrintf(
3072 "[{\"id\": %d,"
3073 " \"filename\":\"slow.txt\"}]",
3074 result_id)));
3075 ASSERT_TRUE(item->GetTargetFilePath().empty());
3076 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3078 // Respond to the onDeterminingFilename.
3079 std::string error;
3080 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
3081 browser()->profile(),
3082 false,
3083 GetExtensionId(),
3084 result_id,
3085 base::FilePath(FILE_PATH_LITERAL("..")),
3086 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3087 &error));
3088 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
3089 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3090 base::StringPrintf(
3091 "[{\"id\": %d,"
3092 " \"filename\": {"
3093 " \"previous\": \"\","
3094 " \"current\": \"%s\"}}]",
3095 result_id,
3096 GetFilename("slow.txt").c_str())));
3097 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3098 base::StringPrintf(
3099 "[{\"id\": %d,"
3100 " \"state\": {"
3101 " \"previous\": \"in_progress\","
3102 " \"current\": \"complete\"}}]",
3103 result_id)));
3106 IN_PROC_BROWSER_TEST_F(
3107 DownloadExtensionTest,
3108 DownloadExtensionTest_OnDeterminingFilename_AbsPathInvalid) {
3109 GoOnTheRecord();
3110 LoadExtension("downloads_split");
3111 AddFilenameDeterminer();
3112 ASSERT_TRUE(StartEmbeddedTestServer());
3113 ASSERT_TRUE(test_server()->Start());
3114 std::string download_url = test_server()->GetURL("slow?0").spec();
3116 // Start downloading a file.
3117 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3118 new DownloadsDownloadFunction(), base::StringPrintf(
3119 "[{\"url\": \"%s\"}]", download_url.c_str())));
3120 ASSERT_TRUE(result.get());
3121 int result_id = -1;
3122 ASSERT_TRUE(result->GetAsInteger(&result_id));
3123 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3124 ASSERT_TRUE(item);
3125 ScopedCancellingItem canceller(item);
3126 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3128 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3129 base::StringPrintf(
3130 "[{\"danger\": \"safe\","
3131 " \"incognito\": false,"
3132 " \"id\": %d,"
3133 " \"mime\": \"text/plain\","
3134 " \"paused\": false,"
3135 " \"url\": \"%s\"}]",
3136 result_id,
3137 download_url.c_str())));
3138 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3139 base::StringPrintf(
3140 "[{\"id\": %d,"
3141 " \"filename\":\"slow.txt\"}]",
3142 result_id)));
3143 ASSERT_TRUE(item->GetTargetFilePath().empty());
3144 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3146 // Respond to the onDeterminingFilename. Absolute paths should be rejected.
3147 std::string error;
3148 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
3149 browser()->profile(),
3150 false,
3151 GetExtensionId(),
3152 result_id,
3153 downloads_directory().Append(FILE_PATH_LITERAL("sneaky.txt")),
3154 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3155 &error));
3156 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
3158 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3159 base::StringPrintf(
3160 "[{\"id\": %d,"
3161 " \"filename\": {"
3162 " \"previous\": \"\","
3163 " \"current\": \"%s\"}}]",
3164 result_id,
3165 GetFilename("slow.txt").c_str())));
3166 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3167 base::StringPrintf(
3168 "[{\"id\": %d,"
3169 " \"state\": {"
3170 " \"previous\": \"in_progress\","
3171 " \"current\": \"complete\"}}]",
3172 result_id)));
3175 IN_PROC_BROWSER_TEST_F(
3176 DownloadExtensionTest,
3177 DownloadExtensionTest_OnDeterminingFilename_EmptyBasenameInvalid) {
3178 GoOnTheRecord();
3179 LoadExtension("downloads_split");
3180 AddFilenameDeterminer();
3181 ASSERT_TRUE(StartEmbeddedTestServer());
3182 ASSERT_TRUE(test_server()->Start());
3183 std::string download_url = test_server()->GetURL("slow?0").spec();
3185 // Start downloading a file.
3186 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3187 new DownloadsDownloadFunction(), base::StringPrintf(
3188 "[{\"url\": \"%s\"}]", download_url.c_str())));
3189 ASSERT_TRUE(result.get());
3190 int result_id = -1;
3191 ASSERT_TRUE(result->GetAsInteger(&result_id));
3192 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3193 ASSERT_TRUE(item);
3194 ScopedCancellingItem canceller(item);
3195 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3197 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3198 base::StringPrintf(
3199 "[{\"danger\": \"safe\","
3200 " \"incognito\": false,"
3201 " \"id\": %d,"
3202 " \"mime\": \"text/plain\","
3203 " \"paused\": false,"
3204 " \"url\": \"%s\"}]",
3205 result_id,
3206 download_url.c_str())));
3207 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3208 base::StringPrintf(
3209 "[{\"id\": %d,"
3210 " \"filename\":\"slow.txt\"}]",
3211 result_id)));
3212 ASSERT_TRUE(item->GetTargetFilePath().empty());
3213 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3215 // Respond to the onDeterminingFilename. Empty basenames should be rejected.
3216 std::string error;
3217 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
3218 browser()->profile(),
3219 false,
3220 GetExtensionId(),
3221 result_id,
3222 base::FilePath(FILE_PATH_LITERAL("foo/")),
3223 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3224 &error));
3225 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
3227 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3228 base::StringPrintf(
3229 "[{\"id\": %d,"
3230 " \"filename\": {"
3231 " \"previous\": \"\","
3232 " \"current\": \"%s\"}}]",
3233 result_id,
3234 GetFilename("slow.txt").c_str())));
3235 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3236 base::StringPrintf(
3237 "[{\"id\": %d,"
3238 " \"state\": {"
3239 " \"previous\": \"in_progress\","
3240 " \"current\": \"complete\"}}]",
3241 result_id)));
3244 // conflictAction may be specified without filename.
3245 IN_PROC_BROWSER_TEST_F(
3246 DownloadExtensionTest,
3247 DownloadExtensionTest_OnDeterminingFilename_Overwrite) {
3248 GoOnTheRecord();
3249 LoadExtension("downloads_split");
3250 AddFilenameDeterminer();
3251 ASSERT_TRUE(StartEmbeddedTestServer());
3252 ASSERT_TRUE(test_server()->Start());
3253 std::string download_url = test_server()->GetURL("slow?0").spec();
3255 // Start downloading a file.
3256 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3257 new DownloadsDownloadFunction(), base::StringPrintf(
3258 "[{\"url\": \"%s\"}]", download_url.c_str())));
3259 ASSERT_TRUE(result.get());
3260 int result_id = -1;
3261 ASSERT_TRUE(result->GetAsInteger(&result_id));
3262 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3263 ASSERT_TRUE(item);
3264 ScopedCancellingItem canceller(item);
3265 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3266 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3267 base::StringPrintf(
3268 "[{\"danger\": \"safe\","
3269 " \"incognito\": false,"
3270 " \"id\": %d,"
3271 " \"mime\": \"text/plain\","
3272 " \"paused\": false,"
3273 " \"url\": \"%s\"}]",
3274 result_id,
3275 download_url.c_str())));
3276 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3277 base::StringPrintf(
3278 "[{\"id\": %d,"
3279 " \"filename\":\"slow.txt\"}]",
3280 result_id)));
3281 ASSERT_TRUE(item->GetTargetFilePath().empty());
3282 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3284 // Respond to the onDeterminingFilename.
3285 std::string error;
3286 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3287 browser()->profile(),
3288 false,
3289 GetExtensionId(),
3290 result_id,
3291 base::FilePath(),
3292 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3293 &error));
3294 EXPECT_EQ("", error);
3296 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3297 base::StringPrintf(
3298 "[{\"id\": %d,"
3299 " \"filename\": {"
3300 " \"previous\": \"\","
3301 " \"current\": \"%s\"}}]",
3302 result_id,
3303 GetFilename("slow.txt").c_str())));
3304 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3305 base::StringPrintf(
3306 "[{\"id\": %d,"
3307 " \"state\": {"
3308 " \"previous\": \"in_progress\","
3309 " \"current\": \"complete\"}}]",
3310 result_id)));
3312 // Start downloading a file.
3313 result.reset(RunFunctionAndReturnResult(
3314 new DownloadsDownloadFunction(), base::StringPrintf(
3315 "[{\"url\": \"%s\"}]", download_url.c_str())));
3316 ASSERT_TRUE(result.get());
3317 result_id = -1;
3318 ASSERT_TRUE(result->GetAsInteger(&result_id));
3319 item = GetCurrentManager()->GetDownload(result_id);
3320 ASSERT_TRUE(item);
3321 ScopedCancellingItem canceller2(item);
3322 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3324 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3325 base::StringPrintf(
3326 "[{\"danger\": \"safe\","
3327 " \"incognito\": false,"
3328 " \"id\": %d,"
3329 " \"mime\": \"text/plain\","
3330 " \"paused\": false,"
3331 " \"url\": \"%s\"}]",
3332 result_id,
3333 download_url.c_str())));
3334 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3335 base::StringPrintf(
3336 "[{\"id\": %d,"
3337 " \"filename\":\"slow.txt\"}]",
3338 result_id)));
3339 ASSERT_TRUE(item->GetTargetFilePath().empty());
3340 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3342 // Respond to the onDeterminingFilename.
3343 // Also test that DetermineFilename allows (chrome) extensions to set
3344 // filenames without (filename) extensions. (Don't ask about v8 extensions or
3345 // python extensions or kernel extensions or firefox extensions...)
3346 error = "";
3347 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3348 browser()->profile(),
3349 false,
3350 GetExtensionId(),
3351 result_id,
3352 base::FilePath(),
3353 downloads::FILENAME_CONFLICT_ACTION_OVERWRITE,
3354 &error));
3355 EXPECT_EQ("", error);
3357 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3358 base::StringPrintf(
3359 "[{\"id\": %d,"
3360 " \"filename\": {"
3361 " \"previous\": \"\","
3362 " \"current\": \"%s\"}}]",
3363 result_id,
3364 GetFilename("slow.txt").c_str())));
3365 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3366 base::StringPrintf(
3367 "[{\"id\": %d,"
3368 " \"state\": {"
3369 " \"previous\": \"in_progress\","
3370 " \"current\": \"complete\"}}]",
3371 result_id)));
3374 IN_PROC_BROWSER_TEST_F(
3375 DownloadExtensionTest,
3376 DownloadExtensionTest_OnDeterminingFilename_Override) {
3377 GoOnTheRecord();
3378 LoadExtension("downloads_split");
3379 AddFilenameDeterminer();
3380 ASSERT_TRUE(StartEmbeddedTestServer());
3381 ASSERT_TRUE(test_server()->Start());
3382 std::string download_url = test_server()->GetURL("slow?0").spec();
3384 // Start downloading a file.
3385 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3386 new DownloadsDownloadFunction(), base::StringPrintf(
3387 "[{\"url\": \"%s\"}]", download_url.c_str())));
3388 ASSERT_TRUE(result.get());
3389 int result_id = -1;
3390 ASSERT_TRUE(result->GetAsInteger(&result_id));
3391 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3392 ASSERT_TRUE(item);
3393 ScopedCancellingItem canceller(item);
3394 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3395 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3396 base::StringPrintf(
3397 "[{\"danger\": \"safe\","
3398 " \"incognito\": false,"
3399 " \"id\": %d,"
3400 " \"mime\": \"text/plain\","
3401 " \"paused\": false,"
3402 " \"url\": \"%s\"}]",
3403 result_id,
3404 download_url.c_str())));
3405 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3406 base::StringPrintf(
3407 "[{\"id\": %d,"
3408 " \"filename\":\"slow.txt\"}]",
3409 result_id)));
3410 ASSERT_TRUE(item->GetTargetFilePath().empty());
3411 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3413 // Respond to the onDeterminingFilename.
3414 std::string error;
3415 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3416 browser()->profile(),
3417 false,
3418 GetExtensionId(),
3419 result_id,
3420 base::FilePath(),
3421 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3422 &error));
3423 EXPECT_EQ("", error);
3425 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3426 base::StringPrintf(
3427 "[{\"id\": %d,"
3428 " \"filename\": {"
3429 " \"previous\": \"\","
3430 " \"current\": \"%s\"}}]",
3431 result_id,
3432 GetFilename("slow.txt").c_str())));
3433 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3434 base::StringPrintf(
3435 "[{\"id\": %d,"
3436 " \"state\": {"
3437 " \"previous\": \"in_progress\","
3438 " \"current\": \"complete\"}}]",
3439 result_id)));
3441 // Start downloading a file.
3442 result.reset(RunFunctionAndReturnResult(
3443 new DownloadsDownloadFunction(), base::StringPrintf(
3444 "[{\"url\": \"%s\"}]", download_url.c_str())));
3445 ASSERT_TRUE(result.get());
3446 result_id = -1;
3447 ASSERT_TRUE(result->GetAsInteger(&result_id));
3448 item = GetCurrentManager()->GetDownload(result_id);
3449 ASSERT_TRUE(item);
3450 ScopedCancellingItem canceller2(item);
3451 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3453 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3454 base::StringPrintf(
3455 "[{\"danger\": \"safe\","
3456 " \"incognito\": false,"
3457 " \"id\": %d,"
3458 " \"mime\": \"text/plain\","
3459 " \"paused\": false,"
3460 " \"url\": \"%s\"}]",
3461 result_id,
3462 download_url.c_str())));
3463 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3464 base::StringPrintf(
3465 "[{\"id\": %d,"
3466 " \"filename\":\"slow.txt\"}]",
3467 result_id)));
3468 ASSERT_TRUE(item->GetTargetFilePath().empty());
3469 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3471 // Respond to the onDeterminingFilename.
3472 // Also test that DetermineFilename allows (chrome) extensions to set
3473 // filenames without (filename) extensions. (Don't ask about v8 extensions or
3474 // python extensions or kernel extensions or firefox extensions...)
3475 error = "";
3476 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3477 browser()->profile(),
3478 false,
3479 GetExtensionId(),
3480 result_id,
3481 base::FilePath(FILE_PATH_LITERAL("foo")),
3482 downloads::FILENAME_CONFLICT_ACTION_OVERWRITE,
3483 &error));
3484 EXPECT_EQ("", error);
3486 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3487 base::StringPrintf(
3488 "[{\"id\": %d,"
3489 " \"filename\": {"
3490 " \"previous\": \"\","
3491 " \"current\": \"%s\"}}]",
3492 result_id,
3493 GetFilename("foo").c_str())));
3494 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3495 base::StringPrintf(
3496 "[{\"id\": %d,"
3497 " \"state\": {"
3498 " \"previous\": \"in_progress\","
3499 " \"current\": \"complete\"}}]",
3500 result_id)));
3503 // TODO test precedence rules: install_time
3505 #if defined(OS_MACOSX)
3506 #define MAYBE_DownloadExtensionTest_OnDeterminingFilename_RemoveFilenameDeterminer \
3507 DISABLED_DownloadExtensionTest_OnDeterminingFilename_RemoveFilenameDeterminer
3508 #else
3509 #define MAYBE_DownloadExtensionTest_OnDeterminingFilename_RemoveFilenameDeterminer \
3510 DownloadExtensionTest_OnDeterminingFilename_RemoveFilenameDeterminer
3511 #endif
3512 IN_PROC_BROWSER_TEST_F(
3513 DownloadExtensionTest,
3514 MAYBE_DownloadExtensionTest_OnDeterminingFilename_RemoveFilenameDeterminer) {
3515 ASSERT_TRUE(StartEmbeddedTestServer());
3516 ASSERT_TRUE(test_server()->Start());
3517 GoOnTheRecord();
3518 LoadExtension("downloads_split");
3519 content::RenderProcessHost* host = AddFilenameDeterminer();
3520 std::string download_url = test_server()->GetURL("slow?0").spec();
3522 // Start downloading a file.
3523 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3524 new DownloadsDownloadFunction(), base::StringPrintf(
3525 "[{\"url\": \"%s\"}]", download_url.c_str())));
3526 ASSERT_TRUE(result.get());
3527 int result_id = -1;
3528 ASSERT_TRUE(result->GetAsInteger(&result_id));
3529 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3530 ASSERT_TRUE(item);
3531 ScopedCancellingItem canceller(item);
3532 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3534 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3535 base::StringPrintf(
3536 "[{\"danger\": \"safe\","
3537 " \"incognito\": false,"
3538 " \"id\": %d,"
3539 " \"mime\": \"text/plain\","
3540 " \"paused\": false,"
3541 " \"url\": \"%s\"}]",
3542 result_id,
3543 download_url.c_str())));
3544 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3545 base::StringPrintf(
3546 "[{\"id\": %d,"
3547 " \"filename\":\"slow.txt\"}]",
3548 result_id)));
3549 ASSERT_TRUE(item->GetTargetFilePath().empty());
3550 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3552 // Remove a determiner while waiting for it.
3553 RemoveFilenameDeterminer(host);
3555 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3556 base::StringPrintf(
3557 "[{\"id\": %d,"
3558 " \"state\": {"
3559 " \"previous\": \"in_progress\","
3560 " \"current\": \"complete\"}}]",
3561 result_id)));
3564 IN_PROC_BROWSER_TEST_F(
3565 DownloadExtensionTest,
3566 DownloadExtensionTest_OnDeterminingFilename_IncognitoSplit) {
3567 LoadExtension("downloads_split");
3568 ASSERT_TRUE(StartEmbeddedTestServer());
3569 ASSERT_TRUE(test_server()->Start());
3570 std::string download_url = test_server()->GetURL("slow?0").spec();
3572 GoOnTheRecord();
3573 AddFilenameDeterminer();
3575 GoOffTheRecord();
3576 AddFilenameDeterminer();
3578 // Start an on-record download.
3579 GoOnTheRecord();
3580 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3581 new DownloadsDownloadFunction(), base::StringPrintf(
3582 "[{\"url\": \"%s\"}]", download_url.c_str())));
3583 ASSERT_TRUE(result.get());
3584 int result_id = -1;
3585 ASSERT_TRUE(result->GetAsInteger(&result_id));
3586 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3587 ASSERT_TRUE(item);
3588 ScopedCancellingItem canceller(item);
3589 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3591 // Wait for the onCreated and onDeterminingFilename events.
3592 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3593 base::StringPrintf(
3594 "[{\"danger\": \"safe\","
3595 " \"incognito\": false,"
3596 " \"id\": %d,"
3597 " \"mime\": \"text/plain\","
3598 " \"paused\": false,"
3599 " \"url\": \"%s\"}]",
3600 result_id,
3601 download_url.c_str())));
3602 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3603 base::StringPrintf(
3604 "[{\"id\": %d,"
3605 " \"incognito\": false,"
3606 " \"filename\":\"slow.txt\"}]",
3607 result_id)));
3608 ASSERT_TRUE(item->GetTargetFilePath().empty());
3609 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3611 // Respond to the onDeterminingFilename events.
3612 std::string error;
3613 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3614 current_browser()->profile(),
3615 false,
3616 GetExtensionId(),
3617 result_id,
3618 base::FilePath(FILE_PATH_LITERAL("42.txt")),
3619 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3620 &error));
3621 EXPECT_EQ("", error);
3623 // The download should complete successfully.
3624 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3625 base::StringPrintf(
3626 "[{\"id\": %d,"
3627 " \"filename\": {"
3628 " \"previous\": \"\","
3629 " \"current\": \"%s\"}}]",
3630 result_id,
3631 GetFilename("42.txt").c_str())));
3632 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3633 base::StringPrintf(
3634 "[{\"id\": %d,"
3635 " \"state\": {"
3636 " \"previous\": \"in_progress\","
3637 " \"current\": \"complete\"}}]",
3638 result_id)));
3640 // Start an incognito download for comparison.
3641 GoOffTheRecord();
3642 result.reset(RunFunctionAndReturnResult(
3643 new DownloadsDownloadFunction(), base::StringPrintf(
3644 "[{\"url\": \"%s\"}]", download_url.c_str())));
3645 ASSERT_TRUE(result.get());
3646 result_id = -1;
3647 ASSERT_TRUE(result->GetAsInteger(&result_id));
3648 item = GetCurrentManager()->GetDownload(result_id);
3649 ASSERT_TRUE(item);
3650 ScopedCancellingItem canceller2(item);
3651 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3653 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3654 base::StringPrintf(
3655 "[{\"danger\": \"safe\","
3656 " \"incognito\": true,"
3657 " \"id\": %d,"
3658 " \"mime\": \"text/plain\","
3659 " \"paused\": false,"
3660 " \"url\": \"%s\"}]",
3661 result_id,
3662 download_url.c_str())));
3663 // On-Record renderers should not see events for off-record items.
3664 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3665 base::StringPrintf(
3666 "[{\"id\": %d,"
3667 " \"incognito\": true,"
3668 " \"filename\":\"slow.txt\"}]",
3669 result_id)));
3670 ASSERT_TRUE(item->GetTargetFilePath().empty());
3671 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3673 // Respond to the onDeterminingFilename.
3674 error = "";
3675 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3676 current_browser()->profile(),
3677 false,
3678 GetExtensionId(),
3679 result_id,
3680 base::FilePath(FILE_PATH_LITERAL("5.txt")),
3681 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3682 &error));
3683 EXPECT_EQ("", error);
3685 // The download should complete successfully.
3686 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3687 base::StringPrintf(
3688 "[{\"id\": %d,"
3689 " \"filename\": {"
3690 " \"previous\": \"\","
3691 " \"current\": \"%s\"}}]",
3692 result_id,
3693 GetFilename("5.txt").c_str())));
3694 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3695 base::StringPrintf(
3696 "[{\"id\": %d,"
3697 " \"state\": {"
3698 " \"previous\": \"in_progress\","
3699 " \"current\": \"complete\"}}]",
3700 result_id)));
3703 IN_PROC_BROWSER_TEST_F(
3704 DownloadExtensionTest,
3705 DownloadExtensionTest_OnDeterminingFilename_IncognitoSpanning) {
3706 LoadExtension("downloads_spanning");
3707 ASSERT_TRUE(StartEmbeddedTestServer());
3708 ASSERT_TRUE(test_server()->Start());
3709 std::string download_url = test_server()->GetURL("slow?0").spec();
3711 GoOnTheRecord();
3712 AddFilenameDeterminer();
3714 // There is a single extension renderer that sees both on-record and
3715 // off-record events. The extension functions see the on-record profile with
3716 // include_incognito=true.
3718 // Start an on-record download.
3719 GoOnTheRecord();
3720 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3721 new DownloadsDownloadFunction(), base::StringPrintf(
3722 "[{\"url\": \"%s\"}]", download_url.c_str())));
3723 ASSERT_TRUE(result.get());
3724 int result_id = -1;
3725 ASSERT_TRUE(result->GetAsInteger(&result_id));
3726 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3727 ASSERT_TRUE(item);
3728 ScopedCancellingItem canceller(item);
3729 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3731 // Wait for the onCreated and onDeterminingFilename events.
3732 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3733 base::StringPrintf(
3734 "[{\"danger\": \"safe\","
3735 " \"incognito\": false,"
3736 " \"id\": %d,"
3737 " \"mime\": \"text/plain\","
3738 " \"paused\": false,"
3739 " \"url\": \"%s\"}]",
3740 result_id,
3741 download_url.c_str())));
3742 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3743 base::StringPrintf(
3744 "[{\"id\": %d,"
3745 " \"incognito\": false,"
3746 " \"filename\":\"slow.txt\"}]",
3747 result_id)));
3748 ASSERT_TRUE(item->GetTargetFilePath().empty());
3749 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3751 // Respond to the onDeterminingFilename events.
3752 std::string error;
3753 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3754 current_browser()->profile(),
3755 true,
3756 GetExtensionId(),
3757 result_id,
3758 base::FilePath(FILE_PATH_LITERAL("42.txt")),
3759 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3760 &error));
3761 EXPECT_EQ("", error);
3763 // The download should complete successfully.
3764 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3765 base::StringPrintf(
3766 "[{\"id\": %d,"
3767 " \"filename\": {"
3768 " \"previous\": \"\","
3769 " \"current\": \"%s\"}}]",
3770 result_id,
3771 GetFilename("42.txt").c_str())));
3772 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3773 base::StringPrintf(
3774 "[{\"id\": %d,"
3775 " \"state\": {"
3776 " \"previous\": \"in_progress\","
3777 " \"current\": \"complete\"}}]",
3778 result_id)));
3780 // Start an incognito download for comparison.
3781 GoOffTheRecord();
3782 result.reset(RunFunctionAndReturnResult(
3783 new DownloadsDownloadFunction(), base::StringPrintf(
3784 "[{\"url\": \"%s\"}]", download_url.c_str())));
3785 ASSERT_TRUE(result.get());
3786 result_id = -1;
3787 ASSERT_TRUE(result->GetAsInteger(&result_id));
3788 item = GetCurrentManager()->GetDownload(result_id);
3789 ASSERT_TRUE(item);
3790 ScopedCancellingItem canceller2(item);
3791 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3793 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3794 base::StringPrintf(
3795 "[{\"danger\": \"safe\","
3796 " \"incognito\": true,"
3797 " \"id\": %d,"
3798 " \"mime\": \"text/plain\","
3799 " \"paused\": false,"
3800 " \"url\": \"%s\"}]",
3801 result_id,
3802 download_url.c_str())));
3803 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3804 base::StringPrintf(
3805 "[{\"id\": %d,"
3806 " \"incognito\": true,"
3807 " \"filename\":\"slow.txt\"}]",
3808 result_id)));
3809 ASSERT_TRUE(item->GetTargetFilePath().empty());
3810 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3812 // Respond to the onDeterminingFilename.
3813 error = "";
3814 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3815 current_browser()->profile(),
3816 true,
3817 GetExtensionId(),
3818 result_id,
3819 base::FilePath(FILE_PATH_LITERAL("42.txt")),
3820 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3821 &error));
3822 EXPECT_EQ("", error);
3824 // The download should complete successfully.
3825 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3826 base::StringPrintf(
3827 "[{\"id\": %d,"
3828 " \"filename\": {"
3829 " \"previous\": \"\","
3830 " \"current\": \"%s\"}}]",
3831 result_id,
3832 GetFilename("42 (1).txt").c_str())));
3833 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3834 base::StringPrintf(
3835 "[{\"id\": %d,"
3836 " \"state\": {"
3837 " \"previous\": \"in_progress\","
3838 " \"current\": \"complete\"}}]",
3839 result_id)));
3842 #if defined(OS_WIN)
3843 // This test is very flaky on Win XP and Aura. http://crbug.com/248438
3844 #define MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume \
3845 DISABLED_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume
3846 #else
3847 #define MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume \
3848 DownloadExtensionTest_OnDeterminingFilename_InterruptedResume
3849 #endif
3851 // Test download interruption while extensions determining filename. Should not
3852 // re-dispatch onDeterminingFilename.
3853 IN_PROC_BROWSER_TEST_F(
3854 DownloadExtensionTest,
3855 MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume) {
3856 base::CommandLine::ForCurrentProcess()->AppendSwitch(
3857 switches::kEnableDownloadResumption);
3858 LoadExtension("downloads_split");
3859 ASSERT_TRUE(StartEmbeddedTestServer());
3860 ASSERT_TRUE(test_server()->Start());
3861 GoOnTheRecord();
3862 content::RenderProcessHost* host = AddFilenameDeterminer();
3864 // Start a download.
3865 DownloadItem* item = NULL;
3867 DownloadManager* manager = GetCurrentManager();
3868 scoped_ptr<content::DownloadTestObserver> observer(
3869 new JustInProgressDownloadObserver(manager, 1));
3870 ASSERT_EQ(0, manager->InProgressCount());
3871 ASSERT_EQ(0, manager->NonMaliciousInProgressCount());
3872 // Tabs created just for a download are automatically closed, invalidating
3873 // the download's WebContents. Downloads without WebContents cannot be
3874 // resumed. http://crbug.com/225901
3875 ui_test_utils::NavigateToURLWithDisposition(
3876 current_browser(),
3877 GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl),
3878 CURRENT_TAB,
3879 ui_test_utils::BROWSER_TEST_NONE);
3880 observer->WaitForFinished();
3881 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
3882 DownloadManager::DownloadVector items;
3883 manager->GetAllDownloads(&items);
3884 for (DownloadManager::DownloadVector::iterator iter = items.begin();
3885 iter != items.end(); ++iter) {
3886 if ((*iter)->GetState() == DownloadItem::IN_PROGRESS) {
3887 // There should be only one IN_PROGRESS item.
3888 EXPECT_EQ(NULL, item);
3889 item = *iter;
3892 ASSERT_TRUE(item);
3894 ScopedCancellingItem canceller(item);
3896 // Wait for the onCreated and onDeterminingFilename event.
3897 ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName,
3898 base::StringPrintf(
3899 "[{\"danger\": \"safe\","
3900 " \"incognito\": false,"
3901 " \"id\": %d,"
3902 " \"mime\": \"application/octet-stream\","
3903 " \"paused\": false}]",
3904 item->GetId())));
3905 ASSERT_TRUE(WaitFor(downloads::OnDeterminingFilename::kEventName,
3906 base::StringPrintf(
3907 "[{\"id\": %d,"
3908 " \"incognito\": false,"
3909 " \"filename\":\"download-unknown-size\"}]",
3910 item->GetId())));
3911 ASSERT_TRUE(item->GetTargetFilePath().empty());
3912 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
3914 ClearEvents();
3915 ui_test_utils::NavigateToURLWithDisposition(
3916 current_browser(),
3917 GURL(net::URLRequestSlowDownloadJob::kErrorDownloadUrl),
3918 NEW_BACKGROUND_TAB,
3919 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
3921 // Errors caught before filename determination are delayed until after
3922 // filename determination.
3923 std::string error;
3924 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3925 current_browser()->profile(),
3926 false,
3927 GetExtensionId(),
3928 item->GetId(),
3929 base::FilePath(FILE_PATH_LITERAL("42.txt")),
3930 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY,
3931 &error))
3932 << error;
3933 EXPECT_EQ("", error);
3934 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3935 base::StringPrintf(
3936 "[{\"id\": %d,"
3937 " \"filename\": {"
3938 " \"previous\": \"\","
3939 " \"current\": \"%s\"}}]",
3940 item->GetId(),
3941 GetFilename("42.txt").c_str())));
3943 content::DownloadUpdatedObserver interrupted(item, base::Bind(
3944 ItemIsInterrupted));
3945 ASSERT_TRUE(interrupted.WaitForEvent());
3946 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3947 base::StringPrintf(
3948 "[{\"id\": %d,"
3949 " \"error\":{\"current\":\"NETWORK_FAILED\"},"
3950 " \"state\":{"
3951 " \"previous\":\"in_progress\","
3952 " \"current\":\"interrupted\"}}]",
3953 item->GetId())));
3955 ClearEvents();
3956 // Downloads that are restarted on resumption trigger another download target
3957 // determination.
3958 RemoveFilenameDeterminer(host);
3959 item->Resume();
3961 // Errors caught before filename determination is complete are delayed until
3962 // after filename determination so that, on resumption, filename determination
3963 // does not need to be re-done. So, there will not be a second
3964 // onDeterminingFilename event.
3966 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3967 base::StringPrintf(
3968 "[{\"id\": %d,"
3969 " \"error\":{\"previous\":\"NETWORK_FAILED\"},"
3970 " \"state\":{"
3971 " \"previous\":\"interrupted\","
3972 " \"current\":\"in_progress\"}}]",
3973 item->GetId())));
3975 ClearEvents();
3976 FinishPendingSlowDownloads();
3978 // The download should complete successfully.
3979 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
3980 base::StringPrintf(
3981 "[{\"id\": %d,"
3982 " \"state\": {"
3983 " \"previous\": \"in_progress\","
3984 " \"current\": \"complete\"}}]",
3985 item->GetId())));
3988 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
3989 DownloadExtensionTest_SetShelfEnabled) {
3990 LoadExtension("downloads_split");
3991 EXPECT_TRUE(RunFunction(new DownloadsSetShelfEnabledFunction(), "[false]"));
3992 EXPECT_FALSE(DownloadServiceFactory::GetForBrowserContext(
3993 browser()->profile())->IsShelfEnabled());
3994 EXPECT_TRUE(RunFunction(new DownloadsSetShelfEnabledFunction(), "[true]"));
3995 EXPECT_TRUE(DownloadServiceFactory::GetForBrowserContext(
3996 browser()->profile())->IsShelfEnabled());
3997 // TODO(benjhayden) Test that existing shelves are hidden.
3998 // TODO(benjhayden) Test multiple extensions.
3999 // TODO(benjhayden) Test disabling extensions.
4000 // TODO(benjhayden) Test that browsers associated with other profiles are not
4001 // affected.
4002 // TODO(benjhayden) Test incognito.
4005 // TODO(benjhayden) Figure out why DisableExtension() does not fire
4006 // OnListenerRemoved.
4008 // TODO(benjhayden) Test that the shelf is shown for download() both with and
4009 // without a WebContents.
4011 void OnDangerPromptCreated(DownloadDangerPrompt* prompt) {
4012 prompt->InvokeActionForTesting(DownloadDangerPrompt::ACCEPT);
4015 #if defined(OS_MACOSX)
4016 // Flakily triggers and assert on Mac.
4017 // http://crbug.com/180759
4018 #define MAYBE_DownloadExtensionTest_AcceptDanger DISABLED_DownloadExtensionTest_AcceptDanger
4019 #else
4020 #define MAYBE_DownloadExtensionTest_AcceptDanger DownloadExtensionTest_AcceptDanger
4021 #endif
4022 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
4023 MAYBE_DownloadExtensionTest_AcceptDanger) {
4024 // Download a file that will be marked dangerous; click the browser action
4025 // button; the browser action poup will call acceptDanger(); when the
4026 // DownloadDangerPrompt is created, pretend that the user clicks the Accept
4027 // button; wait until the download completes.
4028 LoadExtension("downloads_split");
4029 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
4030 new DownloadsDownloadFunction(),
4031 "[{\"url\": \"data:,\", \"filename\": \"dangerous.swf\"}]"));
4032 ASSERT_TRUE(result.get());
4033 int result_id = -1;
4034 ASSERT_TRUE(result->GetAsInteger(&result_id));
4035 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
4036 ASSERT_TRUE(item);
4037 ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
4038 base::StringPrintf(
4039 "[{\"id\": %d, "
4040 " \"danger\": {"
4041 " \"previous\": \"safe\","
4042 " \"current\": \"file\"}}]",
4043 result_id)));
4044 ASSERT_TRUE(item->IsDangerous());
4045 ScopedCancellingItem canceller(item);
4046 scoped_ptr<content::DownloadTestObserver> observer(
4047 new content::DownloadTestObserverTerminal(
4048 GetCurrentManager(), 1,
4049 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_IGNORE));
4050 DownloadsAcceptDangerFunction::OnPromptCreatedCallback callback =
4051 base::Bind(&OnDangerPromptCreated);
4052 DownloadsAcceptDangerFunction::OnPromptCreatedForTesting(
4053 &callback);
4054 BrowserActionTestUtil(browser()).Press(0);
4055 observer->WaitForFinished();
4058 class DownloadsApiTest : public ExtensionApiTest {
4059 public:
4060 DownloadsApiTest() {}
4061 ~DownloadsApiTest() override {}
4063 private:
4064 DISALLOW_COPY_AND_ASSIGN(DownloadsApiTest);
4068 IN_PROC_BROWSER_TEST_F(DownloadsApiTest, DownloadsApiTest) {
4069 ASSERT_TRUE(RunExtensionTest("downloads")) << message_;
4072 TEST(DownloadInterruptReasonEnumsSynced,
4073 DownloadInterruptReasonEnumsSynced) {
4074 #define INTERRUPT_REASON(name, value) \
4075 EXPECT_EQ(InterruptReasonContentToExtension( \
4076 content::DOWNLOAD_INTERRUPT_REASON_##name), \
4077 downloads::INTERRUPT_REASON_##name); \
4078 EXPECT_EQ( \
4079 InterruptReasonExtensionToContent(downloads::INTERRUPT_REASON_##name), \
4080 content::DOWNLOAD_INTERRUPT_REASON_##name);
4081 #include "content/public/browser/download_interrupt_reason_values.h" // NOLINT
4082 #undef INTERRUPT_REASON
4085 TEST(ExtensionDetermineDownloadFilenameInternal,
4086 ExtensionDetermineDownloadFilenameInternal) {
4087 std::string winner_id;
4088 base::FilePath filename;
4089 downloads::FilenameConflictAction conflict_action =
4090 downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY;
4091 WarningSet warnings;
4093 // Empty incumbent determiner
4094 warnings.clear();
4095 ExtensionDownloadsEventRouter::DetermineFilenameInternal(
4096 base::FilePath(FILE_PATH_LITERAL("a")),
4097 downloads::FILENAME_CONFLICT_ACTION_OVERWRITE,
4098 "suggester",
4099 base::Time::Now(),
4101 base::Time(),
4102 &winner_id,
4103 &filename,
4104 &conflict_action,
4105 &warnings);
4106 EXPECT_EQ("suggester", winner_id);
4107 EXPECT_EQ(FILE_PATH_LITERAL("a"), filename.value());
4108 EXPECT_EQ(downloads::FILENAME_CONFLICT_ACTION_OVERWRITE, conflict_action);
4109 EXPECT_TRUE(warnings.empty());
4111 // Incumbent wins
4112 warnings.clear();
4113 ExtensionDownloadsEventRouter::DetermineFilenameInternal(
4114 base::FilePath(FILE_PATH_LITERAL("b")),
4115 downloads::FILENAME_CONFLICT_ACTION_PROMPT,
4116 "suggester",
4117 base::Time::Now() - base::TimeDelta::FromDays(1),
4118 "incumbent",
4119 base::Time::Now(),
4120 &winner_id,
4121 &filename,
4122 &conflict_action,
4123 &warnings);
4124 EXPECT_EQ("incumbent", winner_id);
4125 EXPECT_EQ(FILE_PATH_LITERAL("a"), filename.value());
4126 EXPECT_EQ(downloads::FILENAME_CONFLICT_ACTION_OVERWRITE, conflict_action);
4127 EXPECT_FALSE(warnings.empty());
4128 EXPECT_EQ(Warning::kDownloadFilenameConflict,
4129 warnings.begin()->warning_type());
4130 EXPECT_EQ("suggester", warnings.begin()->extension_id());
4132 // Suggester wins
4133 warnings.clear();
4134 ExtensionDownloadsEventRouter::DetermineFilenameInternal(
4135 base::FilePath(FILE_PATH_LITERAL("b")),
4136 downloads::FILENAME_CONFLICT_ACTION_PROMPT,
4137 "suggester",
4138 base::Time::Now(),
4139 "incumbent",
4140 base::Time::Now() - base::TimeDelta::FromDays(1),
4141 &winner_id,
4142 &filename,
4143 &conflict_action,
4144 &warnings);
4145 EXPECT_EQ("suggester", winner_id);
4146 EXPECT_EQ(FILE_PATH_LITERAL("b"), filename.value());
4147 EXPECT_EQ(downloads::FILENAME_CONFLICT_ACTION_PROMPT, conflict_action);
4148 EXPECT_FALSE(warnings.empty());
4149 EXPECT_EQ(Warning::kDownloadFilenameConflict,
4150 warnings.begin()->warning_type());
4151 EXPECT_EQ("incumbent", warnings.begin()->extension_id());
4154 } // namespace extensions
4156 #endif // http://crbug.com/3061144