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