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