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

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: cleanup Created 7 years, 9 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().AppendASCII(
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 // Fill in most of the information. The version will be discovered later.
234 Version null_version(kNullVersion);
235 pnacl_component_.version = null_version;
236 pnacl_component_.name = "pnacl";
237 pnacl_component_.installer = this;
238 SetPnaclHash(&pnacl_component_);
216 239
217 virtual ~PnaclComponentInstaller() {} 240 #if defined(OS_CHROMEOS)
241 per_user_ = true;
242 profile_observer_.reset(new PnaclProfileObserver(this));
243 #endif
244 }
218 245
219 virtual void OnUpdateError(int error) OVERRIDE; 246 PnaclComponentInstaller::~PnaclComponentInstaller() {
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 } 247 }
232 248
233 void PnaclComponentInstaller::OnUpdateError(int error) { 249 void PnaclComponentInstaller::OnUpdateError(int error) {
234 NOTREACHED() << "Pnacl update error: " << error; 250 NOTREACHED() << "Pnacl update error: " << error;
235 } 251 }
236 252
237 namespace { 253 namespace {
238 254
239 bool PathContainsPnacl(const base::FilePath& base_path) { 255 bool PathContainsPnacl(const base::FilePath& base_path) {
240 // Check that at least one of the compiler files exists, for the current ISA. 256 // Check that at least one of the compiler files exists, for the current ISA.
(...skipping 17 matching lines...) Expand all
258 274
259 Version version; 275 Version version;
260 if (!CheckPnaclComponentManifest(manifest, 276 if (!CheckPnaclComponentManifest(manifest,
261 pnacl_manifest.get(), 277 pnacl_manifest.get(),
262 &version)) { 278 &version)) {
263 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; 279 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing.";
264 return false; 280 return false;
265 } 281 }
266 282
267 // Don't install if the current version is actually newer. 283 // Don't install if the current version is actually newer.
268 if (current_version_.CompareTo(version) > 0) 284 if (current_version().CompareTo(version) > 0)
269 return false; 285 return false;
270 286
271 if (!PathContainsPnacl(unpack_path)) { 287 if (!PathContainsPnacl(unpack_path)) {
272 LOG(WARNING) << "PathContainsPnacl check failed, not installing."; 288 LOG(WARNING) << "PathContainsPnacl check failed, not installing.";
273 return false; 289 return false;
274 } 290 }
275 291
276 // Passed the basic tests. Time to install it. 292 // Passed the basic tests. Time to install it.
277 base::FilePath path = 293 base::FilePath path =
278 GetPnaclBaseDirectory().AppendASCII(version.GetString()); 294 GetPnaclBaseDirectory(per_user()).AppendASCII(version.GetString());
279 if (file_util::PathExists(path)) { 295 if (file_util::PathExists(path)) {
280 LOG(WARNING) << "Target path already exists, not installing."; 296 LOG(WARNING) << "Target path already exists, not installing.";
281 return false; 297 return false;
282 } 298 }
283 if (!file_util::Move(unpack_path, path)) { 299 if (!file_util::Move(unpack_path, path)) {
284 LOG(WARNING) << "Move failed, not installing."; 300 LOG(WARNING) << "Move failed, not installing.";
285 return false; 301 return false;
286 } 302 }
287 303
288 // Installation is done. Now tell the rest of chrome (just the path service 304 // 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 305 // 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 306 // Pnacl webpage and Pnacl was just installed at this time. They should
291 // then be able to reload the page and retry (or something). 307 // then be able to reload the page and retry (or something).
292 // See: http://code.google.com/p/chromium/issues/detail?id=107438 308 // See: http://code.google.com/p/chromium/issues/detail?id=107438
293 current_version_ = version; 309 set_current_version(version);
294 310
295 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); 311 PathService::Override(chrome::DIR_PNACL_COMPONENT, path);
296 return true; 312 return true;
297 } 313 }
298 314
299 namespace { 315 namespace {
300 316
301 void DoCheckForUpdate(ComponentUpdateService* cus, 317 void DoCheckForUpdate(ComponentUpdateService* cus,
302 const CrxComponent& pnacl) { 318 const CrxComponent& pnacl) {
303 if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) { 319 if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) {
304 LOG(WARNING) << "Pnacl check for update failed."; 320 LOG(WARNING) << "Pnacl check for update failed.";
305 } 321 }
306 } 322 }
307 323
308 // Finally, do the registration with the right version number. 324 // Finally, do the registration with the right version number.
309 void FinishPnaclUpdateRegistration(ComponentUpdateService* cus, 325 void FinishPnaclUpdateRegistration(ComponentUpdateService* cus,
310 const Version& current_version) { 326 PnaclComponentInstaller* pci) {
311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
312 // Note: the source is the default of BANDAID, even though the 328 CrxComponent pnacl_component = pci->component();
313 // crxes are hosted from CWS. 329 ComponentUpdateService::Status status =
314 CrxComponent pnacl; 330 cus->RegisterComponent(pnacl_component);
315 pnacl.name = "pnacl"; 331 if (status != ComponentUpdateService::kOk
316 pnacl.installer = new PnaclComponentInstaller(current_version); 332 && status != ComponentUpdateService::kReplaced) {
317 pnacl.version = current_version;
318 SetPnaclHash(&pnacl);
319 if (cus->RegisterComponent(pnacl) != ComponentUpdateService::kOk) {
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
375 pci->set_current_version(version);
376
357 BrowserThread::PostTask( 377 BrowserThread::PostTask(
358 BrowserThread::UI, FROM_HERE, 378 BrowserThread::UI, FROM_HERE,
359 base::Bind(&FinishPnaclUpdateRegistration, cus, version)); 379 base::Bind(&FinishPnaclUpdateRegistration, cus, pci));
360 380
361 // Remove older versions of PNaCl. 381 // Remove older versions of PNaCl.
362 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); 382 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
363 iter != older_dirs.end(); ++iter) { 383 iter != older_dirs.end(); ++iter) {
364 file_util::Delete(*iter, true); 384 file_util::Delete(*iter, true);
365 } 385 }
366 } 386 }
367 387
368 } // namespace 388 } // namespace
369 389
370 void RegisterPnaclComponent(ComponentUpdateService* cus, 390 void PnaclComponentInstaller::RegisterPnaclComponent(
391 ComponentUpdateService* cus,
371 const CommandLine& command_line) { 392 const CommandLine& command_line) {
372 // Only register when given the right flag. This is important since 393 // Only register when given the right flag. This is important since
373 // we do an early component updater check above (in DoCheckForUpdate). 394 // we do an early component updater check above (in DoCheckForUpdate).
374 if (command_line.HasSwitch(switches::kEnablePnacl)) { 395 if (command_line.HasSwitch(switches::kEnablePnacl)) {
396 cus_ = cus;
375 BrowserThread::PostTask( 397 BrowserThread::PostTask(
376 BrowserThread::FILE, FROM_HERE, 398 BrowserThread::FILE, FROM_HERE,
377 base::Bind(&StartPnaclUpdateRegistration, cus)); 399 base::Bind(&StartPnaclUpdateRegistration, cus_, this));
378 } 400 }
379 } 401 }
402
403 void PnaclComponentInstaller::ReRegisterPnacl() {
404 // We only create the profile observer, which can trigger a
405 // call to ReRegisterPnacl, if kEnablePnacl is given on the commandline.
406 // Thus, we don't check the commandline flags again here.
407 BrowserThread::PostTask(
408 BrowserThread::FILE, FROM_HERE,
409 base::Bind(&StartPnaclUpdateRegistration, cus_, this));
410 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698