Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / chromeos / imageburner / burn_manager.cc
blobc2d035d96e28040d4e66b3e8e49a8bd2bbdcaa41
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/imageburner/burn_manager.h"
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/path_service.h"
10 #include "base/string_util.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/chromeos/system/statistics_provider.h"
13 #include "chrome/common/chrome_paths.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "net/url_request/url_fetcher.h"
16 #include "net/url_request/url_request_status.h"
18 using content::BrowserThread;
20 namespace chromeos {
21 namespace imageburner {
23 namespace {
25 // Name for hwid in machine statistics.
26 const char kHwidStatistic[] = "hardware_class";
28 const char kConfigFileUrl[] =
29 "https://dl.google.com/dl/edgedl/chromeos/recovery/recovery.conf";
30 const char kTempImageFolderName[] = "chromeos_image";
32 const int64 kBytesImageDownloadProgressReportInterval = 10240;
34 BurnManager* g_burn_manager = NULL;
36 // Cretes a directory and calls |callback| with the result on UI thread.
37 void CreateDirectory(const FilePath& path,
38 base::Callback<void(bool success)> callback) {
39 const bool success = file_util::CreateDirectory(path);
40 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
41 base::Bind(callback, success));
44 } // namespace
46 const char kName[] = "name";
47 const char kHwid[] = "hwid";
48 const char kFileName[] = "file";
49 const char kUrl[] = "url";
51 ////////////////////////////////////////////////////////////////////////////////
53 // ConfigFile
55 ////////////////////////////////////////////////////////////////////////////////
56 ConfigFile::ConfigFile() {
59 ConfigFile::ConfigFile(const std::string& file_content) {
60 reset(file_content);
63 ConfigFile::~ConfigFile() {
66 void ConfigFile::reset(const std::string& file_content) {
67 clear();
69 std::vector<std::string> lines;
70 Tokenize(file_content, "\n", &lines);
72 std::vector<std::string> key_value_pair;
73 for (size_t i = 0; i < lines.size(); ++i) {
74 if (lines[i].empty())
75 continue;
77 key_value_pair.clear();
78 Tokenize(lines[i], "=", &key_value_pair);
79 // Skip lines that don't contain key-value pair and lines without a key.
80 if (key_value_pair.size() != 2 || key_value_pair[0].empty())
81 continue;
83 ProcessLine(key_value_pair);
86 // Make sure last block has at least one hwid associated with it.
87 DeleteLastBlockIfHasNoHwid();
90 void ConfigFile::clear() {
91 config_struct_.clear();
94 const std::string& ConfigFile::GetProperty(
95 const std::string& property_name,
96 const std::string& hwid) const {
97 // We search for block that has desired hwid property, and if we find it, we
98 // return its property_name property.
99 for (BlockList::const_iterator block_it = config_struct_.begin();
100 block_it != config_struct_.end();
101 ++block_it) {
102 if (block_it->hwids.find(hwid) != block_it->hwids.end()) {
103 PropertyMap::const_iterator property =
104 block_it->properties.find(property_name);
105 if (property != block_it->properties.end()) {
106 return property->second;
107 } else {
108 return EmptyString();
113 return EmptyString();
116 // Check if last block has a hwid associated with it, and erase it if it
117 // doesn't,
118 void ConfigFile::DeleteLastBlockIfHasNoHwid() {
119 if (!config_struct_.empty() && config_struct_.back().hwids.empty()) {
120 config_struct_.pop_back();
124 void ConfigFile::ProcessLine(const std::vector<std::string>& line) {
125 // If line contains name key, new image block is starting, so we have to add
126 // new entry to our data structure.
127 if (line[0] == kName) {
128 // If there was no hardware class defined for previous block, we can
129 // disregard is since we won't be abble to access any of its properties
130 // anyway. This should not happen, but let's be defensive.
131 DeleteLastBlockIfHasNoHwid();
132 config_struct_.resize(config_struct_.size() + 1);
135 // If we still haven't added any blocks to data struct, we disregard this
136 // line. Again, this should never happen.
137 if (config_struct_.empty())
138 return;
140 ConfigFileBlock& last_block = config_struct_.back();
142 if (line[0] == kHwid) {
143 // Check if line contains hwid property. If so, add it to set of hwids
144 // associated with current block.
145 last_block.hwids.insert(line[1]);
146 } else {
147 // Add new block property.
148 last_block.properties.insert(std::make_pair(line[0], line[1]));
152 ConfigFile::ConfigFileBlock::ConfigFileBlock() {
155 ConfigFile::ConfigFileBlock::~ConfigFileBlock() {
158 ////////////////////////////////////////////////////////////////////////////////
160 // StateMachine
162 ////////////////////////////////////////////////////////////////////////////////
163 StateMachine::StateMachine()
164 : download_started_(false),
165 download_finished_(false),
166 state_(INITIAL) {
169 StateMachine::~StateMachine() {
172 void StateMachine::OnError(int error_message_id) {
173 if (state_ == INITIAL)
174 return;
175 if (!download_finished_)
176 download_started_ = false;
178 state_ = INITIAL;
179 FOR_EACH_OBSERVER(Observer, observers_, OnError(error_message_id));
182 void StateMachine::OnSuccess() {
183 if (state_ == INITIAL)
184 return;
185 state_ = INITIAL;
186 OnStateChanged();
189 void StateMachine::OnCancelation() {
190 // We use state CANCELLED only to let observers know that they have to
191 // process cancelation. We don't actually change the state.
192 FOR_EACH_OBSERVER(Observer, observers_, OnBurnStateChanged(CANCELLED));
195 ////////////////////////////////////////////////////////////////////////////////
197 // BurnManager
199 ////////////////////////////////////////////////////////////////////////////////
201 BurnManager::BurnManager()
202 : weak_ptr_factory_(this),
203 config_file_url_(kConfigFileUrl),
204 config_file_fetched_(false),
205 state_machine_(new StateMachine()),
206 bytes_image_download_progress_last_reported_(0) {
209 BurnManager::~BurnManager() {
210 if (!image_dir_.empty()) {
211 file_util::Delete(image_dir_, true);
215 // static
216 void BurnManager::Initialize() {
217 if (g_burn_manager) {
218 LOG(WARNING) << "BurnManager was already initialized";
219 return;
221 g_burn_manager = new BurnManager();
222 VLOG(1) << "BurnManager initialized";
225 // static
226 void BurnManager::Shutdown() {
227 if (!g_burn_manager) {
228 LOG(WARNING) << "BurnManager::Shutdown() called with NULL manager";
229 return;
231 delete g_burn_manager;
232 g_burn_manager = NULL;
233 VLOG(1) << "BurnManager Shutdown completed";
236 // static
237 BurnManager* BurnManager::GetInstance() {
238 return g_burn_manager;
241 void BurnManager::AddObserver(Observer* observer) {
242 observers_.AddObserver(observer);
245 void BurnManager::RemoveObserver(Observer* observer) {
246 observers_.RemoveObserver(observer);
249 void BurnManager::CreateImageDir(Delegate* delegate) {
250 if (image_dir_.empty()) {
251 CHECK(PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &image_dir_));
252 image_dir_ = image_dir_.Append(kTempImageFolderName);
253 BrowserThread::PostBlockingPoolTask(
254 FROM_HERE,
255 base::Bind(CreateDirectory,
256 image_dir_,
257 base::Bind(&BurnManager::OnImageDirCreated,
258 weak_ptr_factory_.GetWeakPtr(),
259 delegate)));
260 } else {
261 const bool success = true;
262 OnImageDirCreated(delegate, success);
266 void BurnManager::OnImageDirCreated(Delegate* delegate, bool success) {
267 delegate->OnImageDirCreated(success);
270 const FilePath& BurnManager::GetImageDir() {
271 return image_dir_;
274 void BurnManager::FetchConfigFile(Delegate* delegate) {
275 if (config_file_fetched_) {
276 delegate->OnConfigFileFetched(true, image_file_name_, image_download_url_);
277 return;
279 downloaders_.push_back(delegate->AsWeakPtr());
281 if (config_fetcher_.get())
282 return;
284 config_fetcher_.reset(net::URLFetcher::Create(
285 config_file_url_, net::URLFetcher::GET, this));
286 config_fetcher_->SetRequestContext(
287 g_browser_process->system_request_context());
288 config_fetcher_->Start();
291 void BurnManager::FetchImage(const GURL& image_url, const FilePath& file_path) {
292 tick_image_download_start_ = base::TimeTicks::Now();
293 bytes_image_download_progress_last_reported_ = 0;
294 image_fetcher_.reset(net::URLFetcher::Create(image_url,
295 net::URLFetcher::GET,
296 this));
297 image_fetcher_->SetRequestContext(
298 g_browser_process->system_request_context());
299 image_fetcher_->SaveResponseToFileAtPath(
300 file_path,
301 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
302 image_fetcher_->Start();
305 void BurnManager::CancelImageFetch() {
306 image_fetcher_.reset();
309 void BurnManager::OnURLFetchComplete(const net::URLFetcher* source) {
310 const bool success =
311 source->GetStatus().status() == net::URLRequestStatus::SUCCESS;
312 if (source == config_fetcher_.get()) {
313 std::string data;
314 if (success)
315 config_fetcher_->GetResponseAsString(&data);
316 config_fetcher_.reset();
317 ConfigFileFetched(success, data);
318 } else if (source == image_fetcher_.get()) {
319 if (success)
320 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCompleted());
321 else
322 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCancelled());
326 void BurnManager::OnURLFetchDownloadProgress(const net::URLFetcher* source,
327 int64 current,
328 int64 total) {
329 if (source == image_fetcher_.get()) {
330 if (current >= bytes_image_download_progress_last_reported_ +
331 kBytesImageDownloadProgressReportInterval) {
332 bytes_image_download_progress_last_reported_ = current;
333 base::TimeDelta time_remaining;
334 if (current > 0) {
335 const base::TimeDelta diff =
336 base::TimeTicks::Now() - tick_image_download_start_;
337 time_remaining = diff*(total - current)/current;
339 FOR_EACH_OBSERVER(Observer, observers_,
340 OnDownloadUpdated(current, total, time_remaining));
345 void BurnManager::ConfigFileFetched(bool fetched, const std::string& content) {
346 if (config_file_fetched_)
347 return;
349 // Get image file name and image download URL.
350 std::string hwid;
351 if (fetched && system::StatisticsProvider::GetInstance()->
352 GetMachineStatistic(kHwidStatistic, &hwid)) {
353 ConfigFile config_file(content);
354 image_file_name_ = config_file.GetProperty(kFileName, hwid);
355 image_download_url_ = GURL(config_file.GetProperty(kUrl, hwid));
358 // Error check.
359 if (fetched && !image_file_name_.empty() && !image_download_url_.is_empty()) {
360 config_file_fetched_ = true;
361 } else {
362 fetched = false;
363 image_file_name_.clear();
364 image_download_url_ = GURL();
367 for (size_t i = 0; i < downloaders_.size(); ++i) {
368 if (downloaders_[i]) {
369 downloaders_[i]->OnConfigFileFetched(fetched,
370 image_file_name_,
371 image_download_url_);
374 downloaders_.clear();
377 } // namespace imageburner
378 } // namespace chromeos