Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: chrome/browser/download/download_browsertest.cc

Issue 17315009: [Downloads] Add more browsertests for resumption. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Serialize alls to TestFileErrorInjector accounting methods. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | content/public/test/test_file_error_injector.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | content/public/test/test_file_error_injector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698