diff options
author | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-04 00:59:39 +0000 |
---|---|---|
committer | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-04 00:59:39 +0000 |
commit | 35e09b2423478119f1175872ca00a165bf455f17 (patch) | |
tree | 5ceb5fd2b46020b83025c86e91f462935c44f742 | |
parent | 8eb475b508d79cf63fde2a81ace45e4ff6b51b27 (diff) | |
download | chromium_src-35e09b2423478119f1175872ca00a165bf455f17.zip chromium_src-35e09b2423478119f1175872ca00a165bf455f17.tar.gz chromium_src-35e09b2423478119f1175872ca00a165bf455f17.tar.bz2 |
Add support for IE9 to user-level installations of Chrome Frame.
BUG=70274
TEST=Install user-level Chrome Frame without admin privileges on a system with IE9. Observe CF being loaded in IE.
Review URL: http://codereview.chromium.org/6246040
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73721 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome_frame/bho_loader.cc | 42 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_helper_util.cc | 107 | ||||
-rw-r--r-- | chrome_frame/chrome_frame_helper_util.h | 28 |
3 files changed, 164 insertions, 13 deletions
diff --git a/chrome_frame/bho_loader.cc b/chrome_frame/bho_loader.cc index d0d94ff..5b28831 100644 --- a/chrome_frame/bho_loader.cc +++ b/chrome_frame/bho_loader.cc @@ -16,6 +16,10 @@ // Describes the window class we look for. const wchar_t kStatusBarWindowClass[] = L"msctls_statusbar32"; +// On IE9, the status bar is disabled by default, so we look for an +// AsyncBoundaryLayer window instead. +const wchar_t kAsyncBoundaryDnWindow[] = L"asynclayerboundarydn\0"; + BHOLoader::BHOLoader() : hooker_(new EventHooker()) { } @@ -29,22 +33,42 @@ BHOLoader::~BHOLoader() { 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)) { - // Check that the window was created on the current thread. + if (!IsWindowOfClass(window, kStatusBarWindowClass) && + !IsWindowOfClass(window, kAsyncBoundaryDnWindow)) { + return; + } else { + // We have the right sort of window, check to make sure it was created + // on the current thread. DWORD thread_id = GetWindowThreadProcessId(window, NULL); _ASSERTE(thread_id == GetCurrentThreadId()); + } + + // Step 2: Check to see if the window is of the right class. + HWND browser_hwnd = NULL; + if (IsWindowOfClass(window, kStatusBarWindowClass)) { + // For IE8 and under, 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. + browser_hwnd = GetParent(window); + } else if (IsWindowOfClass(window, kAsyncBoundaryDnWindow)) { + // For IE9, the status bar is disabled by default, so we look for an + // AsyncBoundaryWindow to be created. When we find that, look for a + // child window owned by the current thread named "tabwindowclass". + // That will be our browser window. + browser_hwnd = RecurseFindWindow(NULL, L"tabwindowclass", NULL, + GetCurrentThreadId(), + GetCurrentProcessId()); + _ASSERTE(NULL != browser_hwnd); + } - HWND parent_window = GetParent(window); + if (browser_hwnd != NULL) { // 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), + UtilGetWebBrowserObjectFromWindow(browser_hwnd, __uuidof(browser), reinterpret_cast<void**>(&browser)); if (browser) { // Figure out if we're already in the property map. diff --git a/chrome_frame/chrome_frame_helper_util.cc b/chrome_frame/chrome_frame_helper_util.cc index d246881..87f0efc 100644 --- a/chrome_frame/chrome_frame_helper_util.cc +++ b/chrome_frame/chrome_frame_helper_util.cc @@ -64,21 +64,32 @@ HRESULT UtilGetWebBrowserObjectFromWindow(HWND window, 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); + DWORD size = 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)) { + if (size < (buf_size - 1)) { + if (!lstrcmpiW(window_class, buffer)) { window_matches = true; } } return window_matches; } +bool IsNamedWindow(HWND window, const wchar_t* window_name) { + bool window_matches = false; + const int buf_size = MAX_PATH; + wchar_t buffer[buf_size] = {0}; + DWORD size = GetWindowText(window, buffer, buf_size); + if (size < (buf_size - 1)) { + if (!lstrcmpiW(window_name, buffer)) { + window_matches = true; + } + } + return window_matches; +} bool IsNamedProcess(const wchar_t* process_name) { wchar_t file_path[2048] = {0}; @@ -86,3 +97,91 @@ bool IsNamedProcess(const wchar_t* process_name) { wchar_t* file_name = PathFindFileName(file_path); return (0 == lstrcmpiW(file_name, process_name)); } + +namespace { +struct FindWindowParams { + HWND parent_; + const wchar_t* class_name_; + const wchar_t* window_name_; + HWND window_found_; + DWORD thread_id_; + DWORD process_id_; + FindWindowParams(HWND parent, + const wchar_t* class_name, + const wchar_t* window_name, + DWORD thread_id, + DWORD process_id) + : parent_(parent), + class_name_(class_name), + window_name_(window_name), + window_found_(NULL), + thread_id_(thread_id), + process_id_(process_id) { + } +}; + +// Checks a window against a set of parameters defined in params. If the +// window matches, fills in params->window_found_ with the HWND of the window +// and returns true. Returns false otherwise. +bool WindowMatches(HWND window, FindWindowParams* params) { + bool found = false; + DWORD process_id = 0; + DWORD thread_id = GetWindowThreadProcessId(window, &process_id); + + // First check that the PID and TID match if we're interested. + if (params->process_id_ == 0 || params->process_id_ == process_id) { + if (params->thread_id_ == 0 || params->thread_id_ == thread_id) { + // Then check that we match on class and window names, again only if + // we're interested. + if ((params->class_name_ == NULL || + IsWindowOfClass(window, params->class_name_)) && + (params->window_name_ == NULL) || + IsNamedWindow(window, params->window_name_)) { + found = true; + params->window_found_ = window; + } + } + } + return found; +} + +} // namespace + +BOOL CALLBACK WndEnumProc(HWND window, LPARAM lparam) { + FindWindowParams* params = reinterpret_cast<FindWindowParams *>(lparam); + if (!params) { + return FALSE; + } + + if (WindowMatches(window, params)) { + // We found a match on a top level window. Return false to stop enumerating. + return FALSE; + } else { + // If criteria not satisfied, let us try child windows. + HWND child_window = RecurseFindWindow(window, + params->class_name_, + params->window_name_, + params->thread_id_, + params->process_id_); + if (child_window != NULL) { + // We found the window we are looking for. + params->window_found_ = child_window; + return FALSE; + } + return TRUE; + } +} + +HWND RecurseFindWindow(HWND parent, + const wchar_t* class_name, + const wchar_t* window_name, + DWORD thread_id_to_match, + DWORD process_id_to_match) { + if ((class_name == NULL) && (window_name == NULL)) { + return NULL; + } + FindWindowParams params(parent, class_name, window_name, + thread_id_to_match, process_id_to_match); + EnumChildWindows(parent, WndEnumProc, reinterpret_cast<LPARAM>(¶ms)); + return params.window_found_; +} diff --git a/chrome_frame/chrome_frame_helper_util.h b/chrome_frame/chrome_frame_helper_util.h index f204debd..d80b07d 100644 --- a/chrome_frame/chrome_frame_helper_util.h +++ b/chrome_frame/chrome_frame_helper_util.h @@ -40,4 +40,32 @@ 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); +// Returns true if window has the name |window_name|, false otherwise. +bool IsNamedWindow(HWND window, const wchar_t* window_name); + +// +// This function recursively enumerates all windows from a given starting point +// and searches for the first occurrence of a window matching +// the class name and window name passed in. We use the EnumChildWindows API +// to search for the window. +// @note The FindWindowEx function does something similar, however, it goes +// only one level deep and does not recurse descendants. +// @param parent [in] The HWND of the window from which to start looking. If +// this is NULL then enumerate all windows on the desktop. +// @param class_name [in, optional] The class name of the matching window +// @param window_name [in, optional] The window text of the matching window. +// At least one of class_name and +// window_name must be non-NULL. +// @param thread_id_to_match [in] This parameter will be used to match +// particular thread id for window. +// @param process_id_to_match [in] This parameter will be used to match +// particular process id for window. +// @return The window handle of the matching window, if found, or NULL. +// +HWND RecurseFindWindow(HWND parent, + const wchar_t* class_name, + const wchar_t* window_name, + DWORD thread_id_to_match, + DWORD process_id_to_match); + #endif // CHROME_FRAME_CHROME_FRAME_HELPER_UTIL_H_ |