Prototype fix for version shear across updates.

BUG=371087

Review URL: https://codereview.chromium.org/274453010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271076 0039d316-1c4b-4281-b951-d872f2087c98
parent 0738c574
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chrome/browser/first_run/upgrade_util.h" #include "chrome/browser/first_run/upgrade_util.h"
#include <windows.h> #include <windows.h>
#include <psapi.h>
#include <shellapi.h> #include <shellapi.h>
#include <algorithm> #include <algorithm>
...@@ -123,26 +124,31 @@ bool RelaunchChromeHelper(const CommandLine& command_line, ...@@ -123,26 +124,31 @@ bool RelaunchChromeHelper(const CommandLine& command_line,
else else
version_str.clear(); version_str.clear();
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return base::LaunchProcess(command_line, base::LaunchOptions(), NULL);
// On Windows 8 we always use the delegate_execute for re-launching chrome.
//
// Pass this Chrome's Start Menu shortcut path to the relauncher so it can
// re-activate chrome via ShellExecute.
base::FilePath chrome_exe; base::FilePath chrome_exe;
if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
NOTREACHED(); NOTREACHED();
return false; return false;
} }
// We need to use ShellExecute to launch the relauncher, which will wait until // Explicitly make sure to relaunch chrome.exe rather than old_chrome.exe.
// we exit. But ShellExecute does not support handle passing to the child // This can happen when old_chrome.exe is launched by a user.
// process so we create a uniquely named mutex that we aquire and never CommandLine chrome_exe_command_line = command_line;
// release. So when we exit, Windows marks our mutex as abandoned and the chrome_exe_command_line.SetProgram(
// wait is satisfied. chrome_exe.DirName().Append(installer::kChromeExe));
// The format of the named mutex is important. See DelegateExecuteOperation
// for more details. if (base::win::GetVersion() < base::win::VERSION_WIN8)
return base::LaunchProcess(chrome_exe_command_line,
base::LaunchOptions(), NULL);
// On Windows 8 we always use the delegate_execute for re-launching chrome.
//
// Pass this Chrome's Start Menu shortcut path to the relauncher so it can re-
// activate chrome via ShellExecute which will wait until we exit. Since
// ShellExecute does not support handle passing to the child process we create
// a uniquely named mutex that we aquire and never release. So when we exit,
// Windows marks our mutex as abandoned and the wait is satisfied. The format
// of the named mutex is important. See DelegateExecuteOperation for more
// details.
base::string16 mutex_name = base::string16 mutex_name =
base::StringPrintf(L"chrome.relaunch.%d", ::GetCurrentProcessId()); base::StringPrintf(L"chrome.relaunch.%d", ::GetCurrentProcessId());
HANDLE mutex = ::CreateMutexW(NULL, TRUE, mutex_name.c_str()); HANDLE mutex = ::CreateMutexW(NULL, TRUE, mutex_name.c_str());
...@@ -246,13 +252,32 @@ bool SwapNewChromeExeIfPresent() { ...@@ -246,13 +252,32 @@ bool SwapNewChromeExeIfPresent() {
return InvokeGoogleUpdateForRename(); return InvokeGoogleUpdateForRename();
} }
bool IsRunningOldChrome() {
// This figures out the actual file name that the section containing the
// mapped exe refers to. This is used instead of GetModuleFileName because the
// .exe may have been renamed out from under us while we've been running which
// GetModuleFileName won't notice.
wchar_t mapped_file_name[MAX_PATH * 2] = {};
if (!::GetMappedFileName(::GetCurrentProcess(),
reinterpret_cast<void*>(::GetModuleHandle(NULL)),
mapped_file_name,
arraysize(mapped_file_name))) {
return false;
}
base::FilePath file_name(base::FilePath(mapped_file_name).BaseName());
return base::FilePath::CompareEqualIgnoreCase(file_name.value(),
installer::kChromeOldExe);
}
bool DoUpgradeTasks(const CommandLine& command_line) { bool DoUpgradeTasks(const CommandLine& command_line) {
// The DelegateExecute verb handler finalizes pending in-use updates for // The DelegateExecute verb handler finalizes pending in-use updates for
// metro mode launches, as Chrome cannot be gracefully relaunched when // metro mode launches, as Chrome cannot be gracefully relaunched when
// running in this mode. // running in this mode.
if (base::win::IsMetroProcess()) if (base::win::IsMetroProcess())
return false; return false;
if (!SwapNewChromeExeIfPresent()) if (!SwapNewChromeExeIfPresent() && !IsRunningOldChrome())
return false; return false;
// At this point the chrome.exe has been swapped with the new one. // At this point the chrome.exe has been swapped with the new one.
if (!RelaunchChromeBrowser(command_line)) { if (!RelaunchChromeBrowser(command_line)) {
......
...@@ -16,6 +16,13 @@ namespace upgrade_util { ...@@ -16,6 +16,13 @@ namespace upgrade_util {
// is no new_chrome.exe or the swap fails the return is false; // is no new_chrome.exe or the swap fails the return is false;
bool SwapNewChromeExeIfPresent(); bool SwapNewChromeExeIfPresent();
// Returns true if the currently running chrome.exe has been renamed to
// old_chrome.exe. This means that the running executable is out of date and
// has been renamed by the in-use update process. old_chrome.exe shouldn't
// continue on and run as the browser process since it may end up launching
// newer chrome.exes as child processes resulting in a version mismatch.
bool IsRunningOldChrome();
// Combines the two methods, RelaunchChromeBrowser and // Combines the two methods, RelaunchChromeBrowser and
// SwapNewChromeExeIfPresent, to perform the rename and relaunch of // SwapNewChromeExeIfPresent, to perform the rename and relaunch of
// the browser. Note that relaunch does NOT exit the existing browser process. // the browser. Note that relaunch does NOT exit the existing browser process.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment