Blink roll 148954:148987
[chromium-blink-merge.git] / chrome_frame / chrome_frame_helper_util.cc
blob02445572b6000ab769c42cb7b191711f83816405
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome_frame/chrome_frame_helper_util.h"
6 #include "chrome_frame/chrome_tab.h"
8 #include <shlwapi.h>
9 #include <stdio.h>
11 namespace {
13 const wchar_t kGetBrowserMessage[] = L"GetAutomationObject";
15 const wchar_t kBHORegistrationPathFmt[] =
16 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer"
17 L"\\Browser Helper Objects\\%s";
18 const wchar_t kChromeFrameClientKey[] =
19 L"Software\\Google\\Update\\Clients\\"
20 L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}";
21 const wchar_t kGoogleUpdateVersionValue[] = L"pv";
23 } // namespace
25 bool UtilIsWebBrowserWindow(HWND window_to_check) {
26 bool is_browser_window = false;
28 if (!IsWindow(window_to_check)) {
29 return is_browser_window;
32 static wchar_t* known_ie_window_classes[] = {
33 L"IEFrame",
34 L"TabWindowClass"
37 for (int i = 0; i < ARRAYSIZE(known_ie_window_classes); i++) {
38 if (IsWindowOfClass(window_to_check, known_ie_window_classes[i])) {
39 is_browser_window = true;
40 break;
44 return is_browser_window;
47 HRESULT UtilGetWebBrowserObjectFromWindow(HWND window,
48 REFIID iid,
49 void** web_browser_object) {
50 if (NULL == web_browser_object) {
51 return E_POINTER;
54 // Check whether this window is really a web browser window.
55 if (UtilIsWebBrowserWindow(window)) {
56 // IWebBroswer2 interface pointer can be retrieved from the browser
57 // window by simply sending a registered message "GetAutomationObject"
58 // Note that since we are sending a message to parent window make sure that
59 // it is in the same thread.
60 if (GetWindowThreadProcessId(window, NULL) != GetCurrentThreadId()) {
61 return E_UNEXPECTED;
64 static const ULONG get_browser_message =
65 RegisterWindowMessageW(kGetBrowserMessage);
67 *web_browser_object =
68 reinterpret_cast<void*>(SendMessage(window,
69 get_browser_message,
70 reinterpret_cast<WPARAM>(&iid),
71 NULL));
72 if (NULL != *web_browser_object) {
73 return S_OK;
75 } else {
76 return E_INVALIDARG;
78 return E_NOINTERFACE;
81 bool IsWindowOfClass(HWND window_to_check, const wchar_t* window_class) {
82 bool window_matches = false;
83 const int buf_size = MAX_PATH;
84 wchar_t buffer[buf_size] = {0};
85 DWORD size = GetClassNameW(window_to_check, buffer, buf_size);
86 // If the window name is any longer than this, it isn't the one we want.
87 if (size < (buf_size - 1)) {
88 if (!lstrcmpiW(window_class, buffer)) {
89 window_matches = true;
92 return window_matches;
95 bool IsNamedWindow(HWND window, const wchar_t* window_name) {
96 bool window_matches = false;
97 const int buf_size = MAX_PATH;
98 wchar_t buffer[buf_size] = {0};
99 DWORD size = GetWindowText(window, buffer, buf_size);
100 if (size < (buf_size - 1)) {
101 if (!lstrcmpiW(window_name, buffer)) {
102 window_matches = true;
105 return window_matches;
108 bool IsNamedProcess(const wchar_t* process_name) {
109 wchar_t file_path[2048] = {0};
110 GetModuleFileName(NULL, file_path, 2047);
111 wchar_t* file_name = PathFindFileName(file_path);
112 return (0 == lstrcmpiW(file_name, process_name));
115 namespace {
116 struct FindWindowParams {
117 HWND parent_;
118 const wchar_t* class_name_;
119 const wchar_t* window_name_;
120 HWND window_found_;
121 DWORD thread_id_;
122 DWORD process_id_;
123 FindWindowParams(HWND parent,
124 const wchar_t* class_name,
125 const wchar_t* window_name,
126 DWORD thread_id,
127 DWORD process_id)
128 : parent_(parent),
129 class_name_(class_name),
130 window_name_(window_name),
131 window_found_(NULL),
132 thread_id_(thread_id),
133 process_id_(process_id) {
137 // Checks a window against a set of parameters defined in params. If the
138 // window matches, fills in params->window_found_ with the HWND of the window
139 // and returns true. Returns false otherwise.
140 bool WindowMatches(HWND window, FindWindowParams* params) {
141 bool found = false;
142 DWORD process_id = 0;
143 DWORD thread_id = GetWindowThreadProcessId(window, &process_id);
145 // First check that the PID and TID match if we're interested.
146 if (params->process_id_ == 0 || params->process_id_ == process_id) {
147 if (params->thread_id_ == 0 || params->thread_id_ == thread_id) {
148 // Then check that we match on class and window names, again only if
149 // we're interested.
150 if ((params->class_name_ == NULL ||
151 IsWindowOfClass(window, params->class_name_)) &&
152 (params->window_name_ == NULL) ||
153 IsNamedWindow(window, params->window_name_)) {
154 found = true;
155 params->window_found_ = window;
159 return found;
162 } // namespace
164 BOOL CALLBACK WndEnumProc(HWND window, LPARAM lparam) {
165 FindWindowParams* params = reinterpret_cast<FindWindowParams *>(lparam);
166 if (!params) {
167 return FALSE;
170 if (WindowMatches(window, params)) {
171 // We found a match on a top level window. Return false to stop enumerating.
172 return FALSE;
173 } else {
174 // If criteria not satisfied, let us try child windows.
175 HWND child_window = RecurseFindWindow(window,
176 params->class_name_,
177 params->window_name_,
178 params->thread_id_,
179 params->process_id_);
180 if (child_window != NULL) {
181 // We found the window we are looking for.
182 params->window_found_ = child_window;
183 return FALSE;
185 return TRUE;
189 HWND RecurseFindWindow(HWND parent,
190 const wchar_t* class_name,
191 const wchar_t* window_name,
192 DWORD thread_id_to_match,
193 DWORD process_id_to_match) {
194 if ((class_name == NULL) && (window_name == NULL)) {
195 return NULL;
197 FindWindowParams params(parent, class_name, window_name,
198 thread_id_to_match, process_id_to_match);
199 EnumChildWindows(parent, WndEnumProc, reinterpret_cast<LPARAM>(&params));
200 return params.window_found_;
203 // TODO(robertshield): This is stolen shamelessly from mini_installer.cc.
204 // Refactor this before (more) bad things happen.
205 LONG ReadValue(HKEY key,
206 const wchar_t* value_name,
207 size_t value_size,
208 wchar_t* value) {
209 DWORD type;
210 DWORD byte_length = static_cast<DWORD>(value_size * sizeof(wchar_t));
211 LONG result = ::RegQueryValueEx(key, value_name, NULL, &type,
212 reinterpret_cast<BYTE*>(value),
213 &byte_length);
214 if (result == ERROR_SUCCESS) {
215 if (type != REG_SZ) {
216 result = ERROR_NOT_SUPPORTED;
217 } else if (byte_length == 0) {
218 *value = L'\0';
219 } else if (value[byte_length/sizeof(wchar_t) - 1] != L'\0') {
220 if ((byte_length / sizeof(wchar_t)) < value_size)
221 value[byte_length / sizeof(wchar_t)] = L'\0';
222 else
223 result = ERROR_MORE_DATA;
226 return result;
229 bool IsBHOLoadingPolicyRegistered() {
230 wchar_t bho_clsid_as_string[MAX_PATH] = {0};
231 int count = StringFromGUID2(CLSID_ChromeFrameBHO, bho_clsid_as_string,
232 ARRAYSIZE(bho_clsid_as_string));
234 bool bho_registered = false;
235 if (count > 0) {
236 wchar_t reg_path_buffer[MAX_PATH] = {0};
237 int path_count = _snwprintf(reg_path_buffer,
238 MAX_PATH - 1,
239 kBHORegistrationPathFmt,
240 bho_clsid_as_string);
242 if (path_count > 0) {
243 HKEY reg_handle = NULL;
244 LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
245 reg_path_buffer,
247 KEY_QUERY_VALUE,
248 &reg_handle);
249 if (result == ERROR_SUCCESS) {
250 RegCloseKey(reg_handle);
251 bho_registered = true;
256 return bho_registered;
259 bool IsSystemLevelChromeFrameInstalled() {
260 bool system_level_installed = false;
261 HKEY reg_handle = NULL;
262 LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
263 kChromeFrameClientKey,
265 KEY_QUERY_VALUE,
266 &reg_handle);
267 if (result == ERROR_SUCCESS) {
268 wchar_t version_buffer[MAX_PATH] = {0};
269 result = ReadValue(reg_handle,
270 kGoogleUpdateVersionValue,
271 MAX_PATH,
272 version_buffer);
273 if (result == ERROR_SUCCESS && version_buffer[0] != L'\0') {
274 system_level_installed = true;
276 RegCloseKey(reg_handle);
279 return system_level_installed;