Chromium Code Reviews| 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 | |
| 188 // IDs and paths of CRX files used in tests. | 222 // IDs and paths of CRX files used in tests. |
| 189 const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; | 223 const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; |
| 190 const base::FilePath kGoodCrxPath(FILE_PATH_LITERAL("extensions/good.crx")); | 224 const base::FilePath kGoodCrxPath(FILE_PATH_LITERAL("extensions/good.crx")); |
| 191 | 225 |
| 192 const char kLargeThemeCrxId[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; | 226 const char kLargeThemeCrxId[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; |
| 193 const base::FilePath kLargeThemePath( | 227 const base::FilePath kLargeThemePath( |
| 194 FILE_PATH_LITERAL("extensions/theme2.crx")); | 228 FILE_PATH_LITERAL("extensions/theme2.crx")); |
| 195 | 229 |
| 196 // Get History Information. | 230 // Get History Information. |
| 197 class DownloadsHistoryDataCollector { | 231 class DownloadsHistoryDataCollector { |
| (...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 998 } | 1032 } |
| 999 } | 1033 } |
| 1000 | 1034 |
| 1001 // A mock install prompt that simulates the user allowing an install request. | 1035 // A mock install prompt that simulates the user allowing an install request. |
| 1002 void SetAllowMockInstallPrompt() { | 1036 void SetAllowMockInstallPrompt() { |
| 1003 download_crx_util::SetMockInstallPromptForTesting( | 1037 download_crx_util::SetMockInstallPromptForTesting( |
| 1004 new MockAutoConfirmExtensionInstallPrompt( | 1038 new MockAutoConfirmExtensionInstallPrompt( |
| 1005 browser()->tab_strip_model()->GetActiveWebContents())); | 1039 browser()->tab_strip_model()->GetActiveWebContents())); |
| 1006 } | 1040 } |
| 1007 | 1041 |
| 1042 // This method: | |
| 1043 // * Starts a mock download by navigating browser() to a URLRequestMockHTTPJob | |
| 1044 // mock URL. | |
| 1045 // * Injects |error| on the first write using |error_injector|. | |
| 1046 // * Waits for the download to be interrupted. | |
| 1047 // * Clears the errors on |error_injector|. | |
| 1048 // * Returns the resulting interrupted download. | |
| 1049 DownloadItem* StartMockDownloadAndInjectError( | |
| 1050 content::TestFileErrorInjector* error_injector, | |
| 1051 content::DownloadInterruptReason error) { | |
| 1052 base::FilePath file_path(FILE_PATH_LITERAL("download-test1.lib")); | |
| 1053 GURL url = URLRequestMockHTTPJob::GetMockUrl(file_path); | |
| 1054 | |
| 1055 content::TestFileErrorInjector::FileErrorInfo error_info; | |
| 1056 error_info.url = url.spec(); | |
| 1057 error_info.code = content::TestFileErrorInjector::FILE_OPERATION_WRITE; | |
| 1058 error_info.operation_instance = 0; | |
| 1059 error_info.error = error; | |
| 1060 error_injector->ClearErrors(); | |
| 1061 error_injector->AddError(error_info); | |
| 1062 error_injector->InjectErrors(); | |
| 1063 | |
| 1064 scoped_ptr<content::DownloadTestObserver> observer( | |
| 1065 new DownloadTestObserverResumable( | |
| 1066 DownloadManagerForBrowser(browser()), 1)); | |
| 1067 ui_test_utils::NavigateToURL(browser(), url); | |
| 1068 observer->WaitForFinished(); | |
| 1069 | |
| 1070 content::DownloadManager::DownloadVector downloads; | |
| 1071 DownloadManagerForBrowser(browser())->GetAllDownloads(&downloads); | |
| 1072 EXPECT_EQ(1u, downloads.size()); | |
| 1073 | |
| 1074 if (downloads.size() != 1) | |
| 1075 return NULL; | |
| 1076 | |
| 1077 error_injector->ClearErrors(); | |
| 1078 error_injector->InjectErrors(); | |
| 1079 DownloadItem* download = downloads[0]; | |
| 1080 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState()); | |
| 1081 EXPECT_EQ(error, download->GetLastReason()); | |
| 1082 return download; | |
| 1083 } | |
| 1084 | |
| 1008 private: | 1085 private: |
| 1009 static void EnsureNoPendingDownloadJobsOnIO(bool* result) { | 1086 static void EnsureNoPendingDownloadJobsOnIO(bool* result) { |
| 1010 if (URLRequestSlowDownloadJob::NumberOutstandingRequests()) | 1087 if (URLRequestSlowDownloadJob::NumberOutstandingRequests()) |
| 1011 *result = false; | 1088 *result = false; |
| 1012 BrowserThread::PostTask( | 1089 BrowserThread::PostTask( |
| 1013 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure()); | 1090 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure()); |
| 1014 } | 1091 } |
| 1015 | 1092 |
| 1016 // Location of the test data. | 1093 // Location of the test data. |
| 1017 base::FilePath test_dir_; | 1094 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()); | 3041 EXPECT_EQ(dir.value(), off_prefs->SaveFilePath().value()); |
| 2965 | 3042 |
| 2966 off_prefs->SetSaveFilePath(dir.AppendASCII("off")); | 3043 off_prefs->SetSaveFilePath(dir.AppendASCII("off")); |
| 2967 EXPECT_EQ(dir.value(), on_prefs->SaveFilePath().value()); | 3044 EXPECT_EQ(dir.value(), on_prefs->SaveFilePath().value()); |
| 2968 EXPECT_EQ(dir.AppendASCII("off").value(), off_prefs->SaveFilePath().value()); | 3045 EXPECT_EQ(dir.AppendASCII("off").value(), off_prefs->SaveFilePath().value()); |
| 2969 | 3046 |
| 2970 on_prefs->SetSaveFilePath(dir.AppendASCII("on")); | 3047 on_prefs->SetSaveFilePath(dir.AppendASCII("on")); |
| 2971 EXPECT_EQ(dir.AppendASCII("on").value(), on_prefs->SaveFilePath().value()); | 3048 EXPECT_EQ(dir.AppendASCII("on").value(), on_prefs->SaveFilePath().value()); |
| 2972 EXPECT_EQ(dir.AppendASCII("off").value(), off_prefs->SaveFilePath().value()); | 3049 EXPECT_EQ(dir.AppendASCII("off").value(), off_prefs->SaveFilePath().value()); |
| 2973 } | 3050 } |
| 3051 | |
| 3052 // A download that is interrupted due to a file error should be able to be | |
| 3053 // resumed. | |
| 3054 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_NoPrompt) { | |
| 3055 CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 3056 switches::kEnableDownloadResumption); | |
| 3057 scoped_refptr<content::TestFileErrorInjector> error_injector( | |
| 3058 content::TestFileErrorInjector::Create( | |
| 3059 DownloadManagerForBrowser(browser()))); | |
| 3060 scoped_ptr<content::DownloadTestObserver> completion_observer( | |
| 3061 CreateWaiter(browser(), 1)); | |
| 3062 EnableFileChooser(true); | |
| 3063 | |
| 3064 DownloadItem* download = StartMockDownloadAndInjectError( | |
| 3065 error_injector, | |
| 3066 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | |
| 3067 ASSERT_TRUE(download); | |
| 3068 | |
| 3069 download->Resume(); | |
| 3070 completion_observer->WaitForFinished(); | |
| 3071 | |
| 3072 EXPECT_EQ( | |
| 3073 1u, completion_observer->NumDownloadsSeenInState(DownloadItem::COMPLETE)); | |
| 3074 EXPECT_FALSE(DidShowFileChooser()); | |
| 3075 } | |
| 3076 | |
| 3077 // A download that's interrupted due to a reason that indicates that the target | |
| 3078 // path is invalid or unusable should cause a prompt to be displayed on | |
| 3079 // resumption. | |
| 3080 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_WithPrompt) { | |
| 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_NO_SPACE); | |
| 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_TRUE(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. | |
|
Randy Smith (Not in Mondays)
2013/06/19 21:46:21
nit: Description doesn't differentiate from previo
asanka
2013/06/20 20:04:01
Done.
| |
| 3106 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_WithPromptAlways) { | |
| 3107 CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 3108 switches::kEnableDownloadResumption); | |
| 3109 browser()->profile()->GetPrefs()->SetBoolean( | |
| 3110 prefs::kPromptForDownload, true); | |
| 3111 scoped_refptr<content::TestFileErrorInjector> error_injector( | |
| 3112 content::TestFileErrorInjector::Create( | |
| 3113 DownloadManagerForBrowser(browser()))); | |
| 3114 scoped_ptr<content::DownloadTestObserver> completion_observer( | |
| 3115 CreateWaiter(browser(), 1)); | |
| 3116 EnableFileChooser(true); | |
| 3117 | |
| 3118 DownloadItem* download = StartMockDownloadAndInjectError( | |
| 3119 error_injector, | |
| 3120 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | |
| 3121 ASSERT_TRUE(download); | |
| 3122 | |
| 3123 // Prompts the user initially because of the kPromptForDownload preference. | |
| 3124 EXPECT_TRUE(DidShowFileChooser()); | |
| 3125 | |
| 3126 download->Resume(); | |
| 3127 completion_observer->WaitForFinished(); | |
| 3128 | |
| 3129 EXPECT_EQ( | |
| 3130 1u, completion_observer->NumDownloadsSeenInState(DownloadItem::COMPLETE)); | |
| 3131 // Shouldn't prompt for resumption. | |
| 3132 EXPECT_FALSE(DidShowFileChooser()); | |
| 3133 } | |
| 3134 | |
| 3135 // A download that is interrupted due to a transient error should be resumed | |
| 3136 // automatically. | |
| 3137 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_Automatic) { | |
| 3138 CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 3139 switches::kEnableDownloadResumption); | |
| 3140 scoped_refptr<content::TestFileErrorInjector> error_injector( | |
| 3141 content::TestFileErrorInjector::Create( | |
| 3142 DownloadManagerForBrowser(browser()))); | |
| 3143 | |
| 3144 DownloadItem* download = StartMockDownloadAndInjectError( | |
| 3145 error_injector, | |
| 3146 content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR); | |
| 3147 ASSERT_TRUE(download); | |
| 3148 | |
| 3149 // The number of times this the download is resumed automatically is defined | |
| 3150 // in DownloadItemImpl::kMaxAutoResumeAttempts. The number of DownloadFiles | |
| 3151 // created should be that number + 1 (for the original download request). We | |
| 3152 // only care that it is greater than 1. | |
| 3153 EXPECT_GT(1u, error_injector->TotalFileCount()); | |
| 3154 } | |
| 3155 | |
| 3156 // An interrupting download should be resumable multiple times. | |
| 3157 IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_MultipleAttempts) { | |
| 3158 CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 3159 switches::kEnableDownloadResumption); | |
| 3160 scoped_refptr<content::TestFileErrorInjector> error_injector( | |
| 3161 content::TestFileErrorInjector::Create( | |
| 3162 DownloadManagerForBrowser(browser()))); | |
| 3163 scoped_ptr<content::DownloadTestObserver> completion_observer( | |
| 3164 CreateWaiter(browser(), 1)); | |
| 3165 // Wait for two transitions to a resumable state | |
| 3166 scoped_ptr<content::DownloadTestObserver> resumable_observer( | |
| 3167 new DownloadTestObserverResumable( | |
| 3168 DownloadManagerForBrowser(browser()), 2)); | |
| 3169 | |
| 3170 EnableFileChooser(true); | |
| 3171 DownloadItem* download = StartMockDownloadAndInjectError( | |
| 3172 error_injector, | |
| 3173 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | |
| 3174 ASSERT_TRUE(download); | |
| 3175 | |
| 3176 content::TestFileErrorInjector::FileErrorInfo error_info; | |
| 3177 error_info.url = download->GetOriginalUrl().spec(); | |
| 3178 error_info.code = content::TestFileErrorInjector::FILE_OPERATION_WRITE; | |
| 3179 error_info.operation_instance = 0; | |
| 3180 error_info.error = content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; | |
| 3181 error_injector->AddError(error_info); | |
| 3182 error_injector->InjectErrors(); | |
| 3183 | |
| 3184 // Resuming should cause the download to be interrupted again due to the | |
| 3185 // errors we are injecting. | |
| 3186 download->Resume(); | |
| 3187 resumable_observer->WaitForFinished(); | |
| 3188 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); | |
| 3189 ASSERT_EQ(content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, | |
| 3190 download->GetLastReason()); | |
| 3191 | |
| 3192 error_injector->ClearErrors(); | |
| 3193 error_injector->InjectErrors(); | |
| 3194 | |
| 3195 // No errors this time. The download should complete successfully. | |
| 3196 download->Resume(); | |
| 3197 completion_observer->WaitForFinished(); | |
|
Randy Smith (Not in Mondays)
2013/06/19 21:46:21
nit: I'd rather have this wait for a transition ou
asanka
2013/06/20 20:04:01
Done.
| |
| 3198 | |
| 3199 EXPECT_FALSE(DidShowFileChooser()); | |
| 3200 } | |
| OLD | NEW |