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