diff options
author | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-27 16:44:31 +0000 |
---|---|---|
committer | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-27 16:44:31 +0000 |
commit | 6a7748e79cb7118089d5857291cb76d57c5c8162 (patch) | |
tree | bdfe13aba5f79d4c090bd27fdf75173ff751bb3c /chrome_frame/chrome_frame_helper_main.cc | |
parent | 13ffa32ea65d5fda56bcb030643b989d5564c586 (diff) | |
download | chromium_src-6a7748e79cb7118089d5857291cb76d57c5c8162.zip chromium_src-6a7748e79cb7118089d5857291cb76d57c5c8162.tar.gz chromium_src-6a7748e79cb7118089d5857291cb76d57c5c8162.tar.bz2 |
Add a self-destruct mechanism to user-level Chrome Frame when it detects that system-level Chrome Frame is present. This is a first step to handling user-to-system-level handoff.
It will cause a user-level install to be correctly replaced with a system-level one once the user logs out and back in again. Additional changelists
will follow that:
1) Ensure full clean-up of the user-level installation.
2) Handle notifications such that logging out and in again isn't required.
BUG=82816
TEST=Install user-level Chrome Frame.
Review URL: http://codereview.chromium.org/7065024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87033 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/chrome_frame_helper_main.cc')
-rw-r--r-- | chrome_frame/chrome_frame_helper_main.cc | 113 |
1 files changed, 110 insertions, 3 deletions
diff --git a/chrome_frame/chrome_frame_helper_main.cc b/chrome_frame/chrome_frame_helper_main.cc index 2f36916..6408ecd 100644 --- a/chrome_frame/chrome_frame_helper_main.cc +++ b/chrome_frame/chrome_frame_helper_main.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. // @@ -13,9 +13,15 @@ // #include <crtdbg.h> +#include <objbase.h> +#include <stdlib.h> #include <windows.h> +#include "chrome_frame/chrome_frame_helper_util.h" #include "chrome_frame/crash_server_init.h" +#include "chrome_frame/registry_watcher.h" + +namespace { // Window class and window names. const wchar_t kChromeFrameHelperWindowClassName[] = @@ -23,6 +29,24 @@ const wchar_t kChromeFrameHelperWindowClassName[] = const wchar_t kChromeFrameHelperWindowName[] = L"ChromeFrameHelperWindowName"; +const wchar_t kChromeFrameClientStateKey[] = + L"Software\\Google\\Update\\ClientState\\" + L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}"; +const wchar_t kChromeFrameUninstallCmdExeValue[] = L"UninstallString"; +const wchar_t kChromeFrameUninstallCmdArgsValue[] = L"UninstallArguments"; + +const wchar_t kBHORegistrationPath[] = + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer" + L"\\Browser Helper Objects"; + +const wchar_t kStartupArg[] = L"--startup"; +const wchar_t kForceUninstall[] = L"--force-uninstall"; + +HWND g_hwnd = NULL; +const UINT kRegistryWatcherChangeMessage = WM_USER + 42; + +} // namespace + // Small helper class that assists in loading the DLL that contains code // to register our event hook callback. Automatically removes the hook and // unloads the DLL on destruction. @@ -108,6 +132,8 @@ LRESULT CALLBACK ChromeFrameHelperWndProc(HWND hwnd, case WM_CREATE: CloseAllHelperWindowsApartFrom(hwnd); break; + case kRegistryWatcherChangeMessage: + // A system level Chrome appeared. Fall through: case WM_DESTROY: PostQuitMessage(0); break; @@ -133,21 +159,102 @@ HWND RegisterAndCreateWindow(HINSTANCE hinstance) { return hwnd; } + +// This method runs the user-level Chrome Frame uninstall command. This is +// intended to allow it to delegate to an existing system-level install. +bool UninstallUserLevelChromeFrame() { + bool success = false; + HKEY reg_handle = NULL; + wchar_t reg_path_buffer[MAX_PATH] = {0}; + LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, + kChromeFrameClientStateKey, + 0, + KEY_QUERY_VALUE, + ®_handle); + if (result == ERROR_SUCCESS) { + wchar_t exe_buffer[MAX_PATH] = {0}; + wchar_t args_buffer[MAX_PATH] = {0}; + LONG exe_result = ReadValue(reg_handle, + kChromeFrameUninstallCmdExeValue, + MAX_PATH, + exe_buffer); + LONG args_result = ReadValue(reg_handle, + kChromeFrameUninstallCmdArgsValue, + MAX_PATH, + args_buffer); + RegCloseKey(reg_handle); + reg_handle = NULL; + + if (exe_result == ERROR_SUCCESS && args_result == ERROR_SUCCESS) { + STARTUPINFO startup_info = {0}; + startup_info.cb = sizeof(startup_info); + startup_info.dwFlags = STARTF_USESHOWWINDOW; + startup_info.wShowWindow = SW_SHOW; + PROCESS_INFORMATION process_info = {0}; + + // Quote the command string in the args. + wchar_t argument_string[MAX_PATH * 3] = {0}; + int arg_len = _snwprintf(argument_string, + _countof(argument_string) - 1, + L"\"%s\" %s %s", + exe_buffer, + args_buffer, + kForceUninstall); + + if (arg_len > 0 && CreateProcess(exe_buffer, argument_string, + NULL, NULL, FALSE, 0, NULL, NULL, + &startup_info, &process_info)) { + // Close handles. + CloseHandle(process_info.hThread); + CloseHandle(process_info.hProcess); + success = true; + } + } + } + + return success; +} + +void WaitCallback() { + // Check if the Chrome Frame BHO is now in the list of registered BHOs: + if (IsBHOLoadingPolicyRegistered()) { + PostMessage(g_hwnd, kRegistryWatcherChangeMessage, 0, 0); + } +} + int APIENTRY wWinMain(HINSTANCE hinstance, HINSTANCE, wchar_t*, int show_cmd) { const wchar_t* cmd_line = ::GetCommandLine(); google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad( InitializeCrashReporting(cmd_line)); + if (IsSystemLevelChromeFrameInstalled()) { + // If we're running at startup, check for system-level Chrome Frame + // installations. If we have one, time + // to bail, also schedule user-level CF to be uninstalled at next logon. + const wchar_t* cmd_line = ::GetCommandLine(); + if (cmd_line && wcsstr(cmd_line, kStartupArg) != NULL) { + bool uninstalled = UninstallUserLevelChromeFrame(); + _ASSERTE(uninstalled); + } + return 0; + } + // Create a window with a known class and title just to listen for WM_CLOSE // messages that will shut us down. - HWND hwnd = RegisterAndCreateWindow(hinstance); - _ASSERTE(hwnd); + g_hwnd = RegisterAndCreateWindow(hinstance); + _ASSERTE(IsWindow(g_hwnd)); // Load the hook dll, and set the event hooks. HookDllLoader loader; bool loaded = loader.Load(); _ASSERTE(loaded); + // Start up the registry watcher + RegistryWatcher registry_watcher(HKEY_LOCAL_MACHINE, kBHORegistrationPath, + WaitCallback); + bool watching = registry_watcher.StartWatching(); + _ASSERTE(watching); + if (loaded) { MSG msg; BOOL ret; |