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

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: review 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 "chrome/common/omaha_query_params.h" 27 #include "chrome/common/omaha_query_params.h"
25 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
26 29
27 using chrome::OmahaQueryParams; 30 using chrome::OmahaQueryParams;
28 using content::BrowserThread; 31 using content::BrowserThread;
29 32
30 namespace { 33 namespace {
31 34
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 } 116 }
114 117
115 118
116 // If we don't have Pnacl installed, this is the version we claim. 119 // If we don't have Pnacl installed, this is the version we claim.
117 const char kNullVersion[] = "0.0.0.0"; 120 const char kNullVersion[] = "0.0.0.0";
118 121
119 // Pnacl components have the version encoded in the path itself: 122 // Pnacl components have the version encoded in the path itself:
120 // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\0.1.2.3\. 123 // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\0.1.2.3\.
121 // and the base directory will be: 124 // and the base directory will be:
122 // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\. 125 // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\.
123 base::FilePath GetPnaclBaseDirectory() { 126 base::FilePath GetPnaclBaseDirectory(bool per_user) {
124 base::FilePath result; 127 // For ChromeOS, temporarily make this user-dependent (for integrity) until
125 CHECK(PathService::Get(chrome::DIR_PNACL_BASE, &result)); 128 // we find a better solution.
126 return result; 129 // This is not ideal because of the following:
130 // (a) We end up with per-user copies instead of a single copy
131 // (b) The profile can change as users log in to different accounts
132 // so we need to watch for user-login-events (see pnacl_profile_observer.h).
133 if (per_user) {
134 Profile* profile = ProfileManager::GetLastUsedProfile();
135 base::FilePath path = profile->GetPath().Append(
136 FILE_PATH_LITERAL("pnacl"));
137 return path;
138 } else {
139 base::FilePath result;
140 CHECK(PathService::Get(chrome::DIR_PNACL_BASE, &result));
141 return result;
142 }
127 } 143 }
128 144
129 bool GetLatestPnaclDirectory(base::FilePath* latest_dir, 145 bool GetLatestPnaclDirectory(bool per_user,
146 base::FilePath* latest_dir,
130 Version* latest_version, 147 Version* latest_version,
131 std::vector<base::FilePath>* older_dirs) { 148 std::vector<base::FilePath>* older_dirs) {
132 // Enumerate all versions starting from the base directory. 149 // Enumerate all versions starting from the base directory.
133 base::FilePath base_dir = GetPnaclBaseDirectory(); 150 base::FilePath base_dir = GetPnaclBaseDirectory(per_user);
134 bool found = false; 151 bool found = false;
135 file_util::FileEnumerator 152 file_util::FileEnumerator
136 file_enumerator(base_dir, false, file_util::FileEnumerator::DIRECTORIES); 153 file_enumerator(base_dir, false, file_util::FileEnumerator::DIRECTORIES);
137 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); 154 for (base::FilePath path = file_enumerator.Next(); !path.value().empty();
138 path = file_enumerator.Next()) { 155 path = file_enumerator.Next()) {
139 Version version(path.BaseName().MaybeAsASCII()); 156 Version version(path.BaseName().MaybeAsASCII());
140 if (!version.IsValid()) 157 if (!version.IsValid())
141 continue; 158 continue;
142 if (found) { 159 if (found) {
143 if (version.CompareTo(*latest_version) > 0) { 160 if (version.CompareTo(*latest_version) > 0) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 if (arch.compare(OmahaQueryParams::getNaclArch()) != 0) { 220 if (arch.compare(OmahaQueryParams::getNaclArch()) != 0) {
204 LOG(WARNING) << "'pnacl-arch' field in manifest is invalid (" 221 LOG(WARNING) << "'pnacl-arch' field in manifest is invalid ("
205 << arch << " vs " << OmahaQueryParams::getNaclArch() << ")"; 222 << arch << " vs " << OmahaQueryParams::getNaclArch() << ")";
206 return false; 223 return false;
207 } 224 }
208 225
209 *version_out = version; 226 *version_out = version;
210 return true; 227 return true;
211 } 228 }
212 229
213 class PnaclComponentInstaller : public ComponentInstaller { 230 PnaclComponentInstaller::PnaclComponentInstaller()
214 public: 231 : per_user_(false),
215 explicit PnaclComponentInstaller(const Version& version); 232 cus_(NULL) {
233 #if defined(OS_CHROMEOS)
234 per_user_ = true;
235 profile_observer_.reset(new PnaclProfileObserver(this));
236 #endif
237 }
216 238
217 virtual ~PnaclComponentInstaller() {} 239 PnaclComponentInstaller::~PnaclComponentInstaller() {
218
219 virtual void OnUpdateError(int error) OVERRIDE;
220
221 virtual bool Install(base::DictionaryValue* manifest,
222 const base::FilePath& unpack_path) OVERRIDE;
223
224 private:
225 Version current_version_;
226 };
227
228 PnaclComponentInstaller::PnaclComponentInstaller(
229 const Version& version) : current_version_(version) {
230 DCHECK(version.IsValid());
231 } 240 }
232 241
233 void PnaclComponentInstaller::OnUpdateError(int error) { 242 void PnaclComponentInstaller::OnUpdateError(int error) {
234 NOTREACHED() << "Pnacl update error: " << error; 243 NOTREACHED() << "Pnacl update error: " << error;
235 } 244 }
236 245
237 namespace { 246 namespace {
238 247
239 bool PathContainsPnacl(const base::FilePath& base_path) { 248 bool PathContainsPnacl(const base::FilePath& base_path) {
240 // Check that at least one of the compiler files exists, for the current ISA. 249 // Check that at least one of the compiler files exists, for the current ISA.
(...skipping 17 matching lines...) Expand all
258 267
259 Version version; 268 Version version;
260 if (!CheckPnaclComponentManifest(manifest, 269 if (!CheckPnaclComponentManifest(manifest,
261 pnacl_manifest.get(), 270 pnacl_manifest.get(),
262 &version)) { 271 &version)) {
263 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; 272 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing.";
264 return false; 273 return false;
265 } 274 }
266 275
267 // Don't install if the current version is actually newer. 276 // Don't install if the current version is actually newer.
268 if (current_version_.CompareTo(version) > 0) 277 if (current_version().CompareTo(version) > 0)
269 return false; 278 return false;
270 279
271 if (!PathContainsPnacl(unpack_path)) { 280 if (!PathContainsPnacl(unpack_path)) {
272 LOG(WARNING) << "PathContainsPnacl check failed, not installing."; 281 LOG(WARNING) << "PathContainsPnacl check failed, not installing.";
273 return false; 282 return false;
274 } 283 }
275 284
276 // Passed the basic tests. Time to install it. 285 // Passed the basic tests. Time to install it.
277 base::FilePath path = 286 base::FilePath path =
278 GetPnaclBaseDirectory().AppendASCII(version.GetString()); 287 GetPnaclBaseDirectory(per_user()).AppendASCII(version.GetString());
279 if (file_util::PathExists(path)) { 288 if (file_util::PathExists(path)) {
280 LOG(WARNING) << "Target path already exists, not installing."; 289 LOG(WARNING) << "Target path already exists, not installing.";
281 return false; 290 return false;
282 } 291 }
283 if (!file_util::Move(unpack_path, path)) { 292 if (!file_util::Move(unpack_path, path)) {
284 LOG(WARNING) << "Move failed, not installing."; 293 LOG(WARNING) << "Move failed, not installing.";
285 return false; 294 return false;
286 } 295 }
287 296
288 // Installation is done. Now tell the rest of chrome (just the path service 297 // Installation is done. Now tell the rest of chrome (just the path service
289 // for now). TODO(jvoung): we need notifications if someone surfed to a 298 // for now). TODO(jvoung): we need notifications if someone surfed to a
290 // Pnacl webpage and Pnacl was just installed at this time. They should 299 // Pnacl webpage and Pnacl was just installed at this time. They should
291 // then be able to reload the page and retry (or something). 300 // then be able to reload the page and retry (or something).
292 // See: http://code.google.com/p/chromium/issues/detail?id=107438 301 // See: http://code.google.com/p/chromium/issues/detail?id=107438
293 current_version_ = version; 302 set_current_version(version);
294 303
295 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); 304 PathService::Override(chrome::DIR_PNACL_COMPONENT, path);
296 return true; 305 return true;
297 } 306 }
298 307
299 namespace { 308 namespace {
300 309
301 void DoCheckForUpdate(ComponentUpdateService* cus, 310 void DoCheckForUpdate(ComponentUpdateService* cus,
302 const CrxComponent& pnacl) { 311 const CrxComponent& pnacl) {
303 if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) { 312 if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) {
304 LOG(WARNING) << "Pnacl check for update failed."; 313 LOG(WARNING) << "Pnacl check for update failed.";
305 } 314 }
306 } 315 }
307 316
308 // Finally, do the registration with the right version number. 317 // Finally, do the registration with the right version number.
309 void FinishPnaclUpdateRegistration(ComponentUpdateService* cus, 318 void FinishPnaclUpdateRegistration(ComponentUpdateService* cus,
310 const Version& current_version) { 319 const Version& current_version,
320 PnaclComponentInstaller* pci) {
311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
312 // Note: the source is the default of BANDAID, even though the 322 CrxComponent pnacl_component;
313 // crxes are hosted from CWS. 323 pnacl_component.version = current_version;
314 CrxComponent pnacl; 324 pnacl_component.name = "pnacl";
315 pnacl.name = "pnacl"; 325 pnacl_component.installer = pci;
316 pnacl.installer = new PnaclComponentInstaller(current_version); 326 pci->set_current_version(current_version);
317 pnacl.version = current_version; 327 SetPnaclHash(&pnacl_component);
318 SetPnaclHash(&pnacl); 328
319 if (cus->RegisterComponent(pnacl) != ComponentUpdateService::kOk) { 329 ComponentUpdateService::Status status =
330 cus->RegisterComponent(pnacl_component);
331 if (status != ComponentUpdateService::kOk
332 && status != ComponentUpdateService::kReplaced) {
320 NOTREACHED() << "Pnacl component registration failed."; 333 NOTREACHED() << "Pnacl component registration failed.";
321 } 334 }
322 335
323 // If PNaCl is not yet installed but it is requested by --enable-pnacl, 336 // If PNaCl is not yet installed but it is requested by --enable-pnacl,
324 // we want it to be available "soon", so kick off an update check 337 // we want it to be available "soon", so kick off an update check
325 // earlier than usual. 338 // earlier than usual.
326 Version null_version(kNullVersion); 339 Version null_version(kNullVersion);
327 if (current_version.Equals(null_version)) { 340 if (pci->current_version().Equals(null_version)) {
328 BrowserThread::PostDelayedTask( 341 BrowserThread::PostDelayedTask(
329 BrowserThread::UI, FROM_HERE, 342 BrowserThread::UI, FROM_HERE,
330 base::Bind(DoCheckForUpdate, cus, pnacl), 343 base::Bind(DoCheckForUpdate, cus, pnacl_component),
331 base::TimeDelta::FromSeconds(kInitialDelaySeconds)); 344 base::TimeDelta::FromSeconds(kInitialDelaySeconds));
332 } 345 }
333 } 346 }
334 347
335 // Check if there is an existing version on disk first to know when 348 // Check if there is an existing version on disk first to know when
336 // a hosted version is actually newer. 349 // a hosted version is actually newer.
337 void StartPnaclUpdateRegistration(ComponentUpdateService* cus) { 350 void StartPnaclUpdateRegistration(ComponentUpdateService* cus,
351 PnaclComponentInstaller* pci) {
338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
339 base::FilePath path = GetPnaclBaseDirectory(); 353 // If installation is per-user, do not start until logged in.
354 bool per_user = pci->per_user();
355 if (per_user && !g_browser_process->profile_manager()->IsLoggedIn())
356 return;
357 base::FilePath path = GetPnaclBaseDirectory(per_user);
340 if (!file_util::PathExists(path)) { 358 if (!file_util::PathExists(path)) {
341 if (!file_util::CreateDirectory(path)) { 359 if (!file_util::CreateDirectory(path)) {
342 NOTREACHED() << "Could not create base Pnacl directory."; 360 NOTREACHED() << "Could not create base Pnacl directory.";
343 return; 361 return;
344 } 362 }
345 } 363 }
346 364
347 Version version(kNullVersion); 365 Version version(kNullVersion);
348 std::vector<base::FilePath> older_dirs; 366 std::vector<base::FilePath> older_dirs;
349 if (GetLatestPnaclDirectory(&path, &version, &older_dirs)) { 367 if (GetLatestPnaclDirectory(per_user, &path, &version, &older_dirs)) {
350 if (!PathContainsPnacl(path)) { 368 if (!PathContainsPnacl(path)) {
351 version = Version(kNullVersion); 369 version = Version(kNullVersion);
352 } else { 370 } else {
353 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); 371 PathService::Override(chrome::DIR_PNACL_COMPONENT, path);
354 } 372 }
355 } 373 }
356 374
357 BrowserThread::PostTask( 375 BrowserThread::PostTask(
358 BrowserThread::UI, FROM_HERE, 376 BrowserThread::UI, FROM_HERE,
359 base::Bind(&FinishPnaclUpdateRegistration, cus, version)); 377 base::Bind(&FinishPnaclUpdateRegistration, cus, version, pci));
360 378
361 // Remove older versions of PNaCl. 379 // Remove older versions of PNaCl.
362 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); 380 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
363 iter != older_dirs.end(); ++iter) { 381 iter != older_dirs.end(); ++iter) {
364 file_util::Delete(*iter, true); 382 file_util::Delete(*iter, true);
365 } 383 }
366 } 384 }
367 385
368 } // namespace 386 } // namespace
369 387
370 void RegisterPnaclComponent(ComponentUpdateService* cus, 388 void PnaclComponentInstaller::RegisterPnaclComponent(
389 ComponentUpdateService* cus,
371 const CommandLine& command_line) { 390 const CommandLine& command_line) {
372 // Only register when given the right flag. This is important since 391 // Only register when given the right flag. This is important since
373 // we do an early component updater check above (in DoCheckForUpdate). 392 // we do an early component updater check above (in DoCheckForUpdate).
374 if (command_line.HasSwitch(switches::kEnablePnacl)) { 393 if (command_line.HasSwitch(switches::kEnablePnacl)) {
394 cus_ = cus;
375 BrowserThread::PostTask( 395 BrowserThread::PostTask(
376 BrowserThread::FILE, FROM_HERE, 396 BrowserThread::FILE, FROM_HERE,
377 base::Bind(&StartPnaclUpdateRegistration, cus)); 397 base::Bind(&StartPnaclUpdateRegistration, cus_, this));
378 } 398 }
379 } 399 }
400
401 void PnaclComponentInstaller::ReRegisterPnacl() {
402 // We only create the profile observer, which can trigger a
403 // call to ReRegisterPnacl, if kEnablePnacl is given on the commandline.
404 // Thus, we don't check the commandline flags again here.
405 BrowserThread::PostTask(
406 BrowserThread::FILE, FROM_HERE,
407 base::Bind(&StartPnaclUpdateRegistration, cus_, this));
408 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698