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