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

Side by Side Diff: chrome/browser/component_updater/pnacl/pnacl_component_installer.cc

Issue 13071002: Turn on component updater on chromeos, only for the pnacl component. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: check if logged in first to not waste early ping on the OTR profile Created 7 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/component_updater/pnacl/pnacl_component_installer.h" 5 #include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
6 6
7 #include "base/base_paths.h" 7 #include "base/base_paths.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
13 #include "base/json/json_file_value_serializer.h" 13 #include "base/json/json_file_value_serializer.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/path_service.h" 15 #include "base/path_service.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/values.h" 17 #include "base/values.h"
18 #include "base/version.h" 18 #include "base/version.h"
19 #include "base/win/windows_version.h" 19 #include "base/win/windows_version.h"
20 #include "build/build_config.h" 20 #include "build/build_config.h"
21 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/component_updater/component_updater_service.h" 22 #include "chrome/browser/component_updater/component_updater_service.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/profiles/profile_manager.h"
22 #include "chrome/common/chrome_paths.h" 25 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/chrome_switches.h" 26 #include "chrome/common/chrome_switches.h"
24 #include "content/public/browser/browser_thread.h" 27 #include "content/public/browser/browser_thread.h"
25 28
26 using content::BrowserThread; 29 using content::BrowserThread;
27 30
28 namespace { 31 namespace {
29 32
30 // If PNaCl isn't installed yet, but a user is running chrome with 33 // If PNaCl isn't installed yet, but a user is running chrome with
31 // --enable-pnacl, this is the amount of time to wait before starting 34 // --enable-pnacl, this is the amount of time to wait before starting
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 137
135 138
136 // If we don't have Pnacl installed, this is the version we claim. 139 // If we don't have Pnacl installed, this is the version we claim.
137 const char kNullVersion[] = "0.0.0.0"; 140 const char kNullVersion[] = "0.0.0.0";
138 141
139 // Pnacl components have the version encoded in the path itself: 142 // Pnacl components have the version encoded in the path itself:
140 // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\0.1.2.3\. 143 // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\0.1.2.3\.
141 // and the base directory will be: 144 // and the base directory will be:
142 // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\. 145 // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\.
143 base::FilePath GetPnaclBaseDirectory() { 146 base::FilePath GetPnaclBaseDirectory() {
147 #if defined(OS_CHROMEOS)
148 // For ChromeOS, temporarily make this user-dependent (for integrity) until
149 // we find a better solution.
150 // This is not ideal because of the following:
151 // (a) We end up with per-user copies instead of a single copy
152 // (b) The profile can change as users log in to different accounts
153 // so we need to watch for user-login-events (see pnacl_profile_observer.h).
154 Profile* profile = ProfileManager::GetLastUsedProfile();
155 base::FilePath path = profile->GetPath().AppendASCII(
156 FILE_PATH_LITERAL("pnacl"));
Dmitry Polukhin 2013/03/26 11:59:56 Nit, 2 idents.
jvoung - send to chromium... 2013/03/26 15:46:53 Done.
157 return path;
158 #else
144 base::FilePath result; 159 base::FilePath result;
145 CHECK(PathService::Get(chrome::DIR_PNACL_BASE, &result)); 160 CHECK(PathService::Get(chrome::DIR_PNACL_BASE, &result));
146 return result; 161 return result;
162 #endif
147 } 163 }
148 164
149 bool GetLatestPnaclDirectory(base::FilePath* latest_dir, 165 bool GetLatestPnaclDirectory(base::FilePath* latest_dir,
150 Version* latest_version, 166 Version* latest_version,
151 std::vector<base::FilePath>* older_dirs) { 167 std::vector<base::FilePath>* older_dirs) {
152 // Enumerate all versions starting from the base directory. 168 // Enumerate all versions starting from the base directory.
153 base::FilePath base_dir = GetPnaclBaseDirectory(); 169 base::FilePath base_dir = GetPnaclBaseDirectory();
154 bool found = false; 170 bool found = false;
155 file_util::FileEnumerator 171 file_util::FileEnumerator
156 file_enumerator(base_dir, false, file_util::FileEnumerator::DIRECTORIES); 172 file_enumerator(base_dir, false, file_util::FileEnumerator::DIRECTORIES);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 if (arch.compare(PnaclArch()) != 0) { 239 if (arch.compare(PnaclArch()) != 0) {
224 LOG(WARNING) << "'pnacl-arch' field in manifest is invalid (" 240 LOG(WARNING) << "'pnacl-arch' field in manifest is invalid ("
225 << arch << " vs " << PnaclArch() << ")"; 241 << arch << " vs " << PnaclArch() << ")";
226 return false; 242 return false;
227 } 243 }
228 244
229 *version_out = version; 245 *version_out = version;
230 return true; 246 return true;
231 } 247 }
232 248
233 class PnaclComponentInstaller : public ComponentInstaller { 249 PnaclComponentInstaller::PnaclComponentInstaller() : cus_(NULL) {
234 public: 250 // Fill in most of the information. The version will be discovered later.
235 explicit PnaclComponentInstaller(const Version& version); 251 Version null_version(kNullVersion);
252 pnacl_component_.version = null_version;
253 pnacl_component_.name = "pnacl";
254 pnacl_component_.installer = this;
255 SetPnaclHash(&pnacl_component_);
236 256
237 virtual ~PnaclComponentInstaller() {} 257 #if defined(OS_CHROMEOS)
258 profile_observer_.reset(new PnaclProfileObserver(this));
259 #endif
260 }
238 261
239 virtual void OnUpdateError(int error) OVERRIDE; 262 PnaclComponentInstaller::~PnaclComponentInstaller() {
240
241 virtual bool Install(base::DictionaryValue* manifest,
242 const base::FilePath& unpack_path) OVERRIDE;
243
244 private:
245 Version current_version_;
246 };
247
248 PnaclComponentInstaller::PnaclComponentInstaller(
249 const Version& version) : current_version_(version) {
250 DCHECK(version.IsValid());
251 } 263 }
252 264
253 void PnaclComponentInstaller::OnUpdateError(int error) { 265 void PnaclComponentInstaller::OnUpdateError(int error) {
254 NOTREACHED() << "Pnacl update error: " << error; 266 NOTREACHED() << "Pnacl update error: " << error;
255 } 267 }
256 268
257 namespace { 269 namespace {
258 270
259 bool PathContainsPnacl(const base::FilePath& base_path) { 271 bool PathContainsPnacl(const base::FilePath& base_path) {
260 // Check that at least one of the compiler files exists, for the current ISA. 272 // Check that at least one of the compiler files exists, for the current ISA.
(...skipping 17 matching lines...) Expand all
278 290
279 Version version; 291 Version version;
280 if (!CheckPnaclComponentManifest(manifest, 292 if (!CheckPnaclComponentManifest(manifest,
281 pnacl_manifest.get(), 293 pnacl_manifest.get(),
282 &version)) { 294 &version)) {
283 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; 295 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing.";
284 return false; 296 return false;
285 } 297 }
286 298
287 // Don't install if the current version is actually newer. 299 // Don't install if the current version is actually newer.
288 if (current_version_.CompareTo(version) > 0) 300 if (get_current_version().CompareTo(version) > 0)
289 return false; 301 return false;
290 302
291 if (!PathContainsPnacl(unpack_path)) { 303 if (!PathContainsPnacl(unpack_path)) {
292 LOG(WARNING) << "PathContainsPnacl check failed, not installing."; 304 LOG(WARNING) << "PathContainsPnacl check failed, not installing.";
293 return false; 305 return false;
294 } 306 }
295 307
296 // Passed the basic tests. Time to install it. 308 // Passed the basic tests. Time to install it.
297 base::FilePath path = 309 base::FilePath path =
298 GetPnaclBaseDirectory().AppendASCII(version.GetString()); 310 GetPnaclBaseDirectory().AppendASCII(version.GetString());
299 if (file_util::PathExists(path)) { 311 if (file_util::PathExists(path)) {
300 LOG(WARNING) << "Target path already exists, not installing."; 312 LOG(WARNING) << "Target path already exists, not installing.";
301 return false; 313 return false;
302 } 314 }
303 if (!file_util::Move(unpack_path, path)) { 315 if (!file_util::Move(unpack_path, path)) {
304 LOG(WARNING) << "Move failed, not installing."; 316 LOG(WARNING) << "Move failed, not installing.";
305 return false; 317 return false;
306 } 318 }
307 319
308 // Installation is done. Now tell the rest of chrome (just the path service 320 // Installation is done. Now tell the rest of chrome (just the path service
309 // for now). TODO(jvoung): we need notifications if someone surfed to a 321 // for now). TODO(jvoung): we need notifications if someone surfed to a
310 // Pnacl webpage and Pnacl was just installed at this time. They should 322 // Pnacl webpage and Pnacl was just installed at this time. They should
311 // then be able to reload the page and retry (or something). 323 // then be able to reload the page and retry (or something).
312 // See: http://code.google.com/p/chromium/issues/detail?id=107438 324 // See: http://code.google.com/p/chromium/issues/detail?id=107438
313 current_version_ = version; 325 set_current_version(version);
314 326
315 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); 327 PathService::Override(chrome::DIR_PNACL_COMPONENT, path);
316 return true; 328 return true;
317 } 329 }
318 330
319 namespace { 331 namespace {
320 332
321 void DoCheckForUpdate(ComponentUpdateService* cus, 333 void DoCheckForUpdate(ComponentUpdateService* cus,
322 const CrxComponent& pnacl) { 334 const CrxComponent& pnacl) {
323 if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) { 335 if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) {
324 LOG(WARNING) << "Pnacl check for update failed."; 336 LOG(WARNING) << "Pnacl check for update failed.";
325 } 337 }
326 } 338 }
327 339
328 // Finally, do the registration with the right version number. 340 // Finally, do the registration with the right version number.
329 void FinishPnaclUpdateRegistration(ComponentUpdateService* cus, 341 void FinishPnaclUpdateRegistration(ComponentUpdateService* cus,
330 const Version& current_version) { 342 PnaclComponentInstaller* pci) {
331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
332 // Note: the source is the default of BANDAID, even though the 344 CrxComponent pnacl_component = pci->get_component();
333 // crxes are hosted from CWS. 345 ComponentUpdateService::Status status =
334 CrxComponent pnacl; 346 cus->RegisterComponent(pnacl_component);
335 pnacl.name = "pnacl"; 347 if (status != ComponentUpdateService::kOk
336 pnacl.installer = new PnaclComponentInstaller(current_version); 348 && status != ComponentUpdateService::kReplaced) {
337 pnacl.version = current_version;
338 SetPnaclHash(&pnacl);
339 if (cus->RegisterComponent(pnacl) != ComponentUpdateService::kOk) {
340 NOTREACHED() << "Pnacl component registration failed."; 349 NOTREACHED() << "Pnacl component registration failed.";
341 } 350 }
342 351
343 // If PNaCl is not yet installed but it is requested by --enable-pnacl, 352 // If PNaCl is not yet installed but it is requested by --enable-pnacl,
344 // we want it to be available "soon", so kick off an update check 353 // we want it to be available "soon", so kick off an update check
345 // earlier than usual. 354 // earlier than usual.
346 Version null_version(kNullVersion); 355 Version null_version(kNullVersion);
347 if (current_version.Equals(null_version)) { 356 if (pci->get_current_version().Equals(null_version)) {
348 BrowserThread::PostDelayedTask( 357 BrowserThread::PostDelayedTask(
349 BrowserThread::UI, FROM_HERE, 358 BrowserThread::UI, FROM_HERE,
350 base::Bind(DoCheckForUpdate, cus, pnacl), 359 base::Bind(DoCheckForUpdate, cus, pnacl_component),
351 base::TimeDelta::FromSeconds(kInitialDelaySeconds)); 360 base::TimeDelta::FromSeconds(kInitialDelaySeconds));
352 } 361 }
353 } 362 }
354 363
355 // Check if there is an existing version on disk first to know when 364 // Check if there is an existing version on disk first to know when
356 // a hosted version is actually newer. 365 // a hosted version is actually newer.
357 void StartPnaclUpdateRegistration(ComponentUpdateService* cus) { 366 void StartPnaclUpdateRegistration(ComponentUpdateService* cus,
367 PnaclComponentInstaller* pci) {
358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 368 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
369 #if defined(OS_CHROMEOS)
370 // For ChromeOS don't start registration until the user has logged in,
371 // since the files are installed per user. See GetPnaclBaseDirectory().
372 if (!g_browser_process->profile_manager()->IsLoggedIn())
373 return;
374 #endif
359 base::FilePath path = GetPnaclBaseDirectory(); 375 base::FilePath path = GetPnaclBaseDirectory();
360 if (!file_util::PathExists(path)) { 376 if (!file_util::PathExists(path)) {
361 if (!file_util::CreateDirectory(path)) { 377 if (!file_util::CreateDirectory(path)) {
362 NOTREACHED() << "Could not create base Pnacl directory."; 378 NOTREACHED() << "Could not create base Pnacl directory.";
363 return; 379 return;
364 } 380 }
365 } 381 }
366 382
367 Version version(kNullVersion); 383 Version version(kNullVersion);
368 std::vector<base::FilePath> older_dirs; 384 std::vector<base::FilePath> older_dirs;
369 if (GetLatestPnaclDirectory(&path, &version, &older_dirs)) { 385 if (GetLatestPnaclDirectory(&path, &version, &older_dirs)) {
370 if (!PathContainsPnacl(path)) { 386 if (!PathContainsPnacl(path)) {
371 version = Version(kNullVersion); 387 version = Version(kNullVersion);
372 } else { 388 } else {
373 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); 389 PathService::Override(chrome::DIR_PNACL_COMPONENT, path);
374 } 390 }
375 } 391 }
376 392
393 pci->set_current_version(version);
394
377 BrowserThread::PostTask( 395 BrowserThread::PostTask(
378 BrowserThread::UI, FROM_HERE, 396 BrowserThread::UI, FROM_HERE,
379 base::Bind(&FinishPnaclUpdateRegistration, cus, version)); 397 base::Bind(&FinishPnaclUpdateRegistration, cus, pci));
380 398
381 // Remove older versions of PNaCl. 399 // Remove older versions of PNaCl.
382 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); 400 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
383 iter != older_dirs.end(); ++iter) { 401 iter != older_dirs.end(); ++iter) {
384 file_util::Delete(*iter, true); 402 file_util::Delete(*iter, true);
385 } 403 }
386 } 404 }
387 405
388 } // namespace 406 } // namespace
389 407
390 void RegisterPnaclComponent(ComponentUpdateService* cus, 408 void PnaclComponentInstaller::RegisterPnaclComponent(
409 ComponentUpdateService* cus,
391 const CommandLine& command_line) { 410 const CommandLine& command_line) {
392 // Only register when given the right flag. This is important since 411 // Only register when given the right flag. This is important since
393 // we do an early component updater check above (in DoCheckForUpdate). 412 // we do an early component updater check above (in DoCheckForUpdate).
394 if (command_line.HasSwitch(switches::kEnablePnacl)) { 413 if (command_line.HasSwitch(switches::kEnablePnacl)) {
414 cus_ = cus;
395 BrowserThread::PostTask( 415 BrowserThread::PostTask(
396 BrowserThread::FILE, FROM_HERE, 416 BrowserThread::FILE, FROM_HERE,
397 base::Bind(&StartPnaclUpdateRegistration, cus)); 417 base::Bind(&StartPnaclUpdateRegistration, cus_, this));
398 } 418 }
399 } 419 }
420
421 #if defined(OS_CHROMEOS)
422 void PnaclComponentInstaller::ReRegisterPnacl() {
423 // We only create the profile observer, which can trigger a
424 // call to ReRegisterPnacl, if kEnablePnacl is given on the commandline.
425 // Thus, we don't check the commandline flags again here.
426 BrowserThread::PostTask(
427 BrowserThread::FILE, FROM_HERE,
428 base::Bind(&StartPnaclUpdateRegistration, cus_, this));
429 }
430 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698