| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <algorithm> | |
| 6 | |
| 7 #include "base/file_util.h" | |
| 8 #include "base/scoped_temp_dir.h" | |
| 9 #include "base/stringprintf.h" | |
| 10 #include "chrome/browser/download/download_extension_api.h" | |
| 11 #include "chrome/browser/download/download_file_icon_extractor.h" | |
| 12 #include "chrome/browser/download/download_service.h" | |
| 13 #include "chrome/browser/download/download_service_factory.h" | |
| 14 #include "chrome/browser/download/download_test_observer.h" | |
| 15 #include "chrome/browser/extensions/extension_function_test_utils.h" | |
| 16 #include "chrome/browser/net/url_request_mock_util.h" | |
| 17 #include "chrome/browser/prefs/pref_service.h" | |
| 18 #include "chrome/browser/profiles/profile.h" | |
| 19 #include "chrome/browser/ui/browser.h" | |
| 20 #include "chrome/common/pref_names.h" | |
| 21 #include "chrome/test/base/in_process_browser_test.h" | |
| 22 #include "chrome/test/base/ui_test_utils.h" | |
| 23 #include "content/public/browser/browser_thread.h" | |
| 24 #include "content/public/browser/download_manager.h" | |
| 25 #include "content/public/browser/download_persistent_store_info.h" | |
| 26 #include "content/test/net/url_request_slow_download_job.h" | |
| 27 #include "net/base/data_url.h" | |
| 28 #include "net/base/net_util.h" | |
| 29 #include "ui/gfx/codec/png_codec.h" | |
| 30 | |
| 31 using content::BrowserThread; | |
| 32 using content::DownloadItem; | |
| 33 using content::DownloadManager; | |
| 34 using content::DownloadPersistentStoreInfo; | |
| 35 | |
| 36 namespace { | |
| 37 | |
| 38 // Comparator that orders download items by their ID. Can be used with | |
| 39 // std::sort. | |
| 40 struct DownloadIdComparator { | |
| 41 bool operator() (DownloadItem* first, DownloadItem* second) { | |
| 42 return first->GetId() < second->GetId(); | |
| 43 } | |
| 44 }; | |
| 45 | |
| 46 class DownloadExtensionTest : public InProcessBrowserTest { | |
| 47 protected: | |
| 48 // Used with CreateHistoryDownloads | |
| 49 struct HistoryDownloadInfo { | |
| 50 // Filename to use. CreateHistoryDownloads will append this filename to the | |
| 51 // temporary downloads directory specified by downloads_directory(). | |
| 52 const FilePath::CharType* filename; | |
| 53 | |
| 54 // State for the download. Note that IN_PROGRESS downloads will be created | |
| 55 // as CANCELLED. | |
| 56 DownloadItem::DownloadState state; | |
| 57 | |
| 58 // Danger type for the download. Only use DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS | |
| 59 // and DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT. | |
| 60 content::DownloadDangerType danger_type; | |
| 61 }; | |
| 62 | |
| 63 virtual Browser* current_browser() { return browser(); } | |
| 64 | |
| 65 // InProcessBrowserTest | |
| 66 virtual void SetUpOnMainThread() OVERRIDE { | |
| 67 BrowserThread::PostTask( | |
| 68 BrowserThread::IO, FROM_HERE, | |
| 69 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true)); | |
| 70 InProcessBrowserTest::SetUpOnMainThread(); | |
| 71 CreateAndSetDownloadsDirectory(); | |
| 72 current_browser()->profile()->GetPrefs()->SetBoolean( | |
| 73 prefs::kPromptForDownload, false); | |
| 74 GetDownloadManager()->RemoveAllDownloads(); | |
| 75 } | |
| 76 | |
| 77 virtual DownloadManager* GetDownloadManager() { | |
| 78 DownloadService* download_service = | |
| 79 DownloadServiceFactory::GetForProfile(current_browser()->profile()); | |
| 80 return download_service->GetDownloadManager(); | |
| 81 } | |
| 82 | |
| 83 // Creates a set of history downloads based on the provided |history_info| | |
| 84 // array. |count| is the number of elements in |history_info|. On success, | |
| 85 // |items| will contain |count| DownloadItems in the order that they were | |
| 86 // specified in |history_info|. Returns true on success and false otherwise. | |
| 87 bool CreateHistoryDownloads(const HistoryDownloadInfo* history_info, | |
| 88 size_t count, | |
| 89 DownloadManager::DownloadVector* items) { | |
| 90 DownloadIdComparator download_id_comparator; | |
| 91 base::Time current = base::Time::Now(); | |
| 92 std::vector<DownloadPersistentStoreInfo> entries; | |
| 93 entries.reserve(count); | |
| 94 for (size_t i = 0; i < count; ++i) { | |
| 95 DownloadPersistentStoreInfo entry( | |
| 96 downloads_directory().Append(history_info[i].filename), | |
| 97 GURL(), GURL(), // URL, referrer | |
| 98 current, current, // start_time, end_time | |
| 99 1, 1, // received_bytes, total_bytes | |
| 100 history_info[i].state, // state | |
| 101 i + 1, // db_handle | |
| 102 false); // opened | |
| 103 entries.push_back(entry); | |
| 104 } | |
| 105 GetDownloadManager()->OnPersistentStoreQueryComplete(&entries); | |
| 106 GetDownloadManager()->GetAllDownloads(FilePath(), items); | |
| 107 EXPECT_EQ(count, items->size()); | |
| 108 if (count != items->size()) | |
| 109 return false; | |
| 110 | |
| 111 // Order by ID so that they are in the order that we created them. | |
| 112 std::sort(items->begin(), items->end(), download_id_comparator); | |
| 113 // Set the danger type if necessary. | |
| 114 for (size_t i = 0; i < count; ++i) { | |
| 115 if (history_info[i].danger_type != | |
| 116 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { | |
| 117 EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT, | |
| 118 history_info[i].danger_type); | |
| 119 items->at(i)->OnContentCheckCompleted(history_info[i].danger_type); | |
| 120 } | |
| 121 } | |
| 122 return true; | |
| 123 } | |
| 124 | |
| 125 void CreateSlowTestDownloads( | |
| 126 size_t count, DownloadManager::DownloadVector* items) { | |
| 127 for (size_t i = 0; i < count; ++i) { | |
| 128 scoped_ptr<DownloadTestObserver> observer( | |
| 129 CreateInProgressDownloadObserver(1)); | |
| 130 GURL slow_download_url(URLRequestSlowDownloadJob::kUnknownSizeUrl); | |
| 131 ui_test_utils::NavigateToURLWithDisposition( | |
| 132 current_browser(), slow_download_url, CURRENT_TAB, | |
| 133 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 134 observer->WaitForFinished(); | |
| 135 EXPECT_EQ( | |
| 136 1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS)); | |
| 137 // We don't expect a select file dialog. | |
| 138 ASSERT_FALSE(observer->select_file_dialog_seen()); | |
| 139 } | |
| 140 GetDownloadManager()->GetAllDownloads(FilePath(), items); | |
| 141 ASSERT_EQ(count, items->size()); | |
| 142 } | |
| 143 | |
| 144 DownloadItem* CreateSlowTestDownload() { | |
| 145 scoped_ptr<DownloadTestObserver> observer( | |
| 146 CreateInProgressDownloadObserver(1)); | |
| 147 GURL slow_download_url(URLRequestSlowDownloadJob::kUnknownSizeUrl); | |
| 148 DownloadManager* manager = GetDownloadManager(); | |
| 149 | |
| 150 EXPECT_EQ(0, manager->InProgressCount()); | |
| 151 if (manager->InProgressCount() != 0) | |
| 152 return NULL; | |
| 153 | |
| 154 ui_test_utils::NavigateToURLWithDisposition( | |
| 155 current_browser(), slow_download_url, CURRENT_TAB, | |
| 156 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 157 | |
| 158 observer->WaitForFinished(); | |
| 159 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS)); | |
| 160 // We don't expect a select file dialog. | |
| 161 if (observer->select_file_dialog_seen()) | |
| 162 return NULL; | |
| 163 | |
| 164 DownloadManager::DownloadVector items; | |
| 165 manager->GetAllDownloads(FilePath(), &items); | |
| 166 | |
| 167 DownloadItem* new_item = NULL; | |
| 168 for (DownloadManager::DownloadVector::iterator iter = items.begin(); | |
| 169 iter != items.end(); ++iter) { | |
| 170 if ((*iter)->GetState() == DownloadItem::IN_PROGRESS) { | |
| 171 // There should be only one IN_PROGRESS item. | |
| 172 EXPECT_EQ(NULL, new_item); | |
| 173 new_item = *iter; | |
| 174 } | |
| 175 } | |
| 176 return new_item; | |
| 177 } | |
| 178 | |
| 179 void FinishPendingSlowDownloads() { | |
| 180 scoped_ptr<DownloadTestObserver> observer( | |
| 181 CreateDownloadObserver(1)); | |
| 182 GURL finish_url(URLRequestSlowDownloadJob::kFinishDownloadUrl); | |
| 183 ui_test_utils::NavigateToURLWithDisposition( | |
| 184 current_browser(), finish_url, NEW_FOREGROUND_TAB, | |
| 185 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 186 observer->WaitForFinished(); | |
| 187 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::COMPLETE)); | |
| 188 } | |
| 189 | |
| 190 DownloadTestObserver* CreateDownloadObserver(size_t download_count) { | |
| 191 return new DownloadTestObserverTerminal( | |
| 192 GetDownloadManager(), download_count, true, | |
| 193 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); | |
| 194 } | |
| 195 | |
| 196 DownloadTestObserver* CreateInProgressDownloadObserver( | |
| 197 size_t download_count) { | |
| 198 return new DownloadTestObserverInProgress(GetDownloadManager(), | |
| 199 download_count, | |
| 200 true); | |
| 201 } | |
| 202 | |
| 203 extension_function_test_utils::RunFunctionFlags GetFlags() { | |
| 204 return current_browser()->profile()->IsOffTheRecord() ? | |
| 205 extension_function_test_utils::INCLUDE_INCOGNITO : | |
| 206 extension_function_test_utils::NONE; | |
| 207 } | |
| 208 | |
| 209 // extension_function_test_utils::RunFunction*() only uses browser for its | |
| 210 // profile(), so pass it the on-record browser so that it always uses the | |
| 211 // on-record profile. | |
| 212 | |
| 213 bool RunFunction(UIThreadExtensionFunction* function, | |
| 214 const std::string& args) { | |
| 215 // extension_function_test_utils::RunFunction() does not take | |
| 216 // ownership of |function|. | |
| 217 scoped_refptr<ExtensionFunction> function_owner(function); | |
| 218 return extension_function_test_utils::RunFunction( | |
| 219 function, args, browser(), GetFlags()); | |
| 220 } | |
| 221 | |
| 222 base::Value* RunFunctionAndReturnResult(UIThreadExtensionFunction* function, | |
| 223 const std::string& args) { | |
| 224 return extension_function_test_utils::RunFunctionAndReturnResult( | |
| 225 function, args, browser(), GetFlags()); | |
| 226 } | |
| 227 | |
| 228 std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function, | |
| 229 const std::string& args) { | |
| 230 return extension_function_test_utils::RunFunctionAndReturnError( | |
| 231 function, args, browser(), GetFlags()); | |
| 232 } | |
| 233 | |
| 234 bool RunFunctionAndReturnString(UIThreadExtensionFunction* function, | |
| 235 const std::string& args, | |
| 236 std::string* result_string) { | |
| 237 scoped_ptr<base::Value> result(RunFunctionAndReturnResult(function, args)); | |
| 238 EXPECT_TRUE(result.get()); | |
| 239 return result.get() && result->GetAsString(result_string); | |
| 240 } | |
| 241 | |
| 242 std::string DownloadItemIdAsArgList(const DownloadItem* download_item) { | |
| 243 return base::StringPrintf("[%d]", download_item->GetId()); | |
| 244 } | |
| 245 | |
| 246 // Checks if a data URL encoded image is a PNG of a given size. | |
| 247 void ExpectDataURLIsPNGWithSize(const std::string& url, int expected_size) { | |
| 248 std::string mime_type; | |
| 249 std::string charset; | |
| 250 std::string data; | |
| 251 EXPECT_FALSE(url.empty()); | |
| 252 EXPECT_TRUE(net::DataURL::Parse(GURL(url), &mime_type, &charset, &data)); | |
| 253 EXPECT_STREQ("image/png", mime_type.c_str()); | |
| 254 EXPECT_FALSE(data.empty()); | |
| 255 | |
| 256 if (data.empty()) | |
| 257 return; | |
| 258 | |
| 259 int width = -1, height = -1; | |
| 260 std::vector<unsigned char> decoded_data; | |
| 261 EXPECT_TRUE(gfx::PNGCodec::Decode( | |
| 262 reinterpret_cast<const unsigned char*>(data.c_str()), data.length(), | |
| 263 gfx::PNGCodec::FORMAT_RGBA, &decoded_data, | |
| 264 &width, &height)); | |
| 265 EXPECT_EQ(expected_size, width); | |
| 266 EXPECT_EQ(expected_size, height); | |
| 267 } | |
| 268 | |
| 269 const FilePath& downloads_directory() { | |
| 270 return downloads_directory_.path(); | |
| 271 } | |
| 272 | |
| 273 private: | |
| 274 void CreateAndSetDownloadsDirectory() { | |
| 275 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir()); | |
| 276 current_browser()->profile()->GetPrefs()->SetFilePath( | |
| 277 prefs::kDownloadDefaultDirectory, | |
| 278 downloads_directory_.path()); | |
| 279 } | |
| 280 | |
| 281 ScopedTempDir downloads_directory_; | |
| 282 }; | |
| 283 | |
| 284 class DownloadExtensionTestIncognito : public DownloadExtensionTest { | |
| 285 public: | |
| 286 virtual Browser* current_browser() OVERRIDE { return current_browser_; } | |
| 287 | |
| 288 virtual void SetUpOnMainThread() OVERRIDE { | |
| 289 GoOnTheRecord(); | |
| 290 DownloadExtensionTest::SetUpOnMainThread(); | |
| 291 incognito_browser_ = CreateIncognitoBrowser(); | |
| 292 GoOffTheRecord(); | |
| 293 GetDownloadManager()->RemoveAllDownloads(); | |
| 294 } | |
| 295 | |
| 296 void GoOnTheRecord() { current_browser_ = browser(); } | |
| 297 void GoOffTheRecord() { current_browser_ = incognito_browser_; } | |
| 298 | |
| 299 private: | |
| 300 Browser* incognito_browser_; | |
| 301 Browser* current_browser_; | |
| 302 }; | |
| 303 | |
| 304 class MockIconExtractorImpl : public DownloadFileIconExtractor { | |
| 305 public: | |
| 306 MockIconExtractorImpl(const FilePath& path, IconLoader::IconSize icon_size, | |
| 307 const std::string& response) | |
| 308 : expected_path_(path), | |
| 309 expected_icon_size_(icon_size), | |
| 310 response_(response) { | |
| 311 } | |
| 312 virtual ~MockIconExtractorImpl() {} | |
| 313 | |
| 314 virtual bool ExtractIconURLForPath(const FilePath& path, | |
| 315 IconLoader::IconSize icon_size, | |
| 316 IconURLCallback callback) OVERRIDE { | |
| 317 EXPECT_STREQ(expected_path_.value().c_str(), path.value().c_str()); | |
| 318 EXPECT_EQ(expected_icon_size_, icon_size); | |
| 319 if (expected_path_ == path && | |
| 320 expected_icon_size_ == icon_size) { | |
| 321 callback_ = callback; | |
| 322 BrowserThread::PostTask( | |
| 323 BrowserThread::UI, FROM_HERE, | |
| 324 base::Bind(&MockIconExtractorImpl::RunCallback, | |
| 325 base::Unretained(this))); | |
| 326 return true; | |
| 327 } else { | |
| 328 return false; | |
| 329 } | |
| 330 } | |
| 331 | |
| 332 private: | |
| 333 void RunCallback() { | |
| 334 callback_.Run(response_); | |
| 335 } | |
| 336 | |
| 337 FilePath expected_path_; | |
| 338 IconLoader::IconSize expected_icon_size_; | |
| 339 std::string response_; | |
| 340 IconURLCallback callback_; | |
| 341 }; | |
| 342 | |
| 343 // Cancels the underlying DownloadItem when the ScopedCancellingItem goes out of | |
| 344 // scope. Like a scoped_ptr, but for DownloadItems. | |
| 345 class ScopedCancellingItem { | |
| 346 public: | |
| 347 explicit ScopedCancellingItem(DownloadItem* item) : item_(item) {} | |
| 348 ~ScopedCancellingItem() { | |
| 349 item_->Cancel(true); | |
| 350 } | |
| 351 DownloadItem* operator*() { return item_; } | |
| 352 DownloadItem* operator->() { return item_; } | |
| 353 DownloadItem* get() { return item_; } | |
| 354 private: | |
| 355 DownloadItem* item_; | |
| 356 DISALLOW_COPY_AND_ASSIGN(ScopedCancellingItem); | |
| 357 }; | |
| 358 | |
| 359 // Cancels all the underlying DownloadItems when the ScopedItemVectorCanceller | |
| 360 // goes out of scope. Generalization of ScopedCancellingItem to many | |
| 361 // DownloadItems. | |
| 362 class ScopedItemVectorCanceller { | |
| 363 public: | |
| 364 explicit ScopedItemVectorCanceller(DownloadManager::DownloadVector* items) | |
| 365 : items_(items) { | |
| 366 } | |
| 367 ~ScopedItemVectorCanceller() { | |
| 368 for (DownloadManager::DownloadVector::const_iterator item = items_->begin(); | |
| 369 item != items_->end(); ++item) { | |
| 370 if ((*item)->IsInProgress()) | |
| 371 (*item)->Cancel(true); | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 private: | |
| 376 DownloadManager::DownloadVector* items_; | |
| 377 DISALLOW_COPY_AND_ASSIGN(ScopedItemVectorCanceller); | |
| 378 }; | |
| 379 | |
| 380 } // namespace | |
| 381 | |
| 382 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_PauseResumeCancel) { | |
| 383 DownloadItem* download_item = CreateSlowTestDownload(); | |
| 384 ASSERT_TRUE(download_item); | |
| 385 | |
| 386 // Call pause(). It should succeed and the download should be paused on | |
| 387 // return. | |
| 388 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), | |
| 389 DownloadItemIdAsArgList(download_item))); | |
| 390 EXPECT_TRUE(download_item->IsPaused()); | |
| 391 | |
| 392 // Calling pause() twice shouldn't be an error. | |
| 393 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), | |
| 394 DownloadItemIdAsArgList(download_item))); | |
| 395 EXPECT_TRUE(download_item->IsPaused()); | |
| 396 | |
| 397 // Now try resuming this download. It should succeed. | |
| 398 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), | |
| 399 DownloadItemIdAsArgList(download_item))); | |
| 400 EXPECT_FALSE(download_item->IsPaused()); | |
| 401 | |
| 402 // Resume again. Resuming a download that wasn't paused is not an error. | |
| 403 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), | |
| 404 DownloadItemIdAsArgList(download_item))); | |
| 405 EXPECT_FALSE(download_item->IsPaused()); | |
| 406 | |
| 407 // Pause again. | |
| 408 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), | |
| 409 DownloadItemIdAsArgList(download_item))); | |
| 410 EXPECT_TRUE(download_item->IsPaused()); | |
| 411 | |
| 412 // And now cancel. | |
| 413 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), | |
| 414 DownloadItemIdAsArgList(download_item))); | |
| 415 EXPECT_TRUE(download_item->IsCancelled()); | |
| 416 | |
| 417 // Cancel again. Shouldn't have any effect. | |
| 418 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), | |
| 419 DownloadItemIdAsArgList(download_item))); | |
| 420 EXPECT_TRUE(download_item->IsCancelled()); | |
| 421 | |
| 422 // Calling paused on a non-active download yields kInvalidOperationError. | |
| 423 std::string error = RunFunctionAndReturnError( | |
| 424 new DownloadsPauseFunction(), DownloadItemIdAsArgList(download_item)); | |
| 425 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 426 error.c_str()); | |
| 427 | |
| 428 // Calling resume on a non-active download yields kInvalidOperationError | |
| 429 error = RunFunctionAndReturnError( | |
| 430 new DownloadsResumeFunction(), DownloadItemIdAsArgList(download_item)); | |
| 431 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 432 error.c_str()); | |
| 433 | |
| 434 // Calling pause()/resume()/cancel() with invalid download Ids is | |
| 435 // tested in the API test (DownloadsApiTest). | |
| 436 } | |
| 437 | |
| 438 // Test downloads.getFileIcon() on in-progress, finished, cancelled and deleted | |
| 439 // download items. | |
| 440 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_FileIcon_Active) { | |
| 441 DownloadItem* download_item = CreateSlowTestDownload(); | |
| 442 ASSERT_TRUE(download_item); | |
| 443 | |
| 444 // Get the icon for the in-progress download. This call should succeed even | |
| 445 // if the file type isn't registered. | |
| 446 std::string args = base::StringPrintf("[%d, {}]", download_item->GetId()); | |
| 447 std::string result_string; | |
| 448 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(), | |
| 449 args, &result_string)); | |
| 450 | |
| 451 // Note: We are checking if the result is a Data URL that has encoded | |
| 452 // image/png data for an icon of a specific size. Of these, only the icon size | |
| 453 // is specified in the API contract. The image type (image/png) and URL type | |
| 454 // (Data) are implementation details. | |
| 455 | |
| 456 // The default size for icons returned by getFileIcon() is 32x32. | |
| 457 ExpectDataURLIsPNGWithSize(result_string, 32); | |
| 458 | |
| 459 // Test whether the correct path is being pased into the icon extractor. | |
| 460 FilePath expected_path(download_item->GetTargetFilePath()); | |
| 461 scoped_refptr<DownloadsGetFileIconFunction> function( | |
| 462 new DownloadsGetFileIconFunction()); | |
| 463 function->SetIconExtractorForTesting(new MockIconExtractorImpl( | |
| 464 expected_path, IconLoader::NORMAL, "foo")); | |
| 465 EXPECT_TRUE(RunFunctionAndReturnString(function.release(), args, | |
| 466 &result_string)); | |
| 467 | |
| 468 // Now try a 16x16 icon. | |
| 469 args = base::StringPrintf("[%d, {\"size\": 16}]", download_item->GetId()); | |
| 470 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(), | |
| 471 args, &result_string)); | |
| 472 ExpectDataURLIsPNGWithSize(result_string, 16); | |
| 473 | |
| 474 // Explicitly asking for 32x32 should give us a 32x32 icon. | |
| 475 args = base::StringPrintf("[%d, {\"size\": 32}]", download_item->GetId()); | |
| 476 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(), | |
| 477 args, &result_string)); | |
| 478 ExpectDataURLIsPNGWithSize(result_string, 32); | |
| 479 | |
| 480 // Finish the download and try again. | |
| 481 FinishPendingSlowDownloads(); | |
| 482 EXPECT_EQ(DownloadItem::COMPLETE, download_item->GetState()); | |
| 483 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(), | |
| 484 args, &result_string)); | |
| 485 ExpectDataURLIsPNGWithSize(result_string, 32); | |
| 486 | |
| 487 // Check the path passed to the icon extractor post-completion. | |
| 488 function = new DownloadsGetFileIconFunction(); | |
| 489 function->SetIconExtractorForTesting(new MockIconExtractorImpl( | |
| 490 expected_path, IconLoader::NORMAL, "foo")); | |
| 491 EXPECT_TRUE(RunFunctionAndReturnString(function.release(), args, | |
| 492 &result_string)); | |
| 493 | |
| 494 // Now create another download. | |
| 495 download_item = CreateSlowTestDownload(); | |
| 496 ASSERT_TRUE(download_item); | |
| 497 expected_path = download_item->GetTargetFilePath(); | |
| 498 | |
| 499 // Cancel the download. As long as the download has a target path, we should | |
| 500 // be able to query the file icon. | |
| 501 download_item->Cancel(true); | |
| 502 // Let cleanup complete on the FILE thread. | |
| 503 ui_test_utils::RunAllPendingInMessageLoop(BrowserThread::FILE); | |
| 504 args = base::StringPrintf("[%d, {\"size\": 32}]", download_item->GetId()); | |
| 505 EXPECT_TRUE(RunFunctionAndReturnString(new DownloadsGetFileIconFunction(), | |
| 506 args, &result_string)); | |
| 507 ExpectDataURLIsPNGWithSize(result_string, 32); | |
| 508 | |
| 509 // Check the path passed to the icon extractor post-cancellation. | |
| 510 function = new DownloadsGetFileIconFunction(); | |
| 511 function->SetIconExtractorForTesting(new MockIconExtractorImpl( | |
| 512 expected_path, IconLoader::NORMAL, "foo")); | |
| 513 EXPECT_TRUE(RunFunctionAndReturnString(function.release(), args, | |
| 514 &result_string)); | |
| 515 | |
| 516 // Simulate an error during icon load by invoking the mock with an empty | |
| 517 // result string. | |
| 518 function = new DownloadsGetFileIconFunction(); | |
| 519 function->SetIconExtractorForTesting(new MockIconExtractorImpl( | |
| 520 expected_path, IconLoader::NORMAL, "")); | |
| 521 std::string error = RunFunctionAndReturnError(function.release(), args); | |
| 522 EXPECT_STREQ(download_extension_errors::kIconNotFoundError, | |
| 523 error.c_str()); | |
| 524 | |
| 525 // Once the download item is deleted, we should return kInvalidOperationError. | |
| 526 download_item->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD); | |
| 527 error = RunFunctionAndReturnError(new DownloadsGetFileIconFunction(), args); | |
| 528 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 529 error.c_str()); | |
| 530 | |
| 531 // Asking for icons of other (invalid) sizes is tested in the API test | |
| 532 // (DownloadsApiTest). | |
| 533 } | |
| 534 | |
| 535 // Test that we can acquire file icons for history downloads regardless of | |
| 536 // whether they exist or not. If the file doesn't exist we should receive a | |
| 537 // generic icon from the OS/toolkit that may or may not be specific to the file | |
| 538 // type. | |
| 539 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_FileIcon_History) { | |
| 540 const HistoryDownloadInfo kHistoryInfo[] = { | |
| 541 { FILE_PATH_LITERAL("real.txt"), | |
| 542 DownloadItem::COMPLETE, | |
| 543 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }, | |
| 544 { FILE_PATH_LITERAL("fake.txt"), | |
| 545 DownloadItem::COMPLETE, | |
| 546 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS } | |
| 547 }; | |
| 548 DownloadManager::DownloadVector all_downloads; | |
| 549 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo), | |
| 550 &all_downloads)); | |
| 551 | |
| 552 FilePath real_path = all_downloads[0]->GetFullPath(); | |
| 553 FilePath fake_path = all_downloads[1]->GetFullPath(); | |
| 554 | |
| 555 EXPECT_EQ(0, file_util::WriteFile(real_path, "", 0)); | |
| 556 ASSERT_TRUE(file_util::PathExists(real_path)); | |
| 557 ASSERT_FALSE(file_util::PathExists(fake_path)); | |
| 558 | |
| 559 for (DownloadManager::DownloadVector::iterator iter = all_downloads.begin(); | |
| 560 iter != all_downloads.end(); | |
| 561 ++iter) { | |
| 562 std::string args(base::StringPrintf("[%d, {\"size\": 32}]", | |
| 563 (*iter)->GetId())); | |
| 564 std::string result_string; | |
| 565 EXPECT_TRUE(RunFunctionAndReturnString( | |
| 566 new DownloadsGetFileIconFunction(), args, &result_string)); | |
| 567 // Note: We are checking if the result is a Data URL that has encoded | |
| 568 // image/png data for an icon of a specific size. Of these, only the icon | |
| 569 // size is specified in the API contract. The image type (image/png) and URL | |
| 570 // type (Data) are implementation details. | |
| 571 ExpectDataURLIsPNGWithSize(result_string, 32); | |
| 572 | |
| 573 // Use a MockIconExtractorImpl to test if the correct path is being passed | |
| 574 // into the DownloadFileIconExtractor. | |
| 575 scoped_refptr<DownloadsGetFileIconFunction> function( | |
| 576 new DownloadsGetFileIconFunction()); | |
| 577 function->SetIconExtractorForTesting(new MockIconExtractorImpl( | |
| 578 (*iter)->GetFullPath(), IconLoader::NORMAL, "hello")); | |
| 579 EXPECT_TRUE(RunFunctionAndReturnString(function.release(), args, | |
| 580 &result_string)); | |
| 581 EXPECT_STREQ("hello", result_string.c_str()); | |
| 582 } | |
| 583 | |
| 584 // The temporary files should be cleaned up when the ScopedTempDir is removed. | |
| 585 } | |
| 586 | |
| 587 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchEmptyQuery) { | |
| 588 ScopedCancellingItem item(CreateSlowTestDownload()); | |
| 589 ASSERT_TRUE(item.get()); | |
| 590 | |
| 591 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 592 new DownloadsSearchFunction(), "[{}]")); | |
| 593 ASSERT_TRUE(result.get()); | |
| 594 base::ListValue* result_list = NULL; | |
| 595 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 596 ASSERT_EQ(1UL, result_list->GetSize()); | |
| 597 } | |
| 598 | |
| 599 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, | |
| 600 DownloadsApi_SearchFilenameRegex) { | |
| 601 const HistoryDownloadInfo kHistoryInfo[] = { | |
| 602 { FILE_PATH_LITERAL("foobar"), | |
| 603 DownloadItem::COMPLETE, | |
| 604 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }, | |
| 605 { FILE_PATH_LITERAL("baz"), | |
| 606 DownloadItem::COMPLETE, | |
| 607 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS } | |
| 608 }; | |
| 609 DownloadManager::DownloadVector all_downloads; | |
| 610 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo), | |
| 611 &all_downloads)); | |
| 612 | |
| 613 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 614 new DownloadsSearchFunction(), "[{\"filenameRegex\": \"foobar\"}]")); | |
| 615 ASSERT_TRUE(result.get()); | |
| 616 base::ListValue* result_list = NULL; | |
| 617 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 618 ASSERT_EQ(1UL, result_list->GetSize()); | |
| 619 base::DictionaryValue* item_value = NULL; | |
| 620 ASSERT_TRUE(result_list->GetDictionary(0, &item_value)); | |
| 621 int item_id = -1; | |
| 622 ASSERT_TRUE(item_value->GetInteger("id", &item_id)); | |
| 623 ASSERT_EQ(0, item_id); | |
| 624 } | |
| 625 | |
| 626 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchId) { | |
| 627 DownloadManager::DownloadVector items; | |
| 628 CreateSlowTestDownloads(2, &items); | |
| 629 ScopedItemVectorCanceller delete_items(&items); | |
| 630 | |
| 631 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 632 new DownloadsSearchFunction(), "[{\"id\": 0}]")); | |
| 633 ASSERT_TRUE(result.get()); | |
| 634 base::ListValue* result_list = NULL; | |
| 635 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 636 ASSERT_EQ(1UL, result_list->GetSize()); | |
| 637 base::DictionaryValue* item_value = NULL; | |
| 638 ASSERT_TRUE(result_list->GetDictionary(0, &item_value)); | |
| 639 int item_id = -1; | |
| 640 ASSERT_TRUE(item_value->GetInteger("id", &item_id)); | |
| 641 ASSERT_EQ(0, item_id); | |
| 642 } | |
| 643 | |
| 644 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, | |
| 645 DownloadsApi_SearchIdAndFilename) { | |
| 646 DownloadManager::DownloadVector items; | |
| 647 CreateSlowTestDownloads(2, &items); | |
| 648 ScopedItemVectorCanceller delete_items(&items); | |
| 649 | |
| 650 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 651 new DownloadsSearchFunction(), "[{\"id\": 0,\"filename\": \"foobar\"}]")); | |
| 652 ASSERT_TRUE(result.get()); | |
| 653 base::ListValue* result_list = NULL; | |
| 654 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 655 ASSERT_EQ(0UL, result_list->GetSize()); | |
| 656 } | |
| 657 | |
| 658 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchOrderBy) { | |
| 659 const HistoryDownloadInfo kHistoryInfo[] = { | |
| 660 { FILE_PATH_LITERAL("zzz"), | |
| 661 DownloadItem::COMPLETE, | |
| 662 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }, | |
| 663 { FILE_PATH_LITERAL("baz"), | |
| 664 DownloadItem::COMPLETE, | |
| 665 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS } | |
| 666 }; | |
| 667 DownloadManager::DownloadVector items; | |
| 668 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo), | |
| 669 &items)); | |
| 670 | |
| 671 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 672 new DownloadsSearchFunction(), "[{\"orderBy\": \"filename\"}]")); | |
| 673 ASSERT_TRUE(result.get()); | |
| 674 base::ListValue* result_list = NULL; | |
| 675 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 676 ASSERT_EQ(2UL, result_list->GetSize()); | |
| 677 base::DictionaryValue* item0_value = NULL; | |
| 678 base::DictionaryValue* item1_value = NULL; | |
| 679 ASSERT_TRUE(result_list->GetDictionary(0, &item0_value)); | |
| 680 ASSERT_TRUE(result_list->GetDictionary(1, &item1_value)); | |
| 681 std::string item0_name, item1_name; | |
| 682 ASSERT_TRUE(item0_value->GetString("filename", &item0_name)); | |
| 683 ASSERT_TRUE(item1_value->GetString("filename", &item1_name)); | |
| 684 ASSERT_GT(items[0]->GetFullPath().value(), items[1]->GetFullPath().value()); | |
| 685 ASSERT_LT(item0_name, item1_name); | |
| 686 } | |
| 687 | |
| 688 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchOrderByEmpty) { | |
| 689 const HistoryDownloadInfo kHistoryInfo[] = { | |
| 690 { FILE_PATH_LITERAL("zzz"), | |
| 691 DownloadItem::COMPLETE, | |
| 692 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }, | |
| 693 { FILE_PATH_LITERAL("baz"), | |
| 694 DownloadItem::COMPLETE, | |
| 695 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS } | |
| 696 }; | |
| 697 DownloadManager::DownloadVector items; | |
| 698 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo), | |
| 699 &items)); | |
| 700 | |
| 701 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 702 new DownloadsSearchFunction(), "[{\"orderBy\": \"\"}]")); | |
| 703 ASSERT_TRUE(result.get()); | |
| 704 base::ListValue* result_list = NULL; | |
| 705 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 706 ASSERT_EQ(2UL, result_list->GetSize()); | |
| 707 base::DictionaryValue* item0_value = NULL; | |
| 708 base::DictionaryValue* item1_value = NULL; | |
| 709 ASSERT_TRUE(result_list->GetDictionary(0, &item0_value)); | |
| 710 ASSERT_TRUE(result_list->GetDictionary(1, &item1_value)); | |
| 711 std::string item0_name, item1_name; | |
| 712 ASSERT_TRUE(item0_value->GetString("filename", &item0_name)); | |
| 713 ASSERT_TRUE(item1_value->GetString("filename", &item1_name)); | |
| 714 ASSERT_GT(items[0]->GetFullPath().value(), items[1]->GetFullPath().value()); | |
| 715 ASSERT_GT(item0_name, item1_name); | |
| 716 } | |
| 717 | |
| 718 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchDanger) { | |
| 719 const HistoryDownloadInfo kHistoryInfo[] = { | |
| 720 { FILE_PATH_LITERAL("zzz"), | |
| 721 DownloadItem::COMPLETE, | |
| 722 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT }, | |
| 723 { FILE_PATH_LITERAL("baz"), | |
| 724 DownloadItem::COMPLETE, | |
| 725 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS } | |
| 726 }; | |
| 727 DownloadManager::DownloadVector items; | |
| 728 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo), | |
| 729 &items)); | |
| 730 | |
| 731 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 732 new DownloadsSearchFunction(), "[{\"danger\": \"content\"}]")); | |
| 733 ASSERT_TRUE(result.get()); | |
| 734 base::ListValue* result_list = NULL; | |
| 735 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 736 ASSERT_EQ(1UL, result_list->GetSize()); | |
| 737 } | |
| 738 | |
| 739 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchState) { | |
| 740 DownloadManager::DownloadVector items; | |
| 741 CreateSlowTestDownloads(2, &items); | |
| 742 ScopedItemVectorCanceller delete_items(&items); | |
| 743 | |
| 744 items[0]->Cancel(true); | |
| 745 | |
| 746 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 747 new DownloadsSearchFunction(), "[{\"state\": \"in_progress\"}]")); | |
| 748 ASSERT_TRUE(result.get()); | |
| 749 base::ListValue* result_list = NULL; | |
| 750 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 751 ASSERT_EQ(1UL, result_list->GetSize()); | |
| 752 } | |
| 753 | |
| 754 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchLimit) { | |
| 755 DownloadManager::DownloadVector items; | |
| 756 CreateSlowTestDownloads(2, &items); | |
| 757 ScopedItemVectorCanceller delete_items(&items); | |
| 758 | |
| 759 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 760 new DownloadsSearchFunction(), "[{\"limit\": 1}]")); | |
| 761 ASSERT_TRUE(result.get()); | |
| 762 base::ListValue* result_list = NULL; | |
| 763 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 764 ASSERT_EQ(1UL, result_list->GetSize()); | |
| 765 } | |
| 766 | |
| 767 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchInvalid) { | |
| 768 std::string error = RunFunctionAndReturnError( | |
| 769 new DownloadsSearchFunction(), "[{\"filenameRegex\": \"(\"}]"); | |
| 770 EXPECT_STREQ(download_extension_errors::kInvalidFilterError, | |
| 771 error.c_str()); | |
| 772 error = RunFunctionAndReturnError( | |
| 773 new DownloadsSearchFunction(), "[{\"danger\": \"goat\"}]"); | |
| 774 EXPECT_STREQ(download_extension_errors::kInvalidDangerTypeError, | |
| 775 error.c_str()); | |
| 776 error = RunFunctionAndReturnError( | |
| 777 new DownloadsSearchFunction(), "[{\"state\": \"goat\"}]"); | |
| 778 EXPECT_STREQ(download_extension_errors::kInvalidStateError, | |
| 779 error.c_str()); | |
| 780 error = RunFunctionAndReturnError( | |
| 781 new DownloadsSearchFunction(), "[{\"orderBy\": \"goat\"}]"); | |
| 782 EXPECT_STREQ(download_extension_errors::kInvalidOrderByError, | |
| 783 error.c_str()); | |
| 784 error = RunFunctionAndReturnError( | |
| 785 new DownloadsSearchFunction(), "[{\"limit\": -1}]"); | |
| 786 EXPECT_STREQ(download_extension_errors::kInvalidQueryLimit, | |
| 787 error.c_str()); | |
| 788 } | |
| 789 | |
| 790 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_SearchPlural) { | |
| 791 const HistoryDownloadInfo kHistoryInfo[] = { | |
| 792 { FILE_PATH_LITERAL("aaa"), | |
| 793 DownloadItem::CANCELLED, | |
| 794 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS }, | |
| 795 { FILE_PATH_LITERAL("zzz"), | |
| 796 DownloadItem::COMPLETE, | |
| 797 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT }, | |
| 798 { FILE_PATH_LITERAL("baz"), | |
| 799 DownloadItem::COMPLETE, | |
| 800 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT }, | |
| 801 }; | |
| 802 DownloadManager::DownloadVector items; | |
| 803 ASSERT_TRUE(CreateHistoryDownloads(kHistoryInfo, arraysize(kHistoryInfo), | |
| 804 &items)); | |
| 805 | |
| 806 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | |
| 807 new DownloadsSearchFunction(), "[{" | |
| 808 "\"state\": \"complete\", " | |
| 809 "\"danger\": \"content\", " | |
| 810 "\"orderBy\": \"filename\", " | |
| 811 "\"limit\": 1}]")); | |
| 812 ASSERT_TRUE(result.get()); | |
| 813 base::ListValue* result_list = NULL; | |
| 814 ASSERT_TRUE(result->GetAsList(&result_list)); | |
| 815 ASSERT_EQ(1UL, result_list->GetSize()); | |
| 816 base::DictionaryValue* item_value = NULL; | |
| 817 ASSERT_TRUE(result_list->GetDictionary(0, &item_value)); | |
| 818 FilePath::StringType item_name; | |
| 819 ASSERT_TRUE(item_value->GetString("filename", &item_name)); | |
| 820 ASSERT_EQ(items[2]->GetFullPath().value(), item_name); | |
| 821 } | |
| 822 | |
| 823 IN_PROC_BROWSER_TEST_F(DownloadExtensionTestIncognito, | |
| 824 DownloadsApi_SearchIncognito) { | |
| 825 scoped_ptr<base::Value> result_value; | |
| 826 base::ListValue* result_list = NULL; | |
| 827 base::DictionaryValue* result_dict = NULL; | |
| 828 FilePath::StringType filename; | |
| 829 bool is_incognito = false; | |
| 830 std::string error; | |
| 831 std::string on_item_arg; | |
| 832 std::string off_item_arg; | |
| 833 std::string result_string; | |
| 834 | |
| 835 // Set up one on-record item and one off-record item. | |
| 836 | |
| 837 GoOnTheRecord(); | |
| 838 DownloadItem* on_item = CreateSlowTestDownload(); | |
| 839 ASSERT_TRUE(on_item); | |
| 840 ASSERT_FALSE(on_item->IsOtr()); | |
| 841 on_item_arg = DownloadItemIdAsArgList(on_item); | |
| 842 | |
| 843 GoOffTheRecord(); | |
| 844 DownloadItem* off_item = CreateSlowTestDownload(); | |
| 845 ASSERT_TRUE(off_item); | |
| 846 ASSERT_TRUE(off_item->IsOtr()); | |
| 847 ASSERT_TRUE(on_item->GetFullPath() != off_item->GetFullPath()); | |
| 848 off_item_arg = DownloadItemIdAsArgList(off_item); | |
| 849 | |
| 850 // Extensions running in the incognito window should have access to both | |
| 851 // items because the Test extension is in spanning mode. | |
| 852 result_value.reset(RunFunctionAndReturnResult( | |
| 853 new DownloadsSearchFunction(), "[{}]")); | |
| 854 ASSERT_TRUE(result_value.get()); | |
| 855 ASSERT_TRUE(result_value->GetAsList(&result_list)); | |
| 856 ASSERT_EQ(2UL, result_list->GetSize()); | |
| 857 ASSERT_TRUE(result_list->GetDictionary(0, &result_dict)); | |
| 858 ASSERT_TRUE(result_dict->GetString("filename", &filename)); | |
| 859 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito)); | |
| 860 EXPECT_TRUE(on_item->GetFullPath() == FilePath(filename)); | |
| 861 EXPECT_FALSE(is_incognito); | |
| 862 ASSERT_TRUE(result_list->GetDictionary(1, &result_dict)); | |
| 863 ASSERT_TRUE(result_dict->GetString("filename", &filename)); | |
| 864 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito)); | |
| 865 EXPECT_TRUE(off_item->GetFullPath() == FilePath(filename)); | |
| 866 EXPECT_TRUE(is_incognito); | |
| 867 | |
| 868 // Extensions running in the on-record window should have access only to the | |
| 869 // on-record item. | |
| 870 GoOnTheRecord(); | |
| 871 result_value.reset(RunFunctionAndReturnResult( | |
| 872 new DownloadsSearchFunction(), "[{}]")); | |
| 873 ASSERT_TRUE(result_value.get()); | |
| 874 ASSERT_TRUE(result_value->GetAsList(&result_list)); | |
| 875 ASSERT_EQ(1UL, result_list->GetSize()); | |
| 876 ASSERT_TRUE(result_list->GetDictionary(0, &result_dict)); | |
| 877 ASSERT_TRUE(result_dict->GetString("filename", &filename)); | |
| 878 EXPECT_TRUE(on_item->GetFullPath() == FilePath(filename)); | |
| 879 ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito)); | |
| 880 EXPECT_FALSE(is_incognito); | |
| 881 | |
| 882 // Pausing/Resuming the off-record item while on the record should return an | |
| 883 // error. Cancelling "non-existent" downloads is not an error. | |
| 884 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), off_item_arg); | |
| 885 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 886 error.c_str()); | |
| 887 error = RunFunctionAndReturnError(new DownloadsResumeFunction(), | |
| 888 off_item_arg); | |
| 889 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 890 error.c_str()); | |
| 891 error = RunFunctionAndReturnError( | |
| 892 new DownloadsGetFileIconFunction(), | |
| 893 base::StringPrintf("[%d, {}]", off_item->GetId())); | |
| 894 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 895 error.c_str()); | |
| 896 | |
| 897 // TODO(benjhayden): Test incognito_split_mode() extension. | |
| 898 // TODO(benjhayden): Test download(), onCreated, onChanged, onErased. | |
| 899 | |
| 900 GoOffTheRecord(); | |
| 901 | |
| 902 // Do the FileIcon test for both the on- and off-items while off the record. | |
| 903 // NOTE(benjhayden): This does not include the FileIcon test from history, | |
| 904 // just active downloads. This shouldn't be a problem. | |
| 905 EXPECT_TRUE(RunFunctionAndReturnString( | |
| 906 new DownloadsGetFileIconFunction(), | |
| 907 base::StringPrintf("[%d, {}]", on_item->GetId()), &result_string)); | |
| 908 EXPECT_TRUE(RunFunctionAndReturnString( | |
| 909 new DownloadsGetFileIconFunction(), | |
| 910 base::StringPrintf("[%d, {}]", off_item->GetId()), &result_string)); | |
| 911 | |
| 912 // Do the pause/resume/cancel test for both the on- and off-items while off | |
| 913 // the record. | |
| 914 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg)); | |
| 915 EXPECT_TRUE(on_item->IsPaused()); | |
| 916 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg)); | |
| 917 EXPECT_TRUE(on_item->IsPaused()); | |
| 918 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), on_item_arg)); | |
| 919 EXPECT_FALSE(on_item->IsPaused()); | |
| 920 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), on_item_arg)); | |
| 921 EXPECT_FALSE(on_item->IsPaused()); | |
| 922 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), on_item_arg)); | |
| 923 EXPECT_TRUE(on_item->IsPaused()); | |
| 924 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), on_item_arg)); | |
| 925 EXPECT_TRUE(on_item->IsCancelled()); | |
| 926 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), on_item_arg)); | |
| 927 EXPECT_TRUE(on_item->IsCancelled()); | |
| 928 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), on_item_arg); | |
| 929 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 930 error.c_str()); | |
| 931 error = RunFunctionAndReturnError(new DownloadsResumeFunction(), on_item_arg); | |
| 932 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 933 error.c_str()); | |
| 934 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg)); | |
| 935 EXPECT_TRUE(off_item->IsPaused()); | |
| 936 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg)); | |
| 937 EXPECT_TRUE(off_item->IsPaused()); | |
| 938 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), off_item_arg)); | |
| 939 EXPECT_FALSE(off_item->IsPaused()); | |
| 940 EXPECT_TRUE(RunFunction(new DownloadsResumeFunction(), off_item_arg)); | |
| 941 EXPECT_FALSE(off_item->IsPaused()); | |
| 942 EXPECT_TRUE(RunFunction(new DownloadsPauseFunction(), off_item_arg)); | |
| 943 EXPECT_TRUE(off_item->IsPaused()); | |
| 944 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), off_item_arg)); | |
| 945 EXPECT_TRUE(off_item->IsCancelled()); | |
| 946 EXPECT_TRUE(RunFunction(new DownloadsCancelFunction(), off_item_arg)); | |
| 947 EXPECT_TRUE(off_item->IsCancelled()); | |
| 948 error = RunFunctionAndReturnError(new DownloadsPauseFunction(), | |
| 949 off_item_arg); | |
| 950 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 951 error.c_str()); | |
| 952 error = RunFunctionAndReturnError(new DownloadsResumeFunction(), | |
| 953 off_item_arg); | |
| 954 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | |
| 955 error.c_str()); | |
| 956 } | |
| OLD | NEW |