blob: 210d648883d25487e2d9b733564ee95e37f19cd1 [file] [log] [blame]
[email protected]466a9222010-06-08 01:03:161// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]f7817822009-09-24 05:11:582// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]2d6503982010-10-17 04:41:545#include "chrome_frame/utils.h"
6
[email protected]723f29922009-12-04 20:42:337#include <htiframe.h>
8#include <mshtml.h>
[email protected]f7817822009-09-24 05:11:589#include <shlobj.h>
10
[email protected]74ecb5a42010-09-03 00:44:3511#include <atlsecurity.h>
12
[email protected]f7817822009-09-24 05:11:5813#include "base/file_util.h"
14#include "base/file_version_info.h"
[email protected]b22ef282009-12-11 19:31:5615#include "base/lazy_instance.h"
[email protected]f7817822009-09-24 05:11:5816#include "base/logging.h"
17#include "base/path_service.h"
[email protected]c9c077792010-08-03 14:39:4218#include "base/string_number_conversions.h"
[email protected]e3a91e72010-06-17 01:19:0419#include "base/string_tokenizer.h"
[email protected]f7817822009-09-24 05:11:5820#include "base/string_util.h"
[email protected]d3451d832010-10-01 11:17:3721#include "base/stringprintf.h"
[email protected]1357c322010-12-30 22:18:5622#include "base/threading/thread_local.h"
[email protected]d55194ca2010-03-11 18:25:4523#include "base/utf_string_conversions.h"
[email protected]2d6503982010-10-17 04:41:5424#include "base/win/registry.h"
[email protected]965722ff2010-10-20 15:50:3025#include "base/win/scoped_bstr.h"
26#include "base/win/scoped_comptr.h"
27#include "base/win/scoped_variant.h"
[email protected]e67a73f42010-08-31 15:05:0228#include "chrome/common/chrome_paths_internal.h"
[email protected]7ce979a2009-10-29 02:07:4529#include "chrome/common/url_constants.h"
[email protected]c41468f2009-11-11 20:39:1830#include "chrome/installer/util/chrome_frame_distribution.h"
[email protected]b22ef282009-12-11 19:31:5631#include "chrome_frame/extra_system_apis.h"
32#include "chrome_frame/html_utils.h"
[email protected]354bcba2010-12-14 04:34:4333#include "chrome_frame/navigation_constraints.h"
[email protected]55604d72010-09-15 14:41:4834#include "chrome_frame/policy_settings.h"
[email protected]36a26ed2010-03-24 03:09:0535#include "chrome_frame/simple_resource_loader.h"
[email protected]f7817822009-09-24 05:11:5836#include "googleurl/src/gurl.h"
[email protected]38d3d422010-03-16 22:24:2637#include "googleurl/src/url_canon.h"
[email protected]36a26ed2010-03-24 03:09:0538#include "grit/chromium_strings.h"
[email protected]1d27bbe2010-09-10 00:32:0639#include "net/base/escape.h"
[email protected]6ee88532010-04-16 01:10:4740#include "net/http/http_util.h"
[email protected]f7817822009-09-24 05:11:5841
[email protected]2d6503982010-10-17 04:41:5442using base::win::RegKey;
[email protected]965722ff2010-10-20 15:50:3043using base::win::ScopedComPtr;
[email protected]2d6503982010-10-17 04:41:5444
[email protected]f7817822009-09-24 05:11:5845// Note that these values are all lower case and are compared to
46// lower-case-transformed values.
47const wchar_t kMetaTag[] = L"meta";
48const wchar_t kHttpEquivAttribName[] = L"http-equiv";
49const wchar_t kContentAttribName[] = L"content";
50const wchar_t kXUACompatValue[] = L"x-ua-compatible";
51const wchar_t kBodyTag[] = L"body";
52const wchar_t kChromeContentPrefix[] = L"chrome=";
[email protected]d266ce82010-08-13 21:33:4053const char kGCFProtocol[] = "gcf";
[email protected]552fb6012010-02-03 17:24:2954const wchar_t kChromeProtocolPrefix[] = L"gcf:";
[email protected]051236f2010-03-12 22:06:1455const wchar_t kChromeMimeType[] = L"application/chromepage";
56const wchar_t kPatchProtocols[] = L"PatchProtocols";
[email protected]e67a73f42010-08-31 15:05:0257const wchar_t kChromeFrameConfigKey[] = L"Software\\Google\\ChromeFrame";
58const wchar_t kRenderInGCFUrlList[] = L"RenderInGcfUrls";
59const wchar_t kRenderInHostUrlList[] = L"RenderInHostUrls";
60const wchar_t kEnableGCFRendererByDefault[] = L"IsDefaultRenderer";
61const wchar_t kIexploreProfileName[] = L"iexplore";
62const wchar_t kRundllProfileName[] = L"rundll32";
[email protected]f7817822009-09-24 05:11:5863
[email protected]69e4b612010-11-24 21:13:1664const wchar_t kAllowUnsafeURLs[] = L"AllowUnsafeURLs";
65const wchar_t kEnableBuggyBhoIntercept[] = L"EnableBuggyBhoIntercept";
66const wchar_t kEnableFirefoxPrivilegeMode[] = L"EnableFirefoxPrivilegeMode";
[email protected]f7817822009-09-24 05:11:5867
[email protected]c41468f2009-11-11 20:39:1868static const wchar_t kChromeFrameNPAPIKey[] =
69 L"Software\\MozillaPlugins\\@google.com/ChromeFrame,version=1.0";
70static const wchar_t kChromeFramePersistNPAPIReg[] = L"PersistNPAPIReg";
71
[email protected]d266ce82010-08-13 21:33:4072const char kAttachExternalTabPrefix[] = "attach_external_tab";
[email protected]f7817822009-09-24 05:11:5873
[email protected]7bc272f2009-12-09 01:09:2874// Indicates that we are running in a test environment, where execptions, etc
75// are handled by the chrome test crash server.
76const wchar_t kChromeFrameHeadlessMode[] = L"ChromeFrameHeadlessMode";
77
[email protected]67700a92010-09-18 07:43:5878// Indicates that we are running in an environment that expects chrome renderer
79// accessibility to be enabled for use in automation tests.
80const wchar_t kChromeFrameAccessibleMode[] = L"ChromeFrameAccessibleMode";
81
[email protected]11903b0d2010-03-26 23:54:3482// Indicates that we are running in an environment that wishes to avoid
83// DLL pinning, such as the perf tests.
84const wchar_t kChromeFrameUnpinnedMode[] = L"kChromeFrameUnpinnedMode";
85
[email protected]5843d2a2010-01-12 14:38:1486// {1AF32B6C-A3BA-48B9-B24E-8AA9C41F6ECD}
87static const IID IID_IWebBrowserPriv2IE7 = { 0x1AF32B6C, 0xA3BA, 0x48B9,
88 { 0xB2, 0x4E, 0x8A, 0xA9, 0xC4, 0x1F, 0x6E, 0xCD } };
89
90// {3ED72303-6FFC-4214-BA90-FAF1862DEC8A}
91static const IID IID_IWebBrowserPriv2IE8 = { 0x3ED72303, 0x6FFC, 0x4214,
92 { 0xBA, 0x90, 0xFA, 0xF1, 0x86, 0x2D, 0xEC, 0x8A } };
93
94// {486F6159-9F3F-4827-82D4-283CEF397733}
95static const IID IID_IWebBrowserPriv2IE8XP = { 0x486F6159, 0x9F3F, 0x4827,
96 { 0x82, 0xD4, 0x28, 0x3C, 0xEF, 0x39, 0x77, 0x33 } };
97
[email protected]94a3fbfa2010-01-30 00:44:2498// {38339692-0BC9-46CB-8E5C-4677A5C83DD5}
99static const IID IID_IWebBrowserPriv2IE8XPBeta = { 0x38339692, 0x0BC9, 0x46CB,
100 { 0x8E, 0x5C, 0x46, 0x77, 0xA5, 0xC8, 0x3D, 0xD5 } };
101
[email protected]b22ef282009-12-11 19:31:56102namespace {
103
104// A flag used to signal when an active browser instance on the current thread
105// is loading a Chrome Frame document. There's no reference stored with the
106// pointer so it should not be dereferenced and used for comparison against a
107// living instance only.
108base::LazyInstance<base::ThreadLocalPointer<IBrowserService> >
109 g_tls_browser_for_cf_navigation(base::LINKER_INITIALIZED);
110
111} // end anonymous namespace
112
[email protected]f7817822009-09-24 05:11:58113HRESULT UtilRegisterTypeLib(HINSTANCE tlb_instance,
114 LPCOLESTR index,
115 bool for_current_user_only) {
116 CComBSTR path;
117 CComPtr<ITypeLib> type_lib;
118 HRESULT hr = AtlLoadTypeLib(tlb_instance, index, &path, &type_lib);
119 if (SUCCEEDED(hr)) {
120 hr = UtilRegisterTypeLib(type_lib, path, NULL, for_current_user_only);
121 }
122 return hr;
123}
124
125HRESULT UtilUnRegisterTypeLib(HINSTANCE tlb_instance,
126 LPCOLESTR index,
127 bool for_current_user_only) {
128 CComBSTR path;
129 CComPtr<ITypeLib> type_lib;
130 HRESULT hr = AtlLoadTypeLib(tlb_instance, index, &path, &type_lib);
131 if (SUCCEEDED(hr)) {
132 hr = UtilUnRegisterTypeLib(type_lib, for_current_user_only);
133 }
134 return hr;
135}
136
137HRESULT UtilRegisterTypeLib(LPCWSTR typelib_path,
138 bool for_current_user_only) {
139 if (NULL == typelib_path) {
140 return E_INVALIDARG;
141 }
142 CComBSTR path;
143 CComPtr<ITypeLib> type_lib;
144 HRESULT hr = ::LoadTypeLib(typelib_path, &type_lib);
145 if (SUCCEEDED(hr)) {
146 hr = UtilRegisterTypeLib(type_lib,
147 typelib_path,
148 NULL,
149 for_current_user_only);
150 }
151 return hr;
152}
153
154HRESULT UtilUnRegisterTypeLib(LPCWSTR typelib_path,
155 bool for_current_user_only) {
156 CComPtr<ITypeLib> type_lib;
157 HRESULT hr = ::LoadTypeLib(typelib_path, &type_lib);
158 if (SUCCEEDED(hr)) {
159 hr = UtilUnRegisterTypeLib(type_lib, for_current_user_only);
160 }
161 return hr;
162}
163
164HRESULT UtilRegisterTypeLib(ITypeLib* typelib,
165 LPCWSTR typelib_path,
166 LPCWSTR help_dir,
167 bool for_current_user_only) {
168 typedef HRESULT(WINAPI *RegisterTypeLibPrototype)(ITypeLib FAR* type_lib,
169 OLECHAR FAR* full_path,
170 OLECHAR FAR* help_dir);
171 LPCSTR function_name =
172 for_current_user_only ? "RegisterTypeLibForUser" : "RegisterTypeLib";
173 RegisterTypeLibPrototype reg_tlb =
174 reinterpret_cast<RegisterTypeLibPrototype>(
175 GetProcAddress(GetModuleHandle(_T("oleaut32.dll")),
176 function_name));
177 if (NULL == reg_tlb) {
178 return E_FAIL;
179 }
180 return reg_tlb(typelib,
181 const_cast<OLECHAR*>(typelib_path),
182 const_cast<OLECHAR*>(help_dir));
183}
184
185HRESULT UtilUnRegisterTypeLib(ITypeLib* typelib,
186 bool for_current_user_only) {
187 if (NULL == typelib) {
188 return E_INVALIDARG;
189 }
190 typedef HRESULT(WINAPI *UnRegisterTypeLibPrototype)(
191 REFGUID libID,
192 unsigned short wVerMajor, // NOLINT
193 unsigned short wVerMinor, // NOLINT
194 LCID lcid,
195 SYSKIND syskind);
196 LPCSTR function_name =
197 for_current_user_only ? "UnRegisterTypeLibForUser" : "UnRegisterTypeLib";
198
199 UnRegisterTypeLibPrototype unreg_tlb =
200 reinterpret_cast<UnRegisterTypeLibPrototype>(
201 GetProcAddress(GetModuleHandle(_T("oleaut32.dll")),
202 function_name));
203 if (NULL == unreg_tlb) {
204 return E_FAIL;
205 }
206 TLIBATTR* tla = NULL;
207 HRESULT hr = typelib->GetLibAttr(&tla);
208 if (SUCCEEDED(hr)) {
209 hr = unreg_tlb(tla->guid,
210 tla->wMajorVerNum,
211 tla->wMinorVerNum,
212 tla->lcid,
213 tla->syskind);
214 typelib->ReleaseTLibAttr(tla);
215 }
216 return hr;
217}
218
[email protected]c41468f2009-11-11 20:39:18219bool UtilIsNPAPIPluginRegistered() {
220 std::wstring npapi_key_name(kChromeFrameNPAPIKey);
221 RegKey npapi_key(HKEY_LOCAL_MACHINE, npapi_key_name.c_str(), KEY_QUERY_VALUE);
222 return npapi_key.Valid();
223}
224
225bool UtilChangePersistentNPAPIMarker(bool set) {
226 BrowserDistribution* cf_dist = BrowserDistribution::GetDistribution();
227 std::wstring cf_state_key_path(cf_dist->GetStateKey());
228
229 RegKey cf_state_key(HKEY_LOCAL_MACHINE, cf_state_key_path.c_str(),
230 KEY_READ | KEY_WRITE);
231
232 bool success = false;
233 if (cf_state_key.Valid()) {
234 if (set) {
[email protected]e06f4d52011-01-19 07:28:46235 success = (cf_state_key.WriteValue(kChromeFramePersistNPAPIReg, 1) ==
236 ERROR_SUCCESS);
[email protected]c41468f2009-11-11 20:39:18237 } else {
[email protected]d7265be42009-11-19 03:09:21238 // Unfortunately, DeleteValue returns true only if the value
239 // previously existed, so we do a separate existence check to
240 // validate success.
241 cf_state_key.DeleteValue(kChromeFramePersistNPAPIReg);
242 success = !cf_state_key.ValueExists(kChromeFramePersistNPAPIReg);
[email protected]c41468f2009-11-11 20:39:18243 }
244 }
245 return success;
246}
247
248bool UtilIsPersistentNPAPIMarkerSet() {
249 BrowserDistribution* cf_dist = BrowserDistribution::GetDistribution();
250 std::wstring cf_state_key_path(cf_dist->GetStateKey());
251
252 RegKey cf_state_key(HKEY_LOCAL_MACHINE, cf_state_key_path.c_str(),
253 KEY_QUERY_VALUE);
254
255 bool success = false;
256 if (cf_state_key.Valid()) {
257 DWORD val = 0;
[email protected]e06f4d52011-01-19 07:28:46258 if (cf_state_key.ReadValueDW(kChromeFramePersistNPAPIReg, &val) ==
259 ERROR_SUCCESS) {
[email protected]c41468f2009-11-11 20:39:18260 success = (val != 0);
261 }
262 }
263 return success;
264}
265
266
[email protected]f7817822009-09-24 05:11:58267HRESULT UtilGetXUACompatContentValue(const std::wstring& html_string,
268 std::wstring* content_value) {
269 if (!content_value) {
270 return E_POINTER;
271 }
272
273 // Fail fast if the string X-UA-Compatible isn't in html_string
274 if (StringToLowerASCII(html_string).find(kXUACompatValue) ==
275 std::wstring::npos) {
276 return E_FAIL;
277 }
278
279 HTMLScanner scanner(html_string.c_str());
280
281 // Build the list of meta tags that occur before the body tag is hit.
282 HTMLScanner::StringRangeList tag_list;
283 scanner.GetTagsByName(kMetaTag, &tag_list, kBodyTag);
284
285 // Search the list of meta tags for one with an http-equiv="X-UA-Compatible"
286 // attribute.
287 HTMLScanner::StringRange attribute;
288 std::string search_attribute_ascii(WideToASCII(kXUACompatValue));
289 HTMLScanner::StringRangeList::const_iterator tag_list_iter(tag_list.begin());
290 for (; tag_list_iter != tag_list.end(); tag_list_iter++) {
291 if (!tag_list_iter->GetTagAttribute(kHttpEquivAttribName, &attribute)) {
292 continue;
293 }
294
295 // We found an http-equiv meta tag, check its value using the ascii
296 // case-insensitive comparison method.
297 if (!attribute.LowerCaseEqualsASCII(search_attribute_ascii.c_str())) {
298 continue;
299 }
300
301 // We found our X-UA-Compatible meta tag so look for and extract
302 // the value of the content attribute.
303 if (!tag_list_iter->GetTagAttribute(kContentAttribName, &attribute)) {
304 continue;
305 }
306
307 // Found the content string, copy and return.
308 content_value->assign(attribute.Copy());
309 return S_OK;
310 }
311
312 return E_FAIL;
313}
314
[email protected]f7817822009-09-24 05:11:58315void DisplayVersionMismatchWarning(HWND parent,
316 const std::string& server_version) {
317 // Obtain the current module version.
318 FileVersionInfo* file_version_info =
319 FileVersionInfo::CreateFileVersionInfoForCurrentModule();
320 DCHECK(file_version_info);
321 std::wstring version_string(file_version_info->file_version());
322 std::wstring wide_server_version;
323 if (server_version.empty()) {
[email protected]36a26ed2010-03-24 03:09:05324 wide_server_version = SimpleResourceLoader::Get(IDS_VERSIONUNKNOWN);
[email protected]f7817822009-09-24 05:11:58325 } else {
326 wide_server_version = ASCIIToWide(server_version);
327 }
[email protected]36a26ed2010-03-24 03:09:05328 std::wstring title = SimpleResourceLoader::Get(IDS_VERSIONMISMATCH_HEADER);
[email protected]f7817822009-09-24 05:11:58329 std::wstring message;
[email protected]d3451d832010-10-01 11:17:37330 base::SStringPrintf(&message,
331 SimpleResourceLoader::Get(IDS_VERSIONMISMATCH).c_str(),
332 wide_server_version.c_str(),
333 version_string.c_str());
[email protected]f7817822009-09-24 05:11:58334
335 ::MessageBox(parent, message.c_str(), title.c_str(), MB_OK);
336}
337
338std::string CreateJavascript(const std::string& function_name,
339 const std::string args) {
340 std::string script_string = "javascript:";
341 script_string += function_name + "(";
342 if (!args.empty()) {
343 script_string += "'";
344 script_string += args;
345 script_string += "'";
346 }
347 script_string += ")";
348 return script_string;
349}
350
351AddRefModule::AddRefModule() {
352 // TODO(tommi): Override the module's Lock/Unlock methods to call
353 // npapi::SetValue(NPPVpluginKeepLibraryInMemory) and keep the dll loaded
354 // while the module's refcount is > 0. Only do this when we're being
355 // used as an NPAPI module.
356 _pAtlModule->Lock();
357}
358
359
360AddRefModule::~AddRefModule() {
361 _pAtlModule->Unlock();
362}
363
[email protected]d8e13512010-09-22 17:02:58364bool IsChrome(RendererType renderer_type) {
365 DCHECK_GE(renderer_type, RENDERER_TYPE_UNDETERMINED);
366 DCHECK_LE(renderer_type, RENDERER_TYPE_OTHER);
367 return renderer_type >= RENDERER_TYPE_CHROME_MIN &&
368 renderer_type <= RENDERER_TYPE_CHROME_MAX;
369}
370
[email protected]f7817822009-09-24 05:11:58371namespace {
372const char kIEImageName[] = "iexplore.exe";
373const char kFirefoxImageName[] = "firefox.exe";
374const char kOperaImageName[] = "opera.exe";
375} // namespace
376
377std::wstring GetHostProcessName(bool include_extension) {
378 FilePath exe;
379 if (PathService::Get(base::FILE_EXE, &exe))
380 exe = exe.BaseName();
381 if (!include_extension) {
382 exe = exe.RemoveExtension();
383 }
[email protected]466a9222010-06-08 01:03:16384 return exe.value();
[email protected]f7817822009-09-24 05:11:58385}
386
387BrowserType GetBrowserType() {
388 static BrowserType browser_type = BROWSER_INVALID;
389
390 if (browser_type == BROWSER_INVALID) {
391 std::wstring exe(GetHostProcessName(true));
392 if (!exe.empty()) {
393 std::wstring::const_iterator begin = exe.begin();
394 std::wstring::const_iterator end = exe.end();
395 if (LowerCaseEqualsASCII(begin, end, kIEImageName)) {
396 browser_type = BROWSER_IE;
397 } else if (LowerCaseEqualsASCII(begin, end, kFirefoxImageName)) {
398 browser_type = BROWSER_FIREFOX;
399 } else if (LowerCaseEqualsASCII(begin, end, kOperaImageName)) {
400 browser_type = BROWSER_OPERA;
401 } else {
402 browser_type = BROWSER_UNKNOWN;
403 }
404 } else {
405 NOTREACHED();
406 }
407 }
408
409 return browser_type;
410}
411
[email protected]b57f03232010-10-25 14:14:39412uint32 GetIEMajorVersion() {
413 static uint32 ie_major_version = UINT_MAX;
[email protected]f7817822009-09-24 05:11:58414
[email protected]b57f03232010-10-25 14:14:39415 if (ie_major_version == UINT_MAX) {
[email protected]f7817822009-09-24 05:11:58416 wchar_t exe_path[MAX_PATH];
417 HMODULE mod = GetModuleHandle(NULL);
418 GetModuleFileName(mod, exe_path, arraysize(exe_path) - 1);
[email protected]20256512010-12-24 01:58:57419 std::wstring exe_name = FilePath(exe_path).BaseName().value();
[email protected]f7817822009-09-24 05:11:58420 if (!LowerCaseEqualsASCII(exe_name, kIEImageName)) {
[email protected]b57f03232010-10-25 14:14:39421 ie_major_version = 0;
[email protected]f7817822009-09-24 05:11:58422 } else {
423 uint32 high = 0;
424 uint32 low = 0;
425 if (GetModuleVersion(mod, &high, &low)) {
[email protected]b57f03232010-10-25 14:14:39426 ie_major_version = HIWORD(high);
[email protected]f7817822009-09-24 05:11:58427 } else {
[email protected]b57f03232010-10-25 14:14:39428 ie_major_version = 0;
[email protected]f7817822009-09-24 05:11:58429 }
430 }
431 }
432
[email protected]b57f03232010-10-25 14:14:39433 return ie_major_version;
434}
435
436IEVersion GetIEVersion() {
437 static IEVersion ie_version = IE_INVALID;
438
439 if (ie_version == IE_INVALID) {
440 uint32 major_version = GetIEMajorVersion();
441 switch (major_version) {
442 case 0:
443 ie_version = NON_IE;
444 break;
445 case 6:
446 ie_version = IE_6;
447 break;
448 case 7:
449 ie_version = IE_7;
450 break;
451 case 8:
452 ie_version = IE_8;
453 break;
454 default:
455 ie_version = major_version >= 9 ? IE_9 : IE_UNSUPPORTED;
456 break;
457 }
458 }
459
[email protected]f7817822009-09-24 05:11:58460 return ie_version;
461}
462
[email protected]bc73b4e52010-03-26 04:16:20463FilePath GetIETemporaryFilesFolder() {
[email protected]bc73b4e52010-03-26 04:16:20464 LPITEMIDLIST tif_pidl = NULL;
465 HRESULT hr = SHGetFolderLocation(NULL, CSIDL_INTERNET_CACHE, NULL,
466 SHGFP_TYPE_CURRENT, &tif_pidl);
[email protected]4ece1c42010-04-05 19:51:55467 if (SUCCEEDED(hr) && tif_pidl) {
468 ScopedComPtr<IShellFolder> parent_folder;
469 LPITEMIDLIST relative_pidl = NULL;
470 hr = SHBindToParent(tif_pidl, IID_IShellFolder,
471 reinterpret_cast<void**>(parent_folder.Receive()),
472 const_cast<LPCITEMIDLIST*>(&relative_pidl));
473 if (SUCCEEDED(hr) && relative_pidl) {
474 STRRET path = {0};
475 hr = parent_folder->GetDisplayNameOf(relative_pidl,
476 SHGDN_NORMAL | SHGDN_FORPARSING,
477 &path);
478 DCHECK(SUCCEEDED(hr));
[email protected]965722ff2010-10-20 15:50:30479 base::win::ScopedBstr temp_internet_files_bstr;
[email protected]4ece1c42010-04-05 19:51:55480 StrRetToBSTR(&path, relative_pidl, temp_internet_files_bstr.Receive());
481 FilePath temp_internet_files(static_cast<BSTR>(temp_internet_files_bstr));
[email protected]4ece1c42010-04-05 19:51:55482 ILFree(tif_pidl);
483 return temp_internet_files;
484 } else {
485 NOTREACHED() << "SHBindToParent failed with Error:" << hr;
486 ILFree(tif_pidl);
487 }
488 } else {
489 NOTREACHED() << "SHGetFolderLocation for internet cache failed. Error:"
490 << hr;
491 }
492 // As a last ditch effort we use the SHGetFolderPath function to retrieve the
493 // path. This function has a limitation of MAX_PATH.
494 wchar_t path[MAX_PATH + 1] = {0};
495 hr = SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL, SHGFP_TYPE_CURRENT,
496 path);
497 if (SUCCEEDED(hr)) {
498 return FilePath(path);
499 } else {
500 NOTREACHED() << "SHGetFolderPath for internet cache failed. Error:"
501 << hr;
502 }
503 return FilePath();
[email protected]bc73b4e52010-03-26 04:16:20504}
505
[email protected]f7817822009-09-24 05:11:58506bool IsIEInPrivate() {
507 typedef BOOL (WINAPI* IEIsInPrivateBrowsingPtr)();
508 bool incognito_mode = false;
509 HMODULE h = GetModuleHandle(L"ieframe.dll");
510 if (h) {
511 IEIsInPrivateBrowsingPtr IsInPrivate =
512 reinterpret_cast<IEIsInPrivateBrowsingPtr>(GetProcAddress(h,
513 "IEIsInPrivateBrowsing"));
514 if (IsInPrivate) {
515 incognito_mode = !!IsInPrivate();
516 }
517 }
518
519 return incognito_mode;
520}
521
[email protected]35f13ab2009-12-16 23:59:17522HRESULT DoFileDownloadInIE(const wchar_t* url) {
523 DCHECK(url);
524
525 HMODULE mod = ::GetModuleHandleA("ieframe.dll");
526 if (!mod)
527 mod = ::GetModuleHandleA("shdocvw.dll");
528
529 if (!mod) {
530 NOTREACHED();
531 return E_UNEXPECTED;
532 }
533
534 typedef HRESULT (WINAPI* DoFileDownloadFn)(const wchar_t*);
535 DoFileDownloadFn fn = reinterpret_cast<DoFileDownloadFn>(
536 ::GetProcAddress(mod, "DoFileDownload"));
537 DCHECK(fn);
538 return fn ? fn(url) : E_UNEXPECTED;
539}
540
[email protected]f7817822009-09-24 05:11:58541bool GetModuleVersion(HMODULE module, uint32* high, uint32* low) {
542 DCHECK(module != NULL)
543 << "Please use GetModuleHandle(NULL) to get the process name";
544 DCHECK(high);
545
546 bool ok = false;
547
548 HRSRC res = FindResource(module,
549 reinterpret_cast<const wchar_t*>(VS_VERSION_INFO), RT_VERSION);
550 if (res) {
551 HGLOBAL res_data = LoadResource(module, res);
552 DWORD version_resource_size = SizeofResource(module, res);
553 const void* readonly_resource_data = LockResource(res_data);
554 if (readonly_resource_data && version_resource_size) {
555 // Copy data as VerQueryValue tries to modify the data. This causes
556 // exceptions and heap corruption errors if debugger is attached.
[email protected]1e11b172009-10-23 00:03:45557 scoped_array<char> data(new char[version_resource_size]);
[email protected]f7817822009-09-24 05:11:58558 memcpy(data.get(), readonly_resource_data, version_resource_size);
559 if (data.get()) {
560 VS_FIXEDFILEINFO* ver_info = NULL;
561 UINT info_size = 0;
562 if (VerQueryValue(data.get(), L"\\",
563 reinterpret_cast<void**>(&ver_info), &info_size)) {
564 *high = ver_info->dwFileVersionMS;
565 if (low != NULL)
566 *low = ver_info->dwFileVersionLS;
567 ok = true;
568 }
569
570 UnlockResource(res_data);
571 }
572 FreeResource(res_data);
573 }
574 }
575
576 return ok;
577}
578
[email protected]00aebd72010-07-16 14:44:32579HMODULE GetModuleFromAddress(void* address) {
580 MEMORY_BASIC_INFORMATION info = {0};
581 ::VirtualQuery(address, &info, sizeof(info));
582 return reinterpret_cast<HMODULE>(info.AllocationBase);
583}
584
[email protected]f7817822009-09-24 05:11:58585namespace {
586
587const int kMaxSubmenuDepth = 10;
588
589// Copies original_menu and returns the copy. The caller is responsible for
590// closing the returned HMENU. This does not currently copy over bitmaps
591// (e.g. hbmpChecked, hbmpUnchecked or hbmpItem), so checkmarks, radio buttons,
592// and custom icons won't work.
593// It also copies over submenus up to a maximum depth of kMaxSubMenuDepth.
594//
595// TODO(robertshield): Add support for the bitmap fields if need be.
596HMENU UtilCloneContextMenuImpl(HMENU original_menu, int depth) {
597 DCHECK(IsMenu(original_menu));
598
599 if (depth >= kMaxSubmenuDepth)
600 return NULL;
601
602 HMENU new_menu = CreatePopupMenu();
603 int item_count = GetMenuItemCount(original_menu);
604 if (item_count <= 0) {
605 NOTREACHED();
606 } else {
607 for (int i = 0; i < item_count; i++) {
608 MENUITEMINFO item_info = { 0 };
609 item_info.cbSize = sizeof(MENUITEMINFO);
610 item_info.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE |
611 MIIM_STATE | MIIM_DATA | MIIM_SUBMENU |
612 MIIM_CHECKMARKS | MIIM_BITMAP;
613
614 // Call GetMenuItemInfo a first time to obtain the buffer size for
615 // the label.
616 if (GetMenuItemInfo(original_menu, i, TRUE, &item_info)) {
617 item_info.cch++; // Increment this as per MSDN
618 std::vector<wchar_t> buffer(item_info.cch, 0);
619 item_info.dwTypeData = &buffer[0];
620
621 // Call GetMenuItemInfo a second time with dwTypeData set to a buffer
622 // of a correct size to get the label.
623 GetMenuItemInfo(original_menu, i, TRUE, &item_info);
624
625 // Clone any submenus. Within reason.
626 if (item_info.hSubMenu) {
627 HMENU new_submenu = UtilCloneContextMenuImpl(item_info.hSubMenu,
628 depth + 1);
629 item_info.hSubMenu = new_submenu;
630 }
631
632 // Now insert the item into the new menu.
633 InsertMenuItem(new_menu, i, TRUE, &item_info);
634 }
635 }
636 }
637 return new_menu;
638}
639
640} // namespace
641
642HMENU UtilCloneContextMenu(HMENU original_menu) {
643 return UtilCloneContextMenuImpl(original_menu, 0);
644}
645
646std::string ResolveURL(const std::string& document,
647 const std::string& relative) {
648 if (document.empty()) {
649 return GURL(relative).spec();
650 } else {
651 return GURL(document).Resolve(relative).spec();
652 }
653}
654
655bool HaveSameOrigin(const std::string& url1, const std::string& url2) {
656 GURL a(url1), b(url2);
657 bool ret;
658 if (a.is_valid() != b.is_valid()) {
659 // Either (but not both) url is invalid, so they can't match.
660 ret = false;
661 } else if (!a.is_valid()) {
662 // Both URLs are invalid (see first check). Just check if the opaque
663 // strings match exactly.
664 ret = url1.compare(url2) == 0;
665 } else if (a.GetOrigin() != b.GetOrigin()) {
666 // The origins don't match.
667 ret = false;
668 } else {
669 // we have a match.
670 ret = true;
671 }
672
673 return ret;
674}
675
676int GetConfigInt(int default_value, const wchar_t* value_name) {
677 int ret = default_value;
678 RegKey config_key;
679 if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey,
[email protected]e06f4d52011-01-19 07:28:46680 KEY_QUERY_VALUE) == ERROR_SUCCESS) {
681 config_key.ReadValueDW(value_name, reinterpret_cast<DWORD*>(&ret));
[email protected]f7817822009-09-24 05:11:58682 }
683
684 return ret;
685}
686
687bool GetConfigBool(bool default_value, const wchar_t* value_name) {
688 DWORD value = GetConfigInt(default_value, value_name);
689 return (value != FALSE);
690}
691
[email protected]7bc272f2009-12-09 01:09:28692bool SetConfigInt(const wchar_t* value_name, int value) {
693 RegKey config_key;
[email protected]75bfc842010-02-04 14:23:52694 if (config_key.Create(HKEY_CURRENT_USER, kChromeFrameConfigKey,
[email protected]e06f4d52011-01-19 07:28:46695 KEY_SET_VALUE) == ERROR_SUCCESS) {
696 if (config_key.WriteValue(value_name, value) == ERROR_SUCCESS) {
[email protected]7bc272f2009-12-09 01:09:28697 return true;
698 }
699 }
700
701 return false;
702}
703
704bool SetConfigBool(const wchar_t* value_name, bool value) {
705 return SetConfigInt(value_name, value);
706}
707
708bool DeleteConfigValue(const wchar_t* value_name) {
709 RegKey config_key;
710 if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey,
[email protected]e06f4d52011-01-19 07:28:46711 KEY_WRITE) == ERROR_SUCCESS) {
712 if (config_key.DeleteValue(value_name) == ERROR_SUCCESS) {
713 return true;
714 }
[email protected]7bc272f2009-12-09 01:09:28715 }
716 return false;
717}
718
[email protected]e67a73f42010-08-31 15:05:02719bool IsGcfDefaultRenderer() {
[email protected]e67a73f42010-08-31 15:05:02720 DWORD is_default = 0; // NOLINT
[email protected]55604d72010-09-15 14:41:48721
722 // First check policy settings
[email protected]687b9602010-12-08 10:43:08723 PolicySettings::RendererForUrl renderer =
724 PolicySettings::GetInstance()->default_renderer();
[email protected]55604d72010-09-15 14:41:48725 if (renderer != PolicySettings::RENDERER_NOT_SPECIFIED) {
726 is_default = (renderer == PolicySettings::RENDER_IN_CHROME_FRAME);
727 } else {
728 // TODO(tommi): Implement caching for this config value as it gets
729 // checked frequently.
730 RegKey config_key;
[email protected]e06f4d52011-01-19 07:28:46731 if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey,
732 KEY_READ) == ERROR_SUCCESS) {
[email protected]55604d72010-09-15 14:41:48733 config_key.ReadValueDW(kEnableGCFRendererByDefault, &is_default);
734 }
[email protected]e67a73f42010-08-31 15:05:02735 }
736
737 return is_default != 0;
738}
739
[email protected]d8e13512010-09-22 17:02:58740RendererType RendererTypeForUrl(const std::wstring& url) {
[email protected]55604d72010-09-15 14:41:48741 // First check if the default renderer settings are specified by policy.
742 // If so, then that overrides the user settings.
[email protected]687b9602010-12-08 10:43:08743 PolicySettings::RendererForUrl renderer =
744 PolicySettings::GetInstance()->GetRendererForUrl(url.c_str());
[email protected]55604d72010-09-15 14:41:48745 if (renderer != PolicySettings::RENDERER_NOT_SPECIFIED) {
[email protected]d8e13512010-09-22 17:02:58746 // We may know at this point that policy says do NOT render in Chrome Frame.
747 // To maintain consistency, we return RENDERER_TYPE_UNDETERMINED so that
748 // content sniffing, etc. still take place.
749 // TODO(tommi): Clarify the intent here.
750 return (renderer == PolicySettings::RENDER_IN_CHROME_FRAME) ?
751 RENDERER_TYPE_CHROME_OPT_IN_URL : RENDERER_TYPE_UNDETERMINED;
[email protected]55604d72010-09-15 14:41:48752 }
753
[email protected]f7817822009-09-24 05:11:58754 RegKey config_key;
[email protected]e06f4d52011-01-19 07:28:46755 if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey,
756 KEY_READ) != ERROR_SUCCESS) {
[email protected]d8e13512010-09-22 17:02:58757 return RENDERER_TYPE_UNDETERMINED;
[email protected]e06f4d52011-01-19 07:28:46758 }
[email protected]f7817822009-09-24 05:11:58759
[email protected]d8e13512010-09-22 17:02:58760 RendererType renderer_type = RENDERER_TYPE_UNDETERMINED;
[email protected]7ab36c4f2010-08-11 03:47:43761
762 const wchar_t* url_list_name = NULL;
763 int render_in_cf_by_default = FALSE;
764 config_key.ReadValueDW(kEnableGCFRendererByDefault,
765 reinterpret_cast<DWORD*>(&render_in_cf_by_default));
766 if (render_in_cf_by_default) {
767 url_list_name = kRenderInHostUrlList;
[email protected]d8e13512010-09-22 17:02:58768 renderer_type = RENDERER_TYPE_CHROME_DEFAULT_RENDERER;
[email protected]7ab36c4f2010-08-11 03:47:43769 } else {
770 url_list_name = kRenderInGCFUrlList;
[email protected]f7817822009-09-24 05:11:58771 }
772
[email protected]7ab36c4f2010-08-11 03:47:43773 bool match_found = false;
[email protected]2d6503982010-10-17 04:41:54774 base::win::RegistryValueIterator url_list(config_key.Handle(), url_list_name);
[email protected]7ab36c4f2010-08-11 03:47:43775 while (!match_found && url_list.Valid()) {
[email protected]44935742010-09-10 08:18:46776 if (MatchPattern(url, url_list.Name())) {
[email protected]7ab36c4f2010-08-11 03:47:43777 match_found = true;
778 } else {
779 ++url_list;
780 }
781 }
782
783 if (match_found) {
[email protected]d8e13512010-09-22 17:02:58784 renderer_type = render_in_cf_by_default ?
785 RENDERER_TYPE_UNDETERMINED :
786 RENDERER_TYPE_CHROME_OPT_IN_URL;
[email protected]7ab36c4f2010-08-11 03:47:43787 }
788
[email protected]d8e13512010-09-22 17:02:58789 return renderer_type;
[email protected]f7817822009-09-24 05:11:58790}
791
[email protected]b22ef282009-12-11 19:31:56792HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker,
[email protected]7e3544b2010-01-22 00:02:34793 const wchar_t* headers, IBindCtx* bind_ctx,
794 const wchar_t* fragment) {
[email protected]b22ef282009-12-11 19:31:56795 DCHECK(browser);
796 DCHECK(moniker);
797 DCHECK(bind_ctx);
[email protected]f7817822009-09-24 05:11:58798
[email protected]b22ef282009-12-11 19:31:56799 ScopedComPtr<IWebBrowser2> web_browser2;
800 HRESULT hr = DoQueryService(SID_SWebBrowserApp, browser,
801 web_browser2.Receive());
802 DCHECK(web_browser2);
[email protected]d3451d832010-10-01 11:17:37803 DLOG_IF(WARNING, FAILED(hr)) << base::StringPrintf(L"SWebBrowserApp 0x%08X",
804 hr);
[email protected]b22ef282009-12-11 19:31:56805 if (FAILED(hr))
806 return hr;
[email protected]f7817822009-09-24 05:11:58807
[email protected]b22ef282009-12-11 19:31:56808 // Create a new bind context that's not associated with our callback.
809 // Calling RevokeBindStatusCallback doesn't disassociate the callback with
810 // the bind context in IE7. The returned bind context has the same
811 // implementation of GetRunningObjectTable as the bind context we held which
812 // basically delegates to ole32's GetRunningObjectTable. The object table
813 // is then used to determine if the moniker is already running and via
814 // that mechanism is associated with the same internet request as has already
815 // been issued.
816
817 // TODO(tommi): See if we can get HlinkSimpleNavigateToMoniker to work
818 // instead. Looks like we'll need to support IHTMLDocument2 (get_URL in
819 // particular), access to IWebBrowser2 etc.
820 // HlinkSimpleNavigateToMoniker(moniker, url, NULL, host, bind_context,
821 // NULL, 0, 0);
822
823 ScopedComPtr<IUriContainer> uri_container;
824 hr = uri_container.QueryFrom(moniker);
825
[email protected]b11a51dd2010-12-04 00:47:21826 base::win::ScopedVariant headers_var;
[email protected]a542e822010-01-16 00:30:04827 if (headers && headers[0])
828 headers_var.Set(headers);
829
[email protected]b22ef282009-12-11 19:31:56830 if (uri_container) {
831 // IE7 and IE8.
[email protected]5843d2a2010-01-12 14:38:14832 const IID* interface_ids[] = {
833 &IID_IWebBrowserPriv2IE7,
834 &IID_IWebBrowserPriv2IE8,
835 &IID_IWebBrowserPriv2IE8XP,
[email protected]94a3fbfa2010-01-30 00:44:24836 &IID_IWebBrowserPriv2IE8XPBeta,
[email protected]5843d2a2010-01-12 14:38:14837 };
838
839 ScopedComPtr<IWebBrowserPriv2Common, NULL> browser_priv2;
840 for (int i = 0; i < arraysize(interface_ids) && browser_priv2 == NULL;
841 ++i) {
842 hr = web_browser2.QueryInterface(*interface_ids[i],
843 reinterpret_cast<void**>(browser_priv2.Receive()));
[email protected]b22ef282009-12-11 19:31:56844 }
845
[email protected]5843d2a2010-01-12 14:38:14846 DCHECK(browser_priv2);
[email protected]b22ef282009-12-11 19:31:56847
[email protected]5843d2a2010-01-12 14:38:14848 if (browser_priv2) {
[email protected]b22ef282009-12-11 19:31:56849 ScopedComPtr<IUri> uri_obj;
850 uri_container->GetIUri(uri_obj.Receive());
851 DCHECK(uri_obj);
[email protected]a542e822010-01-16 00:30:04852
[email protected]7694e6e2011-01-15 01:40:20853 if (GetIEVersion() < IE_9) {
854 hr = browser_priv2->NavigateWithBindCtx2(
855 uri_obj, NULL, NULL, NULL, headers_var.AsInput(), bind_ctx,
856 const_cast<wchar_t*>(fragment));
857 } else {
858 IWebBrowserPriv2CommonIE9* browser_priv2_ie9 =
859 reinterpret_cast<IWebBrowserPriv2CommonIE9*>(browser_priv2.get());
860 hr = browser_priv2_ie9->NavigateWithBindCtx2(
861 uri_obj, NULL, NULL, NULL, headers_var.AsInput(), bind_ctx,
862 const_cast<wchar_t*>(fragment), 0);
863 }
[email protected]b22ef282009-12-11 19:31:56864 DLOG_IF(WARNING, FAILED(hr))
[email protected]d3451d832010-10-01 11:17:37865 << base::StringPrintf(L"NavigateWithBindCtx2 0x%08X", hr);
[email protected]b22ef282009-12-11 19:31:56866 }
867 } else {
868 // IE6
869 LPOLESTR url = NULL;
870 if (SUCCEEDED(hr = moniker->GetDisplayName(bind_ctx, NULL, &url))) {
[email protected]2b9a9f162010-10-19 20:30:45871 DVLOG(1) << __FUNCTION__ << " " << url;
[email protected]b22ef282009-12-11 19:31:56872 ScopedComPtr<IWebBrowserPriv> browser_priv;
873 if (SUCCEEDED(hr = browser_priv.QueryFrom(web_browser2))) {
[email protected]38d3d422010-03-16 22:24:26874 GURL target_url(url);
875 // On IE6 if the original URL has a fragment then the navigation
876 // attempt is ignored. To workaround this we strip the fragment from
877 // the url and initiate the navigation. When the active document loads
878 // we retrieve the original url with the fragment from the Navigation
879 // manager and use it.
880 if (target_url.has_ref()) {
881 url_parse::Component comp;
882 GURL::Replacements replacements;
883 replacements.SetRef("", comp);
884
885 target_url = target_url.ReplaceComponents(replacements);
886 fragment = NULL;
887 }
888
[email protected]b11a51dd2010-12-04 00:47:21889 base::win::ScopedVariant var_url(UTF8ToWide(target_url.spec()).c_str());
[email protected]b22ef282009-12-11 19:31:56890 hr = browser_priv->NavigateWithBindCtx(var_url.AsInput(), NULL, NULL,
[email protected]a542e822010-01-16 00:30:04891 NULL, headers_var.AsInput(),
[email protected]7e3544b2010-01-22 00:02:34892 bind_ctx,
893 const_cast<wchar_t*>(fragment));
[email protected]b22ef282009-12-11 19:31:56894 DLOG_IF(WARNING, FAILED(hr))
[email protected]d3451d832010-10-01 11:17:37895 << base::StringPrintf(L"NavigateWithBindCtx 0x%08X", hr);
[email protected]b22ef282009-12-11 19:31:56896 } else {
897 NOTREACHED();
898 }
899 ::CoTaskMemFree(url);
900 } else {
[email protected]d3451d832010-10-01 11:17:37901 DLOG(ERROR) << base::StringPrintf("GetDisplayName: 0x%08X", hr);
[email protected]b22ef282009-12-11 19:31:56902 }
903 }
[email protected]f7817822009-09-24 05:11:58904
905 return hr;
906}
907
[email protected]b22ef282009-12-11 19:31:56908void MarkBrowserOnThreadForCFNavigation(IBrowserService* browser) {
909 DCHECK(browser != NULL);
[email protected]ecdf6342010-01-22 18:49:47910 DCHECK(g_tls_browser_for_cf_navigation.Pointer()->Get() == NULL ||
911 g_tls_browser_for_cf_navigation.Pointer()->Get() == browser);
[email protected]b22ef282009-12-11 19:31:56912 g_tls_browser_for_cf_navigation.Pointer()->Set(browser);
913}
914
915bool CheckForCFNavigation(IBrowserService* browser, bool clear_flag) {
916 DCHECK(browser);
917 bool ret = (g_tls_browser_for_cf_navigation.Pointer()->Get() == browser);
918 if (ret && clear_flag)
919 g_tls_browser_for_cf_navigation.Pointer()->Set(NULL);
920 return ret;
921}
922
[email protected]d266ce82010-08-13 21:33:40923bool IsValidUrlScheme(const GURL& url, bool is_privileged) {
924 if (url.is_empty())
[email protected]f7817822009-09-24 05:11:58925 return false;
926
[email protected]d266ce82010-08-13 21:33:40927 if (url.SchemeIs(chrome::kHttpScheme) ||
928 url.SchemeIs(chrome::kHttpsScheme) ||
929 url.SchemeIs(chrome::kAboutScheme))
[email protected]f7817822009-09-24 05:11:58930 return true;
931
[email protected]7ce979a2009-10-29 02:07:45932 // Additional checking for view-source. Allow only http and https
933 // URLs in view source.
[email protected]d266ce82010-08-13 21:33:40934 if (url.SchemeIs(chrome::kViewSourceScheme)) {
935 GURL sub_url(url.path());
[email protected]7ce979a2009-10-29 02:07:45936 if (sub_url.SchemeIs(chrome::kHttpScheme) ||
937 sub_url.SchemeIs(chrome::kHttpsScheme))
938 return true;
939 else
940 return false;
941 }
942
[email protected]1f64fc02009-12-10 16:52:39943 if (is_privileged &&
[email protected]d266ce82010-08-13 21:33:40944 (url.SchemeIs(chrome::kDataScheme) ||
945 url.SchemeIs(chrome::kExtensionScheme)))
[email protected]10bf1a72009-10-01 16:00:21946 return true;
947
[email protected]f7817822009-09-24 05:11:58948 return false;
949}
[email protected]b55aaa62009-12-03 00:21:50950
951std::string GetRawHttpHeaders(IWinInetHttpInfo* info) {
952 DCHECK(info);
953
954 std::string buffer;
955
956 DWORD size = 0;
957 DWORD flags = 0;
958 DWORD reserved = 0;
959 HRESULT hr = info->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &size,
960 &flags, &reserved);
961 if (!size) {
962 DLOG(WARNING) << "Failed to query HTTP headers size. Error: " << hr;
963 } else {
964 buffer.resize(size + 1);
965 hr = info->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, &buffer[0],
966 &size, &flags, &reserved);
967 if (FAILED(hr)) {
968 DLOG(WARNING) << "Failed to query HTTP headers. Error: " << hr;
969 }
970 }
971
972 return buffer;
973}
[email protected]723f29922009-12-04 20:42:33974
975bool IsSubFrameRequest(IUnknown* service_provider) {
976 DCHECK(service_provider);
977
978 // We need to be able to get at an IWebBrowser2 if we are to decide whether
979 // this request originates from a non-top-level frame.
980 ScopedComPtr<IWebBrowser2> web_browser;
981 HRESULT hr = DoQueryService(IID_ITargetFrame2, service_provider,
982 web_browser.Receive());
983
[email protected]4974c8d2009-12-16 19:44:50984 bool is_sub_frame_request = false;
[email protected]723f29922009-12-04 20:42:33985 if (web_browser) {
986 // Now check to see if we are in a sub-frame.
987 ScopedComPtr<IHTMLWindow2> current_frame, parent_frame;
988 hr = DoQueryService(IID_IHTMLWindow2, service_provider,
989 current_frame.Receive());
990 if (current_frame) {
991 // Only the top level window will return self when get_parent is called.
992 current_frame->get_parent(parent_frame.Receive());
993 if (parent_frame != current_frame) {
[email protected]2b9a9f162010-10-19 20:30:45994 DVLOG(1) << "Sub frame detected";
[email protected]4974c8d2009-12-16 19:44:50995 is_sub_frame_request = true;
[email protected]723f29922009-12-04 20:42:33996 }
997 }
[email protected]3fbf614b2009-12-06 14:26:16998 } else {
[email protected]2b9a9f162010-10-19 20:30:45999 DVLOG(1) << "IsSubFrameRequest - no IWebBrowser2";
[email protected]4974c8d2009-12-16 19:44:501000 is_sub_frame_request = true;
[email protected]723f29922009-12-04 20:42:331001 }
1002
[email protected]4974c8d2009-12-16 19:44:501003 return is_sub_frame_request;
[email protected]723f29922009-12-04 20:42:331004}
[email protected]7bc272f2009-12-09 01:09:281005
1006bool IsHeadlessMode() {
1007 bool headless = GetConfigBool(false, kChromeFrameHeadlessMode);
1008 return headless;
1009}
1010
[email protected]67700a92010-09-18 07:43:581011bool IsAccessibleMode() {
1012 bool accessible = GetConfigBool(false, kChromeFrameAccessibleMode);
1013 return accessible;
1014}
1015
[email protected]11903b0d2010-03-26 23:54:341016bool IsUnpinnedMode() {
[email protected]ec18ca672010-09-02 13:39:501017 // We only check this value once and then cache it since changing the registry
1018 // once we've pinned the DLL won't have any effect.
1019 static bool unpinned = GetConfigBool(false, kChromeFrameUnpinnedMode);
[email protected]11903b0d2010-03-26 23:54:341020 return unpinned;
1021}
1022
[email protected]7e3544b2010-01-22 00:02:341023std::wstring GetActualUrlFromMoniker(IMoniker* moniker,
1024 IBindCtx* bind_context,
1025 const std::wstring& bho_url) {
1026 CComHeapPtr<WCHAR> display_name;
1027 moniker->GetDisplayName(bind_context, NULL, &display_name);
1028 std::wstring moniker_url = display_name;
1029
1030 GURL parsed_url(WideToUTF8(bho_url));
1031 if (!parsed_url.has_ref())
1032 return moniker_url;
1033
1034 if (StartsWith(bho_url, moniker_url, false) &&
1035 bho_url[moniker_url.length()] == L'#')
1036 return bho_url;
1037
1038 return moniker_url;
1039}
1040
[email protected]4e676aa2010-02-12 18:19:071041bool IsTopLevelWindow(HWND window) {
1042 long style = GetWindowLong(window, GWL_STYLE); // NOLINT
1043 if (!(style & WS_CHILD))
1044 return true;
1045
1046 HWND parent = GetParent(window);
1047 return !parent || (parent == GetDesktopWindow());
1048}
1049
[email protected]051236f2010-03-12 22:06:141050HRESULT RewindStream(IStream* stream) {
1051 HRESULT hr = E_POINTER;
1052 if (stream) {
1053 LARGE_INTEGER zero = {0};
1054 ULARGE_INTEGER new_pos = {0};
1055 hr = stream->Seek(zero, STREAM_SEEK_SET, &new_pos);
1056 }
1057
1058 return hr;
1059}
1060
[email protected]ecd9aa32010-03-01 19:34:391061std::wstring GuidToString(const GUID& guid) {
1062 std::wstring ret;
1063 ::StringFromGUID2(guid, WriteInto(&ret, 39), 39);
1064 return ret;
1065}
[email protected]80b5a8d2010-03-19 16:50:431066
1067int32 MapCookieStateToCookieAction(InternetCookieState cookie_state) {
1068 int32 cookie_action = COOKIEACTION_NONE;
1069
1070 switch (cookie_state) {
1071 case COOKIE_STATE_UNKNOWN:
1072 cookie_action = COOKIEACTION_NONE;
1073 break;
1074 case COOKIE_STATE_ACCEPT:
1075 cookie_action = COOKIEACTION_ACCEPT;
1076 break;
1077 case COOKIE_STATE_LEASH:
1078 cookie_action = COOKIEACTION_LEASH;
1079 break;
1080 case COOKIE_STATE_DOWNGRADE:
1081 cookie_action = COOKIEACTION_DOWNGRADE;
1082 break;
1083 case COOKIE_STATE_REJECT:
1084 cookie_action = COOKIEACTION_REJECT;
1085 break;
1086 default:
1087 cookie_action = COOKIEACTION_REJECT;
1088 break;
1089 }
1090 return cookie_action;
1091}
1092
[email protected]e33f99a12010-04-13 01:27:221093GURL GetUrlWithoutFragment(const wchar_t* url) {
1094 GURL parsed_url(url);
1095
1096 if (parsed_url.has_ref()) {
1097 url_parse::Component comp;
1098 GURL::Replacements replacements;
1099 replacements.SetRef("", comp);
1100
1101 parsed_url = parsed_url.ReplaceComponents(replacements);
1102 }
1103 return parsed_url;
1104}
1105
1106bool CompareUrlsWithoutFragment(const wchar_t* url1, const wchar_t* url2) {
1107 GURL parsed_url1 = GetUrlWithoutFragment(url1);
1108 GURL parsed_url2 = GetUrlWithoutFragment(url2);
1109 return parsed_url1 == parsed_url2;
1110}
1111
[email protected]6ee88532010-04-16 01:10:471112std::string FindReferrerFromHeaders(const wchar_t* headers,
1113 const wchar_t* additional_headers) {
1114 std::string referrer;
1115
1116 const wchar_t* both_headers[] = { headers, additional_headers };
1117 for (int i = 0; referrer.empty() && i < arraysize(both_headers); ++i) {
1118 if (!both_headers[i])
1119 continue;
1120 std::string raw_headers_utf8 = WideToUTF8(both_headers[i]);
1121 net::HttpUtil::HeadersIterator it(raw_headers_utf8.begin(),
1122 raw_headers_utf8.end(), "\r\n");
1123 while (it.GetNext()) {
1124 if (LowerCaseEqualsASCII(it.name(), "referer")) {
1125 referrer = it.values();
1126 break;
1127 }
1128 }
1129 }
1130
1131 return referrer;
1132}
1133
1134std::string GetHttpHeadersFromBinding(IBinding* binding) {
1135 if (binding == NULL) {
1136 DLOG(WARNING) << "GetHttpResponseStatus - no binding_";
1137 return std::string();
1138 }
1139
1140 ScopedComPtr<IWinInetHttpInfo> info;
1141 if (FAILED(info.QueryFrom(binding))) {
1142 DLOG(WARNING) << "Failed to QI for IWinInetHttpInfo";
1143 return std::string();
1144 }
1145
1146 return GetRawHttpHeaders(info);
1147}
1148
1149int GetHttpResponseStatusFromBinding(IBinding* binding) {
[email protected]2b9a9f162010-10-19 20:30:451150 DVLOG(1) << __FUNCTION__;
[email protected]6ee88532010-04-16 01:10:471151 if (binding == NULL) {
1152 DLOG(WARNING) << "GetHttpResponseStatus - no binding_";
1153 return 0;
1154 }
1155
1156 int http_status = 0;
1157
1158 ScopedComPtr<IWinInetHttpInfo> info;
1159 if (SUCCEEDED(info.QueryFrom(binding))) {
1160 char status[10] = {0};
1161 DWORD buf_size = sizeof(status);
1162 DWORD flags = 0;
1163 DWORD reserved = 0;
1164 if (SUCCEEDED(info->QueryInfo(HTTP_QUERY_STATUS_CODE, status, &buf_size,
1165 &flags, &reserved))) {
[email protected]c9c077792010-08-03 14:39:421166 base::StringToInt(status, &http_status);
[email protected]6ee88532010-04-16 01:10:471167 } else {
1168 NOTREACHED() << "Failed to get HTTP status";
1169 }
1170 } else {
1171 NOTREACHED() << "failed to get IWinInetHttpInfo from binding_";
1172 }
1173
1174 return http_status;
1175}
[email protected]830005d2010-04-20 23:28:521176
[email protected]2b3102be2010-04-21 20:07:351177CLIPFORMAT GetTextHtmlClipboardFormat() {
1178 static const CLIPFORMAT text_html = RegisterClipboardFormat(CFSTR_MIME_HTML);
1179 return text_html;
1180}
1181
1182bool IsTextHtmlMimeType(const wchar_t* mime_type) {
1183 return IsTextHtmlClipFormat(RegisterClipboardFormatW(mime_type));
1184}
1185
1186bool IsTextHtmlClipFormat(CLIPFORMAT cf) {
1187 return cf == GetTextHtmlClipboardFormat();
1188}
1189
[email protected]74ecb5a42010-09-03 00:44:351190bool IsSystemProcess() {
1191 bool is_system = false;
1192 CAccessToken process_token;
1193 if (process_token.GetProcessToken(TOKEN_QUERY, GetCurrentProcess())) {
1194 CSid logon_sid;
1195 if (process_token.GetUser(&logon_sid)) {
1196 is_system = logon_sid == Sids::System();
1197 }
1198 }
1199 return is_system;
1200}
1201
1202
[email protected]ce2b9f92010-06-09 16:54:121203std::string BindStatus2Str(ULONG bind_status) {
1204 std::string s;
1205 static const char* const bindstatus_txt[] = {
1206 "BINDSTATUS_FINDINGRESOURCE",
1207 "BINDSTATUS_CONNECTING",
1208 "BINDSTATUS_REDIRECTING",
1209 "BINDSTATUS_BEGINDOWNLOADDATA",
1210 "BINDSTATUS_DOWNLOADINGDATA",
1211 "BINDSTATUS_ENDDOWNLOADDATA",
1212 "BINDSTATUS_BEGINDOWNLOADCOMPONENTS",
1213 "BINDSTATUS_INSTALLINGCOMPONENTS",
1214 "BINDSTATUS_ENDDOWNLOADCOMPONENTS",
1215 "BINDSTATUS_USINGCACHEDCOPY",
1216 "BINDSTATUS_SENDINGREQUEST",
1217 "BINDSTATUS_CLASSIDAVAILABLE",
1218 "BINDSTATUS_MIMETYPEAVAILABLE",
1219 "BINDSTATUS_CACHEFILENAMEAVAILABLE",
1220 "BINDSTATUS_BEGINSYNCOPERATION",
1221 "BINDSTATUS_ENDSYNCOPERATION",
1222 "BINDSTATUS_BEGINUPLOADDATA",
1223 "BINDSTATUS_UPLOADINGDATA",
1224 "BINDSTATUS_ENDUPLOADINGDATA",
1225 "BINDSTATUS_PROTOCOLCLASSID",
1226 "BINDSTATUS_ENCODING",
1227 "BINDSTATUS_VERFIEDMIMETYPEAVAILABLE",
1228 "BINDSTATUS_CLASSINSTALLLOCATION",
1229 "BINDSTATUS_DECODING",
1230 "BINDSTATUS_LOADINGMIMEHANDLER",
1231 "BINDSTATUS_CONTENTDISPOSITIONATTACH",
1232 "BINDSTATUS_FILTERREPORTMIMETYPE",
1233 "BINDSTATUS_CLSIDCANINSTANTIATE",
1234 "BINDSTATUS_IUNKNOWNAVAILABLE",
1235 "BINDSTATUS_DIRECTBIND",
1236 "BINDSTATUS_RAWMIMETYPE",
1237 "BINDSTATUS_PROXYDETECTING",
1238 "BINDSTATUS_ACCEPTRANGES",
1239 "BINDSTATUS_COOKIE_SENT",
1240 "BINDSTATUS_COMPACT_POLICY_RECEIVED",
1241 "BINDSTATUS_COOKIE_SUPPRESSED",
1242 "BINDSTATUS_COOKIE_STATE_UNKNOWN",
1243 "BINDSTATUS_COOKIE_STATE_ACCEPT",
1244 "BINDSTATUS_COOKIE_STATE_REJECT",
1245 "BINDSTATUS_COOKIE_STATE_PROMPT",
1246 "BINDSTATUS_COOKIE_STATE_LEASH",
1247 "BINDSTATUS_COOKIE_STATE_DOWNGRADE",
1248 "BINDSTATUS_POLICY_HREF",
1249 "BINDSTATUS_P3P_HEADER",
1250 "BINDSTATUS_SESSION_COOKIE_RECEIVED",
1251 "BINDSTATUS_PERSISTENT_COOKIE_RECEIVED",
1252 "BINDSTATUS_SESSION_COOKIES_ALLOWED",
1253 "BINDSTATUS_CACHECONTROL",
1254 "BINDSTATUS_CONTENTDISPOSITIONFILENAME",
1255 "BINDSTATUS_MIMETEXTPLAINMISMATCH",
1256 "BINDSTATUS_PUBLISHERAVAILABLE",
1257 "BINDSTATUS_DISPLAYNAMEAVAILABLE",
1258 "BINDSTATUS_SSLUX_NAVBLOCKED",
1259 "BINDSTATUS_SERVER_MIMETYPEAVAILABLE",
1260 "BINDSTATUS_SNIFFED_CLASSIDAVAILABLE",
1261 "BINDSTATUS_64BIT_PROGRESS"
1262 };
1263 if (bind_status >= 1 && bind_status <= BINDSTATUS_64BIT_PROGRESS)
1264 s = bindstatus_txt[bind_status - 1];
1265 else
[email protected]d3451d832010-10-01 11:17:371266 s = base::StringPrintf("UnDoc[%#x]", bind_status);
[email protected]ce2b9f92010-06-09 16:54:121267 return s;
1268}
1269
1270std::string PiFlags2Str(DWORD flags) {
[email protected]bbfa9a12010-08-10 14:09:371271#define ADD_PI_FLAG(x) \
1272 if (flags & x) { \
1273 s.append(#x ## " "); \
1274 flags &= ~x; \
1275 }
1276
[email protected]ce2b9f92010-06-09 16:54:121277 std::string s = " flags ";
1278 ADD_PI_FLAG(PI_PARSE_URL);
1279 ADD_PI_FLAG(PI_FILTER_MODE);
1280 ADD_PI_FLAG(PI_FORCE_ASYNC);
1281 ADD_PI_FLAG(PI_USE_WORKERTHREAD);
1282 ADD_PI_FLAG(PI_MIMEVERIFICATION);
1283 ADD_PI_FLAG(PI_CLSIDLOOKUP);
1284 ADD_PI_FLAG(PI_DATAPROGRESS);
1285 ADD_PI_FLAG(PI_SYNCHRONOUS);
1286 ADD_PI_FLAG(PI_APARTMENTTHREADED);
1287 ADD_PI_FLAG(PI_CLASSINSTALL);
1288 ADD_PI_FLAG(PI_PASSONBINDCTX);
1289 ADD_PI_FLAG(PI_NOMIMEHANDLER);
1290 ADD_PI_FLAG(PI_LOADAPPDIRECT);
1291 ADD_PI_FLAG(PD_FORCE_SWITCH);
1292 ADD_PI_FLAG(PI_PREFERDEFAULTHANDLER);
1293
1294 if (flags)
[email protected]d3451d832010-10-01 11:17:371295 s += base::StringPrintf("+UnDoc[%#x]", flags);
[email protected]ce2b9f92010-06-09 16:54:121296 return s;
1297#undef ADD_PI_FLAG
1298}
1299
1300std::string Bscf2Str(DWORD flags) {
[email protected]bbfa9a12010-08-10 14:09:371301#define ADD_BSCF_FLAG(x) \
1302 if (flags & x) {\
1303 s.append(#x ## " "); \
1304 flags &= ~x; \
1305 }
1306
[email protected]ce2b9f92010-06-09 16:54:121307 std::string s = " flags ";
1308 ADD_BSCF_FLAG(BSCF_FIRSTDATANOTIFICATION)
1309 ADD_BSCF_FLAG(BSCF_INTERMEDIATEDATANOTIFICATION)
1310 ADD_BSCF_FLAG(BSCF_LASTDATANOTIFICATION)
1311 ADD_BSCF_FLAG(BSCF_DATAFULLYAVAILABLE)
1312 ADD_BSCF_FLAG(BSCF_AVAILABLEDATASIZEUNKNOWN)
1313 ADD_BSCF_FLAG(BSCF_SKIPDRAINDATAFORFILEURLS)
1314 ADD_BSCF_FLAG(BSCF_64BITLENGTHDOWNLOAD)
1315
1316 if (flags)
[email protected]d3451d832010-10-01 11:17:371317 s += base::StringPrintf("+UnDoc[%#x]", flags);
[email protected]ce2b9f92010-06-09 16:54:121318 return s;
1319#undef ADD_BSCF_FLAG
1320}
[email protected]897b26272010-06-11 02:23:441321
1322// Reads data from a stream into a string.
1323HRESULT ReadStream(IStream* stream, size_t size, std::string* data) {
1324 DCHECK(stream);
1325 DCHECK(data);
1326
1327 DWORD read = 0;
1328 HRESULT hr = stream->Read(WriteInto(data, size + 1), size, &read);
1329 DCHECK(hr == S_OK || hr == S_FALSE || hr == E_PENDING);
1330 if (read) {
1331 data->erase(read);
1332 DCHECK_EQ(read, data->length());
1333 } else {
1334 data->clear();
1335 // Return S_FALSE if the underlying stream returned S_OK and zero bytes.
1336 if (hr == S_OK)
1337 hr = S_FALSE;
1338 }
1339
1340 return hr;
1341}
1342
[email protected]d266ce82010-08-13 21:33:401343ChromeFrameUrl::ChromeFrameUrl() {
1344 Reset();
[email protected]c4e45b32010-07-28 21:15:151345}
1346
1347bool ChromeFrameUrl::Parse(const std::wstring& url) {
[email protected]d266ce82010-08-13 21:33:401348 Reset();
1349 parsed_url_ = GURL(url);
[email protected]c4e45b32010-07-28 21:15:151350
[email protected]d266ce82010-08-13 21:33:401351 if (parsed_url_.is_empty())
1352 return false;
[email protected]c4e45b32010-07-28 21:15:151353
[email protected]d266ce82010-08-13 21:33:401354 is_chrome_protocol_ = parsed_url_.SchemeIs(kGCFProtocol);
[email protected]c4e45b32010-07-28 21:15:151355 if (is_chrome_protocol_) {
[email protected]d266ce82010-08-13 21:33:401356 parsed_url_ = GURL(url.c_str() + lstrlen(kChromeProtocolPrefix));
1357 return true;
[email protected]c4e45b32010-07-28 21:15:151358 }
1359
[email protected]d266ce82010-08-13 21:33:401360 return ParseAttachExternalTabUrl();
[email protected]c4e45b32010-07-28 21:15:151361}
1362
1363bool ChromeFrameUrl::ParseAttachExternalTabUrl() {
[email protected]d266ce82010-08-13 21:33:401364 std::string query = parsed_url_.query();
1365 if (!StartsWithASCII(query, kAttachExternalTabPrefix, false)) {
1366 return parsed_url_.is_valid();
[email protected]e3a91e72010-06-17 01:19:041367 }
1368
[email protected]d266ce82010-08-13 21:33:401369 attach_to_external_tab_ = true;
1370 StringTokenizer tokenizer(query, "&");
[email protected]e3a91e72010-06-17 01:19:041371 // Skip over kChromeAttachExternalTabPrefix
1372 tokenizer.GetNext();
[email protected]e3a91e72010-06-17 01:19:041373 // Read the following items in order.
1374 // 1. cookie
1375 // 2. disposition
1376 // 3. dimension.x
1377 // 4. dimension.y
1378 // 5. dimension.width
1379 // 6. dimension.height.
1380 if (tokenizer.GetNext()) {
[email protected]d266ce82010-08-13 21:33:401381 char* end_ptr = 0;
1382 cookie_ = _strtoui64(tokenizer.token().c_str(), &end_ptr, 10);
[email protected]e3a91e72010-06-17 01:19:041383 } else {
1384 return false;
1385 }
1386
1387 if (tokenizer.GetNext()) {
[email protected]d266ce82010-08-13 21:33:401388 disposition_ = atoi(tokenizer.token().c_str());
[email protected]e3a91e72010-06-17 01:19:041389 } else {
1390 return false;
1391 }
1392
1393 if (tokenizer.GetNext()) {
[email protected]d266ce82010-08-13 21:33:401394 dimensions_.set_x(atoi(tokenizer.token().c_str()));
[email protected]e3a91e72010-06-17 01:19:041395 } else {
1396 return false;
1397 }
1398
1399 if (tokenizer.GetNext()) {
[email protected]d266ce82010-08-13 21:33:401400 dimensions_.set_y(atoi(tokenizer.token().c_str()));
[email protected]e3a91e72010-06-17 01:19:041401 } else {
1402 return false;
1403 }
1404
1405 if (tokenizer.GetNext()) {
[email protected]d266ce82010-08-13 21:33:401406 dimensions_.set_width(atoi(tokenizer.token().c_str()));
[email protected]e3a91e72010-06-17 01:19:041407 } else {
1408 return false;
1409 }
1410
1411 if (tokenizer.GetNext()) {
[email protected]d266ce82010-08-13 21:33:401412 dimensions_.set_height(atoi(tokenizer.token().c_str()));
[email protected]e3a91e72010-06-17 01:19:041413 } else {
1414 return false;
1415 }
[email protected]8103c7f2010-09-08 22:36:091416
1417 if (tokenizer.GetNext()) {
1418 profile_name_ = tokenizer.token();
[email protected]1d27bbe2010-09-10 00:32:061419 // Escape out special characters like %20, etc.
1420 profile_name_ = UnescapeURLComponent(profile_name_,
1421 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
[email protected]8103c7f2010-09-08 22:36:091422 } else {
1423 return false;
1424 }
1425
[email protected]c4e45b32010-07-28 21:15:151426 return true;
1427}
1428
[email protected]d266ce82010-08-13 21:33:401429void ChromeFrameUrl::Reset() {
1430 attach_to_external_tab_ = false;
1431 is_chrome_protocol_ = false;
1432 cookie_ = 0;
1433 dimensions_.SetRect(0, 0, 0, 0);
1434 disposition_ = 0;
[email protected]8103c7f2010-09-08 22:36:091435 profile_name_.clear();
[email protected]d266ce82010-08-13 21:33:401436}
[email protected]c4e45b32010-07-28 21:15:151437
[email protected]354bcba2010-12-14 04:34:431438bool CanNavigate(const GURL& url,
1439 NavigationConstraints* navigation_constraints) {
[email protected]d266ce82010-08-13 21:33:401440 if (!url.is_valid()) {
1441 DLOG(ERROR) << "Invalid URL passed to InitiateNavigation: " << url;
[email protected]c4e45b32010-07-28 21:15:151442 return false;
1443 }
1444
[email protected]354bcba2010-12-14 04:34:431445 if (!navigation_constraints) {
1446 NOTREACHED() << "Invalid NavigationConstraints passed in";
1447 return false;
1448 }
1449
[email protected]d266ce82010-08-13 21:33:401450 // No sanity checks if unsafe URLs are allowed
[email protected]354bcba2010-12-14 04:34:431451 if (navigation_constraints->AllowUnsafeUrls())
[email protected]d266ce82010-08-13 21:33:401452 return true;
1453
[email protected]354bcba2010-12-14 04:34:431454 if (!navigation_constraints->IsSchemeAllowed(url)) {
[email protected]d266ce82010-08-13 21:33:401455 DLOG(WARNING) << __FUNCTION__ << " Disallowing navigation to url: " << url;
1456 return false;
1457 }
1458
[email protected]354bcba2010-12-14 04:34:431459 if (!navigation_constraints->IsZoneAllowed(url)) {
1460 DLOG(WARNING) << __FUNCTION__
1461 << " Disallowing navigation to restricted url: " << url;
1462 return false;
[email protected]c4e45b32010-07-28 21:15:151463 }
[email protected]e3a91e72010-06-17 01:19:041464 return true;
1465}
[email protected]e67a73f42010-08-31 15:05:021466
[email protected]ec18ca672010-09-02 13:39:501467void PinModule() {
1468 static bool s_pinned = false;
1469 if (!s_pinned && !IsUnpinnedMode()) {
1470 FilePath module_path;
1471 if (PathService::Get(base::FILE_MODULE, &module_path)) {
1472 HMODULE unused;
1473 if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN,
1474 module_path.value().c_str(), &unused)) {
1475 NOTREACHED() << "Failed to pin module " << module_path.value().c_str()
1476 << " , last error: " << GetLastError();
1477 } else {
1478 s_pinned = true;
1479 }
1480 } else {
1481 NOTREACHED() << "Could not get module path.";
1482 }
1483 }
1484}
[email protected]d9d8f0c2010-09-17 21:47:161485
1486void WaitWithMessageLoop(HANDLE* handles, int count, DWORD timeout) {
1487 base::Time now = base::Time::Now();
1488 base::Time wait_until = now + base::TimeDelta::FromMilliseconds(timeout);
1489
1490 while (wait_until >= now) {
1491 base::TimeDelta wait_time = wait_until - now;
1492 DWORD wait = MsgWaitForMultipleObjects(
1493 count, handles, FALSE, static_cast<DWORD>(wait_time.InMilliseconds()),
1494 QS_ALLINPUT);
1495 switch (wait) {
1496 case WAIT_OBJECT_0:
1497 case WAIT_TIMEOUT:
1498 return;
1499
1500 case WAIT_OBJECT_0 + 1: {
1501 MSG msg = {0};
1502 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
1503 TranslateMessage(&msg);
1504 DispatchMessage(&msg);
1505 }
1506 break;
1507 }
1508
1509 default: {
1510 NOTREACHED() << "Unexpected return from MsgWaitForMultipleObjects :"
1511 << wait;
1512 return;
1513 }
1514 }
1515 now = base::Time::Now();
1516 }
1517}
1518
[email protected]8e698b6c2010-10-26 20:29:121519// Returns -1 if no directive is found, std::numeric_limits<int>::max() if the
1520// directive matches all IE versions ('Chrome=1') or the maximum IE version
1521// matched ('Chrome=IE7' => 7)
1522int GetXUaCompatibleDirective(const std::string& directive, char delimiter) {
[email protected]b57f03232010-10-25 14:14:391523 net::HttpUtil::NameValuePairsIterator name_value_pairs(directive.begin(),
1524 directive.end(),
[email protected]8e698b6c2010-10-26 20:29:121525 delimiter);
[email protected]b57f03232010-10-25 14:14:391526
1527 // Loop through the values until a valid 'Chrome=<FILTER>' entry is found
1528 while (name_value_pairs.GetNext()) {
1529 if (!LowerCaseEqualsASCII(name_value_pairs.name_begin(),
1530 name_value_pairs.name_end(),
1531 "chrome")) {
1532 continue;
1533 }
1534 std::string::const_iterator filter_begin = name_value_pairs.value_begin();
1535 std::string::const_iterator filter_end = name_value_pairs.value_end();
1536
1537 size_t filter_length = filter_end - filter_begin;
1538
1539 if (filter_length == 1 && *filter_begin == '1') {
[email protected]8e698b6c2010-10-26 20:29:121540 return std::numeric_limits<int>::max();
[email protected]b57f03232010-10-25 14:14:391541 }
1542
1543 if (filter_length < 3 ||
1544 !LowerCaseEqualsASCII(filter_begin, filter_begin + 2, "ie") ||
1545 !isdigit(*(filter_begin + 2))) { // ensure no leading +/-
1546 continue;
1547 }
1548
1549 int header_ie_version = 0;
1550 if (!base::StringToInt(filter_begin + 2, filter_end, &header_ie_version) ||
1551 header_ie_version == 0) { // ensure it's not a sequence of 0's
1552 continue;
1553 }
1554
1555 // The first valid directive we find wins, whether it matches or not
[email protected]8e698b6c2010-10-26 20:29:121556 return header_ie_version;
[email protected]b57f03232010-10-25 14:14:391557 }
[email protected]8e698b6c2010-10-26 20:29:121558 return -1;
1559}
1560
1561bool CheckXUaCompatibleDirective(const std::string& directive,
1562 int ie_major_version) {
1563 int header_ie_version = GetXUaCompatibleDirective(directive, ';');
1564 if (header_ie_version == -1) {
1565 header_ie_version = GetXUaCompatibleDirective(directive, ',');
1566 }
1567 return header_ie_version >= ie_major_version;
[email protected]b57f03232010-10-25 14:14:391568}
1569
[email protected]5ac670a2010-10-04 23:07:401570void EnumerateKeyValues(HKEY parent_key, const wchar_t* sub_key_name,
1571 std::vector<std::wstring>* values) {
1572 DCHECK(values);
[email protected]2d6503982010-10-17 04:41:541573 base::win::RegistryValueIterator url_list(parent_key, sub_key_name);
[email protected]5ac670a2010-10-04 23:07:401574 while (url_list.Valid()) {
1575 values->push_back(url_list.Value());
1576 ++url_list;
1577 }
1578}
[email protected]6a8515e42010-12-16 19:38:521579
1580std::wstring GetCurrentModuleVersion() {
1581 scoped_ptr<FileVersionInfo> module_version_info(
1582 FileVersionInfo::CreateFileVersionInfoForCurrentModule());
1583 DCHECK(module_version_info.get() != NULL);
1584 return module_version_info->file_version();
1585}