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