• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
operator ()extensions::__anon6d19bd0c0111::DownloadIdComparator74   bool operator() (DownloadItem* first, DownloadItem* second) {
75     return first->GetId() < second->GetId();
76   }
77 };
78 
79 class DownloadsEventsListener : public content::NotificationObserver {
80  public:
DownloadsEventsListener()81   DownloadsEventsListener()
82     : waiting_(false) {
83     registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT,
84                    content::NotificationService::AllSources());
85   }
86 
~DownloadsEventsListener()87   virtual ~DownloadsEventsListener() {
88     registrar_.Remove(this, chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT,
89                       content::NotificationService::AllSources());
90     STLDeleteElements(&events_);
91   }
92 
ClearEvents()93   void ClearEvents() {
94     STLDeleteElements(&events_);
95     events_.clear();
96   }
97 
98   class Event {
99    public:
Event(Profile * profile,const std::string & event_name,const std::string & json_args,base::Time caught)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 
caught()111     const base::Time& caught() { return caught_; }
112 
Satisfies(const Event & other) const113     bool Satisfies(const Event& other) const {
114       return other.SatisfiedBy(*this);
115     }
116 
SatisfiedBy(const Event & other) const117     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 
Debug()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 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)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 
WaitFor(Profile * profile,const std::string & event_name,const std::string & json_args)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:
DownloadExtensionTest()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 
LoadExtension(const char * name)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 
AddFilenameDeterminer()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 
RemoveFilenameDeterminer(content::RenderProcessHost * host)306   void RemoveFilenameDeterminer(content::RenderProcessHost* host) {
307     EventRouter::Get(current_browser()->profile())->RemoveEventListener(
308         downloads::OnDeterminingFilename::kEventName, host, GetExtensionId());
309   }
310 
current_browser()311   Browser* current_browser() { return current_browser_; }
312 
313   // InProcessBrowserTest
SetUpOnMainThread()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 
GoOnTheRecord()331   void GoOnTheRecord() { current_browser_ = browser(); }
332 
GoOffTheRecord()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 
WaitFor(const std::string & event_name,const std::string & json_args)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 
WaitForInterruption(DownloadItem * item,content::DownloadInterruptReason expected_error,const std::string & on_created_event)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 
ClearEvents()368   void ClearEvents() {
369     events_listener_->ClearEvents();
370   }
371 
GetExtensionURL()372   std::string GetExtensionURL() {
373     return extension_->url().spec();
374   }
GetExtensionId()375   std::string GetExtensionId() {
376     return extension_->id();
377   }
378 
GetFilename(const char * path)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 
GetOnRecordManager()393   DownloadManager* GetOnRecordManager() {
394     return BrowserContext::GetDownloadManager(browser()->profile());
395   }
GetOffRecordManager()396   DownloadManager* GetOffRecordManager() {
397     return BrowserContext::GetDownloadManager(
398         browser()->profile()->GetOffTheRecordProfile());
399   }
GetCurrentManager()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.
CreateHistoryDownloads(const HistoryDownloadInfo * history_info,size_t count,DownloadManager::DownloadVector * items)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 
CreateSlowTestDownloads(size_t count,DownloadManager::DownloadVector * items)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 
CreateSlowTestDownload()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 
FinishPendingSlowDownloads()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 
CreateDownloadObserver(size_t download_count)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 
CreateInProgressDownloadObserver(size_t download_count)517   content::DownloadTestObserver* CreateInProgressDownloadObserver(
518       size_t download_count) {
519     return new content::DownloadTestObserverInProgress(
520         GetCurrentManager(), download_count);
521   }
522 
RunFunction(UIThreadExtensionFunction * function,const std::string & args)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 
GetFlags()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 
RunFunctionAndReturnResult(scoped_refptr<UIThreadExtensionFunction> function,const std::string & args)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 
RunFunctionAndReturnError(scoped_refptr<UIThreadExtensionFunction> function,const std::string & args)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 
RunFunctionAndReturnString(scoped_refptr<UIThreadExtensionFunction> function,const std::string & args,std::string * result_string)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 
DownloadItemIdAsArgList(const DownloadItem * download_item)571   std::string DownloadItemIdAsArgList(const DownloadItem* download_item) {
572     return base::StringPrintf("[%d]", download_item->GetId());
573   }
574 
downloads_directory()575   const base::FilePath& downloads_directory() {
576     return downloads_directory_.path();
577   }
578 
events_listener()579   DownloadsEventsListener* events_listener() { return events_listener_.get(); }
580 
581  private:
SetUpExtensionFunction(UIThreadExtensionFunction * function)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 
CreateAndSetDownloadsDirectory()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:
MockIconExtractorImpl(const base::FilePath & path,IconLoader::IconSize icon_size,const std::string & response)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   }
~MockIconExtractorImpl()619   virtual ~MockIconExtractorImpl() {}
620 
ExtractIconURLForPath(const base::FilePath & path,float scale,IconLoader::IconSize icon_size,IconURLCallback callback)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:
RunCallback()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 
ItemNotInProgress(DownloadItem * item)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:
ScopedCancellingItem(DownloadItem * item)661   explicit ScopedCancellingItem(DownloadItem* item) : item_(item) {}
~ScopedCancellingItem()662   ~ScopedCancellingItem() {
663     item_->Cancel(true);
664     content::DownloadUpdatedObserver observer(
665         item_, base::Bind(&ItemNotInProgress));
666     observer.WaitForEvent();
667   }
get()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:
ScopedItemVectorCanceller(DownloadManager::DownloadVector * items)679   explicit ScopedItemVectorCanceller(DownloadManager::DownloadVector* items)
680     : items_(items) {
681   }
~ScopedItemVectorCanceller()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:
CreateFileForTesting(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & path,const char * data,int length)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:
CopyInCompletion(bool * result,base::WaitableEvent * done_event,base::File::Error error)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 
CreateFileForTestingOnIOThread(fileapi::FileSystemContext * context,const fileapi::FileSystemURL & path,const base::FilePath & temp_file,bool * result,base::WaitableEvent * done_event)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:
JustInProgressDownloadObserver(DownloadManager * download_manager,size_t wait_count)755   JustInProgressDownloadObserver(
756       DownloadManager* download_manager, size_t wait_count)
757       : content::DownloadTestObserverInProgress(download_manager, wait_count) {
758   }
759 
~JustInProgressDownloadObserver()760   virtual ~JustInProgressDownloadObserver() {}
761 
762  private:
IsDownloadInFinalState(DownloadItem * item)763   virtual bool IsDownloadInFinalState(DownloadItem* item) OVERRIDE {
764     return item->GetState() == DownloadItem::IN_PROGRESS;
765   }
766 
767   DISALLOW_COPY_AND_ASSIGN(JustInProgressDownloadObserver);
768 };
769 
ItemIsInterrupted(DownloadItem * item)770 bool ItemIsInterrupted(DownloadItem* item) {
771   return item->GetState() == DownloadItem::INTERRUPTED;
772 }
773 
InterruptReasonExtensionToContent(downloads::InterruptReason error)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 
InterruptReasonContentToExtension(content::DownloadInterruptReason error)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Open)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_PauseResumeCancelErase)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 
MockedGetFileIconFunction(const base::FilePath & expected_path,IconLoader::IconSize icon_size,const std::string & response)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_FileIcon_Active)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_FileIcon_History)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().
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchEmptyQuery)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().
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchFilenameRegex)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().
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchId)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().
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchIdAndFilename)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().
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchOrderBy)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().
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchOrderByEmpty)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().
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchDanger)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().
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchState)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().
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchLimit)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchInvalid)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchPlural)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_Basic)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,MAYBE_DownloadExtensionTest_Download_UnsafeHeaders)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
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,MAYBE_DownloadExtensionTest_Download_Subdirectory)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_InvalidFilename)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_InvalidURLs)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_URLFragment)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_ConflictAction)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_DataURL)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
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,MAYBE_DownloadExtensionTest_Download_File)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_AuthBasic_Fail)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_Headers)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_Headers_Fail)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_AuthBasic)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_Post)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_Post_Get)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_Post_NoBody)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_Cancel)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_Download_FileSystemURL)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_NoChange)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DISABLED_DownloadExtensionTest_OnDeterminingFilename_Timeout)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_Twice)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_DangerousOverride)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_ReferencesParentInvalid)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_IllegalFilename)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_IllegalFilenameExtension)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
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,MAYBE_DownloadExtensionTest_OnDeterminingFilename_ReservedFilename)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_CurDirInvalid)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_ParentDirInvalid)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_AbsPathInvalid)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_EmptyBasenameInvalid)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_Overwrite)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_Override)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_RemoveFilenameDeterminer)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_IncognitoSplit)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_OnDeterminingFilename_IncognitoSpanning)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.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume)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 
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,DownloadExtensionTest_SetShelfEnabled)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 
OnDangerPromptCreated(DownloadDangerPrompt * prompt)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
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,MAYBE_DownloadExtensionTest_AcceptDanger)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:
DownloadsApiTest()4007   DownloadsApiTest() {}
~DownloadsApiTest()4008   virtual ~DownloadsApiTest() {}
4009  private:
4010   DISALLOW_COPY_AND_ASSIGN(DownloadsApiTest);
4011 };
4012 
4013 
IN_PROC_BROWSER_TEST_F(DownloadsApiTest,DownloadsApiTest)4014 IN_PROC_BROWSER_TEST_F(DownloadsApiTest, DownloadsApiTest) {
4015   ASSERT_TRUE(RunExtensionTest("downloads")) << message_;
4016 }
4017 
TEST(DownloadInterruptReasonEnumsSynced,DownloadInterruptReasonEnumsSynced)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 
TEST(ExtensionDetermineDownloadFilenameInternal,ExtensionDetermineDownloadFilenameInternal)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