[M87 merge] ambient: fix dcheck blocking error saving backup photos

Perform disk operations in SequencedTaskRunner

BUG=b:170346308
TEST=activate ambient mode, lock screen

(cherry picked from commit ddadb4220d53154ac339a1e34954dc129c5e0089)

Change-Id: I5faefd46e74e6ec8ae7061d56e7f6abd0c80326f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2460796
Commit-Queue: Jeffrey Young <[email protected]>
Reviewed-by: Xiaohui Chen <[email protected]>
Reviewed-by: Tao Wu <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#815959}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2464789
Cr-Commit-Position: refs/branch-heads/4280@{#301}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/ash/ambient/ambient_photo_controller.cc b/ash/ambient/ambient_photo_controller.cc
index 797ba5a..7321caa 100644
--- a/ash/ambient/ambient_photo_controller.cc
+++ b/ash/ambient/ambient_photo_controller.cc
@@ -36,6 +36,7 @@
 #include "base/task/thread_pool.h"
 #include "base/task_runner_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "base/unguessable_token.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/data_decoder/public/cpp/decode_image.h"
 #include "services/network/public/cpp/resource_request.h"
@@ -170,7 +171,10 @@
 
 class AmbientURLLoaderImpl : public AmbientURLLoader {
  public:
-  AmbientURLLoaderImpl() = default;
+  AmbientURLLoaderImpl()
+      : task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+            {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+             base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})) {}
   ~AmbientURLLoaderImpl() override = default;
 
   // AmbientURLLoader:
@@ -195,24 +199,21 @@
     auto simple_loader = CreateSimpleURLLoader(url);
     auto loader_factory = AmbientClient::Get()->GetURLLoaderFactory();
     auto* loader_ptr = simple_loader.get();
+
+    // Create a temporary file path as target for download to guard against race
+    // conditions in reading.
+    base::FilePath temp_path = file_path.DirName().Append(
+        base::UnguessableToken::Create().ToString() + kPhotoFileExt);
+
     // Download to temp file first to guarantee entire image is written without
     // errors before attempting to read it.
-
-    // Create a temp file.
-    base::FilePath temp_file;
-    if (!base::CreateTemporaryFileInDir(file_path.DirName(), &temp_file)) {
-      LOG(ERROR) << "Cannot create a temporary file";
-      std::move(callback).Run(base::FilePath());
-      return;
-    }
-
     loader_ptr->DownloadToFile(
         loader_factory.get(),
         base::BindOnce(&AmbientURLLoaderImpl::OnUrlDownloadedToFile,
                        weak_factory_.GetWeakPtr(), std::move(callback),
                        std::move(simple_loader), std::move(loader_factory),
                        file_path),
-        temp_file);
+        temp_path);
   }
 
  private:
@@ -254,15 +255,37 @@
       LOG(ERROR) << "Downloading to file failed with error code: "
                  << GetResponseCode(simple_loader.get())
                  << " with network error" << simple_loader->NetError();
+
+      if (!temp_path.empty()) {
+        // Clean up temporary file.
+        task_runner_->PostTask(FROM_HERE, base::BindOnce(
+                                              [](const base::FilePath& path) {
+                                                base::DeleteFile(path);
+                                              },
+                                              temp_path));
+      }
       std::move(callback).Run(base::FilePath());
       return;
     }
-    if (!base::ReplaceFile(temp_path, desired_path, /*error=*/nullptr)) {
-      LOG(ERROR) << "Unable to move downloaded file to ambient directory";
-      std::move(callback).Run(base::FilePath());
-      return;
-    }
-    std::move(callback).Run(std::move(desired_path));
+
+    // Swap the temporary file to the desired path, and then run the callback.
+    task_runner_->PostTaskAndReplyWithResult(
+        FROM_HERE,
+        base::BindOnce(
+            [](const base::FilePath& to_path, const base::FilePath& from_path) {
+              if (!base::ReplaceFile(from_path, to_path,
+                                     /*error=*/nullptr)) {
+                LOG(ERROR)
+                    << "Unable to move downloaded file to ambient directory";
+                // Clean up the files.
+                base::DeleteFile(from_path);
+                base::DeleteFile(to_path);
+                return base::FilePath();
+              }
+              return to_path;
+            },
+            desired_path, temp_path),
+        std::move(callback));
   }
 
   int GetResponseCode(network::SimpleURLLoader* simple_loader) {
@@ -274,6 +297,7 @@
     }
   }
 
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
   base::WeakPtrFactory<AmbientURLLoaderImpl> weak_factory_{this};
 };