forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Invoke the CF migration path when applying a CF multi update.
Moves MigrateChromeFrame (without changing its logic) from setup_main.cc into cf_migration.cc. Contributed by robertshield@chromium.org (originally from https://codereview.chromium.org/22632009/). BUG=265952 TEST=A multi Chrome Frame install receiving an update will change to a SxS Chrome Frame install. And will still work. Review URL: https://chromiumcodereview.appspot.com/24287006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@224600 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
grt@chromium.org
committed
Sep 21, 2013
1 parent
9a69d08
commit f86aa4f
Showing
8 changed files
with
328 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// Copyright 2013 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "chrome/installer/setup/cf_migration.h" | ||
|
||
#include "base/command_line.h" | ||
#include "base/files/file_path.h" | ||
#include "base/logging.h" | ||
#include "base/process/launch.h" | ||
#include "base/win/registry.h" | ||
#include "chrome/installer/setup/setup_constants.h" | ||
#include "chrome/installer/setup/setup_main.h" | ||
#include "chrome/installer/setup/setup_util.h" | ||
#include "chrome/installer/util/browser_distribution.h" | ||
#include "chrome/installer/util/install_util.h" | ||
#include "chrome/installer/util/installation_state.h" | ||
#include "chrome/installer/util/installer_state.h" | ||
#include "chrome/installer/util/master_preferences.h" | ||
#include "chrome/installer/util/util_constants.h" | ||
|
||
namespace installer { | ||
|
||
bool LaunchChromeFrameMigrationProcess( | ||
const ProductState& chrome_frame_product, | ||
const CommandLine& command_line, | ||
const base::FilePath& installer_directory, | ||
bool system_level) { | ||
// Before running the migration, mutate the CF ap value to include a | ||
// "-migrate" beacon. This beacon value will be cleaned up by the "ap" | ||
// cleanup in MigrateGoogleUpdateStateMultiToSingle that calls | ||
// ChannelInfo::RemoveAllModifiersAndSuffixes(). | ||
if (chrome_frame_product.is_multi_install()) { | ||
const HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | ||
base::win::RegKey state_key; | ||
installer::ChannelInfo channel_info; | ||
BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( | ||
BrowserDistribution::CHROME_FRAME); | ||
|
||
LONG result = state_key.Open(root, dist->GetStateKey().c_str(), | ||
KEY_QUERY_VALUE | KEY_SET_VALUE); | ||
if (result != ERROR_SUCCESS || !channel_info.Initialize(state_key)) { | ||
LOG(ERROR) << "Failed to read CF channel to store beacon."; | ||
} else if (!channel_info.SetMigratingSuffix(true)) { | ||
LOG(WARNING) << "CF already has migration beacon in channel."; | ||
} else { | ||
VLOG(1) << "Writing CF migration beacon to channel: " | ||
<< channel_info.value(); | ||
channel_info.Write(&state_key); | ||
} | ||
} | ||
|
||
// Call the installed setup.exe using the current installer command line and | ||
// adding the migration flags. This seems like it could be unsafe, here's why | ||
// it's safe today: | ||
// 1) MigrateChromeFrameInChildProcess is called only during a multi update. | ||
// 2) Multi update processing occurs after HandleNonInstallCmdLineOptions is | ||
// called. | ||
// 3) Setup exits if there were any non-install command line options handled. | ||
// 4) Thus, the command line being copied will have no non-install command | ||
// line options at time of copying. | ||
// 5) kMigrateChromeFrame is a non-install command line option. | ||
// 6) Thus, it will be handled (and the child setup process will exit) before | ||
// the child setup process acts on any other flags on the command line. | ||
// 7) Furthermore, --uncompressed-archive takes precedence over | ||
// --install-archive, so it is safe to add the former to the command line | ||
// without removing the latter. | ||
CommandLine setup_cmd(command_line); | ||
setup_cmd.SetProgram(installer_directory.Append(installer::kSetupExe)); | ||
setup_cmd.AppendSwitchPath( | ||
switches::kUncompressedArchive, | ||
installer_directory.Append(installer::kChromeArchive)); | ||
setup_cmd.AppendSwitch(switches::kMigrateChromeFrame); | ||
|
||
VLOG(1) << "Running Chrome Frame migration process with command line: " | ||
<< setup_cmd.GetCommandLineString(); | ||
|
||
base::LaunchOptions options; | ||
options.force_breakaway_from_job_ = true; | ||
if (!base::LaunchProcess(setup_cmd, options, NULL)) { | ||
PLOG(ERROR) << "Launching Chrome Frame migration process failed. " | ||
<< "(Command line: " << setup_cmd.GetCommandLineString() << ")"; | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
InstallStatus MigrateChromeFrame(const InstallationState& original_state, | ||
InstallerState* installer_state) { | ||
const bool system_level = installer_state->system_install(); | ||
|
||
// Nothing to do if multi-install Chrome Frame is not installed. | ||
const ProductState* multi_chrome_frame = original_state.GetProductState( | ||
system_level, BrowserDistribution::CHROME_FRAME); | ||
if (!multi_chrome_frame || !multi_chrome_frame->is_multi_install()) | ||
return INVALID_STATE_FOR_OPTION; | ||
|
||
// Install SxS Chrome Frame. | ||
InstallerState install_gcf(installer_state->level()); | ||
{ | ||
scoped_ptr<Product> chrome_frame( | ||
new Product(BrowserDistribution::GetSpecificDistribution( | ||
BrowserDistribution::CHROME_FRAME))); | ||
install_gcf.AddProduct(&chrome_frame); | ||
} | ||
DCHECK(!install_gcf.is_multi_install()); | ||
|
||
ArchiveType archive_type = UNKNOWN_ARCHIVE_TYPE; | ||
bool delegated_to_existing = false; | ||
InstallStatus install_status = InstallProductsHelper( | ||
original_state, *CommandLine::ForCurrentProcess(), | ||
MasterPreferences::ForCurrentProcess(), install_gcf, | ||
NULL, &archive_type, &delegated_to_existing); | ||
|
||
if (!InstallUtil::GetInstallReturnCode(install_status)) { | ||
// Migration was successful. There's no turning back now. The multi-install | ||
// npchrome_frame.dll and/or chrome.exe may still be in use at this point, | ||
// although the user-level helper will not be. It is not safe to delete the | ||
// multi-install binaries until npchrome_frame.dll and chrome.exe are no | ||
// longer in use. The remaining tasks here are best-effort. Failure does not | ||
// do any harm. | ||
MigrateGoogleUpdateStateMultiToSingle(system_level, | ||
BrowserDistribution::CHROME_FRAME, | ||
original_state); | ||
} | ||
|
||
return install_status; | ||
} | ||
|
||
} // namespace installer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright 2013 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef CHROME_INSTALLER_SETUP_CF_MIGRATION_H_ | ||
#define CHROME_INSTALLER_SETUP_CF_MIGRATION_H_ | ||
|
||
#include "chrome/installer/util/util_constants.h" | ||
|
||
class CommandLine; | ||
|
||
namespace base { | ||
class FilePath; | ||
} | ||
|
||
namespace installer { | ||
|
||
class InstallationState; | ||
class InstallerState; | ||
class ProductState; | ||
|
||
// Invokes a child helper instance of the setup.exe in |installer_directory| to | ||
// run MigrateChromeFrame (see comments below) using the archive in | ||
// |installer_directory| for the given installation level. Returns true if the | ||
// process is launched. | ||
bool LaunchChromeFrameMigrationProcess( | ||
const ProductState& chrome_frame_product, | ||
const CommandLine& command_line, | ||
const base::FilePath& installer_directory, | ||
bool system_level); | ||
|
||
// Migrates multi-install Chrome Frame to single-install at the current | ||
// level. Does not remove the multi-install binaries if no other products are | ||
// using them. --uncompressed-archive=chrome.7z is expected to be given on the | ||
// command line to point this setup.exe at the (possibly patched) archive from | ||
// the calling instance. | ||
// Note about process model: this is called in a child setup.exe that is | ||
// invoked from the setup.exe instance run as part of an update to a | ||
// multi-install Chrome Frame. | ||
InstallStatus MigrateChromeFrame(const InstallationState& original_state, | ||
InstallerState* installer_state); | ||
|
||
} // namespace installer | ||
|
||
#endif // CHROME_INSTALLER_SETUP_CF_MIGRATION_H_ |
Oops, something went wrong.