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

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

Powered by Google App Engine
This is Rietveld 408576698