Skip to content

Commit

Permalink
Invoke the CF migration path when applying a CF multi update.
Browse files Browse the repository at this point in the history
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
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 112 deletions.
2 changes: 2 additions & 0 deletions chrome/chrome_installer.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@
'installer/mini_installer/chrome.release',
'installer/setup/archive_patch_helper.cc',
'installer/setup/archive_patch_helper.h',
'installer/setup/cf_migration.cc',
'installer/setup/cf_migration.h',
'installer/setup/chrome_frame_quick_enable.cc',
'installer/setup/chrome_frame_quick_enable.h',
'installer/setup/chrome_frame_ready_mode.cc',
Expand Down
131 changes: 131 additions & 0 deletions chrome/installer/setup/cf_migration.cc
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
45 changes: 45 additions & 0 deletions chrome/installer/setup/cf_migration.h
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_
Loading

0 comments on commit f86aa4f

Please sign in to comment.