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

Unified Diff: chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc

Issue 2929483002: Chrome Cleaner: download the Chrome Cleaner executable in an empty directory. (Closed)
Patch Set: Nits Created 3 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc
index 9827faf9161a4afcbfe1361576d37af03138c59f..71f7720ba2b8810b4f791b51cd7681ebb381a4dc 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc
@@ -7,13 +7,25 @@
#include <memory>
#include <utility>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/guid.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
#include "base/task_scheduler/post_task.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
+#include "chrome/common/channel_info.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
-#include "components/variations/net/variations_http_headers.h"
+#include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
@@ -27,9 +39,28 @@ namespace safe_browsing {
namespace {
-// Class that will attempt to download the Chrome Cleaner executable and
-// call a given callback when done. Instances of ChromeCleanerFetcher own
-// themselves and will self-delete on completion of the network request.
+base::FilePath::StringType CleanerTempDirectoryPrefix() {
+ base::FilePath::StringType common_prefix = FILE_PATH_LITERAL("ChromeCleaner");
+ switch (chrome::GetChannel()) {
+ case version_info::Channel::UNKNOWN:
+ return common_prefix + FILE_PATH_LITERAL("_0_");
+ case version_info::Channel::CANARY:
+ return common_prefix + FILE_PATH_LITERAL("_1_");
+ case version_info::Channel::DEV:
+ return common_prefix + FILE_PATH_LITERAL("_2_");
+ case version_info::Channel::BETA:
+ return common_prefix + FILE_PATH_LITERAL("_3_");
+ case version_info::Channel::STABLE:
+ return common_prefix + FILE_PATH_LITERAL("_4_");
+ }
+ NOTREACHED();
+ return common_prefix + FILE_PATH_LITERAL("_0_");
+}
+
+// Class that will attempt to download the Chrome Cleaner executable and call a
+// given callback when done. Instances of ChromeCleanerFetcher own themselves
+// and will self-delete if they encounter an error or when the network request
+// has completed.
class ChromeCleanerFetcher : public net::URLFetcherDelegate {
public:
explicit ChromeCleanerFetcher(ChromeCleanerFetchedCallback fetched_callback);
@@ -38,14 +69,31 @@ class ChromeCleanerFetcher : public net::URLFetcherDelegate {
~ChromeCleanerFetcher() override;
private:
+ // Must be called on a sequence where IO is allowed.
+ bool CreateTemporaryDirectory();
+ // Will be called back on the same sequence as this object was created on.
+ void OnTemporaryDirectoryCreated(bool success);
+ void PostCallbackAndDeleteSelf(base::FilePath path,
+ ChromeCleanerFetchStatus fetch_status);
+
// net::URLFetcherDelegate overrides.
void OnURLFetchComplete(const net::URLFetcher* source) override;
ChromeCleanerFetchedCallback fetched_callback_;
+
// The underlying URL fetcher. The instance is alive from construction through
// OnURLFetchComplete.
std::unique_ptr<net::URLFetcher> url_fetcher_;
+ // Used for file operations such as creating a new temporary directory.
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
+
+ // We will take ownership of the scoped temp directory once we know that the
+ // fetch has succeeded. Must be deleted on a sequence where IO is allowed.
+ std::unique_ptr<base::ScopedTempDir, content::BrowserThread::DeleteOnIOThread>
+ scoped_temp_dir_;
+ base::FilePath temp_file_;
+
DISALLOW_COPY_AND_ASSIGN(ChromeCleanerFetcher);
};
@@ -55,42 +103,95 @@ ChromeCleanerFetcher::ChromeCleanerFetcher(
url_fetcher_(net::URLFetcher::Create(0,
GURL(GetSRTDownloadURL()),
net::URLFetcher::GET,
- this)) {
+ this)),
+ blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),
+ scoped_temp_dir_(new base::ScopedTempDir()) {
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_.get(), FROM_HERE,
+ base::Bind(&ChromeCleanerFetcher::CreateTemporaryDirectory,
+ base::Unretained(this)),
+ base::Bind(&ChromeCleanerFetcher::OnTemporaryDirectoryCreated,
+ base::Unretained(this)));
+}
+
+ChromeCleanerFetcher::~ChromeCleanerFetcher() = default;
+
+bool ChromeCleanerFetcher::CreateTemporaryDirectory() {
+ base::FilePath temp_dir;
+ return base::CreateNewTempDirectory(CleanerTempDirectoryPrefix(),
+ &temp_dir) &&
+ scoped_temp_dir_->Set(temp_dir);
+}
+
+void ChromeCleanerFetcher::OnTemporaryDirectoryCreated(bool success) {
+ if (!success) {
+ PostCallbackAndDeleteSelf(
+ base::FilePath(),
+ ChromeCleanerFetchStatus::kFailedToCreateTemporaryDirectory);
+ return;
+ }
+
+ DCHECK(!scoped_temp_dir_->GetPath().empty());
+
+ temp_file_ = scoped_temp_dir_->GetPath().Append(
+ base::ASCIIToUTF16(base::GenerateGUID()) + L".tmp");
+
data_use_measurement::DataUseUserData::AttachToFetcher(
url_fetcher_.get(), data_use_measurement::DataUseUserData::SAFE_BROWSING);
url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
url_fetcher_->SetMaxRetriesOn5xx(3);
- url_fetcher_->SaveResponseToTemporaryFile(
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND}));
+ url_fetcher_->SaveResponseToFileAtPath(temp_file_, blocking_task_runner_);
url_fetcher_->SetRequestContext(g_browser_process->system_request_context());
url_fetcher_->Start();
}
-ChromeCleanerFetcher::~ChromeCleanerFetcher() = default;
+void ChromeCleanerFetcher::PostCallbackAndDeleteSelf(
+ base::FilePath path,
+ ChromeCleanerFetchStatus fetch_status) {
+ DCHECK(fetched_callback_);
+
+ std::move(fetched_callback_).Run(std::move(path), fetch_status);
+
+ // Since url_fetcher_ is passed a pointer to this object during construction,
+ // explicitly destroy the url_fetcher_ to avoid potential destruction races.
+ url_fetcher_.reset();
+
+ // At this point, the url_fetcher_ is gone and this ChromeCleanerFetcher
+ // instance is no longer needed.
+ delete this;
+}
void ChromeCleanerFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
// Take ownership of the fetcher in this scope (source == url_fetcher_).
DCHECK_EQ(url_fetcher_.get(), source);
+ DCHECK(!source->GetStatus().is_io_pending());
+ DCHECK(fetched_callback_);
+
+ if (source->GetResponseCode() == net::HTTP_NOT_FOUND) {
+ PostCallbackAndDeleteSelf(base::FilePath(),
+ ChromeCleanerFetchStatus::kNotFoundOnServer);
+ return;
+ }
base::FilePath download_path;
- if (source->GetStatus().is_success() &&
- source->GetResponseCode() == net::HTTP_OK &&
- source->GetResponseAsFilePath(true, &download_path)) {
- DCHECK(!download_path.empty());
+ if (!source->GetStatus().is_success() ||
+ source->GetResponseCode() != net::HTTP_OK ||
+ !source->GetResponseAsFilePath(/*take_ownership=*/true, &download_path)) {
+ PostCallbackAndDeleteSelf(base::FilePath(),
+ ChromeCleanerFetchStatus::kOtherFailure);
+ return;
}
- DCHECK(fetched_callback_);
- std::move(fetched_callback_)
- .Run(std::move(download_path), source->GetResponseCode());
+ DCHECK(!download_path.empty());
+ DCHECK_EQ(temp_file_.value(), download_path.value());
- // Since url_fetcher_ is passed a pointer to this object during construction,
- // explicitly destroy the url_fetcher_ to avoid potential destruction races.
- url_fetcher_.reset();
+ // Take ownership of the scoped temp directory so it is not deleted.
+ scoped_temp_dir_->Take();
- // At this point, the url_fetcher_ is gone and this ChromeCleanerFetcher
- // instance is no longer needed.
- delete this;
+ PostCallbackAndDeleteSelf(std::move(download_path),
+ ChromeCleanerFetchStatus::kSuccess);
}
} // namespace

Powered by Google App Engine
This is Rietveld 408576698