Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / download / base_file_win.cc
index 252f049..fec1454 100644 (file)
@@ -9,7 +9,8 @@
 #include <objbase.h>
 #include <shellapi.h>
 
-#include "base/file_util.h"
+#include "base/files/file.h"
+#include "base/files/file_util.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,
@@ -68,11 +71,28 @@ DownloadInterruptReason MapShFileOperationCodes(int code) {
   // This switch statement should be kept in sync with the list of codes
   // 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.
+    // Not a pre-Win32 error code; here so that this particular case shows up in
+    // our histograms. Unfortunately, it is used not just to signal actual
+    // ACCESS_DENIED errors, but many other errors as well. So we treat it as a
+    // transient error.
     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 documented but returned from SHFileOperation. Sharing
+    // violations indicate that another process had the file open while we were
+    // trying to rename. Anti-virus is believed to be the cause of this error in
+    // the wild. Treated as a transient error on the assumption that the file
+    // will be made available for renaming at a later time.
+    case ERROR_SHARING_VIOLATION:
+      result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
+      break;
+
+    // This is also not 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:
+      result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
       break;
 
     // The source and destination files are the same file.
@@ -250,12 +270,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
@@ -310,6 +338,7 @@ DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions(
   move_info.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI |
       FOF_NOCONFIRMMKDIR | FOF_NOCOPYSECURITYATTRIBS;
 
+  base::TimeTicks now = base::TimeTicks::Now();
   int result = SHFileOperation(&move_info);
   DownloadInterruptReason interrupt_reason = DOWNLOAD_INTERRUPT_REASON_NONE;