summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-04 00:59:39 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-04 00:59:39 +0000
commit35e09b2423478119f1175872ca00a165bf455f17 (patch)
tree5ceb5fd2b46020b83025c86e91f462935c44f742
parent8eb475b508d79cf63fde2a81ace45e4ff6b51b27 (diff)
downloadchromium_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.cc42
-rw-r--r--chrome_frame/chrome_frame_helper_util.cc107
-rw-r--r--chrome_frame/chrome_frame_helper_util.h28
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>(&params));
+ 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_