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

Side by Side Diff: content/browser/download/base_file_win.cc

Issue 319603003: [Downloads] Retry renames after transient failures. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/download/base_file.h" 5 #include "content/browser/download/base_file.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <cguid.h> 8 #include <cguid.h>
9 #include <objbase.h> 9 #include <objbase.h>
10 #include <shellapi.h> 10 #include <shellapi.h>
11 11
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/files/file.h"
13 #include "base/guid.h" 14 #include "base/guid.h"
14 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
15 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
16 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
17 #include "content/browser/download/download_interrupt_reasons_impl.h" 18 #include "content/browser/download/download_interrupt_reasons_impl.h"
18 #include "content/browser/download/download_stats.h" 19 #include "content/browser/download/download_stats.h"
19 #include "content/browser/safe_util_win.h" 20 #include "content/browser/safe_util_win.h"
20 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
21 22
22 namespace content { 23 namespace content {
23 namespace { 24 namespace {
24 25
25 const int kAllSpecialShFileOperationCodes[] = { 26 const int kAllSpecialShFileOperationCodes[] = {
26 // Should be kept in sync with the case statement below. 27 // Should be kept in sync with the case statement below.
27 ERROR_ACCESS_DENIED, 28 ERROR_ACCESS_DENIED,
29 ERROR_SHARING_VIOLATION,
30 ERROR_INVALID_PARAMETER,
28 0x71, 31 0x71,
29 0x72, 32 0x72,
30 0x73, 33 0x73,
31 0x74, 34 0x74,
32 0x75, 35 0x75,
33 0x76, 36 0x76,
34 0x78, 37 0x78,
35 0x79, 38 0x79,
36 0x7A, 39 0x7A,
37 0x7C, 40 0x7C,
(...skipping 24 matching lines...) Expand all
62 // See http://msdn.microsoft.com/en-us/library/bb762164(VS.85).aspx. 65 // See http://msdn.microsoft.com/en-us/library/bb762164(VS.85).aspx.
63 DownloadInterruptReason MapShFileOperationCodes(int code) { 66 DownloadInterruptReason MapShFileOperationCodes(int code) {
64 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE; 67 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
65 68
66 // Check these pre-Win32 error codes first, then check for matches 69 // Check these pre-Win32 error codes first, then check for matches
67 // in Winerror.h. 70 // in Winerror.h.
68 // This switch statement should be kept in sync with the list of codes 71 // This switch statement should be kept in sync with the list of codes
69 // above. 72 // above.
70 switch (code) { 73 switch (code) {
71 // Not a pre-Win32 error code; here so that this particular 74 // Not a pre-Win32 error code; here so that this particular
72 // case shows up in our histograms. This is redundant with the 75 // case shows up in our histograms.
73 // mapping function net::MapSystemError used later.
74 case ERROR_ACCESS_DENIED: // Access is denied. 76 case ERROR_ACCESS_DENIED: // Access is denied.
75 result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; 77 result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
78 break;
79
80 // This isn't a documented return value of SHFileOperation, but has been
81 // observed in the wild. We are treating it as a transient error based on
82 // the cases we have seen so far.
83 // See http://crbug.com/368455.
84 case ERROR_INVALID_PARAMETER:
Randy Smith (Not in Mondays) 2014/06/11 18:07:29 nit: Just because it's the kind of a-r person I am
asanka 2014/06/12 20:02:37 Haha. Done. That was actually the intent. The cons
85 result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
86 break;
87
88 // This is also undocumented but returned from SHFileOperation. Treated as a
89 // transient error since noone else should be holding on to our file while
90 // we are using it and whomever is holding on may let go momentarily. Value
Randy Smith (Not in Mondays) 2014/06/11 18:07:29 This comment makes me a little uncomfortable, sinc
asanka 2014/06/12 20:02:37 Mentioned AV. But in general sharing violations ar
91 // is converted here so that it shows up on UMA.
92 case ERROR_SHARING_VIOLATION:
93 result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
76 break; 94 break;
77 95
78 // The source and destination files are the same file. 96 // The source and destination files are the same file.
79 // DE_SAMEFILE == 0x71 97 // DE_SAMEFILE == 0x71
80 case 0x71: 98 case 0x71:
81 result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; 99 result = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
82 break; 100 break;
83 101
84 // The operation was canceled by the user, or silently canceled if the 102 // The operation was canceled by the user, or silently canceled if the
85 // appropriate flags were supplied to SHFileOperation. 103 // appropriate flags were supplied to SHFileOperation.
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 } 261 }
244 262
245 if (result == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED) { 263 if (result == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED) {
246 UMA_HISTOGRAM_CUSTOM_ENUMERATION( 264 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
247 "Download.MapWinShErrorAccessDenied", code, 265 "Download.MapWinShErrorAccessDenied", code,
248 base::CustomHistogram::ArrayToCustomRanges( 266 base::CustomHistogram::ArrayToCustomRanges(
249 kAllSpecialShFileOperationCodes, 267 kAllSpecialShFileOperationCodes,
250 arraysize(kAllSpecialShFileOperationCodes))); 268 arraysize(kAllSpecialShFileOperationCodes)));
251 } 269 }
252 270
271 if (result == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR) {
272 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
273 "Download.MapWinShErrorTransientError", code,
274 base::CustomHistogram::ArrayToCustomRanges(
275 kAllSpecialShFileOperationCodes,
276 arraysize(kAllSpecialShFileOperationCodes)));
277 }
278
253 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) 279 if (result != DOWNLOAD_INTERRUPT_REASON_NONE)
254 return result; 280 return result;
255 281
256 // If not one of the above codes, it should be a standard Windows error code. 282 // If not one of the above codes, it should be a standard Windows error code.
257 return ConvertNetErrorToInterruptReason( 283 return ConvertFileErrorToInterruptReason(
258 net::MapSystemError(code), DOWNLOAD_INTERRUPT_FROM_DISK); 284 base::File::OSErrorToFileError(code));
259 } 285 }
260 286
261 // Maps a return code from ScanAndSaveDownloadedFile() to a 287 // Maps a return code from ScanAndSaveDownloadedFile() to a
262 // DownloadInterruptReason. The return code in |result| is usually from the 288 // DownloadInterruptReason. The return code in |result| is usually from the
263 // final IAttachmentExecute::Save() call. 289 // final IAttachmentExecute::Save() call.
264 DownloadInterruptReason MapScanAndSaveErrorCodeToInterruptReason( 290 DownloadInterruptReason MapScanAndSaveErrorCodeToInterruptReason(
265 HRESULT result) { 291 HRESULT result) {
266 if (SUCCEEDED(result)) 292 if (SUCCEEDED(result))
267 return DOWNLOAD_INTERRUPT_REASON_NONE; 293 return DOWNLOAD_INTERRUPT_REASON_NONE;
268 294
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 RecordDownloadCount(FILE_MISSING_AFTER_SUCCESSFUL_SCAN_COUNT); 384 RecordDownloadCount(FILE_MISSING_AFTER_SUCCESSFUL_SCAN_COUNT);
359 result = DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED; 385 result = DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED;
360 } 386 }
361 LogInterruptReason("ScanAndSaveDownloadedFile", hr, result); 387 LogInterruptReason("ScanAndSaveDownloadedFile", hr, result);
362 } 388 }
363 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_ANNOTATED); 389 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_ANNOTATED);
364 return result; 390 return result;
365 } 391 }
366 392
367 } // namespace content 393 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698