| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/files/scoped_temp_dir.h" | 8 #include "base/files/scoped_temp_dir.h" |
| 9 #include "base/json/json_reader.h" | 9 #include "base/json/json_reader.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
| 30 #include "chrome/test/base/in_process_browser_test.h" | 30 #include "chrome/test/base/in_process_browser_test.h" |
| 31 #include "chrome/test/base/ui_test_utils.h" | 31 #include "chrome/test/base/ui_test_utils.h" |
| 32 #include "content/public/browser/browser_context.h" | 32 #include "content/public/browser/browser_context.h" |
| 33 #include "content/public/browser/browser_thread.h" | 33 #include "content/public/browser/browser_thread.h" |
| 34 #include "content/public/browser/download_item.h" | 34 #include "content/public/browser/download_item.h" |
| 35 #include "content/public/browser/download_manager.h" | 35 #include "content/public/browser/download_manager.h" |
| 36 #include "content/public/browser/notification_service.h" | 36 #include "content/public/browser/notification_service.h" |
| 37 #include "content/public/browser/storage_partition.h" | 37 #include "content/public/browser/storage_partition.h" |
| 38 #include "content/public/browser/web_contents.h" | 38 #include "content/public/browser/web_contents.h" |
| 39 #include "content/public/common/content_switches.h" |
| 39 #include "content/public/common/page_transition_types.h" | 40 #include "content/public/common/page_transition_types.h" |
| 40 #include "content/public/test/download_test_observer.h" | 41 #include "content/public/test/download_test_observer.h" |
| 41 #include "content/public/test/test_file_error_injector.h" | |
| 42 #include "content/test/net/url_request_slow_download_job.h" | 42 #include "content/test/net/url_request_slow_download_job.h" |
| 43 #include "net/base/data_url.h" | 43 #include "net/base/data_url.h" |
| 44 #include "net/base/net_util.h" | 44 #include "net/base/net_util.h" |
| 45 #include "net/url_request/url_request.h" | 45 #include "net/url_request/url_request.h" |
| 46 #include "net/url_request/url_request_context.h" | 46 #include "net/url_request/url_request_context.h" |
| 47 #include "net/url_request/url_request_job.h" | 47 #include "net/url_request/url_request_job.h" |
| 48 #include "net/url_request/url_request_job_factory.h" | 48 #include "net/url_request/url_request_job_factory.h" |
| 49 #include "net/url_request/url_request_job_factory_impl.h" | 49 #include "net/url_request/url_request_job_factory_impl.h" |
| 50 #include "webkit/blob/blob_data.h" | 50 #include "webkit/blob/blob_data.h" |
| 51 #include "webkit/blob/blob_storage_controller.h" | 51 #include "webkit/blob/blob_storage_controller.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 79 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, | 79 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, |
| 80 content::NotificationService::AllSources()); | 80 content::NotificationService::AllSources()); |
| 81 } | 81 } |
| 82 | 82 |
| 83 virtual ~DownloadsEventsListener() { | 83 virtual ~DownloadsEventsListener() { |
| 84 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, | 84 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, |
| 85 content::NotificationService::AllSources()); | 85 content::NotificationService::AllSources()); |
| 86 STLDeleteElements(&events_); | 86 STLDeleteElements(&events_); |
| 87 } | 87 } |
| 88 | 88 |
| 89 void ClearEvents() { |
| 90 STLDeleteElements(&events_); |
| 91 events_.clear(); |
| 92 } |
| 93 |
| 89 class Event { | 94 class Event { |
| 90 public: | 95 public: |
| 91 Event(Profile* profile, | 96 Event(Profile* profile, |
| 92 const std::string& event_name, | 97 const std::string& event_name, |
| 93 const std::string& json_args, | 98 const std::string& json_args, |
| 94 base::Time caught) | 99 base::Time caught) |
| 95 : profile_(profile), | 100 : profile_(profile), |
| 96 event_name_(event_name), | 101 event_name_(event_name), |
| 97 json_args_(json_args), | 102 json_args_(json_args), |
| 98 args_(base::JSONReader::Read(json_args)), | 103 args_(base::JSONReader::Read(json_args)), |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 return WaitFor(events::kOnDownloadChanged, | 333 return WaitFor(events::kOnDownloadChanged, |
| 329 base::StringPrintf("[{\"id\": %d," | 334 base::StringPrintf("[{\"id\": %d," |
| 330 " \"error\": {\"current\": %d}," | 335 " \"error\": {\"current\": %d}," |
| 331 " \"state\": {" | 336 " \"state\": {" |
| 332 " \"previous\": \"in_progress\"," | 337 " \"previous\": \"in_progress\"," |
| 333 " \"current\": \"interrupted\"}}]", | 338 " \"current\": \"interrupted\"}}]", |
| 334 item->GetId(), | 339 item->GetId(), |
| 335 expected_error)); | 340 expected_error)); |
| 336 } | 341 } |
| 337 | 342 |
| 343 void ClearEvents() { |
| 344 events_listener_->ClearEvents(); |
| 345 } |
| 346 |
| 338 std::string GetExtensionURL() { | 347 std::string GetExtensionURL() { |
| 339 return extension_->url().spec(); | 348 return extension_->url().spec(); |
| 340 } | 349 } |
| 341 std::string GetExtensionId() { | 350 std::string GetExtensionId() { |
| 342 return extension_->id(); | 351 return extension_->id(); |
| 343 } | 352 } |
| 344 | 353 |
| 345 std::string GetFilename(const char* path) { | 354 std::string GetFilename(const char* path) { |
| 346 std::string result = | 355 std::string result = |
| 347 downloads_directory_.path().AppendASCII(path).AsUTF8Unsafe(); | 356 downloads_directory_.path().AppendASCII(path).AsUTF8Unsafe(); |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 840 scoped_ptr<TestURLRequestContext> url_request_context_; | 849 scoped_ptr<TestURLRequestContext> url_request_context_; |
| 841 fileapi::FileSystemContext* fs_; | 850 fileapi::FileSystemContext* fs_; |
| 842 | 851 |
| 843 DISALLOW_COPY_AND_ASSIGN(HTML5FileWriter); | 852 DISALLOW_COPY_AND_ASSIGN(HTML5FileWriter); |
| 844 }; | 853 }; |
| 845 | 854 |
| 846 const char HTML5FileWriter::kHTML5FileWritten[] = "html5_file_written"; | 855 const char HTML5FileWriter::kHTML5FileWritten[] = "html5_file_written"; |
| 847 const char HTML5FileWriter::kURLRequestContextToreDown[] = | 856 const char HTML5FileWriter::kURLRequestContextToreDown[] = |
| 848 "url_request_context_tore_down"; | 857 "url_request_context_tore_down"; |
| 849 | 858 |
| 859 // TODO(benjhayden) Merge this with the other TestObservers. |
| 860 class JustInProgressDownloadObserver |
| 861 : public content::DownloadTestObserverInProgress { |
| 862 public: |
| 863 JustInProgressDownloadObserver( |
| 864 DownloadManager* download_manager, size_t wait_count) |
| 865 : content::DownloadTestObserverInProgress(download_manager, wait_count) { |
| 866 } |
| 867 |
| 868 virtual ~JustInProgressDownloadObserver() {} |
| 869 |
| 870 private: |
| 871 virtual bool IsDownloadInFinalState(DownloadItem* item) OVERRIDE { |
| 872 return item->GetState() == DownloadItem::IN_PROGRESS; |
| 873 } |
| 874 |
| 875 DISALLOW_COPY_AND_ASSIGN(JustInProgressDownloadObserver); |
| 876 }; |
| 877 |
| 878 bool ItemIsInterrupted(DownloadItem* item) { |
| 879 return item->IsInterrupted(); |
| 880 } |
| 881 |
| 850 } // namespace | 882 } // namespace |
| 851 | 883 |
| 852 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, | 884 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, |
| 853 DownloadExtensionTest_Open) { | 885 DownloadExtensionTest_Open) { |
| 854 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, | 886 EXPECT_STREQ(download_extension_errors::kInvalidOperationError, |
| 855 RunFunctionAndReturnError( | 887 RunFunctionAndReturnError( |
| 856 new DownloadsOpenFunction(), | 888 new DownloadsOpenFunction(), |
| 857 "[-42]").c_str()); | 889 "[-42]").c_str()); |
| 858 | 890 |
| 859 DownloadItem* download_item = CreateSlowTestDownload(); | 891 DownloadItem* download_item = CreateSlowTestDownload(); |
| (...skipping 2229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3089 GetFilename("42 (1).txt.crdownload").c_str(), | 3121 GetFilename("42 (1).txt.crdownload").c_str(), |
| 3090 GetFilename("42 (1).txt").c_str()))); | 3122 GetFilename("42 (1).txt").c_str()))); |
| 3091 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, | 3123 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, |
| 3092 base::StringPrintf("[{\"id\": %d," | 3124 base::StringPrintf("[{\"id\": %d," |
| 3093 " \"state\": {" | 3125 " \"state\": {" |
| 3094 " \"previous\": \"in_progress\"," | 3126 " \"previous\": \"in_progress\"," |
| 3095 " \"current\": \"complete\"}}]", | 3127 " \"current\": \"complete\"}}]", |
| 3096 result_id))); | 3128 result_id))); |
| 3097 } | 3129 } |
| 3098 | 3130 |
| 3099 // Test download interruption while extensions determining filename, re-run | 3131 // Test download interruption while extensions determining filename. Should not |
| 3100 // through fan-out and fan-in. | 3132 // re-dispatch onDeterminingFilename. |
| 3101 // TODO(rdsmith): FILE_OPERATION_INITIALIZE is not right for this test. | |
| 3102 IN_PROC_BROWSER_TEST_F( | 3133 IN_PROC_BROWSER_TEST_F( |
| 3103 DownloadExtensionTest, | 3134 DownloadExtensionTest, |
| 3104 DISABLED_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume) { | 3135 DownloadExtensionTest_OnDeterminingFilename_InterruptedResume) { |
| 3136 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 3137 switches::kEnableDownloadResumption); |
| 3105 LoadExtension("downloads_split"); | 3138 LoadExtension("downloads_split"); |
| 3106 CHECK(StartTestServer()); | 3139 CHECK(StartTestServer()); |
| 3107 std::string download_url = test_server()->GetURL("slow?0").spec(); | |
| 3108 GoOnTheRecord(); | 3140 GoOnTheRecord(); |
| 3109 AddFilenameDeterminer(); | 3141 AddFilenameDeterminer(); |
| 3110 | 3142 |
| 3111 // TODO Interrupt the download instead of responding to onDeterminingFilename. | |
| 3112 scoped_refptr<content::TestFileErrorInjector> injector( | |
| 3113 content::TestFileErrorInjector::Create( | |
| 3114 GetCurrentManager())); | |
| 3115 content::TestFileErrorInjector::FileErrorInfo error_info = { | |
| 3116 download_url, | |
| 3117 content::TestFileErrorInjector::FILE_OPERATION_INITIALIZE, | |
| 3118 0, | |
| 3119 content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE}; | |
| 3120 injector->AddError(error_info); | |
| 3121 injector->InjectErrors(); | |
| 3122 | |
| 3123 // Start a download. | 3143 // Start a download. |
| 3124 scoped_ptr<base::Value> result(RunFunctionAndReturnResult( | 3144 DownloadItem* item = NULL; |
| 3125 new DownloadsDownloadFunction(), base::StringPrintf( | 3145 { |
| 3126 "[{\"url\": \"%s\"}]", download_url.c_str()))); | 3146 DownloadManager* manager = GetCurrentManager(); |
| 3127 ASSERT_TRUE(result.get()); | 3147 scoped_ptr<content::DownloadTestObserver> observer( |
| 3128 int result_id = -1; | 3148 new JustInProgressDownloadObserver(manager, 1)); |
| 3129 ASSERT_TRUE(result->GetAsInteger(&result_id)); | 3149 ASSERT_EQ(0, manager->InProgressCount()); |
| 3130 DownloadItem* item = GetCurrentManager()->GetDownload(result_id); | 3150 // Tabs created just for a download are automatically closed, invalidating |
| 3131 ASSERT_TRUE(item); | 3151 // the download's WebContents. Downloads without WebContents cannot be |
| 3152 // resumed. http://crbug.com/225901 |
| 3153 ui_test_utils::NavigateToURLWithDisposition( |
| 3154 current_browser(), |
| 3155 GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl), |
| 3156 CURRENT_TAB, |
| 3157 ui_test_utils::BROWSER_TEST_NONE); |
| 3158 observer->WaitForFinished(); |
| 3159 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS)); |
| 3160 DownloadManager::DownloadVector items; |
| 3161 manager->GetAllDownloads(&items); |
| 3162 for (DownloadManager::DownloadVector::iterator iter = items.begin(); |
| 3163 iter != items.end(); ++iter) { |
| 3164 if ((*iter)->GetState() == DownloadItem::IN_PROGRESS) { |
| 3165 // There should be only one IN_PROGRESS item. |
| 3166 EXPECT_EQ(NULL, item); |
| 3167 item = *iter; |
| 3168 } |
| 3169 } |
| 3170 ASSERT_TRUE(item); |
| 3171 } |
| 3132 ScopedCancellingItem canceller(item); | 3172 ScopedCancellingItem canceller(item); |
| 3133 ASSERT_EQ(download_url, item->GetOriginalUrl().spec()); | |
| 3134 | 3173 |
| 3135 // Wait for the onCreated and onDeterminingFilename event. | 3174 // Wait for the onCreated and onDeterminingFilename event. |
| 3136 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated, | 3175 ASSERT_TRUE(WaitFor(events::kOnDownloadCreated, |
| 3137 base::StringPrintf("[{\"danger\": \"safe\"," | 3176 base::StringPrintf("[{\"danger\": \"safe\"," |
| 3138 " \"incognito\": false," | 3177 " \"incognito\": false," |
| 3139 " \"id\": %d," | 3178 " \"id\": %d," |
| 3140 " \"mime\": \"text/plain\"," | 3179 " \"mime\": \"application/octet-stream\"," |
| 3141 " \"paused\": false," | 3180 " \"paused\": false}]", |
| 3142 " \"url\": \"%s\"}]", | 3181 item->GetId()))); |
| 3143 result_id, | |
| 3144 download_url.c_str()))); | |
| 3145 ASSERT_TRUE(WaitFor( | 3182 ASSERT_TRUE(WaitFor( |
| 3146 events::kOnDownloadDeterminingFilename, | 3183 events::kOnDownloadDeterminingFilename, |
| 3147 base::StringPrintf("[{\"id\": %d," | 3184 base::StringPrintf("[{\"id\": %d," |
| 3148 " \"incognito\": false," | 3185 " \"incognito\": false," |
| 3149 " \"filename\":\"slow.txt\"}]", | 3186 " \"filename\":\"download-unknown-size\"}]", |
| 3150 result_id))); | 3187 item->GetId()))); |
| 3151 ASSERT_TRUE(item->GetTargetFilePath().empty()); | 3188 ASSERT_TRUE(item->GetTargetFilePath().empty()); |
| 3152 ASSERT_TRUE(item->IsInProgress()); | 3189 ASSERT_TRUE(item->IsInProgress()); |
| 3153 | 3190 |
| 3154 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, | 3191 ClearEvents(); |
| 3155 base::StringPrintf("[{\"id\": %d," | 3192 ui_test_utils::NavigateToURLWithDisposition( |
| 3156 " \"state\": {" | 3193 current_browser(), |
| 3157 " \"previous\": \"in_progress\"," | 3194 GURL(URLRequestSlowDownloadJob::kErrorDownloadUrl), |
| 3158 " \"current\": \"interrupted\"}}]", | 3195 NEW_BACKGROUND_TAB, |
| 3159 result_id))); | 3196 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 3160 ASSERT_TRUE(item->IsInterrupted()); | |
| 3161 item->ResumeInterruptedDownload(); | |
| 3162 | 3197 |
| 3163 // Wait for and respond to the onDeterminingFilename event. | 3198 // Errors caught before filename determination are delayed until after |
| 3164 ASSERT_TRUE(WaitFor( | 3199 // filename determination. |
| 3165 events::kOnDownloadDeterminingFilename, | |
| 3166 base::StringPrintf("[{\"id\": %d," | |
| 3167 " \"incognito\": false," | |
| 3168 " \"filename\":\"slow.txt\"}]", | |
| 3169 result_id))); | |
| 3170 ASSERT_TRUE(item->GetTargetFilePath().empty()); | |
| 3171 ASSERT_TRUE(item->IsInProgress()); | |
| 3172 std::string error; | 3200 std::string error; |
| 3173 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename( | 3201 ASSERT_TRUE(ExtensionDownloadsEventRouter::DetermineFilename( |
| 3174 current_browser()->profile(), | 3202 current_browser()->profile(), |
| 3175 false, | 3203 false, |
| 3176 GetExtensionId(), | 3204 GetExtensionId(), |
| 3177 result_id, | 3205 item->GetId(), |
| 3178 base::FilePath(FILE_PATH_LITERAL("42.txt")), | 3206 base::FilePath(FILE_PATH_LITERAL("42.txt")), |
| 3179 false, | 3207 false, |
| 3180 &error)); | 3208 &error)) << error; |
| 3181 EXPECT_EQ("", error); | 3209 EXPECT_EQ("", error); |
| 3182 | 3210 |
| 3211 content::DownloadUpdatedObserver interrupted(item, base::Bind( |
| 3212 ItemIsInterrupted)); |
| 3213 ASSERT_TRUE(interrupted.WaitForEvent()); |
| 3214 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, |
| 3215 base::StringPrintf("[{\"id\": %d," |
| 3216 " \"error\":{\"current\":20}," |
| 3217 " \"state\":{" |
| 3218 " \"previous\":\"in_progress\"," |
| 3219 " \"current\":\"interrupted\"}}]", |
| 3220 item->GetId()))); |
| 3221 |
| 3222 ClearEvents(); |
| 3223 item->ResumeInterruptedDownload(); |
| 3224 |
| 3225 // Errors caught before filename determination is complete are delayed until |
| 3226 // after filename determination so that, on resumption, filename determination |
| 3227 // does not need to be re-done. So, there will not be a second |
| 3228 // onDeterminingFilename event. |
| 3229 |
| 3230 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, |
| 3231 base::StringPrintf("[{\"id\": %d," |
| 3232 " \"error\":{\"previous\":20}," |
| 3233 " \"state\":{" |
| 3234 " \"previous\":\"interrupted\"," |
| 3235 " \"current\":\"in_progress\"}}]", |
| 3236 item->GetId()))); |
| 3237 |
| 3238 ClearEvents(); |
| 3239 FinishPendingSlowDownloads(); |
| 3240 |
| 3183 // The download should complete successfully. | 3241 // The download should complete successfully. |
| 3184 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, | 3242 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, |
| 3185 base::StringPrintf("[{\"id\": %d," | 3243 base::StringPrintf("[{\"id\": %d," |
| 3186 " \"filename\": {" | 3244 " \"filename\": {" |
| 3187 " \"previous\": \"%s\"," | 3245 " \"previous\": \"%s\"," |
| 3188 " \"current\": \"%s\"}," | 3246 " \"current\": \"%s\"}," |
| 3189 " \"state\": {" | |
| 3190 " \"previous\": \"in_progress\"," | |
| 3191 " \"current\": \"complete\"}}]", | |
| 3192 result_id, | |
| 3193 GetFilename("42.txt.crdownload").c_str(), | |
| 3194 GetFilename("42.txt").c_str()))); | |
| 3195 ASSERT_TRUE(WaitFor(events::kOnDownloadChanged, | |
| 3196 base::StringPrintf("[{\"id\": %d," | |
| 3197 " \"state\": {" | 3247 " \"state\": {" |
| 3198 " \"previous\": \"in_progress\"," | 3248 " \"previous\": \"in_progress\"," |
| 3199 " \"current\": \"complete\"}}]", | 3249 " \"current\": \"complete\"}}]", |
| 3200 result_id))); | 3250 item->GetId(), |
| 3251 GetFilename("42.txt.crdownload").c_str(), |
| 3252 GetFilename("42.txt").c_str()))); |
| 3201 } | 3253 } |
| 3202 | 3254 |
| 3203 // TODO(benjhayden) Figure out why DisableExtension() does not fire | 3255 // TODO(benjhayden) Figure out why DisableExtension() does not fire |
| 3204 // OnListenerRemoved. | 3256 // OnListenerRemoved. |
| OLD | NEW |