Index: content/browser/download/base_file_win.cc |
diff --git a/content/browser/download/base_file_win.cc b/content/browser/download/base_file_win.cc |
index 252f0495d7da5ba1446d1a9a766849e873fc37dc..42162f132b1e90ebef5b344aa312c8d7c7919705 100644 |
--- a/content/browser/download/base_file_win.cc |
+++ b/content/browser/download/base_file_win.cc |
@@ -10,6 +10,7 @@ |
#include <shellapi.h> |
#include "base/file_util.h" |
+#include "base/files/file.h" |
#include "base/guid.h" |
#include "base/metrics/histogram.h" |
#include "base/strings/utf_string_conversions.h" |
@@ -25,6 +26,8 @@ namespace { |
const int kAllSpecialShFileOperationCodes[] = { |
// Should be kept in sync with the case statement below. |
ERROR_ACCESS_DENIED, |
+ ERROR_SHARING_VIOLATION, |
+ ERROR_INVALID_PARAMETER, |
0x71, |
0x72, |
0x73, |
@@ -69,10 +72,25 @@ DownloadInterruptReason MapShFileOperationCodes(int code) { |
// above. |
switch (code) { |
// Not a pre-Win32 error code; here so that this particular |
- // case shows up in our histograms. This is redundant with the |
- // mapping function net::MapSystemError used later. |
+ // case shows up in our histograms. |
case ERROR_ACCESS_DENIED: // Access is denied. |
- result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; |
+ result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; |
+ break; |
+ |
+ // This isn't a documented return value of SHFileOperation, but has been |
+ // observed in the wild. We are treating it as a transient error based on |
+ // the cases we have seen so far. |
+ // See http://crbug.com/368455. |
+ 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
|
+ result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; |
+ break; |
+ |
+ // This is also undocumented but returned from SHFileOperation. Treated as a |
+ // transient error since noone else should be holding on to our file while |
+ // 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
|
+ // is converted here so that it shows up on UMA. |
+ case ERROR_SHARING_VIOLATION: |
+ result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; |
break; |
// The source and destination files are the same file. |
@@ -250,12 +268,20 @@ DownloadInterruptReason MapShFileOperationCodes(int code) { |
arraysize(kAllSpecialShFileOperationCodes))); |
} |
+ if (result == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR) { |
+ UMA_HISTOGRAM_CUSTOM_ENUMERATION( |
+ "Download.MapWinShErrorTransientError", code, |
+ base::CustomHistogram::ArrayToCustomRanges( |
+ kAllSpecialShFileOperationCodes, |
+ arraysize(kAllSpecialShFileOperationCodes))); |
+ } |
+ |
if (result != DOWNLOAD_INTERRUPT_REASON_NONE) |
return result; |
// If not one of the above codes, it should be a standard Windows error code. |
- return ConvertNetErrorToInterruptReason( |
- net::MapSystemError(code), DOWNLOAD_INTERRUPT_FROM_DISK); |
+ return ConvertFileErrorToInterruptReason( |
+ base::File::OSErrorToFileError(code)); |
} |
// Maps a return code from ScanAndSaveDownloadedFile() to a |