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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win .h" 5 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win .h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/files/scoped_temp_dir.h"
15 #include "base/guid.h"
16 #include "base/location.h"
10 #include "base/logging.h" 17 #include "base/logging.h"
11 #include "base/macros.h" 18 #include "base/macros.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/memory/ref_counted.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/task_runner_util.h"
12 #include "base/task_scheduler/post_task.h" 23 #include "base/task_scheduler/post_task.h"
13 #include "chrome/browser/browser_process.h" 24 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h" 25 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
26 #include "chrome/common/channel_info.h"
15 #include "components/data_use_measurement/core/data_use_user_data.h" 27 #include "components/data_use_measurement/core/data_use_user_data.h"
16 #include "components/variations/net/variations_http_headers.h" 28 #include "components/version_info/version_info.h"
17 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
18 #include "net/base/load_flags.h" 30 #include "net/base/load_flags.h"
19 #include "net/http/http_request_headers.h" 31 #include "net/http/http_request_headers.h"
20 #include "net/http/http_status_code.h" 32 #include "net/http/http_status_code.h"
21 #include "net/url_request/url_fetcher.h" 33 #include "net/url_request/url_fetcher.h"
22 #include "net/url_request/url_fetcher_delegate.h" 34 #include "net/url_request/url_fetcher_delegate.h"
23 #include "net/url_request/url_request_context_getter.h" 35 #include "net/url_request/url_request_context_getter.h"
24 #include "url/gurl.h" 36 #include "url/gurl.h"
25 37
26 namespace safe_browsing { 38 namespace safe_browsing {
27 39
28 namespace { 40 namespace {
29 41
30 // Class that will attempt to download the Chrome Cleaner executable and 42 base::FilePath::StringType CleanerTempDirectoryPrefix() {
31 // call a given callback when done. Instances of ChromeCleanerFetcher own 43 base::FilePath::StringType common_prefix = FILE_PATH_LITERAL("ChromeCleaner");
32 // themselves and will self-delete on completion of the network request. 44 switch (chrome::GetChannel()) {
45 case version_info::Channel::UNKNOWN:
46 return common_prefix + FILE_PATH_LITERAL("_0_");
47 case version_info::Channel::CANARY:
48 return common_prefix + FILE_PATH_LITERAL("_1_");
49 case version_info::Channel::DEV:
50 return common_prefix + FILE_PATH_LITERAL("_2_");
51 case version_info::Channel::BETA:
52 return common_prefix + FILE_PATH_LITERAL("_3_");
53 case version_info::Channel::STABLE:
54 return common_prefix + FILE_PATH_LITERAL("_4_");
55 }
56 NOTREACHED();
57 return common_prefix + FILE_PATH_LITERAL("_0_");
58 }
59
60 // Class that will attempt to download the Chrome Cleaner executable and call a
61 // given callback when done. Instances of ChromeCleanerFetcher own themselves
62 // and will self-delete if they encounter an error or when the network request
63 // has completed.
33 class ChromeCleanerFetcher : public net::URLFetcherDelegate { 64 class ChromeCleanerFetcher : public net::URLFetcherDelegate {
34 public: 65 public:
35 explicit ChromeCleanerFetcher(ChromeCleanerFetchedCallback fetched_callback); 66 explicit ChromeCleanerFetcher(ChromeCleanerFetchedCallback fetched_callback);
36 67
37 protected: 68 protected:
38 ~ChromeCleanerFetcher() override; 69 ~ChromeCleanerFetcher() override;
39 70
40 private: 71 private:
72 // Must be called on a sequence where IO is allowed.
73 bool CreateTemporaryDirectory();
74 // Will be called back on the same sequence as this object was created on.
75 void OnTemporaryDirectoryCreated(bool success);
76 void PostCallbackAndDeleteSelf(base::FilePath path,
77 ChromeCleanerFetchStatus fetch_status);
78
41 // net::URLFetcherDelegate overrides. 79 // net::URLFetcherDelegate overrides.
42 void OnURLFetchComplete(const net::URLFetcher* source) override; 80 void OnURLFetchComplete(const net::URLFetcher* source) override;
43 81
44 ChromeCleanerFetchedCallback fetched_callback_; 82 ChromeCleanerFetchedCallback fetched_callback_;
83
45 // The underlying URL fetcher. The instance is alive from construction through 84 // The underlying URL fetcher. The instance is alive from construction through
46 // OnURLFetchComplete. 85 // OnURLFetchComplete.
47 std::unique_ptr<net::URLFetcher> url_fetcher_; 86 std::unique_ptr<net::URLFetcher> url_fetcher_;
48 87
88 // Used for file operations such as creating a new temporary directory.
89 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
90
91 // We will take ownership of the scoped temp directory once we know that the
92 // fetch has succeeded. Must be deleted on a sequence where IO is allowed.
93 std::unique_ptr<base::ScopedTempDir, content::BrowserThread::DeleteOnIOThread>
94 scoped_temp_dir_;
95 base::FilePath temp_file_;
96
49 DISALLOW_COPY_AND_ASSIGN(ChromeCleanerFetcher); 97 DISALLOW_COPY_AND_ASSIGN(ChromeCleanerFetcher);
50 }; 98 };
51 99
52 ChromeCleanerFetcher::ChromeCleanerFetcher( 100 ChromeCleanerFetcher::ChromeCleanerFetcher(
53 ChromeCleanerFetchedCallback fetched_callback) 101 ChromeCleanerFetchedCallback fetched_callback)
54 : fetched_callback_(std::move(fetched_callback)), 102 : fetched_callback_(std::move(fetched_callback)),
55 url_fetcher_(net::URLFetcher::Create(0, 103 url_fetcher_(net::URLFetcher::Create(0,
56 GURL(GetSRTDownloadURL()), 104 GURL(GetSRTDownloadURL()),
57 net::URLFetcher::GET, 105 net::URLFetcher::GET,
58 this)) { 106 this)),
107 blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
108 {base::MayBlock(), base::TaskPriority::BACKGROUND,
109 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),
110 scoped_temp_dir_(new base::ScopedTempDir()) {
111 base::PostTaskAndReplyWithResult(
112 blocking_task_runner_.get(), FROM_HERE,
113 base::Bind(&ChromeCleanerFetcher::CreateTemporaryDirectory,
114 base::Unretained(this)),
115 base::Bind(&ChromeCleanerFetcher::OnTemporaryDirectoryCreated,
116 base::Unretained(this)));
117 }
118
119 ChromeCleanerFetcher::~ChromeCleanerFetcher() = default;
120
121 bool ChromeCleanerFetcher::CreateTemporaryDirectory() {
122 base::FilePath temp_dir;
123 return base::CreateNewTempDirectory(CleanerTempDirectoryPrefix(),
124 &temp_dir) &&
125 scoped_temp_dir_->Set(temp_dir);
126 }
127
128 void ChromeCleanerFetcher::OnTemporaryDirectoryCreated(bool success) {
129 if (!success) {
130 PostCallbackAndDeleteSelf(
131 base::FilePath(),
132 ChromeCleanerFetchStatus::kFailedToCreateTemporaryDirectory);
133 return;
134 }
135
136 DCHECK(!scoped_temp_dir_->GetPath().empty());
137
138 temp_file_ = scoped_temp_dir_->GetPath().Append(
139 base::ASCIIToUTF16(base::GenerateGUID()) + L".tmp");
140
59 data_use_measurement::DataUseUserData::AttachToFetcher( 141 data_use_measurement::DataUseUserData::AttachToFetcher(
60 url_fetcher_.get(), data_use_measurement::DataUseUserData::SAFE_BROWSING); 142 url_fetcher_.get(), data_use_measurement::DataUseUserData::SAFE_BROWSING);
61 url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE); 143 url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
62 url_fetcher_->SetMaxRetriesOn5xx(3); 144 url_fetcher_->SetMaxRetriesOn5xx(3);
63 url_fetcher_->SaveResponseToTemporaryFile( 145 url_fetcher_->SaveResponseToFileAtPath(temp_file_, blocking_task_runner_);
64 base::CreateSequencedTaskRunnerWithTraits(
65 {base::MayBlock(), base::TaskPriority::BACKGROUND}));
66 url_fetcher_->SetRequestContext(g_browser_process->system_request_context()); 146 url_fetcher_->SetRequestContext(g_browser_process->system_request_context());
67 url_fetcher_->Start(); 147 url_fetcher_->Start();
68 } 148 }
69 149
70 ChromeCleanerFetcher::~ChromeCleanerFetcher() = default; 150 void ChromeCleanerFetcher::PostCallbackAndDeleteSelf(
151 base::FilePath path,
152 ChromeCleanerFetchStatus fetch_status) {
153 DCHECK(fetched_callback_);
71 154
72 void ChromeCleanerFetcher::OnURLFetchComplete(const net::URLFetcher* source) { 155 std::move(fetched_callback_).Run(std::move(path), fetch_status);
73 // Take ownership of the fetcher in this scope (source == url_fetcher_).
74 DCHECK_EQ(url_fetcher_.get(), source);
75
76 base::FilePath download_path;
77 if (source->GetStatus().is_success() &&
78 source->GetResponseCode() == net::HTTP_OK &&
79 source->GetResponseAsFilePath(true, &download_path)) {
80 DCHECK(!download_path.empty());
81 }
82
83 DCHECK(fetched_callback_);
84 std::move(fetched_callback_)
85 .Run(std::move(download_path), source->GetResponseCode());
86 156
87 // Since url_fetcher_ is passed a pointer to this object during construction, 157 // Since url_fetcher_ is passed a pointer to this object during construction,
88 // explicitly destroy the url_fetcher_ to avoid potential destruction races. 158 // explicitly destroy the url_fetcher_ to avoid potential destruction races.
89 url_fetcher_.reset(); 159 url_fetcher_.reset();
90 160
91 // At this point, the url_fetcher_ is gone and this ChromeCleanerFetcher 161 // At this point, the url_fetcher_ is gone and this ChromeCleanerFetcher
92 // instance is no longer needed. 162 // instance is no longer needed.
93 delete this; 163 delete this;
94 } 164 }
95 165
166 void ChromeCleanerFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
167 // Take ownership of the fetcher in this scope (source == url_fetcher_).
168 DCHECK_EQ(url_fetcher_.get(), source);
169 DCHECK(!source->GetStatus().is_io_pending());
170 DCHECK(fetched_callback_);
171
172 if (source->GetResponseCode() == net::HTTP_NOT_FOUND) {
173 PostCallbackAndDeleteSelf(base::FilePath(),
174 ChromeCleanerFetchStatus::kNotFoundOnServer);
175 return;
176 }
177
178 base::FilePath download_path;
179 if (!source->GetStatus().is_success() ||
180 source->GetResponseCode() != net::HTTP_OK ||
181 !source->GetResponseAsFilePath(/*take_ownership=*/true, &download_path)) {
182 PostCallbackAndDeleteSelf(base::FilePath(),
183 ChromeCleanerFetchStatus::kOtherFailure);
184 return;
185 }
186
187 DCHECK(!download_path.empty());
188 DCHECK_EQ(temp_file_.value(), download_path.value());
189
190 // Take ownership of the scoped temp directory so it is not deleted.
191 scoped_temp_dir_->Take();
192
193 PostCallbackAndDeleteSelf(std::move(download_path),
194 ChromeCleanerFetchStatus::kSuccess);
195 }
196
96 } // namespace 197 } // namespace
97 198
98 void FetchChromeCleaner(ChromeCleanerFetchedCallback fetched_callback) { 199 void FetchChromeCleaner(ChromeCleanerFetchedCallback fetched_callback) {
99 new ChromeCleanerFetcher(std::move(fetched_callback)); 200 new ChromeCleanerFetcher(std::move(fetched_callback));
100 } 201 }
101 202
102 } // namespace safe_browsing 203 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698