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