diff options
-rw-r--r-- | chrome_frame/bho_loader.cc | 93 | ||||
-rw-r--r-- | chrome_frame/bho_loader.h | 39 | ||||
-rw-r--r-- | chrome_frame/chrome_frame.gyp | 4 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_helper_dll.cc | 28 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_helper_dll.def | 5 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_helper_main.cc | 131 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_helper_util.cc | 88 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_helper_util.h | 43 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_helper_version.rc | 50 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_launcher.gyp | 117 | ||||
-rw-r--r-- | chrome_frame/event_hooker.cc | 58 | ||||
-rw-r--r-- | chrome_frame/event_hooker.h | 36 |
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_ |