blob: 82a5f6fce93d5cf57a41ff68088226ce373b3718 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <algorithm>
6
7#include "base/file_util.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008#include "base/files/scoped_temp_dir.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009#include "base/json/json_reader.h"
Ben Murdoch9ab55632013-07-18 11:57:30 +010010#include "base/message_loop/message_loop.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000011#include "base/prefs/pref_service.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#include "base/stl_util.h"
Torne (Richard Coles)5e3f23d2013-06-11 16:24:11 +010013#include "base/strings/stringprintf.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010014#include "base/synchronization/waitable_event.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010015#include "chrome/browser/chrome_notification_types.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000016#include "chrome/browser/download/download_file_icon_extractor.h"
17#include "chrome/browser/download/download_service.h"
18#include "chrome/browser/download/download_service_factory.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000019#include "chrome/browser/download/download_test_file_activity_observer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000020#include "chrome/browser/extensions/api/downloads/downloads_api.h"
21#include "chrome/browser/extensions/event_names.h"
22#include "chrome/browser/extensions/extension_apitest.h"
23#include "chrome/browser/extensions/extension_function_test_utils.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000024#include "chrome/browser/extensions/extension_service.h"
25#include "chrome/browser/history/download_row.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000026#include "chrome/browser/net/url_request_mock_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000027#include "chrome/browser/profiles/profile.h"
28#include "chrome/browser/ui/browser.h"
29#include "chrome/browser/ui/browser_tabstrip.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000030#include "chrome/common/pref_names.h"
31#include "chrome/test/base/in_process_browser_test.h"
32#include "chrome/test/base/ui_test_utils.h"
33#include "content/public/browser/browser_context.h"
34#include "content/public/browser/browser_thread.h"
35#include "content/public/browser/download_item.h"
36#include "content/public/browser/download_manager.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000037#include "content/public/browser/notification_service.h"
38#include "content/public/browser/storage_partition.h"
39#include "content/public/browser/web_contents.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010040#include "content/public/common/content_switches.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000041#include "content/public/common/page_transition_types.h"
42#include "content/public/test/download_test_observer.h"
43#include "content/test/net/url_request_slow_download_job.h"
44#include "net/base/data_url.h"
45#include "net/base/net_util.h"
46#include "net/url_request/url_request.h"
47#include "net/url_request/url_request_context.h"
48#include "net/url_request/url_request_job.h"
49#include "net/url_request/url_request_job_factory.h"
50#include "net/url_request/url_request_job_factory_impl.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010051#include "webkit/browser/fileapi/file_system_context.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010052#include "webkit/browser/fileapi/file_system_operation_runner.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010053#include "webkit/browser/fileapi/file_system_url.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000054
55using content::BrowserContext;
56using content::BrowserThread;
57using content::DownloadItem;
58using content::DownloadManager;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000059using content::URLRequestSlowDownloadJob;
60
61namespace events = extensions::event_names;
62
Ben Murdoch558790d2013-07-30 15:19:42 +010063namespace errors = download_extension_errors;
64
65namespace api = extensions::api::downloads;
66
Torne (Richard Coles)58218062012-11-14 11:43:16 +000067namespace {
68
69// Comparator that orders download items by their ID. Can be used with
70// std::sort.
71struct DownloadIdComparator {
72 bool operator() (DownloadItem* first, DownloadItem* second) {
73 return first->GetId() < second->GetId();
74 }
75};
76
77class DownloadsEventsListener : public content::NotificationObserver {
78 public:
79 DownloadsEventsListener()
80 : waiting_(false) {
81 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT,
82 content::NotificationService::AllSources());
83 }
84
85 virtual ~DownloadsEventsListener() {
86 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT,
87 content::NotificationService::AllSources());
88 STLDeleteElements(&events_);
89 }
90
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010091 void ClearEvents() {
92 STLDeleteElements(&events_);
93 events_.clear();
94 }
95
Torne (Richard Coles)58218062012-11-14 11:43:16 +000096 class Event {
97 public:
98 Event(Profile* profile,
99 const std::string& event_name,
100 const std::string& json_args,
101 base::Time caught)
102 : profile_(profile),
103 event_name_(event_name),
104 json_args_(json_args),
105 args_(base::JSONReader::Read(json_args)),
106 caught_(caught) {
107 }
108
109 const base::Time& caught() { return caught_; }
110
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100111 bool Satisfies(const Event& other) const {
112 return other.SatisfiedBy(*this);
113 }
114
115 bool SatisfiedBy(const Event& other) const {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000116 if ((profile_ != other.profile_) ||
117 (event_name_ != other.event_name_))
118 return false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000119 if (((event_name_ == events::kOnDownloadDeterminingFilename) ||
120 (event_name_ == events::kOnDownloadCreated) ||
121 (event_name_ == events::kOnDownloadChanged)) &&
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000122 args_.get() &&
123 other.args_.get()) {
124 base::ListValue* left_list = NULL;
125 base::DictionaryValue* left_dict = NULL;
126 base::ListValue* right_list = NULL;
127 base::DictionaryValue* right_dict = NULL;
128 if (!args_->GetAsList(&left_list) ||
129 !other.args_->GetAsList(&right_list) ||
130 !left_list->GetDictionary(0, &left_dict) ||
131 !right_list->GetDictionary(0, &right_dict))
132 return false;
133 for (base::DictionaryValue::Iterator iter(*left_dict);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100134 !iter.IsAtEnd(); iter.Advance()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000135 base::Value* right_value = NULL;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100136 if (!right_dict->HasKey(iter.key()) ||
137 (right_dict->Get(iter.key(), &right_value) &&
138 !iter.value().Equals(right_value))) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000139 return false;
140 }
141 }
142 return true;
143 } else if ((event_name_ == events::kOnDownloadErased) &&
144 args_.get() &&
145 other.args_.get()) {
146 int my_id = -1, other_id = -1;
147 return (args_->GetAsInteger(&my_id) &&
148 other.args_->GetAsInteger(&other_id) &&
149 my_id == other_id);
150 }
151 return json_args_ == other.json_args_;
152 }
153
154 std::string Debug() {
155 return base::StringPrintf("Event(%p, %s, %s, %f)",
156 profile_,
157 event_name_.c_str(),
158 json_args_.c_str(),
159 caught_.ToJsTime());
160 }
161
162 private:
163 Profile* profile_;
164 std::string event_name_;
165 std::string json_args_;
166 scoped_ptr<base::Value> args_;
167 base::Time caught_;
168
169 DISALLOW_COPY_AND_ASSIGN(Event);
170 };
171
172 typedef ExtensionDownloadsEventRouter::DownloadsNotificationSource
173 DownloadsNotificationSource;
174
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000175 virtual void Observe(int type,
176 const content::NotificationSource& source,
177 const content::NotificationDetails& details) OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000178 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() &&
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100190 new_event->Satisfies(*waiting_for_)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000191 waiting_ = false;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100192 base::MessageLoopForUI::current()->Quit();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000193 }
194 break;
195 }
196 default:
197 NOTREACHED();
198 }
199 }
200
201 bool WaitFor(Profile* profile,
202 const std::string& event_name,
203 const std::string& json_args) {
204 waiting_for_.reset(new Event(profile, event_name, json_args, base::Time()));
205 for (std::deque<Event*>::const_iterator iter = events_.begin();
206 iter != events_.end(); ++iter) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100207 if ((*iter)->Satisfies(*waiting_for_.get())) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000208 return true;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100209 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000210 }
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:
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000235 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
244class DownloadExtensionTest : public ExtensionApiTest {
245 public:
246 DownloadExtensionTest()
247 : extension_(NULL),
248 incognito_browser_(NULL),
249 current_browser_(NULL) {
250 }
251
252 protected:
253 // Used with CreateHistoryDownloads
254 struct HistoryDownloadInfo {
255 // Filename to use. CreateHistoryDownloads will append this filename to the
256 // temporary downloads directory specified by downloads_directory().
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000257 const base::FilePath::CharType* filename;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000258
259 // State for the download. Note that IN_PROGRESS downloads will be created
260 // as CANCELLED.
261 DownloadItem::DownloadState state;
262
263 // Danger type for the download. Only use DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
264 // and DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT.
265 content::DownloadDangerType danger_type;
266 };
267
268 void LoadExtension(const char* name) {
269 // Store the created Extension object so that we can attach it to
270 // ExtensionFunctions. Also load the extension in incognito profiles for
271 // testing incognito.
272 extension_ = LoadExtensionIncognito(test_data_dir_.AppendASCII(name));
273 CHECK(extension_);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100274 content::WebContents* tab = chrome::AddSelectedTabWithURL(
275 current_browser(),
276 extension_->GetResourceURL("empty.html"),
277 content::PAGE_TRANSITION_LINK);
278 extensions::ExtensionSystem::Get(current_browser()->profile())->
279 event_router()->AddEventListener(
280 extensions::event_names::kOnDownloadCreated,
281 tab->GetRenderProcessHost(),
282 GetExtensionId());
283 extensions::ExtensionSystem::Get(current_browser()->profile())->
284 event_router()->AddEventListener(
285 extensions::event_names::kOnDownloadChanged,
286 tab->GetRenderProcessHost(),
287 GetExtensionId());
288 extensions::ExtensionSystem::Get(current_browser()->profile())->
289 event_router()->AddEventListener(
290 extensions::event_names::kOnDownloadErased,
291 tab->GetRenderProcessHost(),
292 GetExtensionId());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000293 }
294
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000295 content::RenderProcessHost* AddFilenameDeterminer() {
296 content::WebContents* tab = chrome::AddSelectedTabWithURL(
297 current_browser(),
298 extension_->GetResourceURL("empty.html"),
299 content::PAGE_TRANSITION_LINK);
300 extensions::ExtensionSystem::Get(current_browser()->profile())->
301 event_router()->AddEventListener(
302 extensions::event_names::kOnDownloadDeterminingFilename,
303 tab->GetRenderProcessHost(),
304 GetExtensionId());
305 return tab->GetRenderProcessHost();
306 }
307
308 void RemoveFilenameDeterminer(content::RenderProcessHost* host) {
309 extensions::ExtensionSystem::Get(current_browser()->profile())->
310 event_router()->RemoveEventListener(
311 extensions::event_names::kOnDownloadDeterminingFilename,
312 host,
313 GetExtensionId());
314 }
315
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000316 Browser* current_browser() { return current_browser_; }
317
318 // InProcessBrowserTest
319 virtual void SetUpOnMainThread() OVERRIDE {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100320 ExtensionApiTest::SetUpOnMainThread();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000321 BrowserThread::PostTask(
322 BrowserThread::IO, FROM_HERE,
323 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
324 InProcessBrowserTest::SetUpOnMainThread();
325 GoOnTheRecord();
326 CreateAndSetDownloadsDirectory();
327 current_browser()->profile()->GetPrefs()->SetBoolean(
328 prefs::kPromptForDownload, false);
329 GetOnRecordManager()->RemoveAllDownloads();
330 events_listener_.reset(new DownloadsEventsListener());
331 // Disable file chooser for current profile.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000332 DownloadTestFileActivityObserver observer(current_browser()->profile());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000333 observer.EnableFileChooser(false);
334 }
335
336 void GoOnTheRecord() { current_browser_ = browser(); }
337
338 void GoOffTheRecord() {
339 if (!incognito_browser_) {
340 incognito_browser_ = CreateIncognitoBrowser();
341 GetOffRecordManager()->RemoveAllDownloads();
342 // Disable file chooser for incognito profile.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000343 DownloadTestFileActivityObserver observer(incognito_browser_->profile());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000344 observer.EnableFileChooser(false);
345 }
346 current_browser_ = incognito_browser_;
347 }
348
349 bool WaitFor(const std::string& event_name, const std::string& json_args) {
350 return events_listener_->WaitFor(
351 current_browser()->profile(), event_name, json_args);
352 }
353
Ben Murdoch558790d2013-07-30 15:19:42 +0100354 bool WaitForInterruption(
355 DownloadItem* item,
356 content::DownloadInterruptReason expected_error,
357 const std::string& on_created_event) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000358 if (!WaitFor(events::kOnDownloadCreated, on_created_event))
359 return false;
360 // Now, onCreated is always fired before interruption.
361 return WaitFor(events::kOnDownloadChanged,
362 base::StringPrintf("[{\"id\": %d,"
Ben Murdoch558790d2013-07-30 15:19:42 +0100363 " \"error\": {\"current\": \"%s\"},"
364 " \"state\": {"
365 " \"previous\": \"in_progress\","
366 " \"current\": \"interrupted\"}}]",
367 item->GetId(),
368 content::InterruptReasonDebugString(
369 expected_error).c_str()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000370 }
371
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100372 void ClearEvents() {
373 events_listener_->ClearEvents();
374 }
375
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000376 std::string GetExtensionURL() {
377 return extension_->url().spec();
378 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000379 std::string GetExtensionId() {
380 return extension_->id();
381 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000382
383 std::string GetFilename(const char* path) {
384 std::string result =
385 downloads_directory_.path().AppendASCII(path).AsUTF8Unsafe();
386#if defined(OS_WIN)
387 for (std::string::size_type next = result.find("\\");
388 next != std::string::npos;
389 next = result.find("\\", next)) {
390 result.replace(next, 1, "\\\\");
391 next += 2;
392 }
393#endif
394 return result;
395 }
396
397 DownloadManager* GetOnRecordManager() {
398 return BrowserContext::GetDownloadManager(browser()->profile());
399 }
400 DownloadManager* GetOffRecordManager() {
401 return BrowserContext::GetDownloadManager(
402 browser()->profile()->GetOffTheRecordProfile());
403 }
404 DownloadManager* GetCurrentManager() {
405 return (current_browser_ == incognito_browser_) ?
406 GetOffRecordManager() : GetOnRecordManager();
407 }
408
409 // Creates a set of history downloads based on the provided |history_info|
410 // array. |count| is the number of elements in |history_info|. On success,
411 // |items| will contain |count| DownloadItems in the order that they were
412 // specified in |history_info|. Returns true on success and false otherwise.
413 bool CreateHistoryDownloads(const HistoryDownloadInfo* history_info,
414 size_t count,
415 DownloadManager::DownloadVector* items) {
416 DownloadIdComparator download_id_comparator;
417 base::Time current = base::Time::Now();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000418 items->clear();
419 GetOnRecordManager()->GetAllDownloads(items);
420 CHECK_EQ(0, static_cast<int>(items->size()));
421 std::vector<GURL> url_chain;
422 url_chain.push_back(GURL());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000423 for (size_t i = 0; i < count; ++i) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000424 DownloadItem* item = GetOnRecordManager()->CreateDownloadItem(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100425 content::DownloadItem::kInvalidId + 1 + i,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000426 downloads_directory().Append(history_info[i].filename),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000427 downloads_directory().Append(history_info[i].filename),
428 url_chain, GURL(), // URL Chain, referrer
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000429 current, current, // start_time, end_time
430 1, 1, // received_bytes, total_bytes
431 history_info[i].state, // state
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000432 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
433 content::DOWNLOAD_INTERRUPT_REASON_NONE,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000434 false); // opened
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000435 items->push_back(item);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000436 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000437
438 // Order by ID so that they are in the order that we created them.
439 std::sort(items->begin(), items->end(), download_id_comparator);
440 // Set the danger type if necessary.
441 for (size_t i = 0; i < count; ++i) {
442 if (history_info[i].danger_type !=
443 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
444 EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT,
445 history_info[i].danger_type);
446 items->at(i)->OnContentCheckCompleted(history_info[i].danger_type);
447 }
448 }
449 return true;
450 }
451
452 void CreateSlowTestDownloads(
453 size_t count, DownloadManager::DownloadVector* items) {
454 for (size_t i = 0; i < count; ++i) {
455 scoped_ptr<content::DownloadTestObserver> observer(
456 CreateInProgressDownloadObserver(1));
457 GURL slow_download_url(URLRequestSlowDownloadJob::kUnknownSizeUrl);
458 ui_test_utils::NavigateToURLWithDisposition(
459 current_browser(), slow_download_url, CURRENT_TAB,
460 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
461 observer->WaitForFinished();
462 EXPECT_EQ(
463 1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
464 }
465 GetCurrentManager()->GetAllDownloads(items);
466 ASSERT_EQ(count, items->size());
467 }
468
469 DownloadItem* CreateSlowTestDownload() {
470 scoped_ptr<content::DownloadTestObserver> observer(
471 CreateInProgressDownloadObserver(1));
472 GURL slow_download_url(URLRequestSlowDownloadJob::kUnknownSizeUrl);
473 DownloadManager* manager = GetCurrentManager();
474
475 EXPECT_EQ(0, manager->InProgressCount());
476 if (manager->InProgressCount() != 0)
477 return NULL;
478
479 ui_test_utils::NavigateToURLWithDisposition(
480 current_browser(), slow_download_url, CURRENT_TAB,
481 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
482
483 observer->WaitForFinished();
484 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
485
486 DownloadManager::DownloadVector items;
487 manager->GetAllDownloads(&items);
488
489 DownloadItem* new_item = NULL;
490 for (DownloadManager::DownloadVector::iterator iter = items.begin();
491 iter != items.end(); ++iter) {
492 if ((*iter)->GetState() == DownloadItem::IN_PROGRESS) {
493 // There should be only one IN_PROGRESS item.
494 EXPECT_EQ(NULL, new_item);
495 new_item = *iter;
496 }
497 }
498 return new_item;
499 }
500
501 void FinishPendingSlowDownloads() {
502 scoped_ptr<content::DownloadTestObserver> observer(
503 CreateDownloadObserver(1));
504 GURL finish_url(URLRequestSlowDownloadJob::kFinishDownloadUrl);
505 ui_test_utils::NavigateToURLWithDisposition(
506 current_browser(), finish_url, NEW_FOREGROUND_TAB,
507 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
508 observer->WaitForFinished();
509 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::COMPLETE));
510 }
511
512 content::DownloadTestObserver* CreateDownloadObserver(size_t download_count) {
513 return new content::DownloadTestObserverTerminal(
514 GetCurrentManager(), download_count,
515 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
516 }
517
518 content::DownloadTestObserver* CreateInProgressDownloadObserver(
519 size_t download_count) {
520 return new content::DownloadTestObserverInProgress(
521 GetCurrentManager(), download_count);
522 }
523
524 bool RunFunction(UIThreadExtensionFunction* function,
525 const std::string& args) {
526 scoped_refptr<UIThreadExtensionFunction> delete_function(function);
527 SetUpExtensionFunction(function);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100528 bool result = extension_function_test_utils::RunFunction(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000529 function, args, browser(), GetFlags());
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100530 if (!result) {
531 LOG(ERROR) << function->GetError();
532 }
533 return result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000534 }
535
536 extension_function_test_utils::RunFunctionFlags GetFlags() {
537 return current_browser()->profile()->IsOffTheRecord() ?
538 extension_function_test_utils::INCLUDE_INCOGNITO :
539 extension_function_test_utils::NONE;
540 }
541
542 // extension_function_test_utils::RunFunction*() only uses browser for its
543 // profile(), so pass it the on-record browser so that it always uses the
544 // on-record profile to match real-life behavior.
545
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000546 base::Value* RunFunctionAndReturnResult(
547 scoped_refptr<UIThreadExtensionFunction> function,
548 const std::string& args) {
549 SetUpExtensionFunction(function.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000550 return extension_function_test_utils::RunFunctionAndReturnSingleResult(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000551 function.get(), args, browser(), GetFlags());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000552 }
553
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000554 std::string RunFunctionAndReturnError(
555 scoped_refptr<UIThreadExtensionFunction> function,
556 const std::string& args) {
557 SetUpExtensionFunction(function.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000558 return extension_function_test_utils::RunFunctionAndReturnError(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000559 function.get(), args, browser(), GetFlags());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000560 }
561
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000562 bool RunFunctionAndReturnString(
563 scoped_refptr<UIThreadExtensionFunction> function,
564 const std::string& args,
565 std::string* result_string) {
566 SetUpExtensionFunction(function.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000567 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(function, args));
568 EXPECT_TRUE(result.get());
569 return result.get() && result->GetAsString(result_string);
570 }
571
572 std::string DownloadItemIdAsArgList(const DownloadItem* download_item) {
573 return base::StringPrintf("[%d]", download_item->GetId());
574 }
575
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000576 const base::FilePath& downloads_directory() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000577 return downloads_directory_.path();
578 }
579
580 DownloadsEventsListener* events_listener() { return events_listener_.get(); }
581
582 private:
583 void SetUpExtensionFunction(UIThreadExtensionFunction* function) {
584 if (extension_) {
585 // Recreate the tab each time for insulation.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000586 content::WebContents* tab = chrome::AddSelectedTabWithURL(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000587 current_browser(),
588 extension_->GetResourceURL("empty.html"),
589 content::PAGE_TRANSITION_LINK);
590 function->set_extension(extension_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000591 function->SetRenderViewHost(tab->GetRenderViewHost());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000592 }
593 }
594
595 void CreateAndSetDownloadsDirectory() {
596 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
597 current_browser()->profile()->GetPrefs()->SetFilePath(
598 prefs::kDownloadDefaultDirectory,
599 downloads_directory_.path());
600 }
601
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000602 base::ScopedTempDir downloads_directory_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000603 const extensions::Extension* extension_;
604 Browser* incognito_browser_;
605 Browser* current_browser_;
606 scoped_ptr<DownloadsEventsListener> events_listener_;
607
608 DISALLOW_COPY_AND_ASSIGN(DownloadExtensionTest);
609};
610
611class MockIconExtractorImpl : public DownloadFileIconExtractor {
612 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000613 MockIconExtractorImpl(const base::FilePath& path,
614 IconLoader::IconSize icon_size,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000615 const std::string& response)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000616 : expected_path_(path),
617 expected_icon_size_(icon_size),
618 response_(response) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000619 }
620 virtual ~MockIconExtractorImpl() {}
621
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000622 virtual bool ExtractIconURLForPath(const base::FilePath& path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000623 IconLoader::IconSize icon_size,
624 IconURLCallback callback) OVERRIDE {
625 EXPECT_STREQ(expected_path_.value().c_str(), path.value().c_str());
626 EXPECT_EQ(expected_icon_size_, icon_size);
627 if (expected_path_ == path &&
628 expected_icon_size_ == icon_size) {
629 callback_ = callback;
630 BrowserThread::PostTask(
631 BrowserThread::UI, FROM_HERE,
632 base::Bind(&MockIconExtractorImpl::RunCallback,
633 base::Unretained(this)));
634 return true;
635 } else {
636 return false;
637 }
638 }
639
640 private:
641 void RunCallback() {
642 callback_.Run(response_);
643 }
644
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000645 base::FilePath expected_path_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000646 IconLoader::IconSize expected_icon_size_;
647 std::string response_;
648 IconURLCallback callback_;
649};
650
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000651bool ItemNotInProgress(DownloadItem* item) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100652 return item->GetState() != DownloadItem::IN_PROGRESS;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000653}
654
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000655// Cancels the underlying DownloadItem when the ScopedCancellingItem goes out of
656// scope. Like a scoped_ptr, but for DownloadItems.
657class ScopedCancellingItem {
658 public:
659 explicit ScopedCancellingItem(DownloadItem* item) : item_(item) {}
660 ~ScopedCancellingItem() {
661 item_->Cancel(true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000662 content::DownloadUpdatedObserver observer(
663 item_, base::Bind(&ItemNotInProgress));
664 observer.WaitForEvent();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000665 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000666 DownloadItem* get() { return item_; }
667 private:
668 DownloadItem* item_;
669 DISALLOW_COPY_AND_ASSIGN(ScopedCancellingItem);
670};
671
672// Cancels all the underlying DownloadItems when the ScopedItemVectorCanceller
673// goes out of scope. Generalization of ScopedCancellingItem to many
674// DownloadItems.
675class ScopedItemVectorCanceller {
676 public:
677 explicit ScopedItemVectorCanceller(DownloadManager::DownloadVector* items)
678 : items_(items) {
679 }
680 ~ScopedItemVectorCanceller() {
681 for (DownloadManager::DownloadVector::const_iterator item = items_->begin();
682 item != items_->end(); ++item) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100683 if ((*item)->GetState() == DownloadItem::IN_PROGRESS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000684 (*item)->Cancel(true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000685 content::DownloadUpdatedObserver observer(
686 (*item), base::Bind(&ItemNotInProgress));
687 observer.WaitForEvent();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000688 }
689 }
690
691 private:
692 DownloadManager::DownloadVector* items_;
693 DISALLOW_COPY_AND_ASSIGN(ScopedItemVectorCanceller);
694};
695
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000696// Writes an HTML5 file so that it can be downloaded.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000697class HTML5FileWriter {
698 public:
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100699 static bool CreateFileForTesting(fileapi::FileSystemContext* context,
700 const fileapi::FileSystemURL& path,
701 const char*data,
702 int length) {
703 // Create a temp file.
704 base::FilePath temp_file;
705 if (!file_util::CreateTemporaryFile(&temp_file) ||
706 file_util::WriteFile(temp_file, data, length) != length) {
707 return false;
708 }
709 // Invoke the fileapi to copy it into the sandboxed filesystem.
710 bool result = false;
711 base::WaitableEvent done_event(true, false);
712 BrowserThread::PostTask(
713 BrowserThread::IO, FROM_HERE,
714 base::Bind(&CreateFileForTestingOnIOThread,
715 base::Unretained(context),
716 path, temp_file,
717 base::Unretained(&result),
718 base::Unretained(&done_event)));
719 // Wait for that to finish.
720 done_event.Wait();
721 base::DeleteFile(temp_file, false);
722 return result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000723 }
724
725 private:
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100726 static void CopyInCompletion(bool* result,
727 base::WaitableEvent* done_event,
728 base::PlatformFileError error) {
729 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
730 *result = error == base::PLATFORM_FILE_OK;
731 done_event->Signal();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000732 }
733
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100734 static void CreateFileForTestingOnIOThread(
735 fileapi::FileSystemContext* context,
736 const fileapi::FileSystemURL& path,
737 const base::FilePath& temp_file,
738 bool* result,
739 base::WaitableEvent* done_event) {
740 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
741 context->operation_runner()->CopyInForeignFile(
742 temp_file, path,
743 base::Bind(&CopyInCompletion,
744 base::Unretained(result),
745 base::Unretained(done_event)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000746 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000747};
748
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100749// TODO(benjhayden) Merge this with the other TestObservers.
750class JustInProgressDownloadObserver
751 : public content::DownloadTestObserverInProgress {
752 public:
753 JustInProgressDownloadObserver(
754 DownloadManager* download_manager, size_t wait_count)
755 : content::DownloadTestObserverInProgress(download_manager, wait_count) {
756 }
757
758 virtual ~JustInProgressDownloadObserver() {}
759
760 private:
761 virtual bool IsDownloadInFinalState(DownloadItem* item) OVERRIDE {
762 return item->GetState() == DownloadItem::IN_PROGRESS;
763 }
764
765 DISALLOW_COPY_AND_ASSIGN(JustInProgressDownloadObserver);
766};
767
768bool ItemIsInterrupted(DownloadItem* item) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100769 return item->GetState() == DownloadItem::INTERRUPTED;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100770}
771
Ben Murdoch558790d2013-07-30 15:19:42 +0100772content::DownloadInterruptReason InterruptReasonExtensionToContent(
773 api::InterruptReason error) {
774 switch (error) {
775 case api::INTERRUPT_REASON_NONE:
776 return content::DOWNLOAD_INTERRUPT_REASON_NONE;
777#define INTERRUPT_REASON(name, value) \
778 case api::INTERRUPT_REASON_##name: \
779 return content::DOWNLOAD_INTERRUPT_REASON_##name;
780#include "content/public/browser/download_interrupt_reason_values.h"
781#undef INTERRUPT_REASON
782 }
783 NOTREACHED();
784 return content::DOWNLOAD_INTERRUPT_REASON_NONE;
785}
786
787api::InterruptReason InterruptReasonContentToExtension(
788 content::DownloadInterruptReason error) {
789 switch (error) {
790 case content::DOWNLOAD_INTERRUPT_REASON_NONE:
791 return api::INTERRUPT_REASON_NONE;
792#define INTERRUPT_REASON(name, value) \
793 case content::DOWNLOAD_INTERRUPT_REASON_##name: \
794 return api::INTERRUPT_REASON_##name;
795#include "content/public/browser/download_interrupt_reason_values.h"
796#undef INTERRUPT_REASON
797 }
798 NOTREACHED();
799 return api::INTERRUPT_REASON_NONE;
800}
801
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000802} // namespace
803
804IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000805 DownloadExtensionTest_Open) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100806 LoadExtension("downloads_split");
Ben Murdoch558790d2013-07-30 15:19:42 +0100807 EXPECT_STREQ(errors::kInvalidId,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000808 RunFunctionAndReturnError(
809 new DownloadsOpenFunction(),
810 "[-42]").c_str());
811
812 DownloadItem* download_item = CreateSlowTestDownload();
813 ASSERT_TRUE(download_item);
814 EXPECT_FALSE(download_item->GetOpened());
815 EXPECT_FALSE(download_item->GetOpenWhenComplete());
816 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
817 base::StringPrintf("[{\"danger\": \"safe\","
818 " \"incognito\": false,"
819 " \"mime\": \"application/octet-stream\","
820 " \"paused\": false,"
821 " \"url\": \"%s\"}]",
822 download_item->GetURL().spec().c_str())));
Ben Murdoch558790d2013-07-30 15:19:42 +0100823 EXPECT_STREQ(errors::kNotComplete,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000824 RunFunctionAndReturnError(
825 new DownloadsOpenFunction(),
826 DownloadItemIdAsArgList(download_item)).c_str());
827
828 FinishPendingSlowDownloads();
829 EXPECT_FALSE(download_item->GetOpened());
830 EXPECT_TRUE(RunFunction(new DownloadsOpenFunction(),
831 DownloadItemIdAsArgList(download_item)));
832 EXPECT_TRUE(download_item->GetOpened());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000833}
834
835IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
836 DownloadExtensionTest_PauseResumeCancelErase) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000837 DownloadItem* download_item = CreateSlowTestDownload();
838 ASSERT_TRUE(download_item);
839
840 // Call pause(). It should succeed and the download should be paused on
841 // return.
842 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(),
843 DownloadItemIdAsArgList(download_item)));
844 EXPECT_TRUE(download_item->IsPaused());
845
846 // Calling pause() twice shouldn't be an error.
847 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(),
848 DownloadItemIdAsArgList(download_item)));
849 EXPECT_TRUE(download_item->IsPaused());
850
851 // Now try resuming this download. It should succeed.
852 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(),
853 DownloadItemIdAsArgList(download_item)));
854 EXPECT_FALSE(download_item->IsPaused());
855
856 // Resume again. Resuming a download that wasn't paused is not an error.
857 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(),
858 DownloadItemIdAsArgList(download_item)));
859 EXPECT_FALSE(download_item->IsPaused());
860
861 // Pause again.
862 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(),
863 DownloadItemIdAsArgList(download_item)));
864 EXPECT_TRUE(download_item->IsPaused());
865
866 // And now cancel.
867 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(),
868 DownloadItemIdAsArgList(download_item)));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100869 EXPECT_EQ(DownloadItem::CANCELLED, download_item->GetState());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000870
871 // Cancel again. Shouldn't have any effect.
872 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(),
873 DownloadItemIdAsArgList(download_item)));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100874 EXPECT_EQ(DownloadItem::CANCELLED, download_item->GetState());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000875
Ben Murdoch558790d2013-07-30 15:19:42 +0100876 // Calling paused on a non-active download yields kInvalidId.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000877 std::string error = RunFunctionAndReturnError(
878 new DownloadsPauseFunction(), DownloadItemIdAsArgList(download_item));
Ben Murdoch558790d2013-07-30 15:19:42 +0100879 EXPECT_STREQ(errors::kNotInProgress, error.c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000880
Ben Murdoch558790d2013-07-30 15:19:42 +0100881 // Calling resume on a non-active download yields kInvalidId
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000882 error = RunFunctionAndReturnError(
883 new DownloadsResumeFunction(), DownloadItemIdAsArgList(download_item));
Ben Murdoch558790d2013-07-30 15:19:42 +0100884 EXPECT_STREQ(errors::kNotResumable, error.c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000885
Ben Murdoch558790d2013-07-30 15:19:42 +0100886 // Calling paused on a non-existent download yields kInvalidId.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000887 error = RunFunctionAndReturnError(
888 new DownloadsPauseFunction(), "[-42]");
Ben Murdoch558790d2013-07-30 15:19:42 +0100889 EXPECT_STREQ(errors::kInvalidId, error.c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000890
Ben Murdoch558790d2013-07-30 15:19:42 +0100891 // Calling resume on a non-existent download yields kInvalidId
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000892 error = RunFunctionAndReturnError(
893 new DownloadsResumeFunction(), "[-42]");
Ben Murdoch558790d2013-07-30 15:19:42 +0100894 EXPECT_STREQ(errors::kInvalidId, error.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000895
896 int id = download_item->GetId();
897 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
898 new DownloadsEraseFunction(),
899 base::StringPrintf("[{\"id\": %d}]", id)));
900 DownloadManager::DownloadVector items;
901 GetCurrentManager()->GetAllDownloads(&items);
902 EXPECT_EQ(0UL, items.size());
903 ASSERT_TRUE(result);
904 download_item = NULL;
905 base::ListValue* result_list = NULL;
906 ASSERT_TRUE(result->GetAsList(&result_list));
907 ASSERT_EQ(1UL, result_list->GetSize());
908 int element = -1;
909 ASSERT_TRUE(result_list->GetInteger(0, &element));
910 EXPECT_EQ(id, element);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000911}
912
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000913scoped_refptr<UIThreadExtensionFunction> MockedGetFileIconFunction(
914 const base::FilePath& expected_path,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000915 IconLoader::IconSize icon_size,
916 const std::string& response) {
917 scoped_refptr<DownloadsGetFileIconFunction> function(
918 new DownloadsGetFileIconFunction());
919 function->SetIconExtractorForTesting(new MockIconExtractorImpl(
920 expected_path, icon_size, response));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000921 return function;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000922}
923
924// Test downloads.getFileIcon() on in-progress, finished, cancelled and deleted
925// download items.
926IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
927 DownloadExtensionTest_FileIcon_Active) {
928 DownloadItem* download_item = CreateSlowTestDownload();
929 ASSERT_TRUE(download_item);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000930 ASSERT_FALSE(download_item->GetTargetFilePath().empty());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000931 std::string args32(base::StringPrintf("[%d, {\"size\": 32}]",
932 download_item->GetId()));
933 std::string result_string;
934
935 // Get the icon for the in-progress download. This call should succeed even
936 // if the file type isn't registered.
937 // Test whether the correct path is being pased into the icon extractor.
938 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
939 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
940 base::StringPrintf("[%d, {}]", download_item->GetId()), &result_string));
941
942 // Now try a 16x16 icon.
943 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
944 download_item->GetTargetFilePath(), IconLoader::SMALL, "foo"),
945 base::StringPrintf("[%d, {\"size\": 16}]", download_item->GetId()),
946 &result_string));
947
948 // Explicitly asking for 32x32 should give us a 32x32 icon.
949 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
950 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
951 args32, &result_string));
952
953 // Finish the download and try again.
954 FinishPendingSlowDownloads();
955 EXPECT_EQ(DownloadItem::COMPLETE, download_item->GetState());
956 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
957 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
958 args32, &result_string));
959
960 // Check the path passed to the icon extractor post-completion.
961 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
962 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
963 args32, &result_string));
964
965 // Now create another download.
966 download_item = CreateSlowTestDownload();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000967 ASSERT_TRUE(download_item);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000968 ASSERT_FALSE(download_item->GetTargetFilePath().empty());
969 args32 = base::StringPrintf("[%d, {\"size\": 32}]", download_item->GetId());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000970
971 // Cancel the download. As long as the download has a target path, we should
972 // be able to query the file icon.
973 download_item->Cancel(true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000974 ASSERT_FALSE(download_item->GetTargetFilePath().empty());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000975 // Let cleanup complete on the FILE thread.
976 content::RunAllPendingInMessageLoop(BrowserThread::FILE);
977 // Check the path passed to the icon extractor post-cancellation.
978 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
979 download_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
980 args32,
981 &result_string));
982
983 // Simulate an error during icon load by invoking the mock with an empty
984 // result string.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100985 std::string error = RunFunctionAndReturnError(
986 MockedGetFileIconFunction(download_item->GetTargetFilePath(),
987 IconLoader::NORMAL,
988 std::string()),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000989 args32);
Ben Murdoch558790d2013-07-30 15:19:42 +0100990 EXPECT_STREQ(errors::kIconNotFound, error.c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000991
Ben Murdoch558790d2013-07-30 15:19:42 +0100992 // Once the download item is deleted, we should return kInvalidId.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000993 int id = download_item->GetId();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100994 download_item->Remove();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000995 download_item = NULL;
996 EXPECT_EQ(static_cast<DownloadItem*>(NULL),
997 GetCurrentManager()->GetDownload(id));
998 error = RunFunctionAndReturnError(new DownloadsGetFileIconFunction(), args32);
Ben Murdoch558790d2013-07-30 15:19:42 +0100999 EXPECT_STREQ(errors::kInvalidId,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001000 error.c_str());
1001}
1002
1003// Test that we can acquire file icons for history downloads regardless of
1004// whether they exist or not. If the file doesn't exist we should receive a
1005// generic icon from the OS/toolkit that may or may not be specific to the file
1006// type.
1007IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1008 DownloadExtensionTest_FileIcon_History) {
1009 const HistoryDownloadInfo kHistoryInfo[] = {
1010 { FILE_PATH_LITERAL("real.txt"),
1011 DownloadItem::COMPLETE,
1012 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1013 { FILE_PATH_LITERAL("fake.txt"),
1014 DownloadItem::COMPLETE,
1015 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1016 };
1017 DownloadManager::DownloadVector all_downloads;
1018 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1019 &all_downloads));
1020
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001021 base::FilePath real_path = all_downloads[0]->GetTargetFilePath();
1022 base::FilePath fake_path = all_downloads[1]->GetTargetFilePath();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001023
1024 EXPECT_EQ(0, file_util::WriteFile(real_path, "", 0));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001025 ASSERT_TRUE(base::PathExists(real_path));
1026 ASSERT_FALSE(base::PathExists(fake_path));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001027
1028 for (DownloadManager::DownloadVector::iterator iter = all_downloads.begin();
1029 iter != all_downloads.end();
1030 ++iter) {
1031 std::string result_string;
1032 // Use a MockIconExtractorImpl to test if the correct path is being passed
1033 // into the DownloadFileIconExtractor.
1034 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001035 (*iter)->GetTargetFilePath(), IconLoader::NORMAL, "hello"),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001036 base::StringPrintf("[%d, {\"size\": 32}]", (*iter)->GetId()),
1037 &result_string));
1038 EXPECT_STREQ("hello", result_string.c_str());
1039 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001040}
1041
1042// Test passing the empty query to search().
1043IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1044 DownloadExtensionTest_SearchEmptyQuery) {
1045 ScopedCancellingItem item(CreateSlowTestDownload());
1046 ASSERT_TRUE(item.get());
1047
1048 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1049 new DownloadsSearchFunction(), "[{}]"));
1050 ASSERT_TRUE(result.get());
1051 base::ListValue* result_list = NULL;
1052 ASSERT_TRUE(result->GetAsList(&result_list));
1053 ASSERT_EQ(1UL, result_list->GetSize());
1054}
1055
1056// Test the |filenameRegex| parameter for search().
1057IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1058 DownloadExtensionTest_SearchFilenameRegex) {
1059 const HistoryDownloadInfo kHistoryInfo[] = {
1060 { FILE_PATH_LITERAL("foobar"),
1061 DownloadItem::COMPLETE,
1062 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1063 { FILE_PATH_LITERAL("baz"),
1064 DownloadItem::COMPLETE,
1065 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1066 };
1067 DownloadManager::DownloadVector all_downloads;
1068 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1069 &all_downloads));
1070
1071 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1072 new DownloadsSearchFunction(), "[{\"filenameRegex\": \"foobar\"}]"));
1073 ASSERT_TRUE(result.get());
1074 base::ListValue* result_list = NULL;
1075 ASSERT_TRUE(result->GetAsList(&result_list));
1076 ASSERT_EQ(1UL, result_list->GetSize());
1077 base::DictionaryValue* item_value = NULL;
1078 ASSERT_TRUE(result_list->GetDictionary(0, &item_value));
1079 int item_id = -1;
1080 ASSERT_TRUE(item_value->GetInteger("id", &item_id));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001081 ASSERT_EQ(all_downloads[0]->GetId(), static_cast<uint32>(item_id));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001082}
1083
1084// Test the |id| parameter for search().
1085IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadExtensionTest_SearchId) {
1086 DownloadManager::DownloadVector items;
1087 CreateSlowTestDownloads(2, &items);
1088 ScopedItemVectorCanceller delete_items(&items);
1089
1090 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001091 new DownloadsSearchFunction(), base::StringPrintf(
1092 "[{\"id\": %u}]", items[0]->GetId())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001093 ASSERT_TRUE(result.get());
1094 base::ListValue* result_list = NULL;
1095 ASSERT_TRUE(result->GetAsList(&result_list));
1096 ASSERT_EQ(1UL, result_list->GetSize());
1097 base::DictionaryValue* item_value = NULL;
1098 ASSERT_TRUE(result_list->GetDictionary(0, &item_value));
1099 int item_id = -1;
1100 ASSERT_TRUE(item_value->GetInteger("id", &item_id));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001101 ASSERT_EQ(items[0]->GetId(), static_cast<uint32>(item_id));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001102}
1103
1104// Test specifying both the |id| and |filename| parameters for search().
1105IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1106 DownloadExtensionTest_SearchIdAndFilename) {
1107 DownloadManager::DownloadVector items;
1108 CreateSlowTestDownloads(2, &items);
1109 ScopedItemVectorCanceller delete_items(&items);
1110
1111 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1112 new DownloadsSearchFunction(),
1113 "[{\"id\": 0, \"filename\": \"foobar\"}]"));
1114 ASSERT_TRUE(result.get());
1115 base::ListValue* result_list = NULL;
1116 ASSERT_TRUE(result->GetAsList(&result_list));
1117 ASSERT_EQ(0UL, result_list->GetSize());
1118}
1119
1120// Test a single |orderBy| parameter for search().
1121IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1122 DownloadExtensionTest_SearchOrderBy) {
1123 const HistoryDownloadInfo kHistoryInfo[] = {
1124 { FILE_PATH_LITERAL("zzz"),
1125 DownloadItem::COMPLETE,
1126 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1127 { FILE_PATH_LITERAL("baz"),
1128 DownloadItem::COMPLETE,
1129 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1130 };
1131 DownloadManager::DownloadVector items;
1132 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1133 &items));
1134
1135 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
Ben Murdoch558790d2013-07-30 15:19:42 +01001136 new DownloadsSearchFunction(), "[{\"orderBy\": [\"filename\"]}]"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001137 ASSERT_TRUE(result.get());
1138 base::ListValue* result_list = NULL;
1139 ASSERT_TRUE(result->GetAsList(&result_list));
1140 ASSERT_EQ(2UL, result_list->GetSize());
1141 base::DictionaryValue* item0_value = NULL;
1142 base::DictionaryValue* item1_value = NULL;
1143 ASSERT_TRUE(result_list->GetDictionary(0, &item0_value));
1144 ASSERT_TRUE(result_list->GetDictionary(1, &item1_value));
1145 std::string item0_name, item1_name;
1146 ASSERT_TRUE(item0_value->GetString("filename", &item0_name));
1147 ASSERT_TRUE(item1_value->GetString("filename", &item1_name));
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001148 ASSERT_GT(items[0]->GetTargetFilePath().value(),
1149 items[1]->GetTargetFilePath().value());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001150 ASSERT_LT(item0_name, item1_name);
1151}
1152
1153// Test specifying an empty |orderBy| parameter for search().
1154IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1155 DownloadExtensionTest_SearchOrderByEmpty) {
1156 const HistoryDownloadInfo kHistoryInfo[] = {
1157 { FILE_PATH_LITERAL("zzz"),
1158 DownloadItem::COMPLETE,
1159 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1160 { FILE_PATH_LITERAL("baz"),
1161 DownloadItem::COMPLETE,
1162 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1163 };
1164 DownloadManager::DownloadVector items;
1165 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1166 &items));
1167
1168 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
Ben Murdoch558790d2013-07-30 15:19:42 +01001169 new DownloadsSearchFunction(), "[{\"orderBy\": []}]"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001170 ASSERT_TRUE(result.get());
1171 base::ListValue* result_list = NULL;
1172 ASSERT_TRUE(result->GetAsList(&result_list));
1173 ASSERT_EQ(2UL, result_list->GetSize());
1174 base::DictionaryValue* item0_value = NULL;
1175 base::DictionaryValue* item1_value = NULL;
1176 ASSERT_TRUE(result_list->GetDictionary(0, &item0_value));
1177 ASSERT_TRUE(result_list->GetDictionary(1, &item1_value));
1178 std::string item0_name, item1_name;
1179 ASSERT_TRUE(item0_value->GetString("filename", &item0_name));
1180 ASSERT_TRUE(item1_value->GetString("filename", &item1_name));
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001181 ASSERT_GT(items[0]->GetTargetFilePath().value(),
1182 items[1]->GetTargetFilePath().value());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001183 ASSERT_GT(item0_name, item1_name);
1184}
1185
1186// Test the |danger| option for search().
1187IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1188 DownloadExtensionTest_SearchDanger) {
1189 const HistoryDownloadInfo kHistoryInfo[] = {
1190 { FILE_PATH_LITERAL("zzz"),
1191 DownloadItem::COMPLETE,
1192 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT },
1193 { FILE_PATH_LITERAL("baz"),
1194 DownloadItem::COMPLETE,
1195 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }
1196 };
1197 DownloadManager::DownloadVector items;
1198 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1199 &items));
1200
1201 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1202 new DownloadsSearchFunction(), "[{\"danger\": \"content\"}]"));
1203 ASSERT_TRUE(result.get());
1204 base::ListValue* result_list = NULL;
1205 ASSERT_TRUE(result->GetAsList(&result_list));
1206 ASSERT_EQ(1UL, result_list->GetSize());
1207}
1208
1209// Test the |state| option for search().
1210IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1211 DownloadExtensionTest_SearchState) {
1212 DownloadManager::DownloadVector items;
1213 CreateSlowTestDownloads(2, &items);
1214 ScopedItemVectorCanceller delete_items(&items);
1215
1216 items[0]->Cancel(true);
1217
1218 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1219 new DownloadsSearchFunction(), "[{\"state\": \"in_progress\"}]"));
1220 ASSERT_TRUE(result.get());
1221 base::ListValue* result_list = NULL;
1222 ASSERT_TRUE(result->GetAsList(&result_list));
1223 ASSERT_EQ(1UL, result_list->GetSize());
1224}
1225
1226// Test the |limit| option for search().
1227IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1228 DownloadExtensionTest_SearchLimit) {
1229 DownloadManager::DownloadVector items;
1230 CreateSlowTestDownloads(2, &items);
1231 ScopedItemVectorCanceller delete_items(&items);
1232
1233 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1234 new DownloadsSearchFunction(), "[{\"limit\": 1}]"));
1235 ASSERT_TRUE(result.get());
1236 base::ListValue* result_list = NULL;
1237 ASSERT_TRUE(result->GetAsList(&result_list));
1238 ASSERT_EQ(1UL, result_list->GetSize());
1239}
1240
1241// Test invalid search parameters.
1242IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1243 DownloadExtensionTest_SearchInvalid) {
1244 std::string error = RunFunctionAndReturnError(
1245 new DownloadsSearchFunction(), "[{\"filenameRegex\": \"(\"}]");
Ben Murdoch558790d2013-07-30 15:19:42 +01001246 EXPECT_STREQ(errors::kInvalidFilter,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001247 error.c_str());
1248 error = RunFunctionAndReturnError(
Ben Murdoch558790d2013-07-30 15:19:42 +01001249 new DownloadsSearchFunction(), "[{\"orderBy\": [\"goat\"]}]");
1250 EXPECT_STREQ(errors::kInvalidOrderBy,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001251 error.c_str());
1252 error = RunFunctionAndReturnError(
1253 new DownloadsSearchFunction(), "[{\"limit\": -1}]");
Ben Murdoch558790d2013-07-30 15:19:42 +01001254 EXPECT_STREQ(errors::kInvalidQueryLimit,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001255 error.c_str());
1256}
1257
1258// Test searching using multiple conditions through multiple downloads.
1259IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1260 DownloadExtensionTest_SearchPlural) {
1261 const HistoryDownloadInfo kHistoryInfo[] = {
1262 { FILE_PATH_LITERAL("aaa"),
1263 DownloadItem::CANCELLED,
1264 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS },
1265 { FILE_PATH_LITERAL("zzz"),
1266 DownloadItem::COMPLETE,
1267 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT },
1268 { FILE_PATH_LITERAL("baz"),
1269 DownloadItem::COMPLETE,
1270 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT },
1271 };
1272 DownloadManager::DownloadVector items;
1273 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo),
1274 &items));
1275
1276 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1277 new DownloadsSearchFunction(), "[{"
1278 "\"state\": \"complete\", "
1279 "\"danger\": \"content\", "
Ben Murdoch558790d2013-07-30 15:19:42 +01001280 "\"orderBy\": [\"filename\"], "
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001281 "\"limit\": 1}]"));
1282 ASSERT_TRUE(result.get());
1283 base::ListValue* result_list = NULL;
1284 ASSERT_TRUE(result->GetAsList(&result_list));
1285 ASSERT_EQ(1UL, result_list->GetSize());
1286 base::DictionaryValue* item_value = NULL;
1287 ASSERT_TRUE(result_list->GetDictionary(0, &item_value));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001288 base::FilePath::StringType item_name;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001289 ASSERT_TRUE(item_value->GetString("filename", &item_name));
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001290 ASSERT_EQ(items[2]->GetTargetFilePath().value(), item_name);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001291}
1292
1293// Test that incognito downloads are only visible in incognito contexts, and
1294// test that on-record downloads are visible in both incognito and on-record
1295// contexts, for DownloadsSearchFunction, DownloadsPauseFunction,
1296// DownloadsResumeFunction, and DownloadsCancelFunction.
1297IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1298 DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) {
1299 scoped_ptr<base::Value> result_value;
1300 base::ListValue* result_list = NULL;
1301 base::DictionaryValue* result_dict = NULL;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001302 base::FilePath::StringType filename;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001303 bool is_incognito = false;
1304 std::string error;
1305 std::string on_item_arg;
1306 std::string off_item_arg;
1307 std::string result_string;
1308
1309 // Set up one on-record item and one off-record item.
1310 // Set up the off-record item first because otherwise there are mysteriously 3
1311 // items total instead of 2.
1312 // TODO(benjhayden): Figure out where the third item comes from.
1313 GoOffTheRecord();
1314 DownloadItem* off_item = CreateSlowTestDownload();
1315 ASSERT_TRUE(off_item);
1316 off_item_arg = DownloadItemIdAsArgList(off_item);
1317
1318 GoOnTheRecord();
1319 DownloadItem* on_item = CreateSlowTestDownload();
1320 ASSERT_TRUE(on_item);
1321 on_item_arg = DownloadItemIdAsArgList(on_item);
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001322 ASSERT_TRUE(on_item->GetTargetFilePath() != off_item->GetTargetFilePath());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001323
1324 // Extensions running in the incognito window should have access to both
1325 // items because the Test extension is in spanning mode.
1326 GoOffTheRecord();
1327 result_value.reset(RunFunctionAndReturnResult(
1328 new DownloadsSearchFunction(), "[{}]"));
1329 ASSERT_TRUE(result_value.get());
1330 ASSERT_TRUE(result_value->GetAsList(&result_list));
1331 ASSERT_EQ(2UL, result_list->GetSize());
1332 ASSERT_TRUE(result_list->GetDictionary(0, &result_dict));
1333 ASSERT_TRUE(result_dict->GetString("filename", &filename));
1334 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito));
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001335 EXPECT_TRUE(on_item->GetTargetFilePath() == base::FilePath(filename));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001336 EXPECT_FALSE(is_incognito);
1337 ASSERT_TRUE(result_list->GetDictionary(1, &result_dict));
1338 ASSERT_TRUE(result_dict->GetString("filename", &filename));
1339 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito));
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001340 EXPECT_TRUE(off_item->GetTargetFilePath() == base::FilePath(filename));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001341 EXPECT_TRUE(is_incognito);
1342
1343 // Extensions running in the on-record window should have access only to the
1344 // on-record item.
1345 GoOnTheRecord();
1346 result_value.reset(RunFunctionAndReturnResult(
1347 new DownloadsSearchFunction(), "[{}]"));
1348 ASSERT_TRUE(result_value.get());
1349 ASSERT_TRUE(result_value->GetAsList(&result_list));
1350 ASSERT_EQ(1UL, result_list->GetSize());
1351 ASSERT_TRUE(result_list->GetDictionary(0, &result_dict));
1352 ASSERT_TRUE(result_dict->GetString("filename", &filename));
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001353 EXPECT_TRUE(on_item->GetTargetFilePath() == base::FilePath(filename));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001354 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito));
1355 EXPECT_FALSE(is_incognito);
1356
1357 // Pausing/Resuming the off-record item while on the record should return an
1358 // error. Cancelling "non-existent" downloads is not an error.
1359 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), off_item_arg);
Ben Murdoch558790d2013-07-30 15:19:42 +01001360 EXPECT_STREQ(errors::kInvalidId,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001361 error.c_str());
1362 error = RunFunctionAndReturnError(new DownloadsResumeFunction(),
1363 off_item_arg);
Ben Murdoch558790d2013-07-30 15:19:42 +01001364 EXPECT_STREQ(errors::kInvalidId,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001365 error.c_str());
1366 error = RunFunctionAndReturnError(
1367 new DownloadsGetFileIconFunction(),
1368 base::StringPrintf("[%d, {}]", off_item->GetId()));
Ben Murdoch558790d2013-07-30 15:19:42 +01001369 EXPECT_STREQ(errors::kInvalidId,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001370 error.c_str());
1371
1372 GoOffTheRecord();
1373
1374 // Do the FileIcon test for both the on- and off-items while off the record.
1375 // NOTE(benjhayden): This does not include the FileIcon test from history,
1376 // just active downloads. This shouldn't be a problem.
1377 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
1378 on_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
1379 base::StringPrintf("[%d, {}]", on_item->GetId()), &result_string));
1380 EXPECT_TRUE(RunFunctionAndReturnString(MockedGetFileIconFunction(
1381 off_item->GetTargetFilePath(), IconLoader::NORMAL, "foo"),
1382 base::StringPrintf("[%d, {}]", off_item->GetId()), &result_string));
1383
1384 // Do the pause/resume/cancel test for both the on- and off-items while off
1385 // the record.
1386 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg));
1387 EXPECT_TRUE(on_item->IsPaused());
1388 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg));
1389 EXPECT_TRUE(on_item->IsPaused());
1390 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), on_item_arg));
1391 EXPECT_FALSE(on_item->IsPaused());
1392 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), on_item_arg));
1393 EXPECT_FALSE(on_item->IsPaused());
1394 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg));
1395 EXPECT_TRUE(on_item->IsPaused());
1396 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), on_item_arg));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001397 EXPECT_EQ(DownloadItem::CANCELLED, on_item->GetState());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001398 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), on_item_arg));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001399 EXPECT_EQ(DownloadItem::CANCELLED, on_item->GetState());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001400 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), on_item_arg);
Ben Murdoch558790d2013-07-30 15:19:42 +01001401 EXPECT_STREQ(errors::kNotInProgress, error.c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001402 error = RunFunctionAndReturnError(new DownloadsResumeFunction(), on_item_arg);
Ben Murdoch558790d2013-07-30 15:19:42 +01001403 EXPECT_STREQ(errors::kNotResumable, error.c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001404 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg));
1405 EXPECT_TRUE(off_item->IsPaused());
1406 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg));
1407 EXPECT_TRUE(off_item->IsPaused());
1408 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), off_item_arg));
1409 EXPECT_FALSE(off_item->IsPaused());
1410 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), off_item_arg));
1411 EXPECT_FALSE(off_item->IsPaused());
1412 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg));
1413 EXPECT_TRUE(off_item->IsPaused());
1414 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), off_item_arg));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001415 EXPECT_EQ(DownloadItem::CANCELLED, off_item->GetState());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001416 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), off_item_arg));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001417 EXPECT_EQ(DownloadItem::CANCELLED, off_item->GetState());
Ben Murdoch558790d2013-07-30 15:19:42 +01001418 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), off_item_arg);
1419 EXPECT_STREQ(errors::kNotInProgress, error.c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001420 error = RunFunctionAndReturnError(new DownloadsResumeFunction(),
1421 off_item_arg);
Ben Murdoch558790d2013-07-30 15:19:42 +01001422 EXPECT_STREQ(errors::kNotResumable, error.c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001423}
1424
1425// Test that we can start a download and that the correct sequence of events is
1426// fired for it.
1427IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1428 DownloadExtensionTest_Download_Basic) {
1429 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001430 ASSERT_TRUE(StartEmbeddedTestServer());
1431 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001432 std::string download_url = test_server()->GetURL("slow?0").spec();
1433 GoOnTheRecord();
1434
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001435 // Start downloading a file.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001436 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1437 new DownloadsDownloadFunction(), base::StringPrintf(
1438 "[{\"url\": \"%s\"}]", download_url.c_str())));
1439 ASSERT_TRUE(result.get());
1440 int result_id = -1;
1441 ASSERT_TRUE(result->GetAsInteger(&result_id));
1442 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1443 ASSERT_TRUE(item);
1444 ScopedCancellingItem canceller(item);
1445 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1446
1447 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
1448 base::StringPrintf("[{\"danger\": \"safe\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001449 " \"incognito\": false,"
1450 " \"mime\": \"text/plain\","
1451 " \"paused\": false,"
1452 " \"url\": \"%s\"}]",
1453 download_url.c_str())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001454 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1455 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001456 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001457 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001458 " \"current\": \"%s\"}}]",
1459 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001460 GetFilename("slow.txt").c_str())));
1461 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1462 base::StringPrintf("[{\"id\": %d,"
1463 " \"state\": {"
1464 " \"previous\": \"in_progress\","
1465 " \"current\": \"complete\"}}]",
1466 result_id)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001467}
1468
1469// Test that we can start a download from an incognito context, and that the
1470// download knows that it's incognito.
1471IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1472 DownloadExtensionTest_Download_Incognito) {
1473 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001474 ASSERT_TRUE(StartEmbeddedTestServer());
1475 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001476 GoOffTheRecord();
1477 std::string download_url = test_server()->GetURL("slow?0").spec();
1478
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001479 // Start downloading a file.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001480 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1481 new DownloadsDownloadFunction(), base::StringPrintf(
1482 "[{\"url\": \"%s\"}]", download_url.c_str())));
1483 ASSERT_TRUE(result.get());
1484 int result_id = -1;
1485 ASSERT_TRUE(result->GetAsInteger(&result_id));
1486 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1487 ASSERT_TRUE(item);
1488 ScopedCancellingItem canceller(item);
1489 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1490
1491 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
1492 base::StringPrintf("[{\"danger\": \"safe\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001493 " \"incognito\": true,"
1494 " \"mime\": \"text/plain\","
1495 " \"paused\": false,"
1496 " \"url\": \"%s\"}]",
1497 download_url.c_str())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001498 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1499 base::StringPrintf("[{\"id\":%d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001500 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001501 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001502 " \"current\": \"%s\"}}]",
1503 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001504 GetFilename("slow.txt").c_str())));
1505 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1506 base::StringPrintf("[{\"id\":%d,"
1507 " \"state\": {"
1508 " \"current\": \"complete\","
1509 " \"previous\": \"in_progress\"}}]",
1510 result_id)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001511}
1512
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001513#if defined(OS_WIN) && defined(USE_AURA)
1514// This test is very flaky on Win Aura. http://crbug.com/248438
1515#define MAYBE_DownloadExtensionTest_Download_UnsafeHeaders \
1516 DISABLED_DownloadExtensionTest_Download_UnsafeHeaders
1517#else
1518#define MAYBE_DownloadExtensionTest_Download_UnsafeHeaders \
1519 DownloadExtensionTest_Download_UnsafeHeaders
1520#endif
1521
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001522// Test that we disallow certain headers case-insensitively.
1523IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001524 MAYBE_DownloadExtensionTest_Download_UnsafeHeaders) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001525 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001526 ASSERT_TRUE(StartEmbeddedTestServer());
1527 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001528 GoOnTheRecord();
1529
1530 static const char* kUnsafeHeaders[] = {
1531 "Accept-chArsEt",
1532 "accept-eNcoding",
1533 "coNNection",
1534 "coNteNt-leNgth",
1535 "cooKIE",
1536 "cOOkie2",
1537 "coNteNt-traNsfer-eNcodiNg",
1538 "dAtE",
1539 "ExpEcT",
1540 "hOsT",
1541 "kEEp-aLivE",
1542 "rEfErEr",
1543 "tE",
1544 "trAilER",
1545 "trANsfer-eNcodiNg",
1546 "upGRAde",
1547 "usER-agENt",
1548 "viA",
1549 "pRoxY-",
1550 "sEc-",
1551 "pRoxY-probably-not-evil",
1552 "sEc-probably-not-evil",
1553 "oRiGiN",
1554 "Access-Control-Request-Headers",
1555 "Access-Control-Request-Method",
1556 };
1557
1558 for (size_t index = 0; index < arraysize(kUnsafeHeaders); ++index) {
1559 std::string download_url = test_server()->GetURL("slow?0").spec();
Ben Murdoch558790d2013-07-30 15:19:42 +01001560 EXPECT_STREQ(errors::kInvalidHeader,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001561 RunFunctionAndReturnError(new DownloadsDownloadFunction(),
1562 base::StringPrintf(
1563 "[{\"url\": \"%s\","
1564 " \"filename\": \"unsafe-header-%d.txt\","
1565 " \"headers\": [{"
1566 " \"name\": \"%s\","
1567 " \"value\": \"unsafe\"}]}]",
1568 download_url.c_str(),
1569 static_cast<int>(index),
1570 kUnsafeHeaders[index])).c_str());
1571 }
1572}
1573
Ben Murdoch558790d2013-07-30 15:19:42 +01001574#if defined(OS_WIN)
1575#define MAYBE_DownloadExtensionTest_Download_Subdirectory\
1576 DISABLED_DownloadExtensionTest_Download_Subdirectory
1577#else
1578#define MAYBE_DownloadExtensionTest_Download_Subdirectory\
1579 DownloadExtensionTest_Download_Subdirectory
1580#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001581IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
Ben Murdoch558790d2013-07-30 15:19:42 +01001582 MAYBE_DownloadExtensionTest_Download_Subdirectory) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001583 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001584 ASSERT_TRUE(StartEmbeddedTestServer());
1585 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001586 std::string download_url = test_server()->GetURL("slow?0").spec();
1587 GoOnTheRecord();
1588
Ben Murdoch558790d2013-07-30 15:19:42 +01001589 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1590 new DownloadsDownloadFunction(), base::StringPrintf(
1591 "[{\"url\": \"%s\","
1592 " \"filename\": \"sub/dir/ect/ory.txt\"}]",
1593 download_url.c_str())));
1594 ASSERT_TRUE(result.get());
1595 int result_id = -1;
1596 ASSERT_TRUE(result->GetAsInteger(&result_id));
1597 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1598 ASSERT_TRUE(item);
1599 ScopedCancellingItem canceller(item);
1600 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1601
1602 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
1603 base::StringPrintf("[{\"danger\": \"safe\","
1604 " \"incognito\": false,"
1605 " \"mime\": \"text/plain\","
1606 " \"paused\": false,"
1607 " \"url\": \"%s\"}]",
1608 download_url.c_str())));
1609 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1610 base::StringPrintf("[{\"id\": %d,"
1611 " \"filename\": {"
1612 " \"previous\": \"\","
1613 " \"current\": \"%s\"}}]",
1614 result_id,
1615 GetFilename("sub/dir/ect/ory.txt").c_str())));
1616 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1617 base::StringPrintf("[{\"id\": %d,"
1618 " \"state\": {"
1619 " \"previous\": \"in_progress\","
1620 " \"current\": \"complete\"}}]",
1621 result_id)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001622}
1623
1624// Test that invalid filenames are disallowed.
1625IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1626 DownloadExtensionTest_Download_InvalidFilename) {
1627 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001628 ASSERT_TRUE(StartEmbeddedTestServer());
1629 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001630 std::string download_url = test_server()->GetURL("slow?0").spec();
1631 GoOnTheRecord();
1632
Ben Murdoch558790d2013-07-30 15:19:42 +01001633 EXPECT_STREQ(errors::kInvalidFilename,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001634 RunFunctionAndReturnError(new DownloadsDownloadFunction(),
1635 base::StringPrintf(
1636 "[{\"url\": \"%s\","
1637 " \"filename\": \"../../../../../etc/passwd\"}]",
1638 download_url.c_str())).c_str());
1639}
1640
1641// Test that downloading invalid URLs immediately returns kInvalidURLError.
1642IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1643 DownloadExtensionTest_Download_InvalidURLs) {
1644 LoadExtension("downloads_split");
1645 GoOnTheRecord();
1646
1647 static const char* kInvalidURLs[] = {
1648 "foo bar",
1649 "../hello",
1650 "/hello",
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001651 "http://",
1652 "#frag",
1653 "foo/bar.html#frag",
Ben Murdoch558790d2013-07-30 15:19:42 +01001654 "google.com/",
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001655 };
1656
1657 for (size_t index = 0; index < arraysize(kInvalidURLs); ++index) {
Ben Murdoch558790d2013-07-30 15:19:42 +01001658 EXPECT_STREQ(errors::kInvalidURL,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001659 RunFunctionAndReturnError(new DownloadsDownloadFunction(),
1660 base::StringPrintf(
Ben Murdoch58e6fbe2013-07-26 10:20:38 +01001661 "[{\"url\": \"%s\"}]", kInvalidURLs[index])).c_str())
1662 << kInvalidURLs[index];
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001663 }
Ben Murdoch58e6fbe2013-07-26 10:20:38 +01001664
Ben Murdochbb1529c2013-08-08 10:24:53 +01001665 EXPECT_STREQ("net::ERR_ACCESS_DENIED", RunFunctionAndReturnError(
1666 new DownloadsDownloadFunction(),
1667 "[{\"url\": \"javascript:document.write(\\\"hello\\\");\"}]").c_str());
1668 EXPECT_STREQ("net::ERR_ACCESS_DENIED", RunFunctionAndReturnError(
1669 new DownloadsDownloadFunction(),
1670 "[{\"url\": \"javascript:return false;\"}]").c_str());
1671 EXPECT_STREQ("net::ERR_NOT_IMPLEMENTED", RunFunctionAndReturnError(
1672 new DownloadsDownloadFunction(),
1673 "[{\"url\": \"ftp://example.com/example.txt\"}]").c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001674}
1675
1676// TODO(benjhayden): Set up a test ftp server, add ftp://localhost* to
1677// permissions, test downloading from ftp.
1678
1679// Valid URLs plus fragments are still valid URLs.
1680IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1681 DownloadExtensionTest_Download_URLFragment) {
1682 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001683 ASSERT_TRUE(StartEmbeddedTestServer());
1684 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001685 std::string download_url = test_server()->GetURL("slow?0#fragment").spec();
1686 GoOnTheRecord();
1687
1688 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1689 new DownloadsDownloadFunction(), base::StringPrintf(
1690 "[{\"url\": \"%s\"}]", download_url.c_str())));
1691 ASSERT_TRUE(result.get());
1692 int result_id = -1;
1693 ASSERT_TRUE(result->GetAsInteger(&result_id));
1694 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1695 ASSERT_TRUE(item);
1696 ScopedCancellingItem canceller(item);
1697 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1698
1699 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
1700 base::StringPrintf("[{\"danger\": \"safe\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001701 " \"incognito\": false,"
1702 " \"mime\": \"text/plain\","
1703 " \"paused\": false,"
1704 " \"url\": \"%s\"}]",
1705 download_url.c_str())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001706 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1707 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001708 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001709 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001710 " \"current\": \"%s\"}}]",
1711 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001712 GetFilename("slow.txt").c_str())));
1713 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1714 base::StringPrintf("[{\"id\": %d,"
1715 " \"state\": {"
1716 " \"previous\": \"in_progress\","
1717 " \"current\": \"complete\"}}]",
1718 result_id)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001719}
1720
1721// Valid data URLs are valid URLs.
1722IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1723 DownloadExtensionTest_Download_DataURL) {
1724 LoadExtension("downloads_split");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001725 std::string download_url = "data:text/plain,hello";
1726 GoOnTheRecord();
1727
1728 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1729 new DownloadsDownloadFunction(), base::StringPrintf(
1730 "[{\"url\": \"%s\","
1731 " \"filename\": \"data.txt\"}]", download_url.c_str())));
1732 ASSERT_TRUE(result.get());
1733 int result_id = -1;
1734 ASSERT_TRUE(result->GetAsInteger(&result_id));
1735 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1736 ASSERT_TRUE(item);
1737 ScopedCancellingItem canceller(item);
1738 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1739
1740 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
1741 base::StringPrintf("[{\"danger\": \"safe\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001742 " \"incognito\": false,"
1743 " \"mime\": \"text/plain\","
1744 " \"paused\": false,"
1745 " \"url\": \"%s\"}]",
1746 download_url.c_str())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001747 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1748 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001749 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001750 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001751 " \"current\": \"%s\"}}]",
1752 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001753 GetFilename("data.txt").c_str())));
1754 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1755 base::StringPrintf("[{\"id\": %d,"
1756 " \"state\": {"
1757 " \"previous\": \"in_progress\","
1758 " \"current\": \"complete\"}}]",
1759 result_id)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001760}
1761
1762// Valid file URLs are valid URLs.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001763#if defined(OS_WIN) && defined(USE_AURA)
1764// Disabled due to crbug.com/175711
1765#define MAYBE_DownloadExtensionTest_Download_File \
1766 DISABLED_DownloadExtensionTest_Download_File
1767#else
1768#define MAYBE_DownloadExtensionTest_Download_File \
1769 DownloadExtensionTest_Download_File
1770#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001771IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001772 MAYBE_DownloadExtensionTest_Download_File) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001773 GoOnTheRecord();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001774 LoadExtension("downloads_split");
1775 std::string download_url = "file:///";
1776#if defined(OS_WIN)
1777 download_url += "C:/";
1778#endif
1779
1780 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1781 new DownloadsDownloadFunction(), base::StringPrintf(
1782 "[{\"url\": \"%s\","
1783 " \"filename\": \"file.txt\"}]", download_url.c_str())));
1784 ASSERT_TRUE(result.get());
1785 int result_id = -1;
1786 ASSERT_TRUE(result->GetAsInteger(&result_id));
1787 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1788 ASSERT_TRUE(item);
1789 ScopedCancellingItem canceller(item);
1790 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1791
1792 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
1793 base::StringPrintf("[{\"danger\": \"safe\","
1794 " \"incognito\": false,"
1795 " \"mime\": \"text/html\","
1796 " \"paused\": false,"
1797 " \"url\": \"%s\"}]",
1798 download_url.c_str())));
1799 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1800 base::StringPrintf("[{\"id\": %d,"
1801 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001802 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001803 " \"current\": \"%s\"}}]",
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001804 result_id,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001805 GetFilename("file.txt").c_str())));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001806 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1807 base::StringPrintf("[{\"id\": %d,"
1808 " \"state\": {"
1809 " \"previous\": \"in_progress\","
1810 " \"current\": \"complete\"}}]",
1811 result_id)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001812}
1813
1814// Test that auth-basic-succeed would fail if the resource requires the
1815// Authorization header and chrome fails to propagate it back to the server.
1816// This tests both that testserver.py does not succeed when it should fail as
1817// well as how the downloads extension API exposes the failure to extensions.
1818IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1819 DownloadExtensionTest_Download_AuthBasic_Fail) {
1820 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001821 ASSERT_TRUE(StartEmbeddedTestServer());
1822 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001823 std::string download_url = test_server()->GetURL("auth-basic").spec();
1824 GoOnTheRecord();
1825
1826 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1827 new DownloadsDownloadFunction(), base::StringPrintf(
1828 "[{\"url\": \"%s\","
1829 " \"filename\": \"auth-basic-fail.txt\"}]",
1830 download_url.c_str())));
1831 ASSERT_TRUE(result.get());
1832 int result_id = -1;
1833 ASSERT_TRUE(result->GetAsInteger(&result_id));
1834 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1835 ASSERT_TRUE(item);
1836 ScopedCancellingItem canceller(item);
1837 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1838
Ben Murdoch558790d2013-07-30 15:19:42 +01001839 ASSERT_TRUE(WaitForInterruption(
1840 item,
1841 content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED,
1842 base::StringPrintf("[{\"danger\": \"safe\","
1843 " \"incognito\": false,"
1844 " \"mime\": \"text/html\","
1845 " \"paused\": false,"
1846 " \"url\": \"%s\"}]",
1847 download_url.c_str())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001848}
1849
1850// Test that DownloadsDownloadFunction propagates |headers| to the URLRequest.
1851IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1852 DownloadExtensionTest_Download_Headers) {
1853 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001854 ASSERT_TRUE(StartEmbeddedTestServer());
1855 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001856 std::string download_url = test_server()->GetURL("files/downloads/"
1857 "a_zip_file.zip?expected_headers=Foo:bar&expected_headers=Qx:yo").spec();
1858 GoOnTheRecord();
1859
1860 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1861 new DownloadsDownloadFunction(), base::StringPrintf(
1862 "[{\"url\": \"%s\","
1863 " \"filename\": \"headers-succeed.txt\","
1864 " \"headers\": ["
1865 " {\"name\": \"Foo\", \"value\": \"bar\"},"
1866 " {\"name\": \"Qx\", \"value\":\"yo\"}]}]",
1867 download_url.c_str())));
1868 ASSERT_TRUE(result.get());
1869 int result_id = -1;
1870 ASSERT_TRUE(result->GetAsInteger(&result_id));
1871 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1872 ASSERT_TRUE(item);
1873 ScopedCancellingItem canceller(item);
1874 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1875
1876 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
1877 base::StringPrintf("[{\"danger\": \"safe\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001878 " \"incognito\": false,"
1879 " \"mime\": \"application/octet-stream\","
1880 " \"paused\": false,"
1881 " \"url\": \"%s\"}]",
1882 download_url.c_str())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001883 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1884 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001885 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001886 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001887 " \"current\": \"%s\"}}]",
1888 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001889 GetFilename("headers-succeed.txt").c_str())));
1890 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1891 base::StringPrintf("[{\"id\": %d,"
1892 " \"state\": {"
1893 " \"previous\": \"in_progress\","
1894 " \"current\": \"complete\"}}]",
1895 result_id)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001896}
1897
1898// Test that headers-succeed would fail if the resource requires the headers and
1899// chrome fails to propagate them back to the server. This tests both that
1900// testserver.py does not succeed when it should fail as well as how the
1901// downloads extension api exposes the failure to extensions.
1902IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1903 DownloadExtensionTest_Download_Headers_Fail) {
1904 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001905 ASSERT_TRUE(StartEmbeddedTestServer());
1906 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001907 std::string download_url = test_server()->GetURL("files/downloads/"
1908 "a_zip_file.zip?expected_headers=Foo:bar&expected_headers=Qx:yo").spec();
1909 GoOnTheRecord();
1910
1911 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1912 new DownloadsDownloadFunction(), base::StringPrintf(
1913 "[{\"url\": \"%s\","
1914 " \"filename\": \"headers-fail.txt\"}]",
1915 download_url.c_str())));
1916 ASSERT_TRUE(result.get());
1917 int result_id = -1;
1918 ASSERT_TRUE(result->GetAsInteger(&result_id));
1919 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1920 ASSERT_TRUE(item);
1921 ScopedCancellingItem canceller(item);
1922 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1923
Ben Murdoch558790d2013-07-30 15:19:42 +01001924 ASSERT_TRUE(WaitForInterruption(
1925 item,
1926 content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
1927 base::StringPrintf("[{\"danger\": \"safe\","
1928 " \"incognito\": false,"
1929 " \"bytesReceived\": 0,"
1930 " \"mime\": \"\","
1931 " \"paused\": false,"
1932 " \"url\": \"%s\"}]",
1933 download_url.c_str())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001934}
1935
1936// Test that DownloadsDownloadFunction propagates the Authorization header
1937// correctly.
1938IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1939 DownloadExtensionTest_Download_AuthBasic) {
1940 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001941 ASSERT_TRUE(StartEmbeddedTestServer());
1942 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001943 std::string download_url = test_server()->GetURL("auth-basic").spec();
1944 // This is just base64 of 'username:secret'.
1945 static const char* kAuthorization = "dXNlcm5hbWU6c2VjcmV0";
1946 GoOnTheRecord();
1947
1948 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1949 new DownloadsDownloadFunction(), base::StringPrintf(
1950 "[{\"url\": \"%s\","
1951 " \"filename\": \"auth-basic-succeed.txt\","
1952 " \"headers\": [{"
1953 " \"name\": \"Authorization\","
1954 " \"value\": \"Basic %s\"}]}]",
1955 download_url.c_str(), kAuthorization)));
1956 ASSERT_TRUE(result.get());
1957 int result_id = -1;
1958 ASSERT_TRUE(result->GetAsInteger(&result_id));
1959 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1960 ASSERT_TRUE(item);
1961 ScopedCancellingItem canceller(item);
1962 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
1963
1964 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
1965 base::StringPrintf("[{\"danger\": \"safe\","
1966 " \"incognito\": false,"
1967 " \"mime\": \"text/html\","
1968 " \"paused\": false,"
1969 " \"url\": \"%s\"}]", download_url.c_str())));
1970 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
1971 base::StringPrintf("[{\"id\": %d,"
1972 " \"state\": {"
1973 " \"previous\": \"in_progress\","
1974 " \"current\": \"complete\"}}]", result_id)));
1975}
1976
1977// Test that DownloadsDownloadFunction propagates the |method| and |body|
1978// parameters to the URLRequest.
1979IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
1980 DownloadExtensionTest_Download_Post) {
1981 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01001982 ASSERT_TRUE(StartEmbeddedTestServer());
1983 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001984 std::string download_url = test_server()->GetURL("files/post/downloads/"
1985 "a_zip_file.zip?expected_body=BODY").spec();
1986 GoOnTheRecord();
1987
1988 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
1989 new DownloadsDownloadFunction(), base::StringPrintf(
1990 "[{\"url\": \"%s\","
1991 " \"filename\": \"post-succeed.txt\","
1992 " \"method\": \"POST\","
1993 " \"body\": \"BODY\"}]",
1994 download_url.c_str())));
1995 ASSERT_TRUE(result.get());
1996 int result_id = -1;
1997 ASSERT_TRUE(result->GetAsInteger(&result_id));
1998 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
1999 ASSERT_TRUE(item);
2000 ScopedCancellingItem canceller(item);
2001 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2002
2003 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2004 base::StringPrintf("[{\"danger\": \"safe\","
2005 " \"incognito\": false,"
2006 " \"mime\": \"application/octet-stream\","
2007 " \"paused\": false,"
2008 " \"url\": \"%s\"}]", download_url.c_str())));
2009 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2010 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002011 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002012 " \"previous\": \"\","
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002013 " \"current\": \"%s\"}}]",
2014 result_id,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002015 GetFilename("post-succeed.txt").c_str())));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002016 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2017 base::StringPrintf("[{\"id\": %d,"
2018 " \"state\": {"
2019 " \"previous\": \"in_progress\","
2020 " \"current\": \"complete\"}}]",
2021 result_id)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002022}
2023
2024// Test that downloadPostSuccess would fail if the resource requires the POST
2025// method, and chrome fails to propagate the |method| parameter back to the
2026// server. This tests both that testserver.py does not succeed when it should
2027// fail, and this tests how the downloads extension api exposes the failure to
2028// extensions.
2029IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2030 DownloadExtensionTest_Download_Post_Get) {
2031 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01002032 ASSERT_TRUE(StartEmbeddedTestServer());
2033 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002034 std::string download_url = test_server()->GetURL("files/post/downloads/"
2035 "a_zip_file.zip?expected_body=BODY").spec();
2036 GoOnTheRecord();
2037
2038 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2039 new DownloadsDownloadFunction(), base::StringPrintf(
2040 "[{\"url\": \"%s\","
2041 " \"body\": \"BODY\","
2042 " \"filename\": \"post-get.txt\"}]",
2043 download_url.c_str())));
2044 ASSERT_TRUE(result.get());
2045 int result_id = -1;
2046 ASSERT_TRUE(result->GetAsInteger(&result_id));
2047 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2048 ASSERT_TRUE(item);
2049 ScopedCancellingItem canceller(item);
2050 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2051
Ben Murdoch558790d2013-07-30 15:19:42 +01002052 ASSERT_TRUE(WaitForInterruption(
2053 item,
2054 content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
2055 base::StringPrintf("[{\"danger\": \"safe\","
2056 " \"incognito\": false,"
2057 " \"mime\": \"\","
2058 " \"paused\": false,"
2059 " \"id\": %d,"
2060 " \"url\": \"%s\"}]",
2061 result_id,
2062 download_url.c_str())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002063}
2064
2065// Test that downloadPostSuccess would fail if the resource requires the POST
2066// method, and chrome fails to propagate the |body| parameter back to the
2067// server. This tests both that testserver.py does not succeed when it should
2068// fail, and this tests how the downloads extension api exposes the failure to
2069// extensions.
2070IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2071 DownloadExtensionTest_Download_Post_NoBody) {
2072 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01002073 ASSERT_TRUE(StartEmbeddedTestServer());
2074 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002075 std::string download_url = test_server()->GetURL("files/post/downloads/"
2076 "a_zip_file.zip?expected_body=BODY").spec();
2077 GoOnTheRecord();
2078
2079 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2080 new DownloadsDownloadFunction(), base::StringPrintf(
2081 "[{\"url\": \"%s\","
2082 " \"method\": \"POST\","
2083 " \"filename\": \"post-nobody.txt\"}]",
2084 download_url.c_str())));
2085 ASSERT_TRUE(result.get());
2086 int result_id = -1;
2087 ASSERT_TRUE(result->GetAsInteger(&result_id));
2088 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2089 ASSERT_TRUE(item);
2090 ScopedCancellingItem canceller(item);
2091 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2092
Ben Murdoch558790d2013-07-30 15:19:42 +01002093 ASSERT_TRUE(WaitForInterruption(
2094 item,
2095 content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
2096 base::StringPrintf("[{\"danger\": \"safe\","
2097 " \"incognito\": false,"
2098 " \"mime\": \"\","
2099 " \"paused\": false,"
2100 " \"id\": %d,"
2101 " \"url\": \"%s\"}]",
2102 result_id,
2103 download_url.c_str())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002104}
2105
2106// Test that cancel()ing an in-progress download causes its state to transition
2107// to interrupted, and test that that state transition is detectable by an
2108// onChanged event listener. TODO(benjhayden): Test other sources of
2109// interruptions such as server death.
2110IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2111 DownloadExtensionTest_Download_Cancel) {
2112 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01002113 ASSERT_TRUE(StartEmbeddedTestServer());
2114 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002115 std::string download_url = test_server()->GetURL(
2116 "download-known-size").spec();
2117 GoOnTheRecord();
2118
2119 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2120 new DownloadsDownloadFunction(), base::StringPrintf(
2121 "[{\"url\": \"%s\"}]", download_url.c_str())));
2122 ASSERT_TRUE(result.get());
2123 int result_id = -1;
2124 ASSERT_TRUE(result->GetAsInteger(&result_id));
2125 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2126 ASSERT_TRUE(item);
2127 ScopedCancellingItem canceller(item);
2128 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2129
2130 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2131 base::StringPrintf("[{\"danger\": \"safe\","
2132 " \"incognito\": false,"
2133 " \"mime\": \"application/octet-stream\","
2134 " \"paused\": false,"
2135 " \"id\": %d,"
2136 " \"url\": \"%s\"}]",
2137 result_id,
2138 download_url.c_str())));
2139 item->Cancel(true);
2140 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2141 base::StringPrintf("[{\"id\": %d,"
Ben Murdoch558790d2013-07-30 15:19:42 +01002142 " \"error\": {\"current\":\"USER_CANCELED\"},"
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002143 " \"state\": {"
2144 " \"previous\": \"in_progress\","
2145 " \"current\": \"interrupted\"}}]",
2146 result_id)));
2147}
2148
2149// Test downloading filesystem: URLs.
2150// NOTE: chrome disallows creating HTML5 FileSystem Files in incognito.
2151IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2152 DownloadExtensionTest_Download_FileSystemURL) {
2153 static const char* kPayloadData = "on the record\ndata";
2154 GoOnTheRecord();
2155 LoadExtension("downloads_split");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002156
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01002157 const std::string download_url = "filesystem:" + GetExtensionURL() +
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002158 "temporary/on_record.txt";
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01002159
2160 // Setup a file in the filesystem which we can download.
2161 ASSERT_TRUE(HTML5FileWriter::CreateFileForTesting(
2162 BrowserContext::GetDefaultStoragePartition(browser()->profile())->
2163 GetFileSystemContext(),
2164 fileapi::FileSystemURL::CreateForTest(GURL(download_url)),
2165 kPayloadData, strlen(kPayloadData)));
2166
2167 // Now download it.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002168 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2169 new DownloadsDownloadFunction(), base::StringPrintf(
2170 "[{\"url\": \"%s\"}]", download_url.c_str())));
2171 ASSERT_TRUE(result.get());
2172 int result_id = -1;
2173 ASSERT_TRUE(result->GetAsInteger(&result_id));
2174
2175 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2176 ASSERT_TRUE(item);
2177 ScopedCancellingItem canceller(item);
2178 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2179
2180 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2181 base::StringPrintf("[{\"danger\": \"safe\","
2182 " \"incognito\": false,"
2183 " \"mime\": \"text/plain\","
2184 " \"paused\": false,"
2185 " \"url\": \"%s\"}]",
2186 download_url.c_str())));
2187 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2188 base::StringPrintf("[{\"id\": %d,"
2189 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002190 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002191 " \"current\": \"%s\"}}]",
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002192 result_id,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002193 GetFilename("on_record.txt").c_str())));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002194 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2195 base::StringPrintf("[{\"id\": %d,"
2196 " \"state\": {"
2197 " \"previous\": \"in_progress\","
2198 " \"current\": \"complete\"}}]",
2199 result_id)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002200 std::string disk_data;
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002201 EXPECT_TRUE(file_util::ReadFileToString(item->GetTargetFilePath(),
2202 &disk_data));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002203 EXPECT_STREQ(kPayloadData, disk_data.c_str());
2204}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002205
2206IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
2207 DownloadExtensionTest_OnDeterminingFilename_NoChange) {
2208 GoOnTheRecord();
2209 LoadExtension("downloads_split");
2210 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002211 ASSERT_TRUE(StartEmbeddedTestServer());
2212 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002213 std::string download_url = test_server()->GetURL("slow?0").spec();
2214
2215 // Start downloading a file.
2216 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2217 new DownloadsDownloadFunction(), base::StringPrintf(
2218 "[{\"url\": \"%s\"}]", download_url.c_str())));
2219 ASSERT_TRUE(result.get());
2220 int result_id = -1;
2221 ASSERT_TRUE(result->GetAsInteger(&result_id));
2222 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2223 ASSERT_TRUE(item);
2224 ScopedCancellingItem canceller(item);
2225 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2226
2227 // Wait for the onCreated and onDeterminingFilename events.
2228 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2229 base::StringPrintf("[{\"danger\": \"safe\","
2230 " \"incognito\": false,"
2231 " \"id\": %d,"
2232 " \"mime\": \"text/plain\","
2233 " \"paused\": false,"
2234 " \"url\": \"%s\"}]",
2235 result_id,
2236 download_url.c_str())));
2237 ASSERT_TRUE(WaitFor(
2238 events::kOnDownloadDeterminingFilename,
2239 base::StringPrintf("[{\"id\": %d,"
2240 " \"filename\":\"slow.txt\"}]",
2241 result_id)));
2242 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002243 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002244
2245 // Respond to the onDeterminingFilename.
2246 std::string error;
2247 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
2248 browser()->profile(),
2249 false,
2250 GetExtensionId(),
2251 result_id,
2252 base::FilePath(),
Ben Murdoch558790d2013-07-30 15:19:42 +01002253 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002254 &error));
2255 EXPECT_EQ("", error);
2256
2257 // The download should complete successfully.
2258 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2259 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002260 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002261 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002262 " \"current\": \"%s\"}}]",
2263 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002264 GetFilename("slow.txt").c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002265 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2266 base::StringPrintf("[{\"id\": %d,"
2267 " \"state\": {"
2268 " \"previous\": \"in_progress\","
2269 " \"current\": \"complete\"}}]",
2270 result_id)));
2271}
2272
2273IN_PROC_BROWSER_TEST_F(
2274 DownloadExtensionTest,
2275 DownloadExtensionTest_OnDeterminingFilename_DangerousOverride) {
2276 GoOnTheRecord();
2277 LoadExtension("downloads_split");
2278 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002279 ASSERT_TRUE(StartEmbeddedTestServer());
2280 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002281 std::string download_url = test_server()->GetURL("slow?0").spec();
2282
2283 // Start downloading a file.
2284 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2285 new DownloadsDownloadFunction(), base::StringPrintf(
2286 "[{\"url\": \"%s\"}]", download_url.c_str())));
2287 ASSERT_TRUE(result.get());
2288 int result_id = -1;
2289 ASSERT_TRUE(result->GetAsInteger(&result_id));
2290 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2291 ASSERT_TRUE(item);
2292 ScopedCancellingItem canceller(item);
2293 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2294
2295 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2296 base::StringPrintf("[{\"danger\": \"safe\","
2297 " \"incognito\": false,"
2298 " \"id\": %d,"
2299 " \"mime\": \"text/plain\","
2300 " \"paused\": false,"
2301 " \"url\": \"%s\"}]",
2302 result_id,
2303 download_url.c_str())));
2304 ASSERT_TRUE(WaitFor(
2305 events::kOnDownloadDeterminingFilename,
2306 base::StringPrintf("[{\"id\": %d,"
2307 " \"filename\":\"slow.txt\"}]",
2308 result_id)));
2309 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002310 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002311
2312 // Respond to the onDeterminingFilename.
2313 std::string error;
2314 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
2315 browser()->profile(),
2316 false,
2317 GetExtensionId(),
2318 result_id,
2319 base::FilePath(FILE_PATH_LITERAL("overridden.swf")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002320 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002321 &error));
2322 EXPECT_EQ("", error);
2323
2324 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2325 base::StringPrintf("[{\"id\": %d,"
2326 " \"danger\": {"
2327 " \"previous\":\"safe\","
Ben Murdoch558790d2013-07-30 15:19:42 +01002328 " \"current\":\"file\"}}]",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002329 result_id)));
2330
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002331 item->ValidateDangerousDownload();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002332 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2333 base::StringPrintf("[{\"id\": %d,"
Ben Murdoch558790d2013-07-30 15:19:42 +01002334 " \"danger\": {"
2335 " \"previous\":\"file\","
2336 " \"current\":\"accepted\"}}]",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002337 result_id)));
2338 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2339 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002340 " \"state\": {"
2341 " \"previous\": \"in_progress\","
2342 " \"current\": \"complete\"}}]",
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002343 result_id)));
2344 EXPECT_EQ(downloads_directory().AppendASCII("overridden.swf"),
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002345 item->GetTargetFilePath());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002346}
2347
2348IN_PROC_BROWSER_TEST_F(
2349 DownloadExtensionTest,
2350 DownloadExtensionTest_OnDeterminingFilename_ReferencesParentInvalid) {
2351 GoOnTheRecord();
2352 LoadExtension("downloads_split");
2353 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002354 ASSERT_TRUE(StartEmbeddedTestServer());
2355 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002356 std::string download_url = test_server()->GetURL("slow?0").spec();
2357
2358 // Start downloading a file.
2359 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2360 new DownloadsDownloadFunction(), base::StringPrintf(
2361 "[{\"url\": \"%s\"}]", download_url.c_str())));
2362 ASSERT_TRUE(result.get());
2363 int result_id = -1;
2364 ASSERT_TRUE(result->GetAsInteger(&result_id));
2365 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2366 ASSERT_TRUE(item);
2367 ScopedCancellingItem canceller(item);
2368 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2369
2370 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2371 base::StringPrintf("[{\"danger\": \"safe\","
2372 " \"incognito\": false,"
2373 " \"id\": %d,"
2374 " \"mime\": \"text/plain\","
2375 " \"paused\": false,"
2376 " \"url\": \"%s\"}]",
2377 result_id,
2378 download_url.c_str())));
2379 ASSERT_TRUE(WaitFor(
2380 events::kOnDownloadDeterminingFilename,
2381 base::StringPrintf("[{\"id\": %d,"
2382 " \"filename\":\"slow.txt\"}]",
2383 result_id)));
2384 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002385 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002386
2387 // Respond to the onDeterminingFilename.
2388 std::string error;
2389 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2390 browser()->profile(),
2391 false,
2392 GetExtensionId(),
2393 result_id,
2394 base::FilePath(FILE_PATH_LITERAL("sneaky/../../sneaky.txt")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002395 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002396 &error));
Ben Murdoch558790d2013-07-30 15:19:42 +01002397 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002398 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2399 base::StringPrintf("[{\"id\": %d,"
2400 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002401 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002402 " \"current\": \"%s\"}}]",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002403 result_id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002404 GetFilename("slow.txt").c_str())));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002405 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2406 base::StringPrintf("[{\"id\": %d,"
2407 " \"state\": {"
2408 " \"previous\": \"in_progress\","
2409 " \"current\": \"complete\"}}]",
2410 result_id)));
2411}
2412
2413IN_PROC_BROWSER_TEST_F(
2414 DownloadExtensionTest,
2415 DownloadExtensionTest_OnDeterminingFilename_IllegalFilename) {
2416 GoOnTheRecord();
2417 LoadExtension("downloads_split");
2418 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002419 ASSERT_TRUE(StartEmbeddedTestServer());
2420 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002421 std::string download_url = test_server()->GetURL("slow?0").spec();
2422
2423 // Start downloading a file.
2424 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2425 new DownloadsDownloadFunction(), base::StringPrintf(
2426 "[{\"url\": \"%s\"}]", download_url.c_str())));
2427 ASSERT_TRUE(result.get());
2428 int result_id = -1;
2429 ASSERT_TRUE(result->GetAsInteger(&result_id));
2430 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2431 ASSERT_TRUE(item);
2432 ScopedCancellingItem canceller(item);
2433 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2434
2435 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2436 base::StringPrintf("[{\"danger\": \"safe\","
2437 " \"incognito\": false,"
2438 " \"id\": %d,"
2439 " \"mime\": \"text/plain\","
2440 " \"paused\": false,"
2441 " \"url\": \"%s\"}]",
2442 result_id,
2443 download_url.c_str())));
2444 ASSERT_TRUE(WaitFor(
2445 events::kOnDownloadDeterminingFilename,
2446 base::StringPrintf("[{\"id\": %d,"
2447 " \"filename\":\"slow.txt\"}]",
2448 result_id)));
2449 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002450 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002451
2452 // Respond to the onDeterminingFilename.
2453 std::string error;
2454 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2455 browser()->profile(),
2456 false,
2457 GetExtensionId(),
2458 result_id,
2459 base::FilePath(FILE_PATH_LITERAL("<")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002460 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002461 &error));
Ben Murdoch558790d2013-07-30 15:19:42 +01002462 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002463 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, base::StringPrintf(
2464 "[{\"id\": %d,"
2465 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002466 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002467 " \"current\": \"%s\"}}]",
2468 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002469 GetFilename("slow.txt").c_str())));
2470 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, base::StringPrintf(
2471 "[{\"id\": %d,"
2472 " \"state\": {"
2473 " \"previous\": \"in_progress\","
2474 " \"current\": \"complete\"}}]",
2475 result_id)));
2476}
2477
2478IN_PROC_BROWSER_TEST_F(
2479 DownloadExtensionTest,
2480 DownloadExtensionTest_OnDeterminingFilename_IllegalFilenameExtension) {
2481 GoOnTheRecord();
2482 LoadExtension("downloads_split");
2483 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002484 ASSERT_TRUE(StartEmbeddedTestServer());
2485 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002486 std::string download_url = test_server()->GetURL("slow?0").spec();
2487
2488 // Start downloading a file.
2489 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2490 new DownloadsDownloadFunction(), base::StringPrintf(
2491 "[{\"url\": \"%s\"}]", download_url.c_str())));
2492 ASSERT_TRUE(result.get());
2493 int result_id = -1;
2494 ASSERT_TRUE(result->GetAsInteger(&result_id));
2495 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2496 ASSERT_TRUE(item);
2497 ScopedCancellingItem canceller(item);
2498 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2499
2500 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2501 base::StringPrintf("[{\"danger\": \"safe\","
2502 " \"incognito\": false,"
2503 " \"id\": %d,"
2504 " \"mime\": \"text/plain\","
2505 " \"paused\": false,"
2506 " \"url\": \"%s\"}]",
2507 result_id,
2508 download_url.c_str())));
2509 ASSERT_TRUE(WaitFor(
2510 events::kOnDownloadDeterminingFilename,
2511 base::StringPrintf("[{\"id\": %d,"
2512 " \"filename\":\"slow.txt\"}]",
2513 result_id)));
2514 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002515 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002516
2517 // Respond to the onDeterminingFilename.
2518 std::string error;
2519 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2520 browser()->profile(),
2521 false,
2522 GetExtensionId(),
2523 result_id,
2524 base::FilePath(FILE_PATH_LITERAL(
2525 "My Computer.{20D04FE0-3AEA-1069-A2D8-08002B30309D}/foo")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002526 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002527 &error));
Ben Murdoch558790d2013-07-30 15:19:42 +01002528 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002529 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, base::StringPrintf(
2530 "[{\"id\": %d,"
2531 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002532 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002533 " \"current\": \"%s\"}}]",
2534 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002535 GetFilename("slow.txt").c_str())));
2536 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, base::StringPrintf(
2537 "[{\"id\": %d,"
2538 " \"state\": {"
2539 " \"previous\": \"in_progress\","
2540 " \"current\": \"complete\"}}]",
2541 result_id)));
2542}
2543
2544IN_PROC_BROWSER_TEST_F(
2545 DownloadExtensionTest,
2546 DownloadExtensionTest_OnDeterminingFilename_ReservedFilename) {
2547 GoOnTheRecord();
2548 LoadExtension("downloads_split");
2549 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002550 ASSERT_TRUE(StartEmbeddedTestServer());
2551 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002552 std::string download_url = test_server()->GetURL("slow?0").spec();
2553
2554 // Start downloading a file.
2555 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2556 new DownloadsDownloadFunction(), base::StringPrintf(
2557 "[{\"url\": \"%s\"}]", download_url.c_str())));
2558 ASSERT_TRUE(result.get());
2559 int result_id = -1;
2560 ASSERT_TRUE(result->GetAsInteger(&result_id));
2561 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2562 ASSERT_TRUE(item);
2563 ScopedCancellingItem canceller(item);
2564 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2565
2566 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2567 base::StringPrintf("[{\"danger\": \"safe\","
2568 " \"incognito\": false,"
2569 " \"id\": %d,"
2570 " \"mime\": \"text/plain\","
2571 " \"paused\": false,"
2572 " \"url\": \"%s\"}]",
2573 result_id,
2574 download_url.c_str())));
2575 ASSERT_TRUE(WaitFor(
2576 events::kOnDownloadDeterminingFilename,
2577 base::StringPrintf("[{\"id\": %d,"
2578 " \"filename\":\"slow.txt\"}]",
2579 result_id)));
2580 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002581 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002582
2583 // Respond to the onDeterminingFilename.
2584 std::string error;
2585 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2586 browser()->profile(),
2587 false,
2588 GetExtensionId(),
2589 result_id,
2590 base::FilePath(FILE_PATH_LITERAL("con.foo")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002591 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002592 &error));
Ben Murdoch558790d2013-07-30 15:19:42 +01002593 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002594 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, base::StringPrintf(
2595 "[{\"id\": %d,"
2596 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002597 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002598 " \"current\": \"%s\"}}]",
2599 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002600 GetFilename("slow.txt").c_str())));
2601 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, base::StringPrintf(
2602 "[{\"id\": %d,"
2603 " \"state\": {"
2604 " \"previous\": \"in_progress\","
2605 " \"current\": \"complete\"}}]",
2606 result_id)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002607}
2608
2609IN_PROC_BROWSER_TEST_F(
2610 DownloadExtensionTest,
2611 DownloadExtensionTest_OnDeterminingFilename_CurDirInvalid) {
2612 GoOnTheRecord();
2613 LoadExtension("downloads_split");
2614 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002615 ASSERT_TRUE(StartEmbeddedTestServer());
2616 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002617 std::string download_url = test_server()->GetURL("slow?0").spec();
2618
2619 // Start downloading a file.
2620 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2621 new DownloadsDownloadFunction(), base::StringPrintf(
2622 "[{\"url\": \"%s\"}]", download_url.c_str())));
2623 ASSERT_TRUE(result.get());
2624 int result_id = -1;
2625 ASSERT_TRUE(result->GetAsInteger(&result_id));
2626 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2627 ASSERT_TRUE(item);
2628 ScopedCancellingItem canceller(item);
2629 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2630
2631 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2632 base::StringPrintf("[{\"danger\": \"safe\","
2633 " \"incognito\": false,"
2634 " \"id\": %d,"
2635 " \"mime\": \"text/plain\","
2636 " \"paused\": false,"
2637 " \"url\": \"%s\"}]",
2638 result_id,
2639 download_url.c_str())));
2640 ASSERT_TRUE(WaitFor(
2641 events::kOnDownloadDeterminingFilename,
2642 base::StringPrintf("[{\"id\": %d,"
2643 " \"filename\":\"slow.txt\"}]",
2644 result_id)));
2645 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002646 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002647
2648 // Respond to the onDeterminingFilename.
2649 std::string error;
2650 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2651 browser()->profile(),
2652 false,
2653 GetExtensionId(),
2654 result_id,
2655 base::FilePath(FILE_PATH_LITERAL(".")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002656 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002657 &error));
Ben Murdoch558790d2013-07-30 15:19:42 +01002658 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002659 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2660 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002661 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002662 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002663 " \"current\": \"%s\"}}]",
2664 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002665 GetFilename("slow.txt").c_str())));
2666 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2667 base::StringPrintf("[{\"id\": %d,"
2668 " \"state\": {"
2669 " \"previous\": \"in_progress\","
2670 " \"current\": \"complete\"}}]",
2671 result_id)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002672}
2673
2674IN_PROC_BROWSER_TEST_F(
2675 DownloadExtensionTest,
2676 DownloadExtensionTest_OnDeterminingFilename_ParentDirInvalid) {
Ben Murdocheb525c52013-07-10 11:40:50 +01002677 ASSERT_TRUE(StartEmbeddedTestServer());
2678 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002679 GoOnTheRecord();
2680 LoadExtension("downloads_split");
2681 AddFilenameDeterminer();
2682 std::string download_url = test_server()->GetURL("slow?0").spec();
2683
2684 // Start downloading a file.
2685 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2686 new DownloadsDownloadFunction(), base::StringPrintf(
2687 "[{\"url\": \"%s\"}]", download_url.c_str())));
2688 ASSERT_TRUE(result.get());
2689 int result_id = -1;
2690 ASSERT_TRUE(result->GetAsInteger(&result_id));
2691 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2692 ASSERT_TRUE(item);
2693 ScopedCancellingItem canceller(item);
2694 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2695
2696 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2697 base::StringPrintf("[{\"danger\": \"safe\","
2698 " \"incognito\": false,"
2699 " \"id\": %d,"
2700 " \"mime\": \"text/plain\","
2701 " \"paused\": false,"
2702 " \"url\": \"%s\"}]",
2703 result_id,
2704 download_url.c_str())));
2705 ASSERT_TRUE(WaitFor(
2706 events::kOnDownloadDeterminingFilename,
2707 base::StringPrintf("[{\"id\": %d,"
2708 " \"filename\":\"slow.txt\"}]",
2709 result_id)));
2710 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002711 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002712
2713 // Respond to the onDeterminingFilename.
2714 std::string error;
2715 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2716 browser()->profile(),
2717 false,
2718 GetExtensionId(),
2719 result_id,
2720 base::FilePath(FILE_PATH_LITERAL("..")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002721 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002722 &error));
Ben Murdoch558790d2013-07-30 15:19:42 +01002723 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002724 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2725 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002726 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002727 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002728 " \"current\": \"%s\"}}]",
2729 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002730 GetFilename("slow.txt").c_str())));
2731 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2732 base::StringPrintf("[{\"id\": %d,"
2733 " \"state\": {"
2734 " \"previous\": \"in_progress\","
2735 " \"current\": \"complete\"}}]",
2736 result_id)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002737}
2738
2739IN_PROC_BROWSER_TEST_F(
2740 DownloadExtensionTest,
2741 DownloadExtensionTest_OnDeterminingFilename_AbsPathInvalid) {
2742 GoOnTheRecord();
2743 LoadExtension("downloads_split");
2744 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002745 ASSERT_TRUE(StartEmbeddedTestServer());
2746 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002747 std::string download_url = test_server()->GetURL("slow?0").spec();
2748
2749 // Start downloading a file.
2750 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2751 new DownloadsDownloadFunction(), base::StringPrintf(
2752 "[{\"url\": \"%s\"}]", download_url.c_str())));
2753 ASSERT_TRUE(result.get());
2754 int result_id = -1;
2755 ASSERT_TRUE(result->GetAsInteger(&result_id));
2756 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2757 ASSERT_TRUE(item);
2758 ScopedCancellingItem canceller(item);
2759 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2760
2761 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2762 base::StringPrintf("[{\"danger\": \"safe\","
2763 " \"incognito\": false,"
2764 " \"id\": %d,"
2765 " \"mime\": \"text/plain\","
2766 " \"paused\": false,"
2767 " \"url\": \"%s\"}]",
2768 result_id,
2769 download_url.c_str())));
2770 ASSERT_TRUE(WaitFor(
2771 events::kOnDownloadDeterminingFilename,
2772 base::StringPrintf("[{\"id\": %d,"
2773 " \"filename\":\"slow.txt\"}]",
2774 result_id)));
2775 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002776 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002777
2778 // Respond to the onDeterminingFilename. Absolute paths should be rejected.
2779 std::string error;
2780 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2781 browser()->profile(),
2782 false,
2783 GetExtensionId(),
2784 result_id,
2785 downloads_directory().Append(FILE_PATH_LITERAL("sneaky.txt")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002786 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002787 &error));
Ben Murdoch558790d2013-07-30 15:19:42 +01002788 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002789
2790 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2791 base::StringPrintf("[{\"id\": %d,"
2792 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002793 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002794 " \"current\": \"%s\"}}]",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002795 result_id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002796 GetFilename("slow.txt").c_str())));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002797 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2798 base::StringPrintf("[{\"id\": %d,"
2799 " \"state\": {"
2800 " \"previous\": \"in_progress\","
2801 " \"current\": \"complete\"}}]",
2802 result_id)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002803}
2804
2805IN_PROC_BROWSER_TEST_F(
2806 DownloadExtensionTest,
2807 DownloadExtensionTest_OnDeterminingFilename_EmptyBasenameInvalid) {
2808 GoOnTheRecord();
2809 LoadExtension("downloads_split");
2810 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002811 ASSERT_TRUE(StartEmbeddedTestServer());
2812 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002813 std::string download_url = test_server()->GetURL("slow?0").spec();
2814
2815 // Start downloading a file.
2816 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2817 new DownloadsDownloadFunction(), base::StringPrintf(
2818 "[{\"url\": \"%s\"}]", download_url.c_str())));
2819 ASSERT_TRUE(result.get());
2820 int result_id = -1;
2821 ASSERT_TRUE(result->GetAsInteger(&result_id));
2822 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2823 ASSERT_TRUE(item);
2824 ScopedCancellingItem canceller(item);
2825 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2826
2827 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2828 base::StringPrintf("[{\"danger\": \"safe\","
2829 " \"incognito\": false,"
2830 " \"id\": %d,"
2831 " \"mime\": \"text/plain\","
2832 " \"paused\": false,"
2833 " \"url\": \"%s\"}]",
2834 result_id,
2835 download_url.c_str())));
2836 ASSERT_TRUE(WaitFor(
2837 events::kOnDownloadDeterminingFilename,
2838 base::StringPrintf("[{\"id\": %d,"
2839 " \"filename\":\"slow.txt\"}]",
2840 result_id)));
2841 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002842 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002843
2844 // Respond to the onDeterminingFilename. Empty basenames should be rejected.
2845 std::string error;
2846 ASSERT_FALSE(ExtensionDownloadsEventRouter::DetermineFilename(
2847 browser()->profile(),
2848 false,
2849 GetExtensionId(),
2850 result_id,
2851 base::FilePath(FILE_PATH_LITERAL("foo/")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002852 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002853 &error));
Ben Murdoch558790d2013-07-30 15:19:42 +01002854 EXPECT_STREQ(errors::kInvalidFilename, error.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002855
2856 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2857 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002858 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002859 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002860 " \"current\": \"%s\"}}]",
2861 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002862 GetFilename("slow.txt").c_str())));
2863 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2864 base::StringPrintf("[{\"id\": %d,"
2865 " \"state\": {"
2866 " \"previous\": \"in_progress\","
2867 " \"current\": \"complete\"}}]",
2868 result_id)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002869}
2870
2871IN_PROC_BROWSER_TEST_F(
2872 DownloadExtensionTest,
2873 DownloadExtensionTest_OnDeterminingFilename_Override) {
2874 GoOnTheRecord();
2875 LoadExtension("downloads_split");
2876 AddFilenameDeterminer();
Ben Murdocheb525c52013-07-10 11:40:50 +01002877 ASSERT_TRUE(StartEmbeddedTestServer());
2878 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002879 std::string download_url = test_server()->GetURL("slow?0").spec();
2880
2881 // Start downloading a file.
2882 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
2883 new DownloadsDownloadFunction(), base::StringPrintf(
2884 "[{\"url\": \"%s\"}]", download_url.c_str())));
2885 ASSERT_TRUE(result.get());
2886 int result_id = -1;
2887 ASSERT_TRUE(result->GetAsInteger(&result_id));
2888 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
2889 ASSERT_TRUE(item);
2890 ScopedCancellingItem canceller(item);
2891 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2892 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2893 base::StringPrintf("[{\"danger\": \"safe\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002894 " \"incognito\": false,"
2895 " \"id\": %d,"
2896 " \"mime\": \"text/plain\","
2897 " \"paused\": false,"
2898 " \"url\": \"%s\"}]",
2899 result_id,
2900 download_url.c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002901 ASSERT_TRUE(WaitFor(
2902 events::kOnDownloadDeterminingFilename,
2903 base::StringPrintf("[{\"id\": %d,"
2904 " \"filename\":\"slow.txt\"}]",
2905 result_id)));
2906 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002907 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002908
2909 // Respond to the onDeterminingFilename.
2910 std::string error;
2911 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
2912 browser()->profile(),
2913 false,
2914 GetExtensionId(),
2915 result_id,
2916 base::FilePath(),
Ben Murdoch558790d2013-07-30 15:19:42 +01002917 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002918 &error));
2919 EXPECT_EQ("", error);
2920
2921 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2922 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002923 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002924 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002925 " \"current\": \"%s\"}}]",
2926 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002927 GetFilename("slow.txt").c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002928 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2929 base::StringPrintf("[{\"id\": %d,"
2930 " \"state\": {"
2931 " \"previous\": \"in_progress\","
2932 " \"current\": \"complete\"}}]",
2933 result_id)));
2934
2935 // Start downloading a file.
2936 result.reset(RunFunctionAndReturnResult(
2937 new DownloadsDownloadFunction(), base::StringPrintf(
2938 "[{\"url\": \"%s\"}]", download_url.c_str())));
2939 ASSERT_TRUE(result.get());
2940 result_id = -1;
2941 ASSERT_TRUE(result->GetAsInteger(&result_id));
2942 item = GetCurrentManager()->GetDownload(result_id);
2943 ASSERT_TRUE(item);
2944 ScopedCancellingItem canceller2(item);
2945 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
2946
2947 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
2948 base::StringPrintf("[{\"danger\": \"safe\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002949 " \"incognito\": false,"
2950 " \"id\": %d,"
2951 " \"mime\": \"text/plain\","
2952 " \"paused\": false,"
2953 " \"url\": \"%s\"}]",
2954 result_id,
2955 download_url.c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002956 ASSERT_TRUE(WaitFor(
2957 events::kOnDownloadDeterminingFilename,
2958 base::StringPrintf("[{\"id\": %d,"
2959 " \"filename\":\"slow.txt\"}]",
2960 result_id)));
2961 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002962 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002963
2964 // Respond to the onDeterminingFilename.
2965 // Also test that DetermineFilename allows (chrome) extensions to set
2966 // filenames without (filename) extensions. (Don't ask about v8 extensions or
2967 // python extensions or kernel extensions or firefox extensions...)
2968 error = "";
2969 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
2970 browser()->profile(),
2971 false,
2972 GetExtensionId(),
2973 result_id,
2974 base::FilePath(FILE_PATH_LITERAL("foo")),
Ben Murdoch558790d2013-07-30 15:19:42 +01002975 api::FILENAME_CONFLICT_ACTION_OVERWRITE,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002976 &error));
2977 EXPECT_EQ("", error);
2978
2979 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2980 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002981 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002982 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002983 " \"current\": \"%s\"}}]",
2984 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002985 GetFilename("foo").c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002986 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
2987 base::StringPrintf("[{\"id\": %d,"
2988 " \"state\": {"
2989 " \"previous\": \"in_progress\","
2990 " \"current\": \"complete\"}}]",
2991 result_id)));
2992}
2993
2994// TODO test precedence rules: install_time
2995
2996IN_PROC_BROWSER_TEST_F(
2997 DownloadExtensionTest,
2998 DownloadExtensionTest_OnDeterminingFilename_RemoveFilenameDeterminer) {
Ben Murdocheb525c52013-07-10 11:40:50 +01002999 ASSERT_TRUE(StartEmbeddedTestServer());
3000 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003001 GoOnTheRecord();
3002 LoadExtension("downloads_split");
3003 content::RenderProcessHost* host = AddFilenameDeterminer();
3004 std::string download_url = test_server()->GetURL("slow?0").spec();
3005
3006 // Start downloading a file.
3007 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3008 new DownloadsDownloadFunction(), base::StringPrintf(
3009 "[{\"url\": \"%s\"}]", download_url.c_str())));
3010 ASSERT_TRUE(result.get());
3011 int result_id = -1;
3012 ASSERT_TRUE(result->GetAsInteger(&result_id));
3013 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3014 ASSERT_TRUE(item);
3015 ScopedCancellingItem canceller(item);
3016 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3017
3018 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
3019 base::StringPrintf("[{\"danger\": \"safe\","
3020 " \"incognito\": false,"
3021 " \"id\": %d,"
3022 " \"mime\": \"text/plain\","
3023 " \"paused\": false,"
3024 " \"url\": \"%s\"}]",
3025 result_id,
3026 download_url.c_str())));
3027 ASSERT_TRUE(WaitFor(
3028 events::kOnDownloadDeterminingFilename,
3029 base::StringPrintf("[{\"id\": %d,"
3030 " \"filename\":\"slow.txt\"}]",
3031 result_id)));
3032 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003033 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003034
3035 // Remove a determiner while waiting for it.
3036 RemoveFilenameDeterminer(host);
3037
3038 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3039 base::StringPrintf("[{\"id\": %d,"
3040 " \"state\": {"
3041 " \"previous\": \"in_progress\","
3042 " \"current\": \"complete\"}}]",
3043 result_id)));
3044}
3045
3046IN_PROC_BROWSER_TEST_F(
3047 DownloadExtensionTest,
3048 DownloadExtensionTest_OnDeterminingFilename_IncognitoSplit) {
3049 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01003050 ASSERT_TRUE(StartEmbeddedTestServer());
3051 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003052 std::string download_url = test_server()->GetURL("slow?0").spec();
3053
3054 GoOnTheRecord();
3055 AddFilenameDeterminer();
3056
3057 GoOffTheRecord();
3058 AddFilenameDeterminer();
3059
3060 // Start an on-record download.
3061 GoOnTheRecord();
3062 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3063 new DownloadsDownloadFunction(), base::StringPrintf(
3064 "[{\"url\": \"%s\"}]", download_url.c_str())));
3065 ASSERT_TRUE(result.get());
3066 int result_id = -1;
3067 ASSERT_TRUE(result->GetAsInteger(&result_id));
3068 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3069 ASSERT_TRUE(item);
3070 ScopedCancellingItem canceller(item);
3071 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3072
3073 // Wait for the onCreated and onDeterminingFilename events.
3074 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
3075 base::StringPrintf("[{\"danger\": \"safe\","
3076 " \"incognito\": false,"
3077 " \"id\": %d,"
3078 " \"mime\": \"text/plain\","
3079 " \"paused\": false,"
3080 " \"url\": \"%s\"}]",
3081 result_id,
3082 download_url.c_str())));
3083 ASSERT_TRUE(WaitFor(
3084 events::kOnDownloadDeterminingFilename,
3085 base::StringPrintf("[{\"id\": %d,"
3086 " \"incognito\": false,"
3087 " \"filename\":\"slow.txt\"}]",
3088 result_id)));
3089 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003090 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003091
3092 // Respond to the onDeterminingFilename events.
3093 std::string error;
3094 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3095 current_browser()->profile(),
3096 false,
3097 GetExtensionId(),
3098 result_id,
3099 base::FilePath(FILE_PATH_LITERAL("42.txt")),
Ben Murdoch558790d2013-07-30 15:19:42 +01003100 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003101 &error));
3102 EXPECT_EQ("", error);
3103
3104 // The download should complete successfully.
3105 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3106 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003107 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01003108 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003109 " \"current\": \"%s\"}}]",
3110 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003111 GetFilename("42.txt").c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003112 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3113 base::StringPrintf("[{\"id\": %d,"
3114 " \"state\": {"
3115 " \"previous\": \"in_progress\","
3116 " \"current\": \"complete\"}}]",
3117 result_id)));
3118
3119 // Start an incognito download for comparison.
3120 GoOffTheRecord();
3121 result.reset(RunFunctionAndReturnResult(
3122 new DownloadsDownloadFunction(), base::StringPrintf(
3123 "[{\"url\": \"%s\"}]", download_url.c_str())));
3124 ASSERT_TRUE(result.get());
3125 result_id = -1;
3126 ASSERT_TRUE(result->GetAsInteger(&result_id));
3127 item = GetCurrentManager()->GetDownload(result_id);
3128 ASSERT_TRUE(item);
3129 ScopedCancellingItem canceller2(item);
3130 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3131
3132 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
3133 base::StringPrintf("[{\"danger\": \"safe\","
3134 " \"incognito\": true,"
3135 " \"id\": %d,"
3136 " \"mime\": \"text/plain\","
3137 " \"paused\": false,"
3138 " \"url\": \"%s\"}]",
3139 result_id,
3140 download_url.c_str())));
3141 // On-Record renderers should not see events for off-record items.
3142 ASSERT_TRUE(WaitFor(
3143 events::kOnDownloadDeterminingFilename,
3144 base::StringPrintf("[{\"id\": %d,"
3145 " \"incognito\": true,"
3146 " \"filename\":\"slow.txt\"}]",
3147 result_id)));
3148 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003149 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003150
3151 // Respond to the onDeterminingFilename.
3152 error = "";
3153 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3154 current_browser()->profile(),
3155 false,
3156 GetExtensionId(),
3157 result_id,
3158 base::FilePath(FILE_PATH_LITERAL("5.txt")),
Ben Murdoch558790d2013-07-30 15:19:42 +01003159 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003160 &error));
3161 EXPECT_EQ("", error);
3162
3163 // The download should complete successfully.
3164 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3165 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003166 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01003167 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003168 " \"current\": \"%s\"}}]",
3169 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003170 GetFilename("5.txt").c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003171 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3172 base::StringPrintf("[{\"id\": %d,"
3173 " \"state\": {"
3174 " \"previous\": \"in_progress\","
3175 " \"current\": \"complete\"}}]",
3176 result_id)));
3177}
3178
3179IN_PROC_BROWSER_TEST_F(
3180 DownloadExtensionTest,
3181 DownloadExtensionTest_OnDeterminingFilename_IncognitoSpanning) {
3182 LoadExtension("downloads_spanning");
Ben Murdocheb525c52013-07-10 11:40:50 +01003183 ASSERT_TRUE(StartEmbeddedTestServer());
3184 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003185 std::string download_url = test_server()->GetURL("slow?0").spec();
3186
3187 GoOnTheRecord();
3188 AddFilenameDeterminer();
3189
3190 // There is a single extension renderer that sees both on-record and
3191 // off-record events. The extension functions see the on-record profile with
3192 // include_incognito=true.
3193
3194 // Start an on-record download.
3195 GoOnTheRecord();
3196 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(
3197 new DownloadsDownloadFunction(), base::StringPrintf(
3198 "[{\"url\": \"%s\"}]", download_url.c_str())));
3199 ASSERT_TRUE(result.get());
3200 int result_id = -1;
3201 ASSERT_TRUE(result->GetAsInteger(&result_id));
3202 DownloadItem* item = GetCurrentManager()->GetDownload(result_id);
3203 ASSERT_TRUE(item);
3204 ScopedCancellingItem canceller(item);
3205 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3206
3207 // Wait for the onCreated and onDeterminingFilename events.
3208 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
3209 base::StringPrintf("[{\"danger\": \"safe\","
3210 " \"incognito\": false,"
3211 " \"id\": %d,"
3212 " \"mime\": \"text/plain\","
3213 " \"paused\": false,"
3214 " \"url\": \"%s\"}]",
3215 result_id,
3216 download_url.c_str())));
3217 ASSERT_TRUE(WaitFor(
3218 events::kOnDownloadDeterminingFilename,
3219 base::StringPrintf("[{\"id\": %d,"
3220 " \"incognito\": false,"
3221 " \"filename\":\"slow.txt\"}]",
3222 result_id)));
3223 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003224 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003225
3226 // Respond to the onDeterminingFilename events.
3227 std::string error;
3228 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3229 current_browser()->profile(),
3230 true,
3231 GetExtensionId(),
3232 result_id,
3233 base::FilePath(FILE_PATH_LITERAL("42.txt")),
Ben Murdoch558790d2013-07-30 15:19:42 +01003234 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003235 &error));
3236 EXPECT_EQ("", error);
3237
3238 // The download should complete successfully.
3239 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3240 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003241 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01003242 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003243 " \"current\": \"%s\"}}]",
3244 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003245 GetFilename("42.txt").c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003246 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3247 base::StringPrintf("[{\"id\": %d,"
3248 " \"state\": {"
3249 " \"previous\": \"in_progress\","
3250 " \"current\": \"complete\"}}]",
3251 result_id)));
3252
3253 // Start an incognito download for comparison.
3254 GoOffTheRecord();
3255 result.reset(RunFunctionAndReturnResult(
3256 new DownloadsDownloadFunction(), base::StringPrintf(
3257 "[{\"url\": \"%s\"}]", download_url.c_str())));
3258 ASSERT_TRUE(result.get());
3259 result_id = -1;
3260 ASSERT_TRUE(result->GetAsInteger(&result_id));
3261 item = GetCurrentManager()->GetDownload(result_id);
3262 ASSERT_TRUE(item);
3263 ScopedCancellingItem canceller2(item);
3264 ASSERT_EQ(download_url, item->GetOriginalUrl().spec());
3265
3266 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
3267 base::StringPrintf("[{\"danger\": \"safe\","
3268 " \"incognito\": true,"
3269 " \"id\": %d,"
3270 " \"mime\": \"text/plain\","
3271 " \"paused\": false,"
3272 " \"url\": \"%s\"}]",
3273 result_id,
3274 download_url.c_str())));
3275 ASSERT_TRUE(WaitFor(
3276 events::kOnDownloadDeterminingFilename,
3277 base::StringPrintf("[{\"id\": %d,"
3278 " \"incognito\": true,"
3279 " \"filename\":\"slow.txt\"}]",
3280 result_id)));
3281 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003282 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003283
3284 // Respond to the onDeterminingFilename.
3285 error = "";
3286 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3287 current_browser()->profile(),
3288 true,
3289 GetExtensionId(),
3290 result_id,
3291 base::FilePath(FILE_PATH_LITERAL("42.txt")),
Ben Murdoch558790d2013-07-30 15:19:42 +01003292 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003293 &error));
3294 EXPECT_EQ("", error);
3295
3296 // The download should complete successfully.
3297 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3298 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003299 " \"filename\": {"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01003300 " \"previous\": \"\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003301 " \"current\": \"%s\"}}]",
3302 result_id,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003303 GetFilename("42 (1).txt").c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003304 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3305 base::StringPrintf("[{\"id\": %d,"
3306 " \"state\": {"
3307 " \"previous\": \"in_progress\","
3308 " \"current\": \"complete\"}}]",
3309 result_id)));
3310}
3311
Torne (Richard Coles)5e3f23d2013-06-11 16:24:11 +01003312#if defined(OS_WIN)
3313// This test is very flaky on Win XP and Aura. http://crbug.com/248438
3314#define MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume \
3315 DISABLED_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume
3316#else
3317#define MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume \
3318 DownloadExtensionTest_OnDeterminingFilename_InterruptedResume
3319#endif
3320
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003321// Test download interruption while extensions determining filename. Should not
3322// re-dispatch onDeterminingFilename.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003323IN_PROC_BROWSER_TEST_F(
3324 DownloadExtensionTest,
Torne (Richard Coles)5e3f23d2013-06-11 16:24:11 +01003325 MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003326 CommandLine::ForCurrentProcess()->AppendSwitch(
3327 switches::kEnableDownloadResumption);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003328 LoadExtension("downloads_split");
Ben Murdocheb525c52013-07-10 11:40:50 +01003329 ASSERT_TRUE(StartEmbeddedTestServer());
3330 ASSERT_TRUE(test_server()->Start());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003331 GoOnTheRecord();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01003332 content::RenderProcessHost* host = AddFilenameDeterminer();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003333
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003334 // Start a download.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003335 DownloadItem* item = NULL;
3336 {
3337 DownloadManager* manager = GetCurrentManager();
3338 scoped_ptr<content::DownloadTestObserver> observer(
3339 new JustInProgressDownloadObserver(manager, 1));
3340 ASSERT_EQ(0, manager->InProgressCount());
3341 // Tabs created just for a download are automatically closed, invalidating
3342 // the download's WebContents. Downloads without WebContents cannot be
3343 // resumed. http://crbug.com/225901
3344 ui_test_utils::NavigateToURLWithDisposition(
3345 current_browser(),
3346 GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl),
3347 CURRENT_TAB,
3348 ui_test_utils::BROWSER_TEST_NONE);
3349 observer->WaitForFinished();
3350 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
3351 DownloadManager::DownloadVector items;
3352 manager->GetAllDownloads(&items);
3353 for (DownloadManager::DownloadVector::iterator iter = items.begin();
3354 iter != items.end(); ++iter) {
3355 if ((*iter)->GetState() == DownloadItem::IN_PROGRESS) {
3356 // There should be only one IN_PROGRESS item.
3357 EXPECT_EQ(NULL, item);
3358 item = *iter;
3359 }
3360 }
3361 ASSERT_TRUE(item);
3362 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003363 ScopedCancellingItem canceller(item);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003364
3365 // Wait for the onCreated and onDeterminingFilename event.
3366 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated,
3367 base::StringPrintf("[{\"danger\": \"safe\","
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003368 " \"incognito\": false,"
3369 " \"id\": %d,"
3370 " \"mime\": \"application/octet-stream\","
3371 " \"paused\": false}]",
3372 item->GetId())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003373 ASSERT_TRUE(WaitFor(
3374 events::kOnDownloadDeterminingFilename,
3375 base::StringPrintf("[{\"id\": %d,"
3376 " \"incognito\": false,"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003377 " \"filename\":\"download-unknown-size\"}]",
3378 item->GetId())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003379 ASSERT_TRUE(item->GetTargetFilePath().empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003380 ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003381
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003382 ClearEvents();
3383 ui_test_utils::NavigateToURLWithDisposition(
3384 current_browser(),
3385 GURL(URLRequestSlowDownloadJob::kErrorDownloadUrl),
3386 NEW_BACKGROUND_TAB,
3387 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003388
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003389 // Errors caught before filename determination are delayed until after
3390 // filename determination.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003391 std::string error;
3392 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename(
3393 current_browser()->profile(),
3394 false,
3395 GetExtensionId(),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003396 item->GetId(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003397 base::FilePath(FILE_PATH_LITERAL("42.txt")),
Ben Murdoch558790d2013-07-30 15:19:42 +01003398 api::FILENAME_CONFLICT_ACTION_UNIQUIFY,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003399 &error)) << error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003400 EXPECT_EQ("", error);
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01003401 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3402 base::StringPrintf("[{\"id\": %d,"
3403 " \"filename\": {"
3404 " \"previous\": \"\","
3405 " \"current\": \"%s\"}}]",
3406 item->GetId(),
3407 GetFilename("42.txt").c_str())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003408
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003409 content::DownloadUpdatedObserver interrupted(item, base::Bind(
3410 ItemIsInterrupted));
3411 ASSERT_TRUE(interrupted.WaitForEvent());
3412 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3413 base::StringPrintf("[{\"id\": %d,"
Ben Murdoch558790d2013-07-30 15:19:42 +01003414 " \"error\":{\"current\":\"NETWORK_FAILED\"},"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003415 " \"state\":{"
3416 " \"previous\":\"in_progress\","
3417 " \"current\":\"interrupted\"}}]",
3418 item->GetId())));
3419
3420 ClearEvents();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01003421 // Downloads that are restarted on resumption trigger another download target
3422 // determination.
3423 RemoveFilenameDeterminer(host);
3424 item->Resume();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003425
3426 // Errors caught before filename determination is complete are delayed until
3427 // after filename determination so that, on resumption, filename determination
3428 // does not need to be re-done. So, there will not be a second
3429 // onDeterminingFilename event.
3430
3431 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3432 base::StringPrintf("[{\"id\": %d,"
Ben Murdoch558790d2013-07-30 15:19:42 +01003433 " \"error\":{\"previous\":\"NETWORK_FAILED\"},"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003434 " \"state\":{"
3435 " \"previous\":\"interrupted\","
3436 " \"current\":\"in_progress\"}}]",
3437 item->GetId())));
3438
3439 ClearEvents();
3440 FinishPendingSlowDownloads();
3441
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003442 // The download should complete successfully.
3443 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged,
3444 base::StringPrintf("[{\"id\": %d,"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003445 " \"state\": {"
3446 " \"previous\": \"in_progress\","
3447 " \"current\": \"complete\"}}]",
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003448 item->GetId())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003449}
3450
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01003451IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
3452 DownloadExtensionTest_SetShelfEnabled) {
3453 LoadExtension("downloads_split");
3454 EXPECT_TRUE(RunFunction(new DownloadsSetShelfEnabledFunction(), "[false]"));
3455 EXPECT_FALSE(DownloadServiceFactory::GetForBrowserContext(
3456 browser()->profile())->IsShelfEnabled());
3457 EXPECT_TRUE(RunFunction(new DownloadsSetShelfEnabledFunction(), "[true]"));
3458 EXPECT_TRUE(DownloadServiceFactory::GetForBrowserContext(
3459 browser()->profile())->IsShelfEnabled());
3460 // TODO(benjhayden) Test that existing shelves are hidden.
3461 // TODO(benjhayden) Test multiple extensions.
3462 // TODO(benjhayden) Test disabling extensions.
3463 // TODO(benjhayden) Test that browsers associated with other profiles are not
3464 // affected.
3465 // TODO(benjhayden) Test incognito.
3466}
3467
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003468// TODO(benjhayden) Figure out why DisableExtension() does not fire
3469// OnListenerRemoved.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003470
3471// TODO(benjhayden) Test that the shelf is shown for download() both with and
3472// without a WebContents.
3473
3474class DownloadsApiTest : public ExtensionApiTest {
3475 public:
3476 DownloadsApiTest() {}
3477 virtual ~DownloadsApiTest() {}
3478 private:
3479 DISALLOW_COPY_AND_ASSIGN(DownloadsApiTest);
3480};
3481
3482
3483IN_PROC_BROWSER_TEST_F(DownloadsApiTest, DownloadsApiTest) {
3484 ASSERT_TRUE(RunExtensionTest("downloads")) << message_;
3485}
Ben Murdoch558790d2013-07-30 15:19:42 +01003486
Ben Murdoch558790d2013-07-30 15:19:42 +01003487TEST(DownloadInterruptReasonEnumsSynced,
3488 DownloadInterruptReasonEnumsSynced) {
3489#define INTERRUPT_REASON(name, value) \
3490 EXPECT_EQ(InterruptReasonContentToExtension( \
3491 content::DOWNLOAD_INTERRUPT_REASON_##name), \
3492 api::INTERRUPT_REASON_##name); \
3493 EXPECT_EQ(InterruptReasonExtensionToContent( \
3494 api::INTERRUPT_REASON_##name), \
3495 content::DOWNLOAD_INTERRUPT_REASON_##name);
3496#include "content/public/browser/download_interrupt_reason_values.h"
3497#undef INTERRUPT_REASON
3498}