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

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

Issue 2453633006: [downloads] Move platform specific code out of DownloadTargetDeterminer. (Closed)
Patch Set: . Created 3 years, 8 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "chrome/browser/download/download_target_determiner.h" 5 #include "chrome/browser/download/download_target_determiner.h"
6 6
7 #include <string>
8 #include <vector>
9
7 #include "base/location.h" 10 #include "base/location.h"
8 #include "base/rand_util.h" 11 #include "base/rand_util.h"
9 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
10 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
11 #include "base/task_scheduler/post_task.h" 14 #include "base/task_scheduler/post_task.h"
12 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
13 #include "base/time/time.h" 16 #include "base/time/time.h"
14 #include "build/build_config.h"
15 #include "chrome/browser/download/chrome_download_manager_delegate.h" 17 #include "chrome/browser/download/chrome_download_manager_delegate.h"
16 #include "chrome/browser/download/download_crx_util.h" 18 #include "chrome/browser/download/download_crx_util.h"
17 #include "chrome/browser/download/download_prefs.h" 19 #include "chrome/browser/download/download_prefs.h"
18 #include "chrome/browser/history/history_service_factory.h" 20 #include "chrome/browser/history/history_service_factory.h"
19 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/pref_names.h" 22 #include "chrome/common/pref_names.h"
21 #include "chrome/common/safe_browsing/file_type_policies.h" 23 #include "chrome/common/safe_browsing/file_type_policies.h"
22 #include "chrome/grit/generated_resources.h" 24 #include "chrome/grit/generated_resources.h"
23 #include "components/history/core/browser/history_service.h" 25 #include "components/history/core/browser/history_service.h"
24 #include "components/mime_util/mime_util.h" 26 #include "components/mime_util/mime_util.h"
(...skipping 12 matching lines...) Expand all
37 #include "chrome/browser/extensions/webstore_installer.h" 39 #include "chrome/browser/extensions/webstore_installer.h"
38 #include "extensions/common/feature_switch.h" 40 #include "extensions/common/feature_switch.h"
39 #endif 41 #endif
40 42
41 #if BUILDFLAG(ENABLE_PLUGINS) 43 #if BUILDFLAG(ENABLE_PLUGINS)
42 #include "chrome/browser/plugins/plugin_prefs.h" 44 #include "chrome/browser/plugins/plugin_prefs.h"
43 #include "content/public/browser/plugin_service.h" 45 #include "content/public/browser/plugin_service.h"
44 #include "content/public/common/webplugininfo.h" 46 #include "content/public/common/webplugininfo.h"
45 #endif 47 #endif
46 48
47 #if defined(OS_ANDROID)
48 #include "chrome/browser/android/download/download_controller.h"
49 #include "chrome/browser/android/download/download_manager_service.h"
50 #endif
51
52 #if defined(OS_WIN) 49 #if defined(OS_WIN)
53 #include "chrome/browser/ui/pdf/adobe_reader_info_win.h" 50 #include "chrome/browser/ui/pdf/adobe_reader_info_win.h"
54 #endif 51 #endif
55 52
56 using content::BrowserThread; 53 using content::BrowserThread;
57 using content::DownloadItem; 54 using content::DownloadItem;
58 using safe_browsing::DownloadFileType; 55 using safe_browsing::DownloadFileType;
59 56
60 namespace { 57 namespace {
61 58
(...skipping 14 matching lines...) Expand all
76 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight())); 73 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight()));
77 } 74 }
78 75
79 #if defined(OS_WIN) 76 #if defined(OS_WIN)
80 // Keeps track of whether Adobe Reader is up to date. 77 // Keeps track of whether Adobe Reader is up to date.
81 bool g_is_adobe_reader_up_to_date_ = false; 78 bool g_is_adobe_reader_up_to_date_ = false;
82 #endif 79 #endif
83 80
84 } // namespace 81 } // namespace
85 82
86 DownloadTargetInfo::DownloadTargetInfo()
87 : target_disposition(DownloadItem::TARGET_DISPOSITION_OVERWRITE),
88 danger_type(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
89 danger_level(DownloadFileType::NOT_DANGEROUS),
90 is_filetype_handled_safely(false) {}
91
92 DownloadTargetInfo::~DownloadTargetInfo() {}
93
94 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() { 83 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
95 } 84 }
96 85
97 DownloadTargetDeterminer::DownloadTargetDeterminer( 86 DownloadTargetDeterminer::DownloadTargetDeterminer(
98 DownloadItem* download, 87 DownloadItem* download,
99 const base::FilePath& initial_virtual_path, 88 const base::FilePath& initial_virtual_path,
89 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
100 DownloadPrefs* download_prefs, 90 DownloadPrefs* download_prefs,
101 DownloadTargetDeterminerDelegate* delegate, 91 DownloadTargetDeterminerDelegate* delegate,
102 const CompletionCallback& callback) 92 const CompletionCallback& callback)
103 : next_state_(STATE_GENERATE_TARGET_PATH), 93 : next_state_(STATE_GENERATE_TARGET_PATH),
104 should_prompt_(false), 94 confirmation_reason_(DownloadConfirmationReason::NONE),
105 should_notify_extensions_(false), 95 should_notify_extensions_(false),
106 create_target_directory_(false), 96 create_target_directory_(false),
107 conflict_action_(DownloadPathReservationTracker::OVERWRITE), 97 conflict_action_(conflict_action),
108 danger_type_(download->GetDangerType()), 98 danger_type_(download->GetDangerType()),
109 danger_level_(DownloadFileType::NOT_DANGEROUS), 99 danger_level_(DownloadFileType::NOT_DANGEROUS),
110 virtual_path_(initial_virtual_path), 100 virtual_path_(initial_virtual_path),
111 is_filetype_handled_safely_(false), 101 is_filetype_handled_safely_(false),
112 download_(download), 102 download_(download),
113 is_resumption_(download_->GetLastReason() != 103 is_resumption_(download_->GetLastReason() !=
114 content::DOWNLOAD_INTERRUPT_REASON_NONE && 104 content::DOWNLOAD_INTERRUPT_REASON_NONE &&
115 !initial_virtual_path.empty()), 105 !initial_virtual_path.empty()),
116 download_prefs_(download_prefs), 106 download_prefs_(download_prefs),
117 delegate_(delegate), 107 delegate_(delegate),
(...skipping 24 matching lines...) Expand all
142 case STATE_GENERATE_TARGET_PATH: 132 case STATE_GENERATE_TARGET_PATH:
143 result = DoGenerateTargetPath(); 133 result = DoGenerateTargetPath();
144 break; 134 break;
145 case STATE_NOTIFY_EXTENSIONS: 135 case STATE_NOTIFY_EXTENSIONS:
146 result = DoNotifyExtensions(); 136 result = DoNotifyExtensions();
147 break; 137 break;
148 case STATE_RESERVE_VIRTUAL_PATH: 138 case STATE_RESERVE_VIRTUAL_PATH:
149 result = DoReserveVirtualPath(); 139 result = DoReserveVirtualPath();
150 break; 140 break;
151 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH: 141 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH:
152 result = DoPromptUserForDownloadPath(); 142 result = DoRequestConfirmation();
153 break; 143 break;
154 case STATE_DETERMINE_LOCAL_PATH: 144 case STATE_DETERMINE_LOCAL_PATH:
155 result = DoDetermineLocalPath(); 145 result = DoDetermineLocalPath();
156 break; 146 break;
157 case STATE_DETERMINE_MIME_TYPE: 147 case STATE_DETERMINE_MIME_TYPE:
158 result = DoDetermineMimeType(); 148 result = DoDetermineMimeType();
159 break; 149 break;
160 case STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER: 150 case STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER:
161 result = DoDetermineIfHandledSafely(); 151 result = DoDetermineIfHandledSafely();
162 break; 152 break;
(...skipping 12 matching lines...) Expand all
175 case STATE_NONE: 165 case STATE_NONE:
176 NOTREACHED(); 166 NOTREACHED();
177 return; 167 return;
178 } 168 }
179 } while (result == CONTINUE); 169 } while (result == CONTINUE);
180 // Note that if a callback completes synchronously, the handler will still 170 // Note that if a callback completes synchronously, the handler will still
181 // return QUIT_DOLOOP. In this case, an inner DoLoop() may complete the target 171 // return QUIT_DOLOOP. In this case, an inner DoLoop() may complete the target
182 // determination and delete |this|. 172 // determination and delete |this|.
183 173
184 if (result == COMPLETE) 174 if (result == COMPLETE)
185 ScheduleCallbackAndDeleteSelf(); 175 ScheduleCallbackAndDeleteSelf(content::DOWNLOAD_INTERRUPT_REASON_NONE);
186 } 176 }
187 177
188 DownloadTargetDeterminer::Result 178 DownloadTargetDeterminer::Result
189 DownloadTargetDeterminer::DoGenerateTargetPath() { 179 DownloadTargetDeterminer::DoGenerateTargetPath() {
190 DCHECK_CURRENTLY_ON(BrowserThread::UI); 180 DCHECK_CURRENTLY_ON(BrowserThread::UI);
191 DCHECK(local_path_.empty()); 181 DCHECK(local_path_.empty());
192 DCHECK(!should_prompt_); 182 DCHECK_EQ(confirmation_reason_, DownloadConfirmationReason::NONE);
193 DCHECK(!should_notify_extensions_); 183 DCHECK(!should_notify_extensions_);
194 DCHECK_EQ(DownloadPathReservationTracker::OVERWRITE, conflict_action_);
195 bool is_forced_path = !download_->GetForcedFilePath().empty(); 184 bool is_forced_path = !download_->GetForcedFilePath().empty();
196 185
197 next_state_ = STATE_NOTIFY_EXTENSIONS; 186 next_state_ = STATE_NOTIFY_EXTENSIONS;
198 187
199 if (!virtual_path_.empty() && HasPromptedForPath() && !is_forced_path) { 188 if (!virtual_path_.empty() && HasPromptedForPath() && !is_forced_path) {
200 // The download is being resumed and the user has already been prompted for 189 // The download is being resumed and the user has already been prompted for
201 // a path. Assume that it's okay to overwrite the file if there's a conflict 190 // a path. Assume that it's okay to overwrite the file if there's a conflict
202 // and reuse the selection. 191 // and reuse the selection.
203 should_prompt_ = ShouldPromptForDownload(virtual_path_); 192 confirmation_reason_ = ShouldPromptForDownload(virtual_path_);
193 conflict_action_ = DownloadPathReservationTracker::OVERWRITE;
204 } else if (!is_forced_path) { 194 } else if (!is_forced_path) {
205 // If we don't have a forced path, we should construct a path for the 195 // If we don't have a forced path, we should construct a path for the
206 // download. Forced paths are only specified for programmatic downloads 196 // download. Forced paths are only specified for programmatic downloads
207 // (WebStore, Drag&Drop). Treat the path as a virtual path. We will 197 // (WebStore, Drag&Drop). Treat the path as a virtual path. We will
208 // eventually determine whether this is a local path and if not, figure out 198 // eventually determine whether this is a local path and if not, figure out
209 // a local path. 199 // a local path.
210 std::string suggested_filename = download_->GetSuggestedFilename(); 200 std::string suggested_filename = download_->GetSuggestedFilename();
211 if (suggested_filename.empty() && 201 if (suggested_filename.empty() &&
212 download_->GetMimeType() == "application/x-x509-user-cert") { 202 download_->GetMimeType() == "application/x-x509-user-cert") {
213 suggested_filename = "user.crt"; 203 suggested_filename = "user.crt";
214 } 204 }
215 205
216 std::string default_filename( 206 std::string default_filename(
217 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME)); 207 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME));
218 base::FilePath generated_filename = net::GenerateFileName( 208 base::FilePath generated_filename = net::GenerateFileName(
219 download_->GetURL(), 209 download_->GetURL(),
220 download_->GetContentDisposition(), 210 download_->GetContentDisposition(),
221 GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset), 211 GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset),
222 suggested_filename, 212 suggested_filename,
223 download_->GetMimeType(), 213 download_->GetMimeType(),
224 default_filename); 214 default_filename);
225 should_prompt_ = ShouldPromptForDownload(generated_filename); 215 confirmation_reason_ = ShouldPromptForDownload(generated_filename);
226 base::FilePath target_directory; 216 base::FilePath target_directory;
227 if (should_prompt_) { 217 if (confirmation_reason_ != DownloadConfirmationReason::NONE) {
228 DCHECK(!download_prefs_->IsDownloadPathManaged()); 218 DCHECK(!download_prefs_->IsDownloadPathManaged());
229 // If the user is going to be prompted and the user has been prompted 219 // If the user is going to be prompted and the user has been prompted
230 // before, then always prefer the last directory that the user selected. 220 // before, then always prefer the last directory that the user selected.
231 target_directory = download_prefs_->SaveFilePath(); 221 target_directory = download_prefs_->SaveFilePath();
232 } else { 222 } else {
233 target_directory = download_prefs_->DownloadPath(); 223 target_directory = download_prefs_->DownloadPath();
234 } 224 }
235 #if defined(OS_ANDROID)
236 // If |virtual_path_| is not empty, we are resuming a download which already
237 // has a target path. Don't prompt user in this case.
238 if (!virtual_path_.empty()) {
239 conflict_action_ = DownloadPathReservationTracker::UNIQUIFY;
240 } else {
241 conflict_action_ = DownloadPathReservationTracker::PROMPT;
242 }
243 #else
244 conflict_action_ = DownloadPathReservationTracker::UNIQUIFY;
245 #endif
246 virtual_path_ = target_directory.Append(generated_filename); 225 virtual_path_ = target_directory.Append(generated_filename);
247 should_notify_extensions_ = true; 226 should_notify_extensions_ = true;
248 } else { 227 } else {
228 conflict_action_ = DownloadPathReservationTracker::OVERWRITE;
249 virtual_path_ = download_->GetForcedFilePath(); 229 virtual_path_ = download_->GetForcedFilePath();
250 // If this is a resumed download which was previously interrupted due to an 230 // If this is a resumed download which was previously interrupted due to an
251 // issue with the forced path, the user is still not prompted. If the path 231 // issue with the forced path, the user is still not prompted. If the path
252 // supplied to a programmatic download is invalid, then the caller needs to 232 // supplied to a programmatic download is invalid, then the caller needs to
253 // intervene. 233 // intervene.
254 } 234 }
255 DCHECK(virtual_path_.IsAbsolute()); 235 DCHECK(virtual_path_.IsAbsolute());
256 DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe(); 236 DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe();
257 237
258 return CONTINUE; 238 return CONTINUE;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 return CONTINUE; 298 return CONTINUE;
319 299
320 delegate_->ReserveVirtualPath( 300 delegate_->ReserveVirtualPath(
321 download_, virtual_path_, create_target_directory_, conflict_action_, 301 download_, virtual_path_, create_target_directory_, conflict_action_,
322 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone, 302 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone,
323 weak_ptr_factory_.GetWeakPtr())); 303 weak_ptr_factory_.GetWeakPtr()));
324 return QUIT_DOLOOP; 304 return QUIT_DOLOOP;
325 } 305 }
326 306
327 void DownloadTargetDeterminer::ReserveVirtualPathDone( 307 void DownloadTargetDeterminer::ReserveVirtualPathDone(
328 const base::FilePath& path, bool verified) { 308 PathValidationResult result,
329 DCHECK_CURRENTLY_ON(BrowserThread::UI); 309 const base::FilePath& path) {
310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
330 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe() 311 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe()
331 << " Verified:" << verified; 312 << " Result:" << static_cast<int>(result);
332 DCHECK_EQ(STATE_PROMPT_USER_FOR_DOWNLOAD_PATH, next_state_); 313 DCHECK_EQ(STATE_PROMPT_USER_FOR_DOWNLOAD_PATH, next_state_);
333 #if defined(OS_ANDROID) 314
334 if (!verified) { 315 virtual_path_ = path;
335 if (path.empty()) { 316
336 DownloadManagerService::OnDownloadCanceled( 317 switch (result) {
337 download_, DownloadController::CANCEL_REASON_NO_EXTERNAL_STORAGE); 318 case PathValidationResult::SUCCESS:
338 CancelOnFailureAndDeleteSelf(); 319 break;
339 return; 320
340 } 321 case PathValidationResult::PATH_NOT_WRITABLE:
341 if (!download_->GetWebContents()) { 322 confirmation_reason_ =
342 // If we cannot reserve the path and the WebContent is already gone, there 323 DownloadConfirmationReason::TARGET_PATH_NOT_WRITEABLE;
343 // is no way to prompt user for an infobar. This could happen after chrome 324 break;
344 // gets killed, and user tries to resume a download while another app has 325
345 // created the target file (not the temporary .crdownload file). 326 case PathValidationResult::NAME_TOO_LONG:
346 DownloadManagerService::OnDownloadCanceled( 327 confirmation_reason_ = DownloadConfirmationReason::NAME_TOO_LONG;
347 download_, 328 break;
348 DownloadController::CANCEL_REASON_CANNOT_DETERMINE_DOWNLOAD_TARGET); 329
349 CancelOnFailureAndDeleteSelf(); 330 case PathValidationResult::CONFLICT:
350 return; 331 confirmation_reason_ = DownloadConfirmationReason::TARGET_CONFLICT;
351 } 332 break;
352 } 333 }
353 #endif 334
354 should_prompt_ = (should_prompt_ || !verified);
355 virtual_path_ = path;
356 DoLoop(); 335 DoLoop();
357 } 336 }
358 337
359 DownloadTargetDeterminer::Result 338 DownloadTargetDeterminer::Result
360 DownloadTargetDeterminer::DoPromptUserForDownloadPath() { 339 DownloadTargetDeterminer::DoRequestConfirmation() {
361 DCHECK_CURRENTLY_ON(BrowserThread::UI); 340 DCHECK_CURRENTLY_ON(BrowserThread::UI);
362 DCHECK(!virtual_path_.empty()); 341 DCHECK(!virtual_path_.empty());
363 342
364 next_state_ = STATE_DETERMINE_LOCAL_PATH; 343 next_state_ = STATE_DETERMINE_LOCAL_PATH;
365 344
366 // Avoid prompting for a download if it isn't in-progress. The user will be 345 // Avoid prompting for a download if it isn't in-progress. The user will be
367 // prompted once the download is resumed and headers are available. 346 // prompted once the download is resumed and headers are available.
368 if (should_prompt_ && download_->GetState() == DownloadItem::IN_PROGRESS) { 347 if (confirmation_reason_ != DownloadConfirmationReason::NONE &&
369 delegate_->PromptUserForDownloadPath( 348 download_->GetState() == DownloadItem::IN_PROGRESS) {
370 download_, 349 delegate_->RequestConfirmation(
371 virtual_path_, 350 download_, virtual_path_, confirmation_reason_,
372 base::Bind(&DownloadTargetDeterminer::PromptUserForDownloadPathDone, 351 base::Bind(&DownloadTargetDeterminer::RequestConfirmationDone,
373 weak_ptr_factory_.GetWeakPtr())); 352 weak_ptr_factory_.GetWeakPtr()));
374 return QUIT_DOLOOP; 353 return QUIT_DOLOOP;
375 } 354 }
376 return CONTINUE; 355 return CONTINUE;
377 } 356 }
378 357
379 void DownloadTargetDeterminer::PromptUserForDownloadPathDone( 358 void DownloadTargetDeterminer::RequestConfirmationDone(
359 DownloadConfirmationResult result,
380 const base::FilePath& virtual_path) { 360 const base::FilePath& virtual_path) {
381 DCHECK_CURRENTLY_ON(BrowserThread::UI); 361 DCHECK_CURRENTLY_ON(BrowserThread::UI);
382 DVLOG(20) << "User selected path:" << virtual_path.AsUTF8Unsafe(); 362 DVLOG(20) << "User selected path:" << virtual_path.AsUTF8Unsafe();
383 if (virtual_path.empty()) { 363 if (result == DownloadConfirmationResult::CANCELED) {
384 CancelOnFailureAndDeleteSelf(); 364 ScheduleCallbackAndDeleteSelf(
365 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
385 return; 366 return;
386 } 367 }
368 DCHECK(!virtual_path.empty());
387 DCHECK_EQ(STATE_DETERMINE_LOCAL_PATH, next_state_); 369 DCHECK_EQ(STATE_DETERMINE_LOCAL_PATH, next_state_);
388 370
371 // If the user wasn't prompted, then we need to clear the
372 // confirmation_reason_. This way it's clear that user has not given consent
373 // to download this resource.
374 if (result == DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION)
375 confirmation_reason_ = DownloadConfirmationReason::NONE;
376
389 virtual_path_ = virtual_path; 377 virtual_path_ = virtual_path;
390 download_prefs_->SetSaveFilePath(virtual_path_.DirName()); 378 download_prefs_->SetSaveFilePath(virtual_path_.DirName());
391 DoLoop(); 379 DoLoop();
392 } 380 }
393 381
394 DownloadTargetDeterminer::Result 382 DownloadTargetDeterminer::Result
395 DownloadTargetDeterminer::DoDetermineLocalPath() { 383 DownloadTargetDeterminer::DoDetermineLocalPath() {
396 DCHECK_CURRENTLY_ON(BrowserThread::UI); 384 DCHECK_CURRENTLY_ON(BrowserThread::UI);
397 DCHECK(!virtual_path_.empty()); 385 DCHECK(!virtual_path_.empty());
398 DCHECK(local_path_.empty()); 386 DCHECK(local_path_.empty());
399 387
400 next_state_ = STATE_DETERMINE_MIME_TYPE; 388 next_state_ = STATE_DETERMINE_MIME_TYPE;
401 389
402 delegate_->DetermineLocalPath( 390 delegate_->DetermineLocalPath(
403 download_, 391 download_,
404 virtual_path_, 392 virtual_path_,
405 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone, 393 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone,
406 weak_ptr_factory_.GetWeakPtr())); 394 weak_ptr_factory_.GetWeakPtr()));
407 return QUIT_DOLOOP; 395 return QUIT_DOLOOP;
408 } 396 }
409 397
410 void DownloadTargetDeterminer::DetermineLocalPathDone( 398 void DownloadTargetDeterminer::DetermineLocalPathDone(
411 const base::FilePath& local_path) { 399 const base::FilePath& local_path) {
412 DCHECK_CURRENTLY_ON(BrowserThread::UI); 400 DCHECK_CURRENTLY_ON(BrowserThread::UI);
413 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe(); 401 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe();
414 if (local_path.empty()) { 402 if (local_path.empty()) {
415 // Path subsitution failed. 403 // Path subsitution failed. Usually caused by something going wrong with the
416 CancelOnFailureAndDeleteSelf(); 404 // Google Drive logic (e.g. filesystem error while trying to create the
405 // cache file). We are going to return a generic error here since a more
406 // specific one is unlikely to be helpful to the user.
407 ScheduleCallbackAndDeleteSelf(
408 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
417 return; 409 return;
418 } 410 }
419 DCHECK_EQ(STATE_DETERMINE_MIME_TYPE, next_state_); 411 DCHECK_EQ(STATE_DETERMINE_MIME_TYPE, next_state_);
420 412
421 local_path_ = local_path; 413 local_path_ = local_path;
422 DoLoop(); 414 DoLoop();
423 } 415 }
424 416
425 DownloadTargetDeterminer::Result 417 DownloadTargetDeterminer::Result
426 DownloadTargetDeterminer::DoDetermineMimeType() { 418 DownloadTargetDeterminer::DoDetermineMimeType() {
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 #endif 745 #endif
754 unconfirmed_format.append(kUnconfirmedFormatSuffix); 746 unconfirmed_format.append(kUnconfirmedFormatSuffix);
755 747
756 base::FilePath::StringType file_name = base::StringPrintf( 748 base::FilePath::StringType file_name = base::StringPrintf(
757 unconfirmed_format.c_str(), 749 unconfirmed_format.c_str(),
758 base::RandInt(0, kUnconfirmedUniquifierRange)); 750 base::RandInt(0, kUnconfirmedUniquifierRange));
759 intermediate_path_ = local_path_.DirName().Append(file_name); 751 intermediate_path_ = local_path_.DirName().Append(file_name);
760 return COMPLETE; 752 return COMPLETE;
761 } 753 }
762 754
763 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() { 755 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf(
756 content::DownloadInterruptReason result) {
764 DCHECK(download_); 757 DCHECK(download_);
765 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe() 758 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
766 << " Local:" << local_path_.AsUTF8Unsafe() 759 << " Local:" << local_path_.AsUTF8Unsafe()
767 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe() 760 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
768 << " Should prompt:" << should_prompt_ 761 << " Confirmation reason:" << static_cast<int>(confirmation_reason_)
769 << " Danger type:" << danger_type_ 762 << " Danger type:" << danger_type_
770 << " Danger level:" << danger_level_; 763 << " Danger level:" << danger_level_
764 << " Result:" << static_cast<int>(result);
771 std::unique_ptr<DownloadTargetInfo> target_info(new DownloadTargetInfo); 765 std::unique_ptr<DownloadTargetInfo> target_info(new DownloadTargetInfo);
772 766
773 target_info->target_path = local_path_; 767 target_info->target_path = local_path_;
768 target_info->result = result;
774 target_info->target_disposition = 769 target_info->target_disposition =
775 (HasPromptedForPath() || should_prompt_ 770 (HasPromptedForPath() ||
771 confirmation_reason_ != DownloadConfirmationReason::NONE
776 ? DownloadItem::TARGET_DISPOSITION_PROMPT 772 ? DownloadItem::TARGET_DISPOSITION_PROMPT
777 : DownloadItem::TARGET_DISPOSITION_OVERWRITE); 773 : DownloadItem::TARGET_DISPOSITION_OVERWRITE);
778 target_info->danger_type = danger_type_; 774 target_info->danger_type = danger_type_;
779 target_info->danger_level = danger_level_; 775 target_info->danger_level = danger_level_;
780 target_info->intermediate_path = intermediate_path_; 776 target_info->intermediate_path = intermediate_path_;
781 target_info->mime_type = mime_type_; 777 target_info->mime_type = mime_type_;
782 target_info->is_filetype_handled_safely = is_filetype_handled_safely_; 778 target_info->is_filetype_handled_safely = is_filetype_handled_safely_;
783 779
784 base::ThreadTaskRunnerHandle::Get()->PostTask( 780 base::ThreadTaskRunnerHandle::Get()->PostTask(
785 FROM_HERE, base::Bind(completion_callback_, base::Passed(&target_info))); 781 FROM_HERE, base::Bind(completion_callback_, base::Passed(&target_info)));
786 completion_callback_.Reset(); 782 completion_callback_.Reset();
787 delete this; 783 delete this;
788 } 784 }
789 785
790 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
791 // Path substitution failed.
792 virtual_path_.clear();
793 local_path_.clear();
794 intermediate_path_.clear();
795 ScheduleCallbackAndDeleteSelf();
796 }
797
798 Profile* DownloadTargetDeterminer::GetProfile() const { 786 Profile* DownloadTargetDeterminer::GetProfile() const {
799 DCHECK(download_->GetBrowserContext()); 787 DCHECK(download_->GetBrowserContext());
800 return Profile::FromBrowserContext(download_->GetBrowserContext()); 788 return Profile::FromBrowserContext(download_->GetBrowserContext());
801 } 789 }
802 790
803 bool DownloadTargetDeterminer::ShouldPromptForDownload( 791 DownloadConfirmationReason DownloadTargetDeterminer::ShouldPromptForDownload(
804 const base::FilePath& filename) const { 792 const base::FilePath& filename) const {
805 #if defined(OS_ANDROID)
806 // Don't prompt user about saving path on Android.
807 // TODO(qinmin): show an error toast to warn user in certain cases.
808 return false;
809 #endif
810 if (is_resumption_) { 793 if (is_resumption_) {
811 // For resumed downloads, if the target disposition or prefs require 794 // For resumed downloads, if the target disposition or prefs require
812 // prompting, the user has already been prompted. Try to respect the user's 795 // prompting, the user has already been prompted. Try to respect the user's
813 // selection, unless we've discovered that the target path cannot be used 796 // selection, unless we've discovered that the target path cannot be used
814 // for some reason. 797 // for some reason.
815 content::DownloadInterruptReason reason = download_->GetLastReason(); 798 content::DownloadInterruptReason reason = download_->GetLastReason();
816 return (reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED || 799 switch (reason) {
817 reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE || 800 case content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
818 reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE); 801 return DownloadConfirmationReason::TARGET_PATH_NOT_WRITEABLE;
802
803 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
804 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
805 return DownloadConfirmationReason::TARGET_NO_SPACE;
806
807 default:
808 return DownloadConfirmationReason::NONE;
809 }
819 } 810 }
820 811
821 // If the download path is forced, don't prompt. 812 // If the download path is forced, don't prompt.
822 if (!download_->GetForcedFilePath().empty()) { 813 if (!download_->GetForcedFilePath().empty()) {
823 // 'Save As' downloads shouldn't have a forced path. 814 // 'Save As' downloads shouldn't have a forced path.
824 DCHECK(DownloadItem::TARGET_DISPOSITION_PROMPT != 815 DCHECK(DownloadItem::TARGET_DISPOSITION_PROMPT !=
825 download_->GetTargetDisposition()); 816 download_->GetTargetDisposition());
826 return false; 817 return DownloadConfirmationReason::NONE;
827 } 818 }
828 819
829 // Don't ask where to save if the download path is managed. Even if the user 820 // Don't ask where to save if the download path is managed. Even if the user
830 // wanted to be prompted for "all" downloads, or if this was a 'Save As' 821 // wanted to be prompted for "all" downloads, or if this was a 'Save As'
831 // download. 822 // download.
832 if (download_prefs_->IsDownloadPathManaged()) 823 if (download_prefs_->IsDownloadPathManaged())
833 return false; 824 return DownloadConfirmationReason::NONE;
834 825
835 // Prompt if this is a 'Save As' download. 826 // Prompt if this is a 'Save As' download.
836 if (download_->GetTargetDisposition() == 827 if (download_->GetTargetDisposition() ==
837 DownloadItem::TARGET_DISPOSITION_PROMPT) 828 DownloadItem::TARGET_DISPOSITION_PROMPT)
838 return true; 829 return DownloadConfirmationReason::SAVE_AS;
839 830
840 // Check if the user has the "Always prompt for download location" preference 831 #if BUILDFLAG(ENABLE_EXTENSIONS)
841 // set. If so we prompt for most downloads except for the following scenarios: 832 // Don't prompt for extension downloads.
842 // 1) Extension installation. Note that we only care here about the case where 833 if (download_crx_util::IsExtensionDownload(*download_) ||
843 // an extension is installed, not when one is downloaded with "save as...". 834 filename.MatchesExtension(extensions::kExtensionFileExtension))
844 // 2) Filetypes marked "always open." If the user just wants this file opened, 835 return DownloadConfirmationReason::NONE;
845 // don't bother asking where to keep it. 836 #endif
846 if (download_prefs_->PromptForDownload() &&
847 !download_crx_util::IsExtensionDownload(*download_) &&
848 !filename.MatchesExtension(extensions::kExtensionFileExtension) &&
849 !download_prefs_->IsAutoOpenEnabledBasedOnExtension(filename))
850 return true;
851 837
852 // Otherwise, don't prompt. Note that the user might still be prompted if 838 // Don't prompt for file types that are marked for opening automatically.
853 // there are unresolved conflicts during path reservation (e.g. due to the 839 if (download_prefs_->IsAutoOpenEnabledBasedOnExtension(filename))
854 // target path being unwriteable or because there are too many conflicting 840 return DownloadConfirmationReason::NONE;
855 // files), or if an extension signals that the user be prompted on a filename 841
856 // conflict. 842 // For everything else, prompting is controlled by the PromptForDownload pref.
857 return false; 843 // The user may still be prompted even if this pref is disabled due to, for
844 // example, there being an unresolvable filename conflict or the target path
845 // is not writeable.
846 return download_prefs_->PromptForDownload()
847 ? DownloadConfirmationReason::PREFERENCE
848 : DownloadConfirmationReason::NONE;
858 } 849 }
859 850
860 bool DownloadTargetDeterminer::HasPromptedForPath() const { 851 bool DownloadTargetDeterminer::HasPromptedForPath() const {
861 return (is_resumption_ && download_->GetTargetDisposition() == 852 return (is_resumption_ && download_->GetTargetDisposition() ==
862 DownloadItem::TARGET_DISPOSITION_PROMPT); 853 DownloadItem::TARGET_DISPOSITION_PROMPT);
863 } 854 }
864 855
865 DownloadFileType::DangerLevel DownloadTargetDeterminer::GetDangerLevel( 856 DownloadFileType::DangerLevel DownloadTargetDeterminer::GetDangerLevel(
866 PriorVisitsToReferrer visits) const { 857 PriorVisitsToReferrer visits) const {
867 DCHECK_CURRENTLY_ON(BrowserThread::UI); 858 DCHECK_CURRENTLY_ON(BrowserThread::UI);
868 859
869 // If the user has has been prompted or will be, assume that the user has 860 // If the user has has been prompted or will be, assume that the user has
870 // approved the download. A programmatic download is considered safe unless it 861 // approved the download. A programmatic download is considered safe unless it
871 // contains malware. 862 // contains malware.
872 if (HasPromptedForPath() || should_prompt_ || 863 if (HasPromptedForPath() ||
864 confirmation_reason_ != DownloadConfirmationReason::NONE ||
873 !download_->GetForcedFilePath().empty()) 865 !download_->GetForcedFilePath().empty())
874 return DownloadFileType::NOT_DANGEROUS; 866 return DownloadFileType::NOT_DANGEROUS;
875 867
876 const bool is_extension_download = 868 const bool is_extension_download =
877 download_crx_util::IsExtensionDownload(*download_); 869 download_crx_util::IsExtensionDownload(*download_);
878 870
879 // User-initiated extension downloads from pref-whitelisted sources are not 871 // User-initiated extension downloads from pref-whitelisted sources are not
880 // considered dangerous. 872 // considered dangerous.
881 if (download_->HasUserGesture() && 873 if (download_->HasUserGesture() &&
882 is_extension_download && 874 is_extension_download &&
(...skipping 29 matching lines...) Expand all
912 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) != 0 || 904 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) != 0 ||
913 (download_->HasUserGesture() && visits == VISITED_REFERRER))) 905 (download_->HasUserGesture() && visits == VISITED_REFERRER)))
914 return DownloadFileType::NOT_DANGEROUS; 906 return DownloadFileType::NOT_DANGEROUS;
915 return danger_level; 907 return danger_level;
916 } 908 }
917 909
918 void DownloadTargetDeterminer::OnDownloadDestroyed( 910 void DownloadTargetDeterminer::OnDownloadDestroyed(
919 DownloadItem* download) { 911 DownloadItem* download) {
920 DCHECK_CURRENTLY_ON(BrowserThread::UI); 912 DCHECK_CURRENTLY_ON(BrowserThread::UI);
921 DCHECK_EQ(download_, download); 913 DCHECK_EQ(download_, download);
922 CancelOnFailureAndDeleteSelf(); 914 ScheduleCallbackAndDeleteSelf(
915 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
923 } 916 }
924 917
925 // static 918 // static
926 void DownloadTargetDeterminer::Start(content::DownloadItem* download, 919 void DownloadTargetDeterminer::Start(
927 const base::FilePath& initial_virtual_path, 920 content::DownloadItem* download,
928 DownloadPrefs* download_prefs, 921 const base::FilePath& initial_virtual_path,
929 DownloadTargetDeterminerDelegate* delegate, 922 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
930 const CompletionCallback& callback) { 923 DownloadPrefs* download_prefs,
924 DownloadTargetDeterminerDelegate* delegate,
925 const CompletionCallback& callback) {
931 // DownloadTargetDeterminer owns itself and will self destruct when the job is 926 // DownloadTargetDeterminer owns itself and will self destruct when the job is
932 // complete or the download item is destroyed. The callback is always invoked 927 // complete or the download item is destroyed. The callback is always invoked
933 // asynchronously. 928 // asynchronously.
934 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs, 929 new DownloadTargetDeterminer(download, initial_virtual_path, conflict_action,
935 delegate, callback); 930 download_prefs, delegate, callback);
936 } 931 }
937 932
938 // static 933 // static
939 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath( 934 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath(
940 const base::FilePath& suggested_path) { 935 const base::FilePath& suggested_path) {
941 return base::FilePath(suggested_path.value() + kCrdownloadSuffix); 936 return base::FilePath(suggested_path.value() + kCrdownloadSuffix);
942 } 937 }
943 938
944 #if defined(OS_WIN) 939 #if defined(OS_WIN)
945 // static 940 // static
946 bool DownloadTargetDeterminer::IsAdobeReaderUpToDate() { 941 bool DownloadTargetDeterminer::IsAdobeReaderUpToDate() {
947 return g_is_adobe_reader_up_to_date_; 942 return g_is_adobe_reader_up_to_date_;
948 } 943 }
949 #endif 944 #endif
OLDNEW
« no previous file with comments | « chrome/browser/download/download_target_determiner.h ('k') | chrome/browser/download/download_target_determiner_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698