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