summaryrefslogtreecommitdiffstats
path: root/chrome_frame/chrome_frame_helper_main.cc
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-27 16:44:31 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-27 16:44:31 +0000
commit6a7748e79cb7118089d5857291cb76d57c5c8162 (patch)
treebdfe13aba5f79d4c090bd27fdf75173ff751bb3c /chrome_frame/chrome_frame_helper_main.cc
parent13ffa32ea65d5fda56bcb030643b989d5564c586 (diff)
downloadchromium_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.cc113
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,
+ &reg_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;