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