| OLD | NEW |
| 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/recovery_component_installer.h" | 5 #include "chrome/browser/component_updater/recovery_component_installer.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "components/prefs/pref_registry_simple.h" | 37 #include "components/prefs/pref_registry_simple.h" |
| 38 #include "components/prefs/pref_service.h" | 38 #include "components/prefs/pref_service.h" |
| 39 #include "components/update_client/update_client.h" | 39 #include "components/update_client/update_client.h" |
| 40 #include "components/update_client/utils.h" | 40 #include "components/update_client/utils.h" |
| 41 #include "content/public/browser/browser_thread.h" | 41 #include "content/public/browser/browser_thread.h" |
| 42 | 42 |
| 43 using content::BrowserThread; | 43 using content::BrowserThread; |
| 44 | 44 |
| 45 namespace component_updater { | 45 namespace component_updater { |
| 46 | 46 |
| 47 #if defined(GOOGLE_CHROME_BUILD) |
| 48 #if defined(OS_WIN) || defined(OS_MACOSX) |
| 49 |
| 47 namespace { | 50 namespace { |
| 48 | 51 |
| 49 // CRX hash. The extension id is: npdjjkjlcidkjlamlmmdelcjbcpdjocm. | 52 // CRX hash. The extension id is: npdjjkjlcidkjlamlmmdelcjbcpdjocm. |
| 50 const uint8_t kSha2Hash[] = {0xdf, 0x39, 0x9a, 0x9b, 0x28, 0x3a, 0x9b, 0x0c, | 53 const uint8_t kSha2Hash[] = {0xdf, 0x39, 0x9a, 0x9b, 0x28, 0x3a, 0x9b, 0x0c, |
| 51 0xbc, 0xc3, 0x4b, 0x29, 0x12, 0xf3, 0x9e, 0x2c, | 54 0xbc, 0xc3, 0x4b, 0x29, 0x12, 0xf3, 0x9e, 0x2c, |
| 52 0x19, 0x7a, 0x71, 0x4b, 0x0a, 0x7c, 0x80, 0x1c, | 55 0x19, 0x7a, 0x71, 0x4b, 0x0a, 0x7c, 0x80, 0x1c, |
| 53 0xf6, 0x29, 0x7c, 0x0a, 0x5f, 0xea, 0x67, 0xb7}; | 56 0xf6, 0x29, 0x7c, 0x0a, 0x5f, 0xea, 0x67, 0xb7}; |
| 54 | 57 |
| 55 // File name of the recovery binary on different platforms. | 58 // File name of the recovery binary on different platforms. |
| 56 const base::FilePath::CharType kRecoveryFileName[] = | 59 const base::FilePath::CharType kRecoveryFileName[] = |
| (...skipping 24 matching lines...) Expand all Loading... |
| 81 RCE_ELEVATED_SKIPPED = 8, | 84 RCE_ELEVATED_SKIPPED = 8, |
| 82 RCE_COMPONENT_DOWNLOAD_ERROR = 9, | 85 RCE_COMPONENT_DOWNLOAD_ERROR = 9, |
| 83 RCE_ELEVATED_UNKNOWN_RESULT = 10, | 86 RCE_ELEVATED_UNKNOWN_RESULT = 10, |
| 84 RCE_COUNT | 87 RCE_COUNT |
| 85 }; | 88 }; |
| 86 | 89 |
| 87 void RecordRecoveryComponentUMAEvent(RecoveryComponentEvent event) { | 90 void RecordRecoveryComponentUMAEvent(RecoveryComponentEvent event) { |
| 88 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", event, RCE_COUNT); | 91 UMA_HISTOGRAM_ENUMERATION("RecoveryComponent.Event", event, RCE_COUNT); |
| 89 } | 92 } |
| 90 | 93 |
| 91 #if !defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD) | |
| 92 // Checks if elevated recovery simulation switch was present on the command | 94 // Checks if elevated recovery simulation switch was present on the command |
| 93 // line. This is for testing purpose. | 95 // line. This is for testing purpose. |
| 94 bool SimulatingElevatedRecovery() { | 96 bool SimulatingElevatedRecovery() { |
| 95 return base::CommandLine::ForCurrentProcess()->HasSwitch( | 97 return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 96 switches::kSimulateElevatedRecovery); | 98 switches::kSimulateElevatedRecovery); |
| 97 } | 99 } |
| 98 #endif // !defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD) | |
| 99 | 100 |
| 100 std::vector<std::string> GetRecoveryInstallArguments( | 101 std::vector<std::string> GetRecoveryInstallArguments( |
| 101 const base::DictionaryValue& manifest, | 102 const base::DictionaryValue& manifest, |
| 102 bool is_deferred_run, | 103 bool is_deferred_run, |
| 103 const base::Version& version) { | 104 const base::Version& version) { |
| 104 std::vector<std::string> arguments; | 105 std::vector<std::string> arguments; |
| 105 | 106 |
| 106 // Add a flag for re-attempted install with elevated privilege so that the | 107 // Add a flag for re-attempted install with elevated privilege so that the |
| 107 // recovery executable can report back accordingly. | 108 // recovery executable can report back accordingly. |
| 108 if (is_deferred_run) | 109 if (is_deferred_run) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 130 base::CommandLine command_line(command); | 131 base::CommandLine command_line(command); |
| 131 | 132 |
| 132 const auto arguments = GetRecoveryInstallArguments( | 133 const auto arguments = GetRecoveryInstallArguments( |
| 133 manifest, is_deferred_run, version); | 134 manifest, is_deferred_run, version); |
| 134 for (const auto& arg : arguments) | 135 for (const auto& arg : arguments) |
| 135 command_line.AppendArg(arg); | 136 command_line.AppendArg(arg); |
| 136 | 137 |
| 137 return command_line; | 138 return command_line; |
| 138 } | 139 } |
| 139 | 140 |
| 140 #if defined(OS_WIN) || defined(OS_MACOSX) | |
| 141 std::unique_ptr<base::DictionaryValue> ReadManifest( | 141 std::unique_ptr<base::DictionaryValue> ReadManifest( |
| 142 const base::FilePath& manifest) { | 142 const base::FilePath& manifest) { |
| 143 JSONFileValueDeserializer deserializer(manifest); | 143 JSONFileValueDeserializer deserializer(manifest); |
| 144 std::string error; | 144 std::string error; |
| 145 return base::DictionaryValue::From(deserializer.Deserialize(NULL, &error)); | 145 return base::DictionaryValue::From(deserializer.Deserialize(NULL, &error)); |
| 146 } | 146 } |
| 147 | 147 |
| 148 void WaitForElevatedInstallToComplete(base::Process process) { | 148 void WaitForElevatedInstallToComplete(base::Process process) { |
| 149 int installer_exit_code = 0; | 149 int installer_exit_code = 0; |
| 150 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600); | 150 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 | 236 |
| 237 void ElevatedInstallRecoveryComponent(const base::FilePath& installer_path) { | 237 void ElevatedInstallRecoveryComponent(const base::FilePath& installer_path) { |
| 238 base::PostTaskWithTraits( | 238 base::PostTaskWithTraits( |
| 239 FROM_HERE, base::TaskTraits() | 239 FROM_HERE, base::TaskTraits() |
| 240 .WithShutdownBehavior( | 240 .WithShutdownBehavior( |
| 241 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) | 241 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) |
| 242 .WithPriority(base::TaskPriority::BACKGROUND) | 242 .WithPriority(base::TaskPriority::BACKGROUND) |
| 243 .MayBlock(), | 243 .MayBlock(), |
| 244 base::Bind(&DoElevatedInstallRecoveryComponent, installer_path)); | 244 base::Bind(&DoElevatedInstallRecoveryComponent, installer_path)); |
| 245 } | 245 } |
| 246 #endif // defined(OS_WIN) | |
| 247 | 246 |
| 248 } // namespace | 247 } // namespace |
| 249 | 248 |
| 250 // Component installer that is responsible to repair the chrome installation | 249 // Component installer that is responsible to repair the chrome installation |
| 251 // or repair the Google update installation. This is a last resort safety | 250 // or repair the Google update installation. This is a last resort safety |
| 252 // mechanism. | 251 // mechanism. |
| 253 // For user Chrome, recovery component just installs silently. For machine | 252 // For user Chrome, recovery component just installs silently. For machine |
| 254 // Chrome, elevation may be needed. If that happens, the installer will set | 253 // Chrome, elevation may be needed. If that happens, the installer will set |
| 255 // preference flag prefs::kRecoveryComponentNeedsElevation to request that. | 254 // preference flag prefs::kRecoveryComponentNeedsElevation to request that. |
| 256 // There is a global error service monitors this flag and will pop up | 255 // There is a global error service monitors this flag and will pop up |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 const base::Version& version, PrefService* prefs) | 324 const base::Version& version, PrefService* prefs) |
| 326 : current_version_(version), prefs_(prefs) { | 325 : current_version_(version), prefs_(prefs) { |
| 327 DCHECK(version.IsValid()); | 326 DCHECK(version.IsValid()); |
| 328 } | 327 } |
| 329 | 328 |
| 330 void RecoveryComponentInstaller::OnUpdateError(int error) { | 329 void RecoveryComponentInstaller::OnUpdateError(int error) { |
| 331 RecordRecoveryComponentUMAEvent(RCE_COMPONENT_DOWNLOAD_ERROR); | 330 RecordRecoveryComponentUMAEvent(RCE_COMPONENT_DOWNLOAD_ERROR); |
| 332 NOTREACHED() << "Recovery component update error: " << error; | 331 NOTREACHED() << "Recovery component update error: " << error; |
| 333 } | 332 } |
| 334 | 333 |
| 335 #if defined(OS_WIN) || defined(OS_MACOSX) | |
| 336 void WaitForInstallToComplete(base::Process process, | 334 void WaitForInstallToComplete(base::Process process, |
| 337 const base::FilePath& installer_folder, | 335 const base::FilePath& installer_folder, |
| 338 PrefService* prefs) { | 336 PrefService* prefs) { |
| 339 int installer_exit_code = 0; | 337 int installer_exit_code = 0; |
| 340 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600); | 338 const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600); |
| 341 if (process.WaitForExitWithTimeout(kMaxWaitTime, &installer_exit_code)) { | 339 if (process.WaitForExitWithTimeout(kMaxWaitTime, &installer_exit_code)) { |
| 342 if (installer_exit_code == EXIT_CODE_ELEVATION_NEEDED) { | 340 if (installer_exit_code == EXIT_CODE_ELEVATION_NEEDED) { |
| 343 RecordRecoveryComponentUMAEvent(RCE_ELEVATION_NEEDED); | 341 RecordRecoveryComponentUMAEvent(RCE_ELEVATION_NEEDED); |
| 344 | 342 |
| 345 BrowserThread::PostTask( | 343 BrowserThread::PostTask( |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 .WithPriority(base::TaskPriority::BACKGROUND) | 378 .WithPriority(base::TaskPriority::BACKGROUND) |
| 381 .WithBaseSyncPrimitives(), | 379 .WithBaseSyncPrimitives(), |
| 382 base::Bind(&WaitForInstallToComplete, base::Passed(&process), | 380 base::Bind(&WaitForInstallToComplete, base::Passed(&process), |
| 383 installer_folder, prefs_)); | 381 installer_folder, prefs_)); |
| 384 | 382 |
| 385 // Returns true regardless of install result since from updater service | 383 // Returns true regardless of install result since from updater service |
| 386 // perspective the install is done, even we may need to do elevated | 384 // perspective the install is done, even we may need to do elevated |
| 387 // install later. | 385 // install later. |
| 388 return true; | 386 return true; |
| 389 } | 387 } |
| 390 #else | |
| 391 bool RecoveryComponentInstaller::RunInstallCommand( | |
| 392 const base::CommandLine& cmdline, | |
| 393 const base::FilePath&) const { | |
| 394 return base::LaunchProcess(cmdline, base::LaunchOptions()).IsValid(); | |
| 395 } | |
| 396 #endif // defined(OS_WIN) | |
| 397 | 388 |
| 398 #if defined(OS_POSIX) | 389 #if defined(OS_POSIX) |
| 399 // Sets the POSIX executable permissions on a file | 390 // Sets the POSIX executable permissions on a file |
| 400 bool SetPosixExecutablePermission(const base::FilePath& path) { | 391 bool SetPosixExecutablePermission(const base::FilePath& path) { |
| 401 int permissions = 0; | 392 int permissions = 0; |
| 402 if (!base::GetPosixFilePermissions(path, &permissions)) | 393 if (!base::GetPosixFilePermissions(path, &permissions)) |
| 403 return false; | 394 return false; |
| 404 const int kExecutableMask = base::FILE_PERMISSION_EXECUTE_BY_USER | | 395 const int kExecutableMask = base::FILE_PERMISSION_EXECUTE_BY_USER | |
| 405 base::FILE_PERMISSION_EXECUTE_BY_GROUP | | 396 base::FILE_PERMISSION_EXECUTE_BY_GROUP | |
| 406 base::FILE_PERMISSION_EXECUTE_BY_OTHERS; | 397 base::FILE_PERMISSION_EXECUTE_BY_OTHERS; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 bool RecoveryComponentInstaller::GetInstalledFile( | 475 bool RecoveryComponentInstaller::GetInstalledFile( |
| 485 const std::string& file, | 476 const std::string& file, |
| 486 base::FilePath* installed_file) { | 477 base::FilePath* installed_file) { |
| 487 return false; | 478 return false; |
| 488 } | 479 } |
| 489 | 480 |
| 490 bool RecoveryComponentInstaller::Uninstall() { | 481 bool RecoveryComponentInstaller::Uninstall() { |
| 491 return false; | 482 return false; |
| 492 } | 483 } |
| 493 | 484 |
| 485 #endif // defined(OS_WIN) || defined(OS_MACOSX) |
| 486 #endif // defined(GOOGLE_CHROME_BUILD) |
| 487 |
| 494 void RegisterRecoveryComponent(ComponentUpdateService* cus, | 488 void RegisterRecoveryComponent(ComponentUpdateService* cus, |
| 495 PrefService* prefs) { | 489 PrefService* prefs) { |
| 496 #if !defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD) | 490 #if defined(GOOGLE_CHROME_BUILD) |
| 491 #if defined(OS_WIN) || defined(OS_MACOSX) |
| 497 if (SimulatingElevatedRecovery()) { | 492 if (SimulatingElevatedRecovery()) { |
| 498 BrowserThread::PostTask( | 493 BrowserThread::PostTask( |
| 499 BrowserThread::UI, | 494 BrowserThread::UI, |
| 500 FROM_HERE, | 495 FROM_HERE, |
| 501 base::Bind(&SimulateElevatedRecoveryHelper, prefs)); | 496 base::Bind(&SimulateElevatedRecoveryHelper, prefs)); |
| 502 } | 497 } |
| 503 | 498 |
| 504 // We delay execute the registration because we are not required in | 499 // We delay execute the registration because we are not required in |
| 505 // the critical path during browser startup. | 500 // the critical path during browser startup. |
| 506 BrowserThread::PostDelayedTask( | 501 BrowserThread::PostDelayedTask( |
| 507 BrowserThread::UI, | 502 BrowserThread::UI, |
| 508 FROM_HERE, | 503 FROM_HERE, |
| 509 base::Bind(&RecoveryRegisterHelper, cus, prefs), | 504 base::Bind(&RecoveryRegisterHelper, cus, prefs), |
| 510 base::TimeDelta::FromSeconds(6)); | 505 base::TimeDelta::FromSeconds(6)); |
| 511 #endif // !defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD) | 506 #endif |
| 507 #endif |
| 512 } | 508 } |
| 513 | 509 |
| 514 void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) { | 510 void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) { |
| 515 registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0"); | 511 registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0"); |
| 516 registry->RegisterFilePathPref(prefs::kRecoveryComponentUnpackPath, | 512 registry->RegisterFilePathPref(prefs::kRecoveryComponentUnpackPath, |
| 517 base::FilePath()); | 513 base::FilePath()); |
| 518 registry->RegisterBooleanPref(prefs::kRecoveryComponentNeedsElevation, false); | 514 registry->RegisterBooleanPref(prefs::kRecoveryComponentNeedsElevation, false); |
| 519 } | 515 } |
| 520 | 516 |
| 521 void AcceptedElevatedRecoveryInstall(PrefService* prefs) { | 517 void AcceptedElevatedRecoveryInstall(PrefService* prefs) { |
| 522 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 518 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 523 | 519 |
| 520 #if defined(GOOGLE_CHROME_BUILD) |
| 524 #if defined(OS_WIN) || defined(OS_MACOSX) | 521 #if defined(OS_WIN) || defined(OS_MACOSX) |
| 525 ElevatedInstallRecoveryComponent( | 522 ElevatedInstallRecoveryComponent( |
| 526 prefs->GetFilePath(prefs::kRecoveryComponentUnpackPath)); | 523 prefs->GetFilePath(prefs::kRecoveryComponentUnpackPath)); |
| 527 #endif // OS_WIN | 524 #endif |
| 525 #endif |
| 526 |
| 528 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); | 527 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); |
| 529 } | 528 } |
| 530 | 529 |
| 531 void DeclinedElevatedRecoveryInstall(PrefService* prefs) { | 530 void DeclinedElevatedRecoveryInstall(PrefService* prefs) { |
| 532 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 531 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 533 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); | 532 prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, false); |
| 534 } | 533 } |
| 535 | 534 |
| 536 } // namespace component_updater | 535 } // namespace component_updater |
| OLD | NEW |