summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-30 15:34:11 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-30 15:34:11 +0000
commit9ceda77323dcc335680d3cb47b0b76e2821199ad (patch)
treef5280e2a394d7d66a035b57d2c6b835bcbd7057b
parentcf993864f9e684fb2e58f5b89d669ae680feefd9 (diff)
downloadchromium_src-9ceda77323dcc335680d3cb47b0b76e2821199ad.zip
chromium_src-9ceda77323dcc335680d3cb47b0b76e2821199ad.tar.gz
chromium_src-9ceda77323dcc335680d3cb47b0b76e2821199ad.tar.bz2
Add a helper process to Chrome Frame to allow for non-administrative installs. The helper process registers a hook dll that performs the necessary BHO injection instead of registering it in HKLM.
BUG=53127 TEST=Non-admin CF installs work. Review URL: http://codereview.chromium.org/3158036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57860 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome_frame/bho_loader.cc93
-rw-r--r--chrome_frame/bho_loader.h39
-rw-r--r--chrome_frame/chrome_frame.gyp4
-rw-r--r--chrome_frame/chrome_frame_helper_dll.cc28
-rw-r--r--chrome_frame/chrome_frame_helper_dll.def5
-rw-r--r--chrome_frame/chrome_frame_helper_main.cc131
-rw-r--r--chrome_frame/chrome_frame_helper_util.cc88
-rw-r--r--chrome_frame/chrome_frame_helper_util.h43
-rw-r--r--chrome_frame/chrome_frame_helper_version.rc50
-rw-r--r--chrome_frame/chrome_frame_launcher.gyp117
-rw-r--r--chrome_frame/event_hooker.cc58
-rw-r--r--chrome_frame/event_hooker.h36
12 files changed, 669 insertions, 23 deletions
diff --git a/chrome_frame/bho_loader.cc b/chrome_frame/bho_loader.cc
new file mode 100644
index 0000000..fb8f71d
--- /dev/null
+++ b/chrome_frame/bho_loader.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2010 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_frame/bho_loader.h"
+
+#include <atlbase.h>
+#include <atlcomcli.h>
+#include <exdisp.h>
+
+#include "chrome_frame/chrome_frame_helper_util.h"
+#include "chrome_frame/event_hooker.h"
+#include "chrome_tab.h" // NOLINT
+
+
+// Describes the window class we look for.
+const wchar_t kStatusBarWindowClass[] = L"msctls_statusbar32";
+
+BHOLoader::BHOLoader() : hooker_(new EventHooker()) {
+}
+
+BHOLoader::~BHOLoader() {
+ if (hooker_) {
+ delete hooker_;
+ hooker_ = NULL;
+ }
+}
+
+void BHOLoader::OnHookEvent(DWORD event, HWND window) {
+ // Step 1: Make sure that we are in a process named iexplore.exe.
+ if (IsNamedProcess(L"iexplore.exe")) {
+ // Step 2: Check to see if the window is of the right class.
+ // IE loads BHOs in the WM_CREATE handler of the tab window approximately
+ // after it creates the status bar window. To be as close to IE as possible
+ // in our simulation on BHO loading, we watch for the status bar to be
+ // created and do our simulated BHO loading at that time.
+ if (IsWindowOfClass(window, kStatusBarWindowClass)) {
+ HWND parent_window = GetParent(window);
+ // Step 3:
+ // Parent window of status bar window is the web browser window. Try to
+ // get its IWebBrowser2 interface
+ CComPtr<IWebBrowser2> browser;
+ UtilGetWebBrowserObjectFromWindow(parent_window, __uuidof(browser),
+ reinterpret_cast<void**>(&browser));
+ if (browser) {
+ // TODO(robertshield): We may need to find a way to prevent doing this
+ // twice. A marker of some kind would do. Ask during review for good
+ // suggestions.
+
+ // Step 4:
+ // We have the IWebBrowser2 interface. Now create the BHO instance
+ CComPtr<IObjectWithSite> bho_object;
+ HRESULT error_code = bho_object.CoCreateInstance(CLSID_ChromeFrameBHO,
+ NULL,
+ CLSCTX_INPROC_SERVER);
+
+ if (SUCCEEDED(error_code) && bho_object) {
+ // Step 5:
+ // Initialize the BHO by calling SetSite and passing it IWebBrowser2
+ error_code = bho_object->SetSite(browser);
+ if (SUCCEEDED(error_code)) {
+ // Step 6:
+ // Now add the BHO to the collection of automation objects. This
+ // will ensure that BHO will be accessible from the web pages as
+ // any other BHO. Importantly, it will make sure that our BHO
+ // will be cleaned up at the right time along with other BHOs.
+ wchar_t bho_clsid_as_string[MAX_PATH] = {0};
+ StringFromGUID2(CLSID_ChromeFrameBHO, bho_clsid_as_string,
+ ARRAYSIZE(bho_clsid_as_string));
+
+ CComBSTR bho_clsid_as_string_bstr(bho_clsid_as_string);
+ CComVariant object_variant(bho_object);
+
+ browser->PutProperty(bho_clsid_as_string_bstr, object_variant);
+ }
+ }
+ }
+ }
+ }
+}
+
+bool BHOLoader::StartHook() {
+ return hooker_->StartHook();
+}
+
+void BHOLoader::StopHook() {
+ hooker_->StopHook();
+}
+
+BHOLoader* BHOLoader::GetInstance() {
+ static BHOLoader loader;
+ return &loader;
+}
diff --git a/chrome_frame/bho_loader.h b/chrome_frame/bho_loader.h
new file mode 100644
index 0000000..0503375
--- /dev/null
+++ b/chrome_frame/bho_loader.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2010 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_FRAME_BHO_LOADER_H_
+#define CHROME_FRAME_BHO_LOADER_H_
+
+#include <windows.h>
+
+// Forward.
+class EventHooker;
+
+// This class simulates BHO loading in an IE process. It watches for the
+// creation of a specific window and then retrieves the web browser object
+// for that window and simulates loading of the BHO.
+class BHOLoader {
+ public:
+ BHOLoader();
+ ~BHOLoader();
+
+ // Callback invoked on receipt of an accessibility event.
+ void OnHookEvent(DWORD event, HWND window);
+
+ // Call this to install event hooks that will trigger on window creation
+ // and reparenting. Returns true if the hooks are successfully installed,
+ // false otherwise.
+ bool StartHook();
+
+ // Call this to remove the event hooks that are installed by StartHook().
+ void StopHook();
+
+ // Retrieve the BHOLoader instance. Note that this is NOT thread-safe.
+ static BHOLoader* GetInstance();
+
+ private:
+ EventHooker* hooker_;
+};
+
+#endif // CHROME_FRAME_BHO_LOADER_H_
diff --git a/chrome_frame/chrome_frame.gyp b/chrome_frame/chrome_frame.gyp
index 0580d81..c005104 100644
--- a/chrome_frame/chrome_frame.gyp
+++ b/chrome_frame/chrome_frame.gyp
@@ -758,6 +758,8 @@
'chrome_frame_utils',
'xulrunner_sdk',
'chrome_frame_launcher.gyp:chrome_launcher',
+ 'chrome_frame_launcher.gyp:chrome_frame_helper',
+ 'chrome_frame_launcher.gyp:chrome_frame_helper_dll',
'../chrome/chrome.gyp:chrome_version_header',
'../chrome/chrome.gyp:common',
'../chrome/chrome.gyp:utility',
@@ -783,7 +785,7 @@
'include_dirs': [
# To allow including "chrome_tab.h"
'<(INTERMEDIATE_DIR)',
- '<(INTERMEDIATE_DIR)/../chrome_frame',
+ '<(INTERMEDIATE_DIR)/../npchrome_frame',
],
'conditions': [
['OS=="win"', {
diff --git a/chrome_frame/chrome_frame_helper_dll.cc b/chrome_frame/chrome_frame_helper_dll.cc
new file mode 100644
index 0000000..2c3a4a8
--- /dev/null
+++ b/chrome_frame/chrome_frame_helper_dll.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2010 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.
+
+// chrome_frame_helper_dll.cc : Implementation of a helper DLL that initializes
+// a listener for WinEvent hooks on load.
+//
+// Calling the StartUserModeBrowserInjection will set an in-context WinEvent
+// hook that will cause this DLL to get loaded in any process that sends
+// EVENT_OBJECT_CREATE accessibility events. This is a poor substitute to
+// getting in via vetted means (i.e. real BHO registration).
+
+#include "chrome_frame/bho_loader.h"
+#include "chrome_frame/chrome_frame_helper_util.h"
+
+STDAPI StartUserModeBrowserInjection() {
+ return BHOLoader::GetInstance()->StartHook() ? S_OK : E_FAIL;
+}
+
+STDAPI StopUserModeBrowserInjection() {
+ BHOLoader::GetInstance()->StopHook();
+ return S_OK;
+}
+
+BOOL APIENTRY DllMain(HMODULE module, DWORD reason_for_call, void* reserved) {
+ return TRUE;
+}
+
diff --git a/chrome_frame/chrome_frame_helper_dll.def b/chrome_frame/chrome_frame_helper_dll.def
new file mode 100644
index 0000000..54f7f36
--- /dev/null
+++ b/chrome_frame/chrome_frame_helper_dll.def
@@ -0,0 +1,5 @@
+LIBRARY "chrome_frame_helper.dll"
+
+EXPORTS
+ StartUserModeBrowserInjection PRIVATE
+ StopUserModeBrowserInjection PRIVATE
diff --git a/chrome_frame/chrome_frame_helper_main.cc b/chrome_frame/chrome_frame_helper_main.cc
new file mode 100644
index 0000000..f4369a88
--- /dev/null
+++ b/chrome_frame/chrome_frame_helper_main.cc
@@ -0,0 +1,131 @@
+// Copyright (c) 2010 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.
+//
+// chrome_frame_helper_main.cc : The .exe that bootstraps the
+// chrome_frame_helper.dll.
+//
+// This is a small exe that loads the hook dll to set the event hooks and then
+// waits in a message loop. It is intended to be shut down by looking for a
+// window with the class and title
+// kChromeFrameHelperWindowClassName and kChromeFrameHelperWindowName and then
+// sending that window a WM_CLOSE message.
+//
+
+#include <crtdbg.h>
+#include <windows.h>
+
+// Window class and window names.
+const wchar_t kChromeFrameHelperWindowClassName[] =
+ L"ChromeFrameHelperWindowClass";
+const wchar_t kChromeFrameHelperWindowName[] =
+ L"ChromeFrameHelperWindowName";
+
+// 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.
+class HookDllLoader {
+ public:
+ HookDllLoader() : dll_(NULL), start_proc_(NULL), stop_proc_(NULL) {}
+ ~HookDllLoader() {
+ if (dll_) {
+ Unload();
+ }
+ }
+
+ bool Load() {
+ dll_ = LoadLibrary(L"chrome_frame_helper.dll");
+ if (dll_) {
+ start_proc_ = GetProcAddress(dll_, "StartUserModeBrowserInjection");
+ stop_proc_ = GetProcAddress(dll_, "StopUserModeBrowserInjection");
+ }
+
+ bool result = true;
+ if (!start_proc_ || !stop_proc_) {
+ _ASSERTE(L"failed to load hook dll.");
+ result = false;
+ } else {
+ if (FAILED(start_proc_())) {
+ _ASSERTE(L"failed to initialize hook dll.");
+ result = false;
+ }
+ }
+ return result;
+ }
+
+ void Unload() {
+ if (stop_proc_) {
+ stop_proc_();
+ }
+ if (dll_) {
+ FreeLibrary(dll_);
+ }
+ }
+
+ private:
+ HMODULE dll_;
+ PROC start_proc_;
+ PROC stop_proc_;
+};
+
+
+LRESULT CALLBACK ChromeFrameHelperWndProc(HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam) {
+ switch (message) {
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+ default:
+ return ::DefWindowProc(hwnd, message, wparam, lparam);
+ }
+ return 0;
+}
+
+HWND RegisterAndCreateWindow(HINSTANCE hinstance) {
+ WNDCLASSEX wcex = {0};
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.lpfnWndProc = ChromeFrameHelperWndProc;
+ wcex.hInstance = GetModuleHandle(NULL);
+ wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1);
+ wcex.lpszClassName = kChromeFrameHelperWindowClassName;
+ RegisterClassEx(&wcex);
+
+ HWND hwnd = CreateWindow(kChromeFrameHelperWindowClassName,
+ kChromeFrameHelperWindowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0,
+ CW_USEDEFAULT, 0, NULL, NULL, hinstance, NULL);
+
+ return hwnd;
+}
+
+int APIENTRY wWinMain(HINSTANCE hinstance, HINSTANCE, wchar_t*, int show_cmd) {
+ // TODO(robertshield): Before this actually gets used, add breakpad
+ // integration.
+
+ // 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);
+
+ // Load the hook dll, and set the event hooks.
+ HookDllLoader loader;
+ bool loaded = loader.Load();
+ _ASSERTE(loaded);
+
+ if (loaded) {
+ MSG msg;
+ BOOL ret;
+ // Main message loop:
+ while ((ret = GetMessage(&msg, NULL, 0, 0))) {
+ if (ret == -1) {
+ break;
+ } else {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/chrome_frame/chrome_frame_helper_util.cc b/chrome_frame/chrome_frame_helper_util.cc
new file mode 100644
index 0000000..d246881
--- /dev/null
+++ b/chrome_frame/chrome_frame_helper_util.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 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_frame/chrome_frame_helper_util.h"
+
+#include <shlwapi.h>
+
+const wchar_t kGetBrowserMessage[] = L"GetAutomationObject";
+
+bool UtilIsWebBrowserWindow(HWND window_to_check) {
+ bool is_browser_window = false;
+
+ if (!IsWindow(window_to_check)) {
+ return is_browser_window;
+ }
+
+ static wchar_t* known_ie_window_classes[] = {
+ L"IEFrame",
+ L"TabWindowClass"
+ };
+
+ for (int i = 0; i < ARRAYSIZE(known_ie_window_classes); i++) {
+ if (IsWindowOfClass(window_to_check, known_ie_window_classes[i])) {
+ is_browser_window = true;
+ break;
+ }
+ }
+
+ return is_browser_window;
+}
+
+HRESULT UtilGetWebBrowserObjectFromWindow(HWND window,
+ REFIID iid,
+ void** web_browser_object) {
+ if (NULL == web_browser_object) {
+ return E_POINTER;
+ }
+
+ // Check whether this window is really a web browser window.
+ if (UtilIsWebBrowserWindow(window)) {
+ // IWebBroswer2 interface pointer can be retrieved from the browser
+ // window by simply sending a registered message "GetAutomationObject"
+ // Note that since we are sending a message to parent window make sure that
+ // it is in the same thread.
+ if (GetWindowThreadProcessId(window, NULL) != GetCurrentThreadId()) {
+ return E_UNEXPECTED;
+ }
+
+ static const ULONG get_browser_message =
+ RegisterWindowMessageW(kGetBrowserMessage);
+
+ *web_browser_object =
+ reinterpret_cast<void*>(SendMessage(window,
+ get_browser_message,
+ reinterpret_cast<WPARAM>(&iid),
+ NULL));
+ if (NULL != *web_browser_object) {
+ return S_OK;
+ }
+ } else {
+ return E_INVALIDARG;
+ }
+ return E_NOINTERFACE;
+}
+
+
+bool IsWindowOfClass(HWND window_to_check, const wchar_t* window_class) {
+ bool window_matches = false;
+ const int buf_size = MAX_PATH;
+ wchar_t buffer[buf_size] = {0};
+ DWORD dwRetSize = GetClassNameW(window_to_check, buffer, buf_size);
+ // If the window name is any longer than this, it isn't the one we want.
+ if (dwRetSize < (buf_size - 1)) {
+ if (0 == lstrcmpiW(window_class, buffer)) {
+ window_matches = true;
+ }
+ }
+ return window_matches;
+}
+
+
+bool IsNamedProcess(const wchar_t* process_name) {
+ wchar_t file_path[2048] = {0};
+ GetModuleFileName(NULL, file_path, 2047);
+ wchar_t* file_name = PathFindFileName(file_path);
+ return (0 == lstrcmpiW(file_name, process_name));
+}
diff --git a/chrome_frame/chrome_frame_helper_util.h b/chrome_frame/chrome_frame_helper_util.h
new file mode 100644
index 0000000..f204debd
--- /dev/null
+++ b/chrome_frame/chrome_frame_helper_util.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2010 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_FRAME_CHROME_FRAME_HELPER_UTIL_H_
+#define CHROME_FRAME_CHROME_FRAME_HELPER_UTIL_H_
+
+#include <windows.h>
+
+// Compare the given class name with the known window class names for
+// internet explorer browser windows.
+//
+// @param [in] window_to_check handle to the window to be checked
+//
+// @return true if the window class matches known class names for IE browser.
+//
+bool UtilIsWebBrowserWindow(HWND window_to_check);
+
+// A utility function that retrieves the specified web browser COM interface
+// from the web browser window. The passed in window must be the web browser
+// window (class name "IEFrame" in IE6 and "TabWindowClass" in IE7)
+// @param[in] window The web browser window whose COM object is to be fetched
+// @param[in] iid The IID of the interface to be fetched
+// @param[out] web_browser_object
+// The requested interface pointer to the web browser object
+// is returned in this variable upon success
+//
+HRESULT UtilGetWebBrowserObjectFromWindow(HWND window,
+ REFIID iid,
+ void** web_browser_object);
+
+// Checks to see whether the passed in window is of the class specified.
+// of the heirarchy list
+// @param hwnd_to_match [in] The handle of the window that is to be
+// matched.
+// @param window_class [in] The window class to match against.
+//
+bool IsWindowOfClass(HWND hwnd_to_match, const wchar_t* window_class);
+
+// Returns true if the current process name is process_name, false otherwise.
+bool IsNamedProcess(const wchar_t* process_name);
+
+#endif // CHROME_FRAME_CHROME_FRAME_HELPER_UTIL_H_
diff --git a/chrome_frame/chrome_frame_helper_version.rc b/chrome_frame/chrome_frame_helper_version.rc
new file mode 100644
index 0000000..126207d
--- /dev/null
+++ b/chrome_frame/chrome_frame_helper_version.rc
@@ -0,0 +1,50 @@
+#include "version.h"
+
+#ifdef APSTUDIO_INVOKED
+# error Don't open this in the GUI, it'll be massacred on save.
+#endif // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION CHROME_VERSION
+ PRODUCTVERSION CHROME_VERSION
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ // Note that Firefox 3.0 requires the charset to be 04e4 (multi-lingual).
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", COMPANY_FULLNAME_STRING
+ VALUE "CompanyShortName", COMPANY_SHORTNAME_STRING
+ VALUE "ProductName", "Google Chrome Frame"
+ VALUE "ProductShortName", "ChromeFrame"
+ VALUE "ProductVersion", CHROME_VERSION_STRING
+ VALUE "FileDescription", "Chrome Frame renders the Web of the future in the browsers of the past. It's like strapping a rocket engine to a minivan."
+ VALUE "FileVersion", CHROME_VERSION_STRING
+ VALUE "InternalName", "Google Chrome Frame"
+ VALUE "LegalCopyright", COPYRIGHT_STRING
+ VALUE "FileExtents", "chromeframe"
+ VALUE "FileOpenName", "chromeframe"
+ VALUE "LastChange", LASTCHANGE_STRING
+ VALUE "Official Build", OFFICIAL_BUILD_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ // Note that Firefox 3.0 requires the charset to be 1252 (multi-lingual).
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/chrome_frame/chrome_frame_launcher.gyp b/chrome_frame/chrome_frame_launcher.gyp
index 0e94c55..9a3d7a0 100644
--- a/chrome_frame/chrome_frame_launcher.gyp
+++ b/chrome_frame/chrome_frame_launcher.gyp
@@ -37,6 +37,29 @@
# all our own includes are relative to src/
'..',
],
+ 'configurations': {
+ 'Release_Base': {
+ # Set flags to unconditionally optimize chrome_frame_launcher.exe
+ # for release builds.
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkTimeCodeGeneration': '1',
+ },
+ 'VCCLCompilerTool': {
+ 'Optimization': '3',
+ 'InlineFunctionExpansion': '2',
+ 'EnableIntrinsicFunctions': 'true',
+ 'FavorSizeOrSpeed': '2',
+ 'OmitFramePointers': 'true',
+ 'EnableFiberSafeOptimizations': 'true',
+ 'WholeProgramOptimization': 'true',
+ },
+ 'VCLibrarianTool': {
+ 'AdditionalOptions': ['/ltcg', '/expectedoutputsize:120000000'],
+ },
+ },
+ },
+ },
},
'targets': [
{
@@ -67,28 +90,78 @@
'shlwapi.lib',
],
},
- },
- 'configurations': {
- 'Release_Base': {
- # Set flags to unconditionally optimize chrome_frame_launcher.exe
- # for release builds.
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'LinkTimeCodeGeneration': '1',
- },
- 'VCCLCompilerTool': {
- 'Optimization': '3',
- 'InlineFunctionExpansion': '2',
- 'EnableIntrinsicFunctions': 'true',
- 'FavorSizeOrSpeed': '2',
- 'OmitFramePointers': 'true',
- 'EnableFiberSafeOptimizations': 'true',
- 'WholeProgramOptimization': 'true',
- },
- 'VCLibrarianTool': {
- 'AdditionalOptions': ['/ltcg', '/expectedoutputsize:120000000'],
- },
- },
+ },
+ },
+ {
+ 'target_name': 'chrome_frame_helper',
+ 'type': 'executable',
+ 'msvs_guid': 'BF4FFA36-2F66-4B65-9A91-AB7EC08D1042',
+ 'dependencies': [
+ '../breakpad/breakpad.gyp:breakpad_handler',
+ '../chrome/chrome.gyp:chrome_version_header',
+ 'chrome_frame_helper_dll',
+ ],
+ 'resource_include_dirs': [
+ '<(INTERMEDIATE_DIR)',
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'include_dirs': [
+ # To allow including "chrome_tab.h"
+ '<(INTERMEDIATE_DIR)',
+ '<(INTERMEDIATE_DIR)/../chrome_frame',
+ ],
+ 'sources': [
+ 'chrome_frame_helper_main.cc',
+ 'chrome_frame_helper_version.rc',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile':
+ '$(OutDir)\\servers\\$(ProjectName).exe',
+ # Set /SUBSYSTEM:WINDOWS since this is not a command-line program.
+ 'SubSystem': '2',
+ },
+ },
+ },
+ {
+ 'target_name': 'chrome_frame_helper_dll',
+ 'type': 'shared_library',
+ 'msvs_guid': '5E80032F-7033-4661-9016-D98268244783',
+ 'dependencies': [
+ '../chrome/chrome.gyp:chrome_version_header',
+ ],
+ 'resource_include_dirs': [
+ '<(INTERMEDIATE_DIR)',
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'include_dirs': [
+ # To allow including "chrome_tab.h"
+ '<(INTERMEDIATE_DIR)',
+ '<(INTERMEDIATE_DIR)/../chrome_frame',
+ ],
+ 'sources': [
+ 'bho_loader.cc',
+ 'bho_loader.h',
+ 'chrome_frame_helper_dll.cc',
+ 'chrome_frame_helper_dll.def',
+ 'chrome_frame_helper_util.cc',
+ 'chrome_frame_helper_util.h',
+ 'chrome_frame_helper_version.rc',
+ 'chrome_tab.h',
+ 'chrome_tab.idl',
+ 'event_hooker.cc',
+ 'event_hooker.h',
+ 'iids.cc',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile':
+ '$(OutDir)\\servers\\chrome_frame_helper.dll',
+ # Set /SUBSYSTEM:WINDOWS since this is not a command-line program.
+ 'SubSystem': '2',
+ 'AdditionalDependencies': [
+ 'shlwapi.lib',
+ ],
},
},
},
diff --git a/chrome_frame/event_hooker.cc b/chrome_frame/event_hooker.cc
new file mode 100644
index 0000000..839b3ad
--- /dev/null
+++ b/chrome_frame/event_hooker.cc
@@ -0,0 +1,58 @@
+// Copyright (c) 2010 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_frame/event_hooker.h"
+
+#include <crtdbg.h>
+#include "chrome_frame/bho_loader.h"
+
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;
+
+EventHooker::EventHooker()
+: window_creation_hook_(NULL) {}
+
+EventHooker::~EventHooker() {
+ StopHook();
+}
+
+bool EventHooker::StartHook() {
+ if ((NULL != window_creation_hook_)) {
+ return false;
+ }
+
+ window_creation_hook_ = SetWinEventHook(EVENT_OBJECT_CREATE,
+ EVENT_OBJECT_CREATE,
+ reinterpret_cast<HMODULE>(
+ &__ImageBase),
+ WindowCreationHookProc,
+ 0,
+ 0,
+ WINEVENT_INCONTEXT);
+ if (NULL == window_creation_hook_) {
+ return false;
+ }
+ return true;
+}
+
+void EventHooker::StopHook() {
+ if (NULL != window_creation_hook_) {
+ UnhookWinEvent(window_creation_hook_);
+ window_creation_hook_ = NULL;
+ }
+}
+
+VOID CALLBACK EventHooker::WindowCreationHookProc(HWINEVENTHOOK hook,
+ DWORD event,
+ HWND window,
+ LONG object_id,
+ LONG child_id,
+ DWORD event_tid,
+ DWORD event_time) {
+ _ASSERTE((EVENT_OBJECT_CREATE == event) ||
+ (EVENT_OBJECT_PARENTCHANGE == event));
+ if (OBJID_WINDOW == object_id) {
+ BHOLoader::GetInstance()->OnHookEvent(event, window);
+ }
+}
+
diff --git a/chrome_frame/event_hooker.h b/chrome_frame/event_hooker.h
new file mode 100644
index 0000000..1f62fbf
--- /dev/null
+++ b/chrome_frame/event_hooker.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 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 <windows.h>
+
+#ifndef CHROME_FRAME_EVENT_HOOKER_H_
+#define CHROME_FRAME_EVENT_HOOKER_H_
+
+class EventHooker {
+ public:
+ EventHooker();
+ ~EventHooker();
+
+ // Call this to install event hooks that will trigger on window creation
+ // and reparenting. Returns true if the hooks are successfully installed,
+ // false otherwise.
+ bool StartHook();
+
+ // Call this to remove the event hooks that are installed by StartHook().
+ void StopHook();
+
+ // The callback invoked in response to an event registered for in StartHook().
+ static VOID CALLBACK WindowCreationHookProc(HWINEVENTHOOK hook,
+ DWORD event,
+ HWND window,
+ LONG object_id,
+ LONG child_id,
+ DWORD event_tid,
+ DWORD event_time);
+
+ private:
+ HWINEVENTHOOK window_creation_hook_;
+};
+
+#endif // CHROME_FRAME_EVENT_HOOKER_H_