Remove old Windows *.TMP files.

When renaming a file, Windows will use an intermediate name and leave
that file around if the final destination name already exists.  These
files are unknown to Chrome and so tend to accumulate which is a
problem when the files are 1MB "metrics" files.

Bug: 934164
Change-Id: I30fa0d81db81af411d7c8775f389206904062412
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1611104
Commit-Queue: Alexei Svitkine <asvitkine@chromium.org>
Reviewed-by: Alexei Svitkine <asvitkine@chromium.org>
Cr-Commit-Position: refs/heads/master@{#662473}
diff --git a/components/metrics/persistent_histograms.cc b/components/metrics/persistent_histograms.cc
index 4be700d2..ba8d2cb 100644
--- a/components/metrics/persistent_histograms.cc
+++ b/components/metrics/persistent_histograms.cc
@@ -6,12 +6,16 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
 #include "base/metrics/field_trial.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/persistent_histogram_allocator.h"
+#include "base/strings/string_util.h"
 #include "base/system/sys_info.h"
 #include "base/task/post_task.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/metrics/persistent_system_profile.h"
 #include "components/variations/variations_associated_data.h"
@@ -32,6 +36,52 @@
 constexpr int kSpareFileCreateDelaySeconds = 90;
 #endif
 
+#if defined(OS_WIN)
+
+// Windows sometimes creates files of the form MyFile.pma~RF71cb1793.TMP
+// when trying to rename a file to something that exists but is in-use, and
+// then fails to remove them. See https://crbug.com/934164
+void DeleteOldWindowsTempFiles(const base::FilePath& dir) {
+  // Look for any temp files older than one day and remove them. The time check
+  // unsures that nothing in active transition gets deleted; these names only
+  // exists on the order of milliseconds when working properly so "one day" is
+  // generous but still ensures no big build up of these files. This is an
+  // I/O intensive task so do it in the background (enforced by "file" calls).
+  base::Time one_day_ago = base::Time::Now() - base::TimeDelta::FromDays(1);
+  int delete_count = 0;
+  base::FileEnumerator file_iter(dir, /*recursive=*/false,
+                                 base::FileEnumerator::FILES);
+  for (base::FilePath path = file_iter.Next(); !path.empty();
+       path = file_iter.Next()) {
+    if (base::ToUpperASCII(path.FinalExtension()) !=
+            FILE_PATH_LITERAL(".TMP") ||
+        base::ToUpperASCII(path.BaseName().value())
+                .find(FILE_PATH_LITERAL(".PMA~RF")) < 0) {
+      continue;
+    }
+
+    const auto& info = file_iter.GetInfo();
+    if (info.IsDirectory())
+      continue;
+    if (info.GetLastModifiedTime() > one_day_ago)
+      continue;
+
+    base::DeleteFile(path, /*recursive=*/false);
+    delete_count++;
+  }
+
+  base::UmaHistogramCounts1000("UMA.PersistentHistograms.TmpRemovals",
+                               delete_count);
+}
+
+// How much time after startup to run the above function. Two minutes is
+// enough for the system to stabilize and get the user what they want before
+// spending time on clean-up efforts.
+constexpr base::TimeDelta kDeleteOldWindowsTempFilesDelay =
+    base::TimeDelta::FromMinutes(2);
+
+#endif  // defined(OS_WIN)
+
 }  // namespace
 
 const char kBrowserMetricsName[] = "BrowserMetrics";
@@ -162,4 +212,13 @@
 
   // Create tracking histograms for the allocator and record storage file.
   allocator->CreateTrackingHistograms(kBrowserMetricsName);
+
+#if defined(OS_WIN)
+  base::PostDelayedTaskWithTraits(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskPriority::LOWEST,
+       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+      base::BindOnce(&DeleteOldWindowsTempFiles, std::move(metrics_dir)),
+      kDeleteOldWindowsTempFilesDelay);
+#endif  // defined(OS_WIN)
 }
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 765c9d85..74e87f1 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -133729,6 +133729,16 @@
   </summary>
 </histogram>
 
+<histogram name="UMA.PersistentHistograms.TmpRemovals" expires_after="M77">
+  <owner>bcwhite@chromium.org</owner>
+  <owner>asvitkine@chromium.org</owner>
+  <summary>
+    Number of old .tmp files of the kind that Windows creates and leaves around
+    when trying to rename a file to another one that already exists. See
+    https://crbug.com/934164
+  </summary>
+</histogram>
+
 <histogram name="UMA.PrimaryUserType" enum="UserType"
     expires_after="2020-04-01">
   <owner>michaelpg@chromium.org</owner>