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 <sstream> | 5 #include <sstream> |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/command_line.h" |
9 #include "base/file_util.h" | 10 #include "base/file_util.h" |
10 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
11 #include "base/files/scoped_temp_dir.h" | 12 #include "base/files/scoped_temp_dir.h" |
12 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
13 #include "base/path_service.h" | 14 #include "base/path_service.h" |
14 #include "base/prefs/pref_service.h" | 15 #include "base/prefs/pref_service.h" |
15 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
16 #include "base/strings/string_split.h" | 17 #include "base/strings/string_split.h" |
17 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
18 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 #include "chrome/test/base/ui_test_utils.h" | 62 #include "chrome/test/base/ui_test_utils.h" |
62 #include "content/public/browser/download_item.h" | 63 #include "content/public/browser/download_item.h" |
63 #include "content/public/browser/download_manager.h" | 64 #include "content/public/browser/download_manager.h" |
64 #include "content/public/browser/download_save_info.h" | 65 #include "content/public/browser/download_save_info.h" |
65 #include "content/public/browser/download_url_parameters.h" | 66 #include "content/public/browser/download_url_parameters.h" |
66 #include "content/public/browser/notification_source.h" | 67 #include "content/public/browser/notification_source.h" |
67 #include "content/public/browser/plugin_service.h" | 68 #include "content/public/browser/plugin_service.h" |
68 #include "content/public/browser/render_view_host.h" | 69 #include "content/public/browser/render_view_host.h" |
69 #include "content/public/browser/resource_context.h" | 70 #include "content/public/browser/resource_context.h" |
70 #include "content/public/browser/web_contents.h" | 71 #include "content/public/browser/web_contents.h" |
| 72 #include "content/public/common/content_switches.h" |
71 #include "content/public/common/context_menu_params.h" | 73 #include "content/public/common/context_menu_params.h" |
72 #include "content/public/common/page_transition_types.h" | 74 #include "content/public/common/page_transition_types.h" |
73 #include "content/public/test/browser_test_utils.h" | 75 #include "content/public/test/browser_test_utils.h" |
74 #include "content/public/test/download_test_observer.h" | 76 #include "content/public/test/download_test_observer.h" |
75 #include "content/public/test/test_file_error_injector.h" | 77 #include "content/public/test/test_file_error_injector.h" |
76 #include "content/public/test/test_navigation_observer.h" | 78 #include "content/public/test/test_navigation_observer.h" |
77 #include "content/test/net/url_request_mock_http_job.h" | 79 #include "content/test/net/url_request_mock_http_job.h" |
78 #include "content/test/net/url_request_slow_download_job.h" | 80 #include "content/test/net/url_request_slow_download_job.h" |
79 #include "grit/generated_resources.h" | 81 #include "grit/generated_resources.h" |
80 #include "net/base/net_util.h" | 82 #include "net/base/net_util.h" |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 } | 180 } |
179 | 181 |
180 content::DownloadItem* item_; | 182 content::DownloadItem* item_; |
181 bool waiting_; | 183 bool waiting_; |
182 bool error_; | 184 bool error_; |
183 int prev_percent_; | 185 int prev_percent_; |
184 | 186 |
185 DISALLOW_COPY_AND_ASSIGN(PercentWaiter); | 187 DISALLOW_COPY_AND_ASSIGN(PercentWaiter); |
186 }; | 188 }; |
187 | 189 |
| 190 // DownloadTestObserver subclass that observes one download until it transitions |
| 191 // from a non-resumable state to a resumable state a specified number of |
| 192 // times. Note that this observer can only observe a single download. |
| 193 class DownloadTestObserverResumable : public content::DownloadTestObserver { |
| 194 public: |
| 195 // Construct a new observer. |transition_count| is the number of times the |
| 196 // download should transition from a non-resumable state to a resumable state. |
| 197 DownloadTestObserverResumable(DownloadManager* download_manager, |
| 198 size_t transition_count) |
| 199 : DownloadTestObserver(download_manager, 1, |
| 200 ON_DANGEROUS_DOWNLOAD_FAIL), |
| 201 was_previously_resumable_(false), |
| 202 transitions_left_(transition_count) { |
| 203 Init(); |
| 204 } |
| 205 virtual ~DownloadTestObserverResumable() {} |
| 206 |
| 207 private: |
| 208 virtual bool IsDownloadInFinalState(DownloadItem* download) OVERRIDE { |
| 209 bool is_resumable_now = download->CanResume(); |
| 210 if (!was_previously_resumable_ && is_resumable_now) |
| 211 --transitions_left_; |
| 212 was_previously_resumable_ = is_resumable_now; |
| 213 return transitions_left_ == 0; |
| 214 } |
| 215 |
| 216 bool was_previously_resumable_; |
| 217 size_t transitions_left_; |
| 218 |
| 219 DISALLOW_COPY_AND_ASSIGN(DownloadTestObserverResumable); |
| 220 }; |
| 221 |
| 222 // DownloadTestObserver subclass that observes a download until it transitions |
| 223 // from IN_PROGRESS to another state, but only after StartObserving() is called. |
| 224 class DownloadTestObserverNotInProgress : public content::DownloadTestObserver { |
| 225 public: |
| 226 DownloadTestObserverNotInProgress(DownloadManager* download_manager, |
| 227 size_t count) |
| 228 : DownloadTestObserver(download_manager, count, |
| 229 ON_DANGEROUS_DOWNLOAD_FAIL), |
| 230 started_observing_(false) { |
| 231 Init(); |
| 232 } |
| 233 virtual ~DownloadTestObserverNotInProgress() {} |
| 234 |
| 235 void StartObserving() { |
| 236 started_observing_ = true; |
| 237 } |
| 238 |
| 239 private: |
| 240 virtual bool IsDownloadInFinalState(DownloadItem* download) OVERRIDE { |
| 241 return started_observing_ && |
| 242 download->GetState() != DownloadItem::IN_PROGRESS; |
| 243 } |
| 244 |
| 245 bool started_observing_; |
| 246 }; |
| 247 |
188 // IDs and paths of CRX files used in tests. | 248 // IDs and paths of CRX files used in tests. |
189 const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; | 249 const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; |
190 const base::FilePath kGoodCrxPath(FILE_PATH_LITERAL("extensions/good.crx")); | 250 const base::FilePath kGoodCrxPath(FILE_PATH_LITERAL("extensions/good.crx")); |
191 | 251 |
192 const char kLargeThemeCrxId[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; | 252 const char kLargeThemeCrxId[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; |
193 const base::FilePath kLargeThemePath( | 253 const base::FilePath kLargeThemePath( |
194 FILE_PATH_LITERAL("extensions/theme2.crx")); | 254 FILE_PATH_LITERAL("extensions/theme2.crx")); |
195 | 255 |
196 // Get History Information. | 256 // Get History Information. |
197 class DownloadsHistoryDataCollector { | 257 class DownloadsHistoryDataCollector { |
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 } | 1058 } |
999 } | 1059 } |
1000 | 1060 |
1001 // A mock install prompt that simulates the user allowing an install request. | 1061 // A mock install prompt that simulates the user allowing an install request. |
1002 void SetAllowMockInstallPrompt() { | 1062 void SetAllowMockInstallPrompt() { |
1003 download_crx_util::SetMockInstallPromptForTesting( | 1063 download_crx_util::SetMockInstallPromptForTesting( |
1004 new MockAutoConfirmExtensionInstallPrompt( | 1064 new MockAutoConfirmExtensionInstallPrompt( |
1005 browser()->tab_strip_model()->GetActiveWebContents())); | 1065 browser()->tab_strip_model()->GetActiveWebContents())); |
1006 } | 1066 } |
1007 | 1067 |
| 1068 // This method: |
| 1069 // * Starts a mock download by navigating browser() to a URLRequestMockHTTPJob |
| 1070 // mock URL. |
| 1071 // * Injects |error| on the first write using |error_injector|. |
| 1072 // * Waits for the download to be interrupted. |
| 1073 // * Clears the errors on |error_injector|. |
| 1074 // * Returns the resulting interrupted download. |
| 1075 DownloadItem* StartMockDownloadAndInjectError( |
| 1076 content::TestFileErrorInjector* error_injector, |
| 1077 content::DownloadInterruptReason error) { |
| 1078 base::FilePath file_path(FILE_PATH_LITERAL("download-test1.lib")); |
| 1079 GURL url = URLRequestMockHTTPJob::GetMockUrl(file_path); |
| 1080 |
| 1081 content::TestFileErrorInjector::FileErrorInfo error_info; |
| 1082 error_info.url = url.spec(); |
| 1083 error_info.code = content::TestFileErrorInjector::FILE_OPERATION_WRITE; |
| 1084 error_info.operation_instance = 0; |
| 1085 error_info.error = error; |
| 1086 error_injector->ClearErrors(); |
| 1087 error_injector->AddError(error_info); |
| 1088 error_injector->InjectErrors(); |
| 1089 |
| 1090 scoped_ptr<content::DownloadTestObserver> observer( |
| 1091 new DownloadTestObserverResumable( |
| 1092 DownloadManagerForBrowser(browser()), 1)); |
| 1093 ui_test_utils::NavigateToURL(browser(), url); |
| 1094 observer->WaitForFinished(); |
| 1095 |
| 1096 content::DownloadManager::DownloadVector downloads; |
| 1097 DownloadManagerForBrowser(browser())->GetAllDownloads(&downloads); |
| 1098 EXPECT_EQ(1u, downloads.size()); |
| 1099 |
| 1100 if (downloads.size() != 1) |
| 1101 return NULL; |
| 1102 |
| 1103 error_injector->ClearErrors(); |
| 1104 error_injector->InjectErrors(); |
| 1105 DownloadItem* download = downloads[0]; |
| 1106 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState()); |
| 1107 EXPECT_EQ(error, download->GetLastReason()); |
| 1108 return download; |
| 1109 } |
| 1110 |
1008 private: | 1111 private: |
1009 static void EnsureNoPendingDownloadJobsOnIO(bool* result) { | 1112 static void EnsureNoPendingDownloadJobsOnIO(bool* result) { |
1010 if (URLRequestSlowDownloadJob::NumberOutstandingRequests()) | 1113 if (URLRequestSlowDownloadJob::NumberOutstandingRequests()) |
1011 *result = false; | 1114 *result = false; |
1012 BrowserThread::PostTask( | 1115 BrowserThread::PostTask( |
1013 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure()); | 1116 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure()); |
1014 } | 1117 } |
1015 | 1118 |
1016 // Location of the test data. | 1119 // Location of the test data. |
1017 base::FilePath test_dir_; | 1120 base::FilePath test_dir_; |
(...skipping 1946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2964 EXPECT_EQ(dir.value(), off_prefs->SaveFilePath().value()); | 3067 EXPECT_EQ(dir.value(), off_prefs->SaveFilePath().value()); |
2965 | 3068 |
2966 off_prefs->SetSaveFilePath(dir.AppendASCII("off")); | 3069 off_prefs->SetSaveFilePath(dir.AppendASCII("off")); |
2967 EXPECT_EQ(dir.value(), on_prefs->SaveFilePath().value()); | 3070 EXPECT_EQ(dir.value(), on_prefs->SaveFilePath().value()); |
2968 EXPECT_EQ(dir.AppendASCII("off").value(), off_prefs->SaveFilePath().value()); | 3071 EXPECT_EQ(dir.AppendASCII("off").value(), off_prefs->SaveFilePath().value()); |
2969 | 3072 |
2970 on_prefs->SetSaveFilePath(dir.AppendASCII("on")); | 3073 on_prefs->SetSaveFilePath(dir.AppendASCII("on")); |
2971 EXPECT_EQ(dir.AppendASCII("on").value(), on_prefs->SaveFilePath().value()); | 3074 EXPECT_EQ(dir.AppendASCII("on").value(), on_prefs->SaveFilePath().value()); |
2972 EXPECT_EQ(dir.AppendASCII("off").value(), off_prefs->SaveFilePath().value()); | 3075 EXPECT_EQ(dir.AppendASCII("off").value(), off_prefs->SaveFilePath().value()); |
2973 } | 3076 } |
| 3077 |
| 3078 // A download that is interrupted due to a file error should be able to be |
| 3079 // resumed. |
| 3080 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_NoPrompt) { |
| 3081 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 3082 switches::kEnableDownloadResumption); |
| 3083 scoped_refptr<content::TestFileErrorInjector> error_injector( |
| 3084 content::TestFileErrorInjector::Create( |
| 3085 DownloadManagerForBrowser(browser()))); |
| 3086 scoped_ptr<content::DownloadTestObserver> completion_observer( |
| 3087 CreateWaiter(browser(), 1)); |
| 3088 EnableFileChooser(true); |
| 3089 |
| 3090 DownloadItem* download = StartMockDownloadAndInjectError( |
| 3091 error_injector, |
| 3092 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); |
| 3093 ASSERT_TRUE(download); |
| 3094 |
| 3095 download->Resume(); |
| 3096 completion_observer->WaitForFinished(); |
| 3097 |
| 3098 EXPECT_EQ( |
| 3099 1u, completion_observer->NumDownloadsSeenInState(DownloadItem::COMPLETE)); |
| 3100 EXPECT_FALSE(DidShowFileChooser()); |
| 3101 } |
| 3102 |
| 3103 // A download that's interrupted due to a reason that indicates that the target |
| 3104 // path is invalid or unusable should cause a prompt to be displayed on |
| 3105 // resumption. |
| 3106 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_WithPrompt) { |
| 3107 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 3108 switches::kEnableDownloadResumption); |
| 3109 scoped_refptr<content::TestFileErrorInjector> error_injector( |
| 3110 content::TestFileErrorInjector::Create( |
| 3111 DownloadManagerForBrowser(browser()))); |
| 3112 scoped_ptr<content::DownloadTestObserver> completion_observer( |
| 3113 CreateWaiter(browser(), 1)); |
| 3114 EnableFileChooser(true); |
| 3115 |
| 3116 DownloadItem* download = StartMockDownloadAndInjectError( |
| 3117 error_injector, |
| 3118 content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE); |
| 3119 ASSERT_TRUE(download); |
| 3120 |
| 3121 download->Resume(); |
| 3122 completion_observer->WaitForFinished(); |
| 3123 |
| 3124 EXPECT_EQ( |
| 3125 1u, completion_observer->NumDownloadsSeenInState(DownloadItem::COMPLETE)); |
| 3126 EXPECT_TRUE(DidShowFileChooser()); |
| 3127 } |
| 3128 |
| 3129 // The user shouldn't be prompted on a resumed download unless a prompt is |
| 3130 // necessary due to the interrupt reason. |
| 3131 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_WithPromptAlways) { |
| 3132 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 3133 switches::kEnableDownloadResumption); |
| 3134 browser()->profile()->GetPrefs()->SetBoolean( |
| 3135 prefs::kPromptForDownload, true); |
| 3136 scoped_refptr<content::TestFileErrorInjector> error_injector( |
| 3137 content::TestFileErrorInjector::Create( |
| 3138 DownloadManagerForBrowser(browser()))); |
| 3139 scoped_ptr<content::DownloadTestObserver> completion_observer( |
| 3140 CreateWaiter(browser(), 1)); |
| 3141 EnableFileChooser(true); |
| 3142 |
| 3143 DownloadItem* download = StartMockDownloadAndInjectError( |
| 3144 error_injector, |
| 3145 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); |
| 3146 ASSERT_TRUE(download); |
| 3147 |
| 3148 // Prompts the user initially because of the kPromptForDownload preference. |
| 3149 EXPECT_TRUE(DidShowFileChooser()); |
| 3150 |
| 3151 download->Resume(); |
| 3152 completion_observer->WaitForFinished(); |
| 3153 |
| 3154 EXPECT_EQ( |
| 3155 1u, completion_observer->NumDownloadsSeenInState(DownloadItem::COMPLETE)); |
| 3156 // Shouldn't prompt for resumption. |
| 3157 EXPECT_FALSE(DidShowFileChooser()); |
| 3158 } |
| 3159 |
| 3160 // A download that is interrupted due to a transient error should be resumed |
| 3161 // automatically. |
| 3162 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_Automatic) { |
| 3163 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 3164 switches::kEnableDownloadResumption); |
| 3165 scoped_refptr<content::TestFileErrorInjector> error_injector( |
| 3166 content::TestFileErrorInjector::Create( |
| 3167 DownloadManagerForBrowser(browser()))); |
| 3168 |
| 3169 DownloadItem* download = StartMockDownloadAndInjectError( |
| 3170 error_injector, |
| 3171 content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR); |
| 3172 ASSERT_TRUE(download); |
| 3173 |
| 3174 // The number of times this the download is resumed automatically is defined |
| 3175 // in DownloadItemImpl::kMaxAutoResumeAttempts. The number of DownloadFiles |
| 3176 // created should be that number + 1 (for the original download request). We |
| 3177 // only care that it is greater than 1. |
| 3178 EXPECT_GT(1u, error_injector->TotalFileCount()); |
| 3179 } |
| 3180 |
| 3181 // An interrupting download should be resumable multiple times. |
| 3182 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_MultipleAttempts) { |
| 3183 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 3184 switches::kEnableDownloadResumption); |
| 3185 scoped_refptr<content::TestFileErrorInjector> error_injector( |
| 3186 content::TestFileErrorInjector::Create( |
| 3187 DownloadManagerForBrowser(browser()))); |
| 3188 scoped_ptr<DownloadTestObserverNotInProgress> completion_observer( |
| 3189 new DownloadTestObserverNotInProgress( |
| 3190 DownloadManagerForBrowser(browser()), 1)); |
| 3191 // Wait for two transitions to a resumable state |
| 3192 scoped_ptr<content::DownloadTestObserver> resumable_observer( |
| 3193 new DownloadTestObserverResumable( |
| 3194 DownloadManagerForBrowser(browser()), 2)); |
| 3195 |
| 3196 EnableFileChooser(true); |
| 3197 DownloadItem* download = StartMockDownloadAndInjectError( |
| 3198 error_injector, |
| 3199 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); |
| 3200 ASSERT_TRUE(download); |
| 3201 |
| 3202 content::TestFileErrorInjector::FileErrorInfo error_info; |
| 3203 error_info.url = download->GetOriginalUrl().spec(); |
| 3204 error_info.code = content::TestFileErrorInjector::FILE_OPERATION_WRITE; |
| 3205 error_info.operation_instance = 0; |
| 3206 error_info.error = content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; |
| 3207 error_injector->AddError(error_info); |
| 3208 error_injector->InjectErrors(); |
| 3209 |
| 3210 // Resuming should cause the download to be interrupted again due to the |
| 3211 // errors we are injecting. |
| 3212 download->Resume(); |
| 3213 resumable_observer->WaitForFinished(); |
| 3214 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); |
| 3215 ASSERT_EQ(content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, |
| 3216 download->GetLastReason()); |
| 3217 |
| 3218 error_injector->ClearErrors(); |
| 3219 error_injector->InjectErrors(); |
| 3220 |
| 3221 // No errors this time. The download should complete successfully. |
| 3222 EXPECT_FALSE(completion_observer->IsFinished()); |
| 3223 completion_observer->StartObserving(); |
| 3224 download->Resume(); |
| 3225 completion_observer->WaitForFinished(); |
| 3226 EXPECT_EQ(DownloadItem::COMPLETE, download->GetState()); |
| 3227 |
| 3228 EXPECT_FALSE(DidShowFileChooser()); |
| 3229 } |
OLD | NEW |