OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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. | |
4 | |
5 #include "chrome_frame/utils.h" | |
6 | |
7 #include <atlsafe.h> | |
8 #include <atlsecurity.h> | |
9 #include <htiframe.h> | |
10 #include <mshtml.h> | |
11 #include <shlobj.h> | |
12 #include <limits> | |
13 | |
14 #include "base/file_version_info.h" | |
15 #include "base/lazy_instance.h" | |
16 #include "base/logging.h" | |
17 #include "base/path_service.h" | |
18 #include "base/strings/string_number_conversions.h" | |
19 #include "base/strings/string_piece.h" | |
20 #include "base/strings/string_tokenizer.h" | |
21 #include "base/strings/string_util.h" | |
22 #include "base/strings/stringprintf.h" | |
23 #include "base/strings/utf_string_conversions.h" | |
24 #include "base/threading/thread_local.h" | |
25 #include "base/win/registry.h" | |
26 #include "base/win/scoped_bstr.h" | |
27 #include "base/win/scoped_comptr.h" | |
28 #include "base/win/scoped_variant.h" | |
29 #include "chrome/common/automation_messages.h" | |
30 #include "chrome/common/chrome_paths_internal.h" | |
31 #include "chrome/common/url_constants.h" | |
32 #include "chrome/installer/util/chrome_frame_distribution.h" | |
33 #include "chrome_frame/chrome_tab.h" | |
34 #include "chrome_frame/extra_system_apis.h" | |
35 #include "chrome_frame/html_utils.h" | |
36 #include "chrome_frame/navigation_constraints.h" | |
37 #include "chrome_frame/policy_settings.h" | |
38 #include "chrome_frame/registry_list_preferences_holder.h" | |
39 #include "chrome_frame/simple_resource_loader.h" | |
40 #include "extensions/common/constants.h" | |
41 #include "grit/chromium_strings.h" | |
42 #include "net/base/escape.h" | |
43 #include "net/http/http_util.h" | |
44 #include "ui/base/models/menu_model.h" | |
45 #include "url/gurl.h" | |
46 #include "url/url_canon.h" | |
47 | |
48 using base::win::RegKey; | |
49 | |
50 // Note that these values are all lower case and are compared to | |
51 // lower-case-transformed values. | |
52 const char kGCFProtocol[] = "gcf"; | |
53 const wchar_t kBodyTag[] = L"body"; | |
54 const wchar_t kContentAttribName[] = L"content"; | |
55 const wchar_t kChromeContentPrefix[] = L"chrome="; | |
56 const wchar_t kChromeMimeType[] = L"application/chromepage"; | |
57 const wchar_t kChromeProtocolPrefix[] = L"gcf:"; | |
58 const wchar_t kHttpEquivAttribName[] = L"http-equiv"; | |
59 const wchar_t kIexploreProfileName[] = L"iexplore"; | |
60 const wchar_t kMetaTag[] = L"meta"; | |
61 const wchar_t kRundllProfileName[] = L"rundll32"; | |
62 const wchar_t kXUACompatValue[] = L"x-ua-compatible"; | |
63 | |
64 // Registry key and value names related to Chrome Frame configuration options. | |
65 const wchar_t kAllowUnsafeURLs[] = L"AllowUnsafeURLs"; | |
66 const wchar_t kChromeFrameConfigKey[] = L"Software\\Google\\ChromeFrame"; | |
67 const wchar_t kEnableBuggyBhoIntercept[] = L"EnableBuggyBhoIntercept"; | |
68 const wchar_t kEnableGCFRendererByDefault[] = L"IsDefaultRenderer"; | |
69 const wchar_t kSkipGCFMetadataCheck[] = L"SkipGCFMetadataCheck"; | |
70 const wchar_t kExcludeUAFromDomainList[] = L"ExcludeUAFromDomain"; | |
71 const wchar_t kPatchProtocols[] = L"PatchProtocols"; | |
72 const wchar_t kRenderInGCFUrlList[] = L"RenderInGcfUrls"; | |
73 const wchar_t kRenderInHostUrlList[] = L"RenderInHostUrls"; | |
74 | |
75 static const wchar_t kChromeFramePersistNPAPIReg[] = L"PersistNPAPIReg"; | |
76 | |
77 const char kAttachExternalTabPrefix[] = "attach_external_tab"; | |
78 | |
79 // Indicates that we are running in a test environment, where execptions, etc | |
80 // are handled by the chrome test crash server. | |
81 const wchar_t kChromeFrameHeadlessMode[] = L"ChromeFrameHeadlessMode"; | |
82 | |
83 // Indicates that we are running in an environment that expects chrome renderer | |
84 // accessibility to be enabled for use in automation tests. | |
85 const wchar_t kChromeFrameAccessibleMode[] = L"ChromeFrameAccessibleMode"; | |
86 | |
87 // Indicates that we are running in an environment that wishes to avoid | |
88 // DLL pinning, such as the perf tests. | |
89 const wchar_t kChromeFrameUnpinnedMode[] = L"kChromeFrameUnpinnedMode"; | |
90 | |
91 // Controls whether we download subresources, etc on the chrome frame page in | |
92 // the background worker thread. Defaults to true. | |
93 const wchar_t kUseBackgroundThreadForSubResources[] | |
94 = L"BackgroundHTTPWorkerThread"; | |
95 | |
96 // {1AF32B6C-A3BA-48B9-B24E-8AA9C41F6ECD} | |
97 static const IID IID_IWebBrowserPriv2IE7 = { 0x1AF32B6C, 0xA3BA, 0x48B9, | |
98 { 0xB2, 0x4E, 0x8A, 0xA9, 0xC4, 0x1F, 0x6E, 0xCD } }; | |
99 | |
100 // {3ED72303-6FFC-4214-BA90-FAF1862DEC8A} | |
101 static const IID IID_IWebBrowserPriv2IE8 = { 0x3ED72303, 0x6FFC, 0x4214, | |
102 { 0xBA, 0x90, 0xFA, 0xF1, 0x86, 0x2D, 0xEC, 0x8A } }; | |
103 | |
104 // {486F6159-9F3F-4827-82D4-283CEF397733} | |
105 static const IID IID_IWebBrowserPriv2IE8XP = { 0x486F6159, 0x9F3F, 0x4827, | |
106 { 0x82, 0xD4, 0x28, 0x3C, 0xEF, 0x39, 0x77, 0x33 } }; | |
107 | |
108 // {38339692-0BC9-46CB-8E5C-4677A5C83DD5} | |
109 static const IID IID_IWebBrowserPriv2IE8XPBeta = { 0x38339692, 0x0BC9, 0x46CB, | |
110 { 0x8E, 0x5C, 0x46, 0x77, 0xA5, 0xC8, 0x3D, 0xD5 } }; | |
111 | |
112 namespace { | |
113 | |
114 // A flag used to signal when an active browser instance on the current thread | |
115 // is loading a Chrome Frame document. There's no reference stored with the | |
116 // pointer so it should not be dereferenced and used for comparison against a | |
117 // living instance only. | |
118 base::LazyInstance<base::ThreadLocalPointer<IBrowserService> > | |
119 g_tls_browser_for_cf_navigation = LAZY_INSTANCE_INITIALIZER; | |
120 | |
121 // Holds the cached preferences for the per-url render type settings. | |
122 base::LazyInstance<RegistryListPreferencesHolder>::Leaky | |
123 g_render_type_for_url_holder; | |
124 | |
125 // Holds the cached preferences for the per-url user agent filter. | |
126 base::LazyInstance<RegistryListPreferencesHolder>::Leaky | |
127 g_user_agent_filter_holder; | |
128 | |
129 } // end anonymous namespace | |
130 | |
131 HRESULT UtilRegisterTypeLib(HINSTANCE tlb_instance, | |
132 LPCOLESTR index, | |
133 bool for_current_user_only) { | |
134 CComBSTR path; | |
135 CComPtr<ITypeLib> type_lib; | |
136 HRESULT hr = AtlLoadTypeLib(tlb_instance, index, &path, &type_lib); | |
137 if (SUCCEEDED(hr)) { | |
138 hr = UtilRegisterTypeLib(type_lib, path, NULL, for_current_user_only); | |
139 } | |
140 return hr; | |
141 } | |
142 | |
143 HRESULT UtilUnRegisterTypeLib(HINSTANCE tlb_instance, | |
144 LPCOLESTR index, | |
145 bool for_current_user_only) { | |
146 CComBSTR path; | |
147 CComPtr<ITypeLib> type_lib; | |
148 HRESULT hr = AtlLoadTypeLib(tlb_instance, index, &path, &type_lib); | |
149 if (SUCCEEDED(hr)) { | |
150 hr = UtilUnRegisterTypeLib(type_lib, for_current_user_only); | |
151 } | |
152 return hr; | |
153 } | |
154 | |
155 HRESULT UtilRegisterTypeLib(LPCWSTR typelib_path, | |
156 bool for_current_user_only) { | |
157 if (NULL == typelib_path) { | |
158 return E_INVALIDARG; | |
159 } | |
160 CComBSTR path; | |
161 CComPtr<ITypeLib> type_lib; | |
162 HRESULT hr = ::LoadTypeLib(typelib_path, &type_lib); | |
163 if (SUCCEEDED(hr)) { | |
164 hr = UtilRegisterTypeLib(type_lib, | |
165 typelib_path, | |
166 NULL, | |
167 for_current_user_only); | |
168 } | |
169 return hr; | |
170 } | |
171 | |
172 HRESULT UtilUnRegisterTypeLib(LPCWSTR typelib_path, | |
173 bool for_current_user_only) { | |
174 CComPtr<ITypeLib> type_lib; | |
175 HRESULT hr = ::LoadTypeLib(typelib_path, &type_lib); | |
176 if (SUCCEEDED(hr)) { | |
177 hr = UtilUnRegisterTypeLib(type_lib, for_current_user_only); | |
178 } | |
179 return hr; | |
180 } | |
181 | |
182 HRESULT UtilRegisterTypeLib(ITypeLib* typelib, | |
183 LPCWSTR typelib_path, | |
184 LPCWSTR help_dir, | |
185 bool for_current_user_only) { | |
186 typedef HRESULT(WINAPI *RegisterTypeLibPrototype)(ITypeLib FAR* type_lib, | |
187 OLECHAR FAR* full_path, | |
188 OLECHAR FAR* help_dir); | |
189 LPCSTR function_name = | |
190 for_current_user_only ? "RegisterTypeLibForUser" : "RegisterTypeLib"; | |
191 RegisterTypeLibPrototype reg_tlb = | |
192 reinterpret_cast<RegisterTypeLibPrototype>( | |
193 GetProcAddress(GetModuleHandle(_T("oleaut32.dll")), | |
194 function_name)); | |
195 if (NULL == reg_tlb) { | |
196 return E_FAIL; | |
197 } | |
198 return reg_tlb(typelib, | |
199 const_cast<OLECHAR*>(typelib_path), | |
200 const_cast<OLECHAR*>(help_dir)); | |
201 } | |
202 | |
203 HRESULT UtilUnRegisterTypeLib(ITypeLib* typelib, | |
204 bool for_current_user_only) { | |
205 if (NULL == typelib) { | |
206 return E_INVALIDARG; | |
207 } | |
208 typedef HRESULT(WINAPI *UnRegisterTypeLibPrototype)( | |
209 REFGUID libID, | |
210 unsigned short wVerMajor, // NOLINT | |
211 unsigned short wVerMinor, // NOLINT | |
212 LCID lcid, | |
213 SYSKIND syskind); | |
214 LPCSTR function_name = | |
215 for_current_user_only ? "UnRegisterTypeLibForUser" : "UnRegisterTypeLib"; | |
216 | |
217 UnRegisterTypeLibPrototype unreg_tlb = | |
218 reinterpret_cast<UnRegisterTypeLibPrototype>( | |
219 GetProcAddress(GetModuleHandle(_T("oleaut32.dll")), | |
220 function_name)); | |
221 if (NULL == unreg_tlb) { | |
222 return E_FAIL; | |
223 } | |
224 TLIBATTR* tla = NULL; | |
225 HRESULT hr = typelib->GetLibAttr(&tla); | |
226 if (SUCCEEDED(hr)) { | |
227 hr = unreg_tlb(tla->guid, | |
228 tla->wMajorVerNum, | |
229 tla->wMinorVerNum, | |
230 tla->lcid, | |
231 tla->syskind); | |
232 typelib->ReleaseTLibAttr(tla); | |
233 } | |
234 return hr; | |
235 } | |
236 | |
237 bool UtilRemovePersistentNPAPIMarker() { | |
238 BrowserDistribution* cf_dist = BrowserDistribution::GetDistribution(); | |
239 std::wstring cf_state_key_path(cf_dist->GetStateKey()); | |
240 RegKey cf_state_key; | |
241 | |
242 LONG result = cf_state_key.Open(HKEY_LOCAL_MACHINE, cf_state_key_path.c_str(), | |
243 KEY_SET_VALUE); | |
244 if (result == ERROR_SUCCESS) | |
245 result = cf_state_key.DeleteValue(kChromeFramePersistNPAPIReg); | |
246 return (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); | |
247 } | |
248 | |
249 HRESULT UtilGetXUACompatContentValue(const std::wstring& html_string, | |
250 std::wstring* content_value) { | |
251 if (!content_value) { | |
252 return E_POINTER; | |
253 } | |
254 | |
255 // Fail fast if the string X-UA-Compatible isn't in html_string | |
256 if (StringToLowerASCII(html_string).find(kXUACompatValue) == | |
257 std::wstring::npos) { | |
258 return E_FAIL; | |
259 } | |
260 | |
261 HTMLScanner scanner(html_string.c_str()); | |
262 | |
263 // Build the list of meta tags that occur before the body tag is hit. | |
264 HTMLScanner::StringRangeList tag_list; | |
265 scanner.GetTagsByName(kMetaTag, &tag_list, kBodyTag); | |
266 | |
267 // Search the list of meta tags for one with an http-equiv="X-UA-Compatible" | |
268 // attribute. | |
269 HTMLScanner::StringRange attribute; | |
270 std::string search_attribute_ascii(WideToASCII(kXUACompatValue)); | |
271 HTMLScanner::StringRangeList::const_iterator tag_list_iter(tag_list.begin()); | |
272 for (; tag_list_iter != tag_list.end(); tag_list_iter++) { | |
273 if (!tag_list_iter->GetTagAttribute(kHttpEquivAttribName, &attribute)) { | |
274 continue; | |
275 } | |
276 | |
277 // We found an http-equiv meta tag, check its value using the ascii | |
278 // case-insensitive comparison method. | |
279 if (!attribute.LowerCaseEqualsASCII(search_attribute_ascii.c_str())) { | |
280 continue; | |
281 } | |
282 | |
283 // We found our X-UA-Compatible meta tag so look for and extract | |
284 // the value of the content attribute. | |
285 if (!tag_list_iter->GetTagAttribute(kContentAttribName, &attribute)) { | |
286 continue; | |
287 } | |
288 | |
289 // Found the content string, copy and return. | |
290 content_value->assign(attribute.Copy()); | |
291 return S_OK; | |
292 } | |
293 | |
294 return E_FAIL; | |
295 } | |
296 | |
297 void DisplayVersionMismatchWarning(HWND parent, | |
298 const std::string& server_version) { | |
299 // Obtain the current module version. | |
300 scoped_ptr<FileVersionInfo> module_version_info( | |
301 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); | |
302 base::string16 version_string(module_version_info->file_version()); | |
303 std::wstring wide_server_version; | |
304 if (server_version.empty()) { | |
305 wide_server_version = SimpleResourceLoader::Get(IDS_VERSIONUNKNOWN); | |
306 } else { | |
307 wide_server_version = base::ASCIIToWide(server_version); | |
308 } | |
309 std::wstring title = SimpleResourceLoader::Get(IDS_VERSIONMISMATCH_HEADER); | |
310 std::wstring message; | |
311 base::SStringPrintf(&message, | |
312 SimpleResourceLoader::Get(IDS_VERSIONMISMATCH).c_str(), | |
313 wide_server_version.c_str(), | |
314 version_string.c_str()); | |
315 | |
316 ::MessageBox(parent, message.c_str(), title.c_str(), MB_OK); | |
317 } | |
318 | |
319 std::string CreateJavascript(const std::string& function_name, | |
320 const std::string args) { | |
321 std::string script_string = "javascript:"; | |
322 script_string += function_name + "("; | |
323 if (!args.empty()) { | |
324 script_string += "'"; | |
325 script_string += args; | |
326 script_string += "'"; | |
327 } | |
328 script_string += ")"; | |
329 return script_string; | |
330 } | |
331 | |
332 AddRefModule::AddRefModule() { | |
333 // TODO(tommi): Override the module's Lock/Unlock methods to call | |
334 // npapi::SetValue(NPPVpluginKeepLibraryInMemory) and keep the dll loaded | |
335 // while the module's refcount is > 0. Only do this when we're being | |
336 // used as an NPAPI module. | |
337 _pAtlModule->Lock(); | |
338 } | |
339 | |
340 | |
341 AddRefModule::~AddRefModule() { | |
342 _pAtlModule->Unlock(); | |
343 } | |
344 | |
345 bool IsChrome(RendererType renderer_type) { | |
346 DCHECK_GE(renderer_type, RENDERER_TYPE_UNDETERMINED); | |
347 DCHECK_LE(renderer_type, RENDERER_TYPE_OTHER); | |
348 return renderer_type >= RENDERER_TYPE_CHROME_MIN && | |
349 renderer_type <= RENDERER_TYPE_CHROME_MAX; | |
350 } | |
351 | |
352 namespace { | |
353 const char kIEImageName[] = "iexplore.exe"; | |
354 } // namespace | |
355 | |
356 std::wstring GetHostProcessName(bool include_extension) { | |
357 base::FilePath exe; | |
358 if (PathService::Get(base::FILE_EXE, &exe)) | |
359 exe = exe.BaseName(); | |
360 if (!include_extension) { | |
361 exe = exe.RemoveExtension(); | |
362 } | |
363 return exe.value(); | |
364 } | |
365 | |
366 BrowserType GetBrowserType() { | |
367 static BrowserType browser_type = BROWSER_INVALID; | |
368 | |
369 if (browser_type == BROWSER_INVALID) { | |
370 std::wstring exe(GetHostProcessName(true)); | |
371 if (!exe.empty()) { | |
372 std::wstring::const_iterator begin = exe.begin(); | |
373 std::wstring::const_iterator end = exe.end(); | |
374 if (LowerCaseEqualsASCII(begin, end, kIEImageName)) { | |
375 browser_type = BROWSER_IE; | |
376 } else { | |
377 browser_type = BROWSER_UNKNOWN; | |
378 } | |
379 } else { | |
380 NOTREACHED(); | |
381 } | |
382 } | |
383 | |
384 return browser_type; | |
385 } | |
386 | |
387 uint32 GetIEMajorVersion() { | |
388 static uint32 ie_major_version = UINT_MAX; | |
389 | |
390 if (ie_major_version == UINT_MAX) { | |
391 wchar_t exe_path[MAX_PATH]; | |
392 HMODULE mod = GetModuleHandle(NULL); | |
393 GetModuleFileName(mod, exe_path, arraysize(exe_path) - 1); | |
394 std::wstring exe_name = base::FilePath(exe_path).BaseName().value(); | |
395 if (!LowerCaseEqualsASCII(exe_name, kIEImageName)) { | |
396 ie_major_version = 0; | |
397 } else { | |
398 uint32 high = 0; | |
399 uint32 low = 0; | |
400 if (GetModuleVersion(mod, &high, &low)) { | |
401 ie_major_version = HIWORD(high); | |
402 } else { | |
403 ie_major_version = 0; | |
404 } | |
405 } | |
406 } | |
407 | |
408 return ie_major_version; | |
409 } | |
410 | |
411 IEVersion GetIEVersion() { | |
412 static IEVersion ie_version = IE_INVALID; | |
413 | |
414 if (ie_version == IE_INVALID) { | |
415 uint32 major_version = GetIEMajorVersion(); | |
416 switch (major_version) { | |
417 case 0: | |
418 ie_version = NON_IE; | |
419 break; | |
420 case 6: | |
421 ie_version = IE_6; | |
422 break; | |
423 case 7: | |
424 ie_version = IE_7; | |
425 break; | |
426 case 8: | |
427 ie_version = IE_8; | |
428 break; | |
429 case 9: | |
430 ie_version = IE_9; | |
431 break; | |
432 case 10: | |
433 ie_version = IE_10; | |
434 break; | |
435 default: | |
436 ie_version = (major_version >= 11) ? IE_11 : IE_UNSUPPORTED; | |
437 break; | |
438 } | |
439 } | |
440 | |
441 return ie_version; | |
442 } | |
443 | |
444 base::FilePath GetIETemporaryFilesFolder() { | |
445 LPITEMIDLIST tif_pidl = NULL; | |
446 HRESULT hr = SHGetFolderLocation(NULL, CSIDL_INTERNET_CACHE, NULL, | |
447 SHGFP_TYPE_CURRENT, &tif_pidl); | |
448 if (SUCCEEDED(hr) && tif_pidl) { | |
449 base::win::ScopedComPtr<IShellFolder> parent_folder; | |
450 LPITEMIDLIST relative_pidl = NULL; | |
451 hr = SHBindToParent(tif_pidl, IID_IShellFolder, | |
452 reinterpret_cast<void**>(parent_folder.Receive()), | |
453 const_cast<LPCITEMIDLIST*>(&relative_pidl)); | |
454 if (SUCCEEDED(hr) && relative_pidl) { | |
455 STRRET path = {0}; | |
456 hr = parent_folder->GetDisplayNameOf(relative_pidl, | |
457 SHGDN_NORMAL | SHGDN_FORPARSING, | |
458 &path); | |
459 DCHECK(SUCCEEDED(hr)); | |
460 base::win::ScopedBstr temp_internet_files_bstr; | |
461 StrRetToBSTR(&path, relative_pidl, temp_internet_files_bstr.Receive()); | |
462 base::FilePath temp_internet_files( | |
463 static_cast<BSTR>(temp_internet_files_bstr)); | |
464 ILFree(tif_pidl); | |
465 return temp_internet_files; | |
466 } else { | |
467 NOTREACHED() << "SHBindToParent failed with Error:" << hr; | |
468 ILFree(tif_pidl); | |
469 } | |
470 } else { | |
471 NOTREACHED() << "SHGetFolderLocation for internet cache failed. Error:" | |
472 << hr; | |
473 } | |
474 // As a last ditch effort we use the SHGetFolderPath function to retrieve the | |
475 // path. This function has a limitation of MAX_PATH. | |
476 wchar_t path[MAX_PATH + 1] = {0}; | |
477 hr = SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL, SHGFP_TYPE_CURRENT, | |
478 path); | |
479 if (SUCCEEDED(hr)) { | |
480 return base::FilePath(path); | |
481 } else { | |
482 NOTREACHED() << "SHGetFolderPath for internet cache failed. Error:" | |
483 << hr; | |
484 } | |
485 return base::FilePath(); | |
486 } | |
487 | |
488 bool IsIEInPrivate() { | |
489 typedef BOOL (WINAPI* IEIsInPrivateBrowsingPtr)(); | |
490 bool incognito_mode = false; | |
491 HMODULE h = GetModuleHandle(L"ieframe.dll"); | |
492 if (h) { | |
493 IEIsInPrivateBrowsingPtr IsInPrivate = | |
494 reinterpret_cast<IEIsInPrivateBrowsingPtr>(GetProcAddress(h, | |
495 "IEIsInPrivateBrowsing")); | |
496 if (IsInPrivate) { | |
497 incognito_mode = !!IsInPrivate(); | |
498 } | |
499 } | |
500 | |
501 return incognito_mode; | |
502 } | |
503 | |
504 HRESULT DoFileDownloadInIE(const wchar_t* url) { | |
505 DCHECK(url); | |
506 | |
507 HMODULE mod = ::GetModuleHandleA("ieframe.dll"); | |
508 if (!mod) | |
509 mod = ::GetModuleHandleA("shdocvw.dll"); | |
510 | |
511 if (!mod) { | |
512 NOTREACHED(); | |
513 return E_UNEXPECTED; | |
514 } | |
515 | |
516 typedef HRESULT (WINAPI* DoFileDownloadFn)(const wchar_t*); | |
517 DoFileDownloadFn fn = reinterpret_cast<DoFileDownloadFn>( | |
518 ::GetProcAddress(mod, "DoFileDownload")); | |
519 DCHECK(fn); | |
520 return fn ? fn(url) : E_UNEXPECTED; | |
521 } | |
522 | |
523 bool GetModuleVersion(HMODULE module, uint32* high, uint32* low) { | |
524 DCHECK(module != NULL) | |
525 << "Please use GetModuleHandle(NULL) to get the process name"; | |
526 DCHECK(high); | |
527 | |
528 bool ok = false; | |
529 | |
530 HRSRC res = FindResource(module, | |
531 reinterpret_cast<const wchar_t*>(VS_VERSION_INFO), RT_VERSION); | |
532 if (res) { | |
533 HGLOBAL res_data = LoadResource(module, res); | |
534 DWORD version_resource_size = SizeofResource(module, res); | |
535 const void* readonly_resource_data = LockResource(res_data); | |
536 if (readonly_resource_data && version_resource_size) { | |
537 // Copy data as VerQueryValue tries to modify the data. This causes | |
538 // exceptions and heap corruption errors if debugger is attached. | |
539 scoped_ptr<char[]> data(new char[version_resource_size]); | |
540 if (data.get()) { | |
541 memcpy(data.get(), readonly_resource_data, version_resource_size); | |
542 VS_FIXEDFILEINFO* ver_info = NULL; | |
543 UINT info_size = 0; | |
544 if (VerQueryValue(data.get(), L"\\", | |
545 reinterpret_cast<void**>(&ver_info), &info_size)) { | |
546 *high = ver_info->dwFileVersionMS; | |
547 if (low != NULL) | |
548 *low = ver_info->dwFileVersionLS; | |
549 ok = true; | |
550 } | |
551 | |
552 UnlockResource(res_data); | |
553 } | |
554 FreeResource(res_data); | |
555 } | |
556 } | |
557 | |
558 return ok; | |
559 } | |
560 | |
561 std::string ResolveURL(const std::string& document, | |
562 const std::string& relative) { | |
563 if (document.empty()) { | |
564 return GURL(relative).spec(); | |
565 } else { | |
566 return GURL(document).Resolve(relative).spec(); | |
567 } | |
568 } | |
569 | |
570 bool HaveSameOrigin(const std::string& url1, const std::string& url2) { | |
571 GURL a(url1), b(url2); | |
572 bool ret; | |
573 if (a.is_valid() != b.is_valid()) { | |
574 // Either (but not both) url is invalid, so they can't match. | |
575 ret = false; | |
576 } else if (!a.is_valid()) { | |
577 // Both URLs are invalid (see first check). Just check if the opaque | |
578 // strings match exactly. | |
579 ret = url1.compare(url2) == 0; | |
580 } else if (a.GetOrigin() != b.GetOrigin()) { | |
581 // The origins don't match. | |
582 ret = false; | |
583 } else { | |
584 // we have a match. | |
585 ret = true; | |
586 } | |
587 | |
588 return ret; | |
589 } | |
590 | |
591 int GetConfigInt(int default_value, const wchar_t* value_name) { | |
592 int ret = default_value; | |
593 RegKey config_key; | |
594 if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey, | |
595 KEY_QUERY_VALUE) == ERROR_SUCCESS) { | |
596 config_key.ReadValueDW(value_name, reinterpret_cast<DWORD*>(&ret)); | |
597 } | |
598 | |
599 return ret; | |
600 } | |
601 | |
602 int64 GetConfigInt64(int64 default_value, const wchar_t* value_name) { | |
603 int64 ret = default_value; | |
604 RegKey config_key; | |
605 if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey, | |
606 KEY_QUERY_VALUE) == ERROR_SUCCESS) { | |
607 config_key.ReadInt64(value_name, &ret); | |
608 } | |
609 | |
610 return ret; | |
611 } | |
612 | |
613 bool GetConfigBool(bool default_value, const wchar_t* value_name) { | |
614 DWORD value = GetConfigInt(default_value, value_name); | |
615 return (value != FALSE); | |
616 } | |
617 | |
618 bool SetConfigInt(const wchar_t* value_name, int value) { | |
619 RegKey config_key; | |
620 if (config_key.Create(HKEY_CURRENT_USER, kChromeFrameConfigKey, | |
621 KEY_SET_VALUE) == ERROR_SUCCESS) { | |
622 if (config_key.WriteValue(value_name, value) == ERROR_SUCCESS) { | |
623 return true; | |
624 } | |
625 } | |
626 | |
627 return false; | |
628 } | |
629 | |
630 bool SetConfigBool(const wchar_t* value_name, bool value) { | |
631 return SetConfigInt(value_name, value); | |
632 } | |
633 | |
634 bool SetConfigInt64(const wchar_t* value_name, int64 value) { | |
635 RegKey config_key; | |
636 if (config_key.Create(HKEY_CURRENT_USER, kChromeFrameConfigKey, | |
637 KEY_SET_VALUE) == ERROR_SUCCESS) { | |
638 if (config_key.WriteValue(value_name, &value, sizeof(value), | |
639 REG_QWORD) == ERROR_SUCCESS) { | |
640 return true; | |
641 } | |
642 } | |
643 | |
644 return false; | |
645 } | |
646 | |
647 bool DeleteConfigValue(const wchar_t* value_name) { | |
648 RegKey config_key; | |
649 if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey, | |
650 KEY_WRITE) == ERROR_SUCCESS) { | |
651 if (config_key.DeleteValue(value_name) == ERROR_SUCCESS) { | |
652 return true; | |
653 } | |
654 } | |
655 return false; | |
656 } | |
657 | |
658 bool IsGcfDefaultRenderer() { | |
659 DWORD is_default = 0; // NOLINT | |
660 | |
661 // First check policy settings | |
662 PolicySettings::RendererForUrl renderer = | |
663 PolicySettings::GetInstance()->default_renderer(); | |
664 if (renderer != PolicySettings::RENDERER_NOT_SPECIFIED) { | |
665 is_default = (renderer == PolicySettings::RENDER_IN_CHROME_FRAME); | |
666 } else { | |
667 // TODO(tommi): Implement caching for this config value as it gets | |
668 // checked frequently. | |
669 RegKey config_key; | |
670 if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey, | |
671 KEY_READ) == ERROR_SUCCESS) { | |
672 config_key.ReadValueDW(kEnableGCFRendererByDefault, &is_default); | |
673 } | |
674 } | |
675 | |
676 return is_default != 0; | |
677 } | |
678 | |
679 // Check for the registry key 'SkipGCFMetadataCheck' and if true, then | |
680 // ignore presence of <meta http-equiv="X-UA-Compatible" content="chrome=1"> | |
681 bool SkipMetadataCheck() { | |
682 // Check policy settings | |
683 PolicySettings::SkipMetadataCheck metadataCheck = | |
684 PolicySettings::GetInstance()->skip_metadata_check(); | |
685 if (metadataCheck != PolicySettings::SKIP_METADATA_CHECK_NOT_SPECIFIED) | |
686 return (metadataCheck == PolicySettings::SKIP_METADATA_CHECK_YES); | |
687 | |
688 DWORD skip = 0; | |
689 RegKey config_key; | |
690 if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey, | |
691 KEY_READ) == ERROR_SUCCESS) { | |
692 config_key.ReadValueDW(kSkipGCFMetadataCheck, &skip); | |
693 } | |
694 return skip != 0; | |
695 } | |
696 | |
697 RendererType RendererTypeForUrl(const std::wstring& url) { | |
698 // First check if the default renderer settings are specified by policy. | |
699 // If so, then that overrides the user settings. | |
700 PolicySettings::RendererForUrl renderer = | |
701 PolicySettings::GetInstance()->GetRendererForUrl(url.c_str()); | |
702 if (renderer != PolicySettings::RENDERER_NOT_SPECIFIED) { | |
703 // We may know at this point that policy says do NOT render in Chrome Frame. | |
704 // To maintain consistency, we return RENDERER_TYPE_UNDETERMINED so that | |
705 // content sniffing, etc. still take place. | |
706 // TODO(tommi): Clarify the intent here. | |
707 return (renderer == PolicySettings::RENDER_IN_CHROME_FRAME) ? | |
708 RENDERER_TYPE_CHROME_OPT_IN_URL : RENDERER_TYPE_UNDETERMINED; | |
709 } | |
710 | |
711 // TODO(robertshield): Move this into a holder-type class that listens | |
712 // for reg change events as well. | |
713 static int render_in_cf_by_default = FALSE; | |
714 | |
715 RegistryListPreferencesHolder& render_type_for_url_holder = | |
716 g_render_type_for_url_holder.Get(); | |
717 if (!render_type_for_url_holder.Valid()) { | |
718 const wchar_t* url_list_name = kRenderInGCFUrlList; | |
719 if (IsGcfDefaultRenderer()) { | |
720 url_list_name = kRenderInHostUrlList; | |
721 render_in_cf_by_default = TRUE; | |
722 } else { | |
723 render_in_cf_by_default = FALSE; | |
724 } | |
725 | |
726 render_type_for_url_holder.Init(HKEY_CURRENT_USER, | |
727 kChromeFrameConfigKey, | |
728 url_list_name); | |
729 } | |
730 DCHECK(render_type_for_url_holder.Valid()); | |
731 | |
732 RendererType renderer_type = | |
733 render_in_cf_by_default ? RENDERER_TYPE_CHROME_DEFAULT_RENDERER : | |
734 RENDERER_TYPE_UNDETERMINED; | |
735 | |
736 if (render_type_for_url_holder.ListMatches(url)) { | |
737 renderer_type = render_in_cf_by_default ? | |
738 RENDERER_TYPE_UNDETERMINED : | |
739 RENDERER_TYPE_CHROME_OPT_IN_URL; | |
740 } | |
741 | |
742 return renderer_type; | |
743 } | |
744 | |
745 bool ShouldRemoveUAForUrl(const base::string16& url) { | |
746 // TODO(robertshield): Wire up the stuff in PolicySettings here so the value | |
747 // can be specified via group policy. | |
748 // TODO(robertshield): Add a default list of exclusions here for site with | |
749 // known bad UA parsing. | |
750 RegistryListPreferencesHolder& user_agent_filter_holder = | |
751 g_user_agent_filter_holder.Get(); | |
752 if (!user_agent_filter_holder.Valid()) { | |
753 user_agent_filter_holder.Init(HKEY_CURRENT_USER, | |
754 kChromeFrameConfigKey, | |
755 kExcludeUAFromDomainList); | |
756 } | |
757 DCHECK(user_agent_filter_holder.Valid()); | |
758 | |
759 return user_agent_filter_holder.ListMatches(url); | |
760 } | |
761 | |
762 RegistryListPreferencesHolder& GetRendererTypePreferencesHolderForTesting() { | |
763 return g_render_type_for_url_holder.Get(); | |
764 } | |
765 | |
766 RegistryListPreferencesHolder& GetUserAgentPreferencesHolderForTesting() { | |
767 return g_user_agent_filter_holder.Get(); | |
768 } | |
769 | |
770 HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker, | |
771 const wchar_t* headers, IBindCtx* bind_ctx, | |
772 const wchar_t* fragment, IStream* post_data, | |
773 VARIANT* flags) { | |
774 DCHECK(browser); | |
775 DCHECK(moniker); | |
776 DCHECK(bind_ctx); | |
777 | |
778 base::win::ScopedComPtr<IWebBrowser2> web_browser2; | |
779 HRESULT hr = DoQueryService(SID_SWebBrowserApp, browser, | |
780 web_browser2.Receive()); | |
781 DCHECK(web_browser2); | |
782 DLOG_IF(WARNING, FAILED(hr)) << base::StringPrintf(L"SWebBrowserApp 0x%08X", | |
783 hr); | |
784 if (FAILED(hr)) | |
785 return hr; | |
786 | |
787 // If the data to be downloaded was received in response to a post request | |
788 // then we need to reissue the post request. | |
789 base::win::ScopedVariant post_data_variant; | |
790 if (post_data) { | |
791 RewindStream(post_data); | |
792 | |
793 CComSafeArray<uint8> safe_array_post; | |
794 | |
795 STATSTG stat; | |
796 post_data->Stat(&stat, STATFLAG_NONAME); | |
797 | |
798 if (stat.cbSize.LowPart > 0) { | |
799 std::string data; | |
800 | |
801 HRESULT hr = E_FAIL; | |
802 while ((hr = ReadStream(post_data, 0xffff, &data)) == S_OK) { | |
803 safe_array_post.Add( | |
804 data.size(), | |
805 reinterpret_cast<unsigned char*>(const_cast<char*>(data.data()))); | |
806 data.clear(); | |
807 } | |
808 } else { | |
809 // If we get here it means that the navigation is being reissued for a | |
810 // POST request with no data. To ensure that the new window used as a | |
811 // target to handle the new navigation issues a POST request | |
812 // we need valid POST data. In this case we create a dummy 1 byte array. | |
813 // May not work as expected with some web sites. | |
814 DLOG(WARNING) << "Reissuing navigation with empty POST data. May not" | |
815 << " work as expected"; | |
816 safe_array_post.Create(1); | |
817 } | |
818 post_data_variant.Set(safe_array_post.Detach()); | |
819 } | |
820 // Create a new bind context that's not associated with our callback. | |
821 // Calling RevokeBindStatusCallback doesn't disassociate the callback with | |
822 // the bind context in IE7. The returned bind context has the same | |
823 // implementation of GetRunningObjectTable as the bind context we held which | |
824 // basically delegates to ole32's GetRunningObjectTable. The object table | |
825 // is then used to determine if the moniker is already running and via | |
826 // that mechanism is associated with the same internet request as has already | |
827 // been issued. | |
828 | |
829 // TODO(tommi): See if we can get HlinkSimpleNavigateToMoniker to work | |
830 // instead. Looks like we'll need to support IHTMLDocument2 (get_URL in | |
831 // particular), access to IWebBrowser2 etc. | |
832 // HlinkSimpleNavigateToMoniker(moniker, url, NULL, host, bind_context, | |
833 // NULL, 0, 0); | |
834 | |
835 base::win::ScopedComPtr<IUriContainer> uri_container; | |
836 hr = uri_container.QueryFrom(moniker); | |
837 | |
838 base::win::ScopedVariant headers_var; | |
839 if (headers && headers[0]) | |
840 headers_var.Set(headers); | |
841 | |
842 if (uri_container) { | |
843 // IE7 and IE8. | |
844 const IID* interface_ids[] = { | |
845 &IID_IWebBrowserPriv2IE7, | |
846 &IID_IWebBrowserPriv2IE8, | |
847 &IID_IWebBrowserPriv2IE8XP, | |
848 &IID_IWebBrowserPriv2IE8XPBeta, | |
849 }; | |
850 | |
851 base::win::ScopedComPtr<IWebBrowserPriv2Common, NULL> browser_priv2; | |
852 for (int i = 0; i < arraysize(interface_ids) && browser_priv2 == NULL; | |
853 ++i) { | |
854 hr = web_browser2.QueryInterface(*interface_ids[i], | |
855 reinterpret_cast<void**>(browser_priv2.Receive())); | |
856 } | |
857 | |
858 DCHECK(browser_priv2); | |
859 | |
860 if (browser_priv2) { | |
861 base::win::ScopedComPtr<IUri> uri_obj; | |
862 uri_container->GetIUri(uri_obj.Receive()); | |
863 DCHECK(uri_obj); | |
864 | |
865 if (GetIEVersion() < IE_9) { | |
866 hr = browser_priv2->NavigateWithBindCtx2( | |
867 uri_obj, flags, NULL, post_data_variant.AsInput(), | |
868 headers_var.AsInput(), bind_ctx, | |
869 const_cast<wchar_t*>(fragment)); | |
870 } else { | |
871 IWebBrowserPriv2CommonIE9* browser_priv2_ie9 = | |
872 reinterpret_cast<IWebBrowserPriv2CommonIE9*>(browser_priv2.get()); | |
873 hr = browser_priv2_ie9->NavigateWithBindCtx2( | |
874 uri_obj, flags, NULL, post_data_variant.AsInput(), | |
875 headers_var.AsInput(), bind_ctx, | |
876 const_cast<wchar_t*>(fragment), 0); | |
877 } | |
878 DLOG_IF(WARNING, FAILED(hr)) | |
879 << base::StringPrintf(L"NavigateWithBindCtx2 0x%08X", hr); | |
880 } | |
881 } else { | |
882 // IE6 | |
883 LPOLESTR url = NULL; | |
884 if (SUCCEEDED(hr = moniker->GetDisplayName(bind_ctx, NULL, &url))) { | |
885 DVLOG(1) << __FUNCTION__ << " " << url; | |
886 base::win::ScopedComPtr<IWebBrowserPriv> browser_priv; | |
887 if (SUCCEEDED(hr = browser_priv.QueryFrom(web_browser2))) { | |
888 GURL target_url(url); | |
889 // On IE6 if the original URL has a fragment then the navigation | |
890 // attempt is ignored. To workaround this we strip the fragment from | |
891 // the url and initiate the navigation. When the active document loads | |
892 // we retrieve the original url with the fragment from the Navigation | |
893 // manager and use it. | |
894 if (target_url.has_ref()) { | |
895 url_parse::Component comp; | |
896 GURL::Replacements replacements; | |
897 replacements.SetRef("", comp); | |
898 | |
899 target_url = target_url.ReplaceComponents(replacements); | |
900 fragment = NULL; | |
901 } | |
902 | |
903 base::win::ScopedVariant var_url( | |
904 base::UTF8ToWide(target_url.spec()).c_str()); | |
905 hr = browser_priv->NavigateWithBindCtx(var_url.AsInput(), flags, NULL, | |
906 post_data_variant.AsInput(), | |
907 headers_var.AsInput(), bind_ctx, | |
908 const_cast<wchar_t*>(fragment)); | |
909 DLOG_IF(WARNING, FAILED(hr)) | |
910 << base::StringPrintf(L"NavigateWithBindCtx 0x%08X", hr); | |
911 } else { | |
912 NOTREACHED(); | |
913 } | |
914 ::CoTaskMemFree(url); | |
915 } else { | |
916 DLOG(ERROR) << base::StringPrintf("GetDisplayName: 0x%08X", hr); | |
917 } | |
918 } | |
919 | |
920 return hr; | |
921 } | |
922 | |
923 void MarkBrowserOnThreadForCFNavigation(IBrowserService* browser) { | |
924 DCHECK(browser != NULL); | |
925 DCHECK(g_tls_browser_for_cf_navigation.Pointer()->Get() == NULL || | |
926 g_tls_browser_for_cf_navigation.Pointer()->Get() == browser); | |
927 g_tls_browser_for_cf_navigation.Pointer()->Set(browser); | |
928 } | |
929 | |
930 bool CheckForCFNavigation(IBrowserService* browser, bool clear_flag) { | |
931 DCHECK(browser); | |
932 bool ret = (g_tls_browser_for_cf_navigation.Pointer()->Get() == browser); | |
933 if (ret && clear_flag) | |
934 g_tls_browser_for_cf_navigation.Pointer()->Set(NULL); | |
935 return ret; | |
936 } | |
937 | |
938 bool IsValidUrlScheme(const GURL& url, bool is_privileged) { | |
939 if (url.is_empty()) | |
940 return false; | |
941 | |
942 if (url.SchemeIs(content::kHttpScheme) || | |
943 url.SchemeIs(content::kHttpsScheme) || | |
944 url.SchemeIs(chrome::kAboutScheme)) | |
945 return true; | |
946 | |
947 // Additional checking for view-source. Allow only http and https | |
948 // URLs in view source. | |
949 if (url.SchemeIs(content::kViewSourceScheme)) { | |
950 GURL sub_url(url.GetContent()); | |
951 if (sub_url.SchemeIs(content::kHttpScheme) || | |
952 sub_url.SchemeIs(content::kHttpsScheme)) | |
953 return true; | |
954 else | |
955 return false; | |
956 } | |
957 | |
958 if (is_privileged && | |
959 (url.SchemeIs(chrome::kDataScheme) || | |
960 url.SchemeIs(extensions::kExtensionScheme))) | |
961 return true; | |
962 | |
963 return false; | |
964 } | |
965 | |
966 std::string GetRawHttpHeaders(IWinInetHttpInfo* info) { | |
967 DCHECK(info); | |
968 | |
969 std::string buffer; | |
970 | |
971 DWORD size = 0; | |
972 DWORD flags = 0; | |
973 DWORD reserved = 0; | |
974 HRESULT hr = info->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &size, | |
975 &flags, &reserved); | |
976 if (!size) { | |
977 DLOG(WARNING) << "Failed to query HTTP headers size. Error: " << hr; | |
978 } else { | |
979 buffer.resize(size + 1); | |
980 hr = info->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, &buffer[0], | |
981 &size, &flags, &reserved); | |
982 if (FAILED(hr)) { | |
983 DLOG(WARNING) << "Failed to query HTTP headers. Error: " << hr; | |
984 } | |
985 } | |
986 | |
987 return buffer; | |
988 } | |
989 | |
990 bool IsSubFrameRequest(IUnknown* service_provider) { | |
991 DCHECK(service_provider); | |
992 | |
993 // We need to be able to get at an IWebBrowser2 if we are to decide whether | |
994 // this request originates from a non-top-level frame. | |
995 base::win::ScopedComPtr<IWebBrowser2> web_browser; | |
996 HRESULT hr = DoQueryService(IID_ITargetFrame2, service_provider, | |
997 web_browser.Receive()); | |
998 | |
999 bool is_sub_frame_request = false; | |
1000 if (web_browser) { | |
1001 // Now check to see if we are in a sub-frame. | |
1002 base::win::ScopedComPtr<IHTMLWindow2> current_frame, parent_frame; | |
1003 hr = DoQueryService(IID_IHTMLWindow2, service_provider, | |
1004 current_frame.Receive()); | |
1005 if (current_frame) { | |
1006 // Only the top level window will return self when get_parent is called. | |
1007 current_frame->get_parent(parent_frame.Receive()); | |
1008 if (parent_frame != current_frame) { | |
1009 DVLOG(1) << "Sub frame detected"; | |
1010 is_sub_frame_request = true; | |
1011 } | |
1012 } | |
1013 } else { | |
1014 DVLOG(1) << "IsSubFrameRequest - no IWebBrowser2"; | |
1015 is_sub_frame_request = true; | |
1016 } | |
1017 | |
1018 return is_sub_frame_request; | |
1019 } | |
1020 | |
1021 bool IsHeadlessMode() { | |
1022 bool headless = GetConfigBool(false, kChromeFrameHeadlessMode); | |
1023 return headless; | |
1024 } | |
1025 | |
1026 bool IsAccessibleMode() { | |
1027 bool accessible = GetConfigBool(false, kChromeFrameAccessibleMode); | |
1028 return accessible; | |
1029 } | |
1030 | |
1031 bool IsUnpinnedMode() { | |
1032 // We only check this value once and then cache it since changing the registry | |
1033 // once we've pinned the DLL won't have any effect. | |
1034 static bool unpinned = GetConfigBool(false, kChromeFrameUnpinnedMode); | |
1035 return unpinned; | |
1036 } | |
1037 | |
1038 std::wstring GetActualUrlFromMoniker(IMoniker* moniker, | |
1039 IBindCtx* bind_context, | |
1040 const std::wstring& bho_url) { | |
1041 CComHeapPtr<WCHAR> display_name; | |
1042 moniker->GetDisplayName(bind_context, NULL, &display_name); | |
1043 std::wstring moniker_url = display_name; | |
1044 | |
1045 GURL parsed_url(base::WideToUTF8(bho_url)); | |
1046 if (!parsed_url.has_ref()) | |
1047 return moniker_url; | |
1048 | |
1049 if (StartsWith(bho_url, moniker_url, false) && | |
1050 bho_url[moniker_url.length()] == L'#') | |
1051 return bho_url; | |
1052 | |
1053 return moniker_url; | |
1054 } | |
1055 | |
1056 bool IsTopLevelWindow(HWND window) { | |
1057 long style = GetWindowLong(window, GWL_STYLE); // NOLINT | |
1058 if (!(style & WS_CHILD)) | |
1059 return true; | |
1060 | |
1061 HWND parent = GetParent(window); | |
1062 return !parent || (parent == GetDesktopWindow()); | |
1063 } | |
1064 | |
1065 HRESULT RewindStream(IStream* stream) { | |
1066 HRESULT hr = E_POINTER; | |
1067 if (stream) { | |
1068 LARGE_INTEGER zero = {0}; | |
1069 ULARGE_INTEGER new_pos = {0}; | |
1070 hr = stream->Seek(zero, STREAM_SEEK_SET, &new_pos); | |
1071 } | |
1072 | |
1073 return hr; | |
1074 } | |
1075 | |
1076 std::wstring GuidToString(const GUID& guid) { | |
1077 std::wstring ret; | |
1078 ::StringFromGUID2(guid, WriteInto(&ret, 39), 39); | |
1079 return ret; | |
1080 } | |
1081 | |
1082 int32 MapCookieStateToCookieAction(InternetCookieState cookie_state) { | |
1083 int32 cookie_action = COOKIEACTION_NONE; | |
1084 | |
1085 switch (cookie_state) { | |
1086 case COOKIE_STATE_UNKNOWN: | |
1087 cookie_action = COOKIEACTION_NONE; | |
1088 break; | |
1089 case COOKIE_STATE_ACCEPT: | |
1090 cookie_action = COOKIEACTION_ACCEPT; | |
1091 break; | |
1092 case COOKIE_STATE_LEASH: | |
1093 cookie_action = COOKIEACTION_LEASH; | |
1094 break; | |
1095 case COOKIE_STATE_DOWNGRADE: | |
1096 cookie_action = COOKIEACTION_DOWNGRADE; | |
1097 break; | |
1098 case COOKIE_STATE_REJECT: | |
1099 cookie_action = COOKIEACTION_REJECT; | |
1100 break; | |
1101 default: | |
1102 cookie_action = COOKIEACTION_REJECT; | |
1103 break; | |
1104 } | |
1105 return cookie_action; | |
1106 } | |
1107 | |
1108 GURL GetUrlWithoutFragment(const wchar_t* url) { | |
1109 GURL parsed_url(url); | |
1110 | |
1111 if (parsed_url.has_ref()) { | |
1112 url_parse::Component comp; | |
1113 GURL::Replacements replacements; | |
1114 replacements.SetRef("", comp); | |
1115 | |
1116 parsed_url = parsed_url.ReplaceComponents(replacements); | |
1117 } | |
1118 return parsed_url; | |
1119 } | |
1120 | |
1121 bool CompareUrlsWithoutFragment(const wchar_t* url1, const wchar_t* url2) { | |
1122 GURL parsed_url1 = GetUrlWithoutFragment(url1); | |
1123 GURL parsed_url2 = GetUrlWithoutFragment(url2); | |
1124 return parsed_url1 == parsed_url2; | |
1125 } | |
1126 | |
1127 std::string FindReferrerFromHeaders(const wchar_t* headers, | |
1128 const wchar_t* additional_headers) { | |
1129 std::string referrer; | |
1130 | |
1131 const wchar_t* both_headers[] = { headers, additional_headers }; | |
1132 for (int i = 0; referrer.empty() && i < arraysize(both_headers); ++i) { | |
1133 if (!both_headers[i]) | |
1134 continue; | |
1135 std::string raw_headers_utf8 = base::WideToUTF8(both_headers[i]); | |
1136 net::HttpUtil::HeadersIterator it(raw_headers_utf8.begin(), | |
1137 raw_headers_utf8.end(), "\r\n"); | |
1138 while (it.GetNext()) { | |
1139 if (LowerCaseEqualsASCII(it.name(), "referer")) { | |
1140 referrer = it.values(); | |
1141 break; | |
1142 } | |
1143 } | |
1144 } | |
1145 | |
1146 return referrer; | |
1147 } | |
1148 | |
1149 std::string GetHttpHeadersFromBinding(IBinding* binding) { | |
1150 if (binding == NULL) { | |
1151 DLOG(WARNING) << "GetHttpResponseStatus - no binding_"; | |
1152 return std::string(); | |
1153 } | |
1154 | |
1155 base::win::ScopedComPtr<IWinInetHttpInfo> info; | |
1156 if (FAILED(info.QueryFrom(binding))) { | |
1157 DLOG(WARNING) << "Failed to QI for IWinInetHttpInfo"; | |
1158 return std::string(); | |
1159 } | |
1160 | |
1161 return GetRawHttpHeaders(info); | |
1162 } | |
1163 | |
1164 int GetHttpResponseStatusFromBinding(IBinding* binding) { | |
1165 DVLOG(1) << __FUNCTION__; | |
1166 if (binding == NULL) { | |
1167 DLOG(WARNING) << "GetHttpResponseStatus - no binding_"; | |
1168 return 0; | |
1169 } | |
1170 | |
1171 int http_status = 0; | |
1172 | |
1173 base::win::ScopedComPtr<IWinInetHttpInfo> info; | |
1174 if (SUCCEEDED(info.QueryFrom(binding))) { | |
1175 char status[10] = {0}; | |
1176 DWORD buf_size = sizeof(status); | |
1177 DWORD flags = 0; | |
1178 DWORD reserved = 0; | |
1179 if (SUCCEEDED(info->QueryInfo(HTTP_QUERY_STATUS_CODE, status, &buf_size, | |
1180 &flags, &reserved))) { | |
1181 base::StringToInt(status, &http_status); | |
1182 } else { | |
1183 NOTREACHED() << "Failed to get HTTP status"; | |
1184 } | |
1185 } else { | |
1186 NOTREACHED() << "failed to get IWinInetHttpInfo from binding_"; | |
1187 } | |
1188 | |
1189 return http_status; | |
1190 } | |
1191 | |
1192 CLIPFORMAT GetTextHtmlClipboardFormat() { | |
1193 static const CLIPFORMAT text_html = RegisterClipboardFormat(CFSTR_MIME_HTML); | |
1194 return text_html; | |
1195 } | |
1196 | |
1197 bool IsTextHtmlMimeType(const wchar_t* mime_type) { | |
1198 return IsTextHtmlClipFormat(RegisterClipboardFormatW(mime_type)); | |
1199 } | |
1200 | |
1201 bool IsTextHtmlClipFormat(CLIPFORMAT cf) { | |
1202 return cf == GetTextHtmlClipboardFormat(); | |
1203 } | |
1204 | |
1205 bool IsSystemProcess() { | |
1206 bool is_system = false; | |
1207 CAccessToken process_token; | |
1208 if (process_token.GetProcessToken(TOKEN_QUERY, GetCurrentProcess())) { | |
1209 CSid logon_sid; | |
1210 if (process_token.GetUser(&logon_sid)) { | |
1211 is_system = logon_sid == Sids::System(); | |
1212 } | |
1213 } | |
1214 return is_system; | |
1215 } | |
1216 | |
1217 | |
1218 std::string BindStatus2Str(ULONG bind_status) { | |
1219 std::string s; | |
1220 static const char* const bindstatus_txt[] = { | |
1221 "BINDSTATUS_FINDINGRESOURCE", | |
1222 "BINDSTATUS_CONNECTING", | |
1223 "BINDSTATUS_REDIRECTING", | |
1224 "BINDSTATUS_BEGINDOWNLOADDATA", | |
1225 "BINDSTATUS_DOWNLOADINGDATA", | |
1226 "BINDSTATUS_ENDDOWNLOADDATA", | |
1227 "BINDSTATUS_BEGINDOWNLOADCOMPONENTS", | |
1228 "BINDSTATUS_INSTALLINGCOMPONENTS", | |
1229 "BINDSTATUS_ENDDOWNLOADCOMPONENTS", | |
1230 "BINDSTATUS_USINGCACHEDCOPY", | |
1231 "BINDSTATUS_SENDINGREQUEST", | |
1232 "BINDSTATUS_CLASSIDAVAILABLE", | |
1233 "BINDSTATUS_MIMETYPEAVAILABLE", | |
1234 "BINDSTATUS_CACHEFILENAMEAVAILABLE", | |
1235 "BINDSTATUS_BEGINSYNCOPERATION", | |
1236 "BINDSTATUS_ENDSYNCOPERATION", | |
1237 "BINDSTATUS_BEGINUPLOADDATA", | |
1238 "BINDSTATUS_UPLOADINGDATA", | |
1239 "BINDSTATUS_ENDUPLOADINGDATA", | |
1240 "BINDSTATUS_PROTOCOLCLASSID", | |
1241 "BINDSTATUS_ENCODING", | |
1242 "BINDSTATUS_VERFIEDMIMETYPEAVAILABLE", | |
1243 "BINDSTATUS_CLASSINSTALLLOCATION", | |
1244 "BINDSTATUS_DECODING", | |
1245 "BINDSTATUS_LOADINGMIMEHANDLER", | |
1246 "BINDSTATUS_CONTENTDISPOSITIONATTACH", | |
1247 "BINDSTATUS_FILTERREPORTMIMETYPE", | |
1248 "BINDSTATUS_CLSIDCANINSTANTIATE", | |
1249 "BINDSTATUS_IUNKNOWNAVAILABLE", | |
1250 "BINDSTATUS_DIRECTBIND", | |
1251 "BINDSTATUS_RAWMIMETYPE", | |
1252 "BINDSTATUS_PROXYDETECTING", | |
1253 "BINDSTATUS_ACCEPTRANGES", | |
1254 "BINDSTATUS_COOKIE_SENT", | |
1255 "BINDSTATUS_COMPACT_POLICY_RECEIVED", | |
1256 "BINDSTATUS_COOKIE_SUPPRESSED", | |
1257 "BINDSTATUS_COOKIE_STATE_UNKNOWN", | |
1258 "BINDSTATUS_COOKIE_STATE_ACCEPT", | |
1259 "BINDSTATUS_COOKIE_STATE_REJECT", | |
1260 "BINDSTATUS_COOKIE_STATE_PROMPT", | |
1261 "BINDSTATUS_COOKIE_STATE_LEASH", | |
1262 "BINDSTATUS_COOKIE_STATE_DOWNGRADE", | |
1263 "BINDSTATUS_POLICY_HREF", | |
1264 "BINDSTATUS_P3P_HEADER", | |
1265 "BINDSTATUS_SESSION_COOKIE_RECEIVED", | |
1266 "BINDSTATUS_PERSISTENT_COOKIE_RECEIVED", | |
1267 "BINDSTATUS_SESSION_COOKIES_ALLOWED", | |
1268 "BINDSTATUS_CACHECONTROL", | |
1269 "BINDSTATUS_CONTENTDISPOSITIONFILENAME", | |
1270 "BINDSTATUS_MIMETEXTPLAINMISMATCH", | |
1271 "BINDSTATUS_PUBLISHERAVAILABLE", | |
1272 "BINDSTATUS_DISPLAYNAMEAVAILABLE", | |
1273 "BINDSTATUS_SSLUX_NAVBLOCKED", | |
1274 "BINDSTATUS_SERVER_MIMETYPEAVAILABLE", | |
1275 "BINDSTATUS_SNIFFED_CLASSIDAVAILABLE", | |
1276 "BINDSTATUS_64BIT_PROGRESS" | |
1277 }; | |
1278 if (bind_status >= 1 && bind_status <= BINDSTATUS_64BIT_PROGRESS) | |
1279 s = bindstatus_txt[bind_status - 1]; | |
1280 else | |
1281 s = base::StringPrintf("UnDoc[%#x]", bind_status); | |
1282 return s; | |
1283 } | |
1284 | |
1285 std::string PiFlags2Str(DWORD flags) { | |
1286 #define ADD_PI_FLAG(x) \ | |
1287 if (flags & x) { \ | |
1288 s.append(#x ## " "); \ | |
1289 flags &= ~x; \ | |
1290 } | |
1291 | |
1292 std::string s = " flags "; | |
1293 ADD_PI_FLAG(PI_PARSE_URL); | |
1294 ADD_PI_FLAG(PI_FILTER_MODE); | |
1295 ADD_PI_FLAG(PI_FORCE_ASYNC); | |
1296 ADD_PI_FLAG(PI_USE_WORKERTHREAD); | |
1297 ADD_PI_FLAG(PI_MIMEVERIFICATION); | |
1298 ADD_PI_FLAG(PI_CLSIDLOOKUP); | |
1299 ADD_PI_FLAG(PI_DATAPROGRESS); | |
1300 ADD_PI_FLAG(PI_SYNCHRONOUS); | |
1301 ADD_PI_FLAG(PI_APARTMENTTHREADED); | |
1302 ADD_PI_FLAG(PI_CLASSINSTALL); | |
1303 ADD_PI_FLAG(PI_PASSONBINDCTX); | |
1304 ADD_PI_FLAG(PI_NOMIMEHANDLER); | |
1305 ADD_PI_FLAG(PI_LOADAPPDIRECT); | |
1306 ADD_PI_FLAG(PD_FORCE_SWITCH); | |
1307 ADD_PI_FLAG(PI_PREFERDEFAULTHANDLER); | |
1308 | |
1309 if (flags) | |
1310 s += base::StringPrintf("+UnDoc[%#x]", flags); | |
1311 return s; | |
1312 #undef ADD_PI_FLAG | |
1313 } | |
1314 | |
1315 std::string Bscf2Str(DWORD flags) { | |
1316 #define ADD_BSCF_FLAG(x) \ | |
1317 if (flags & x) {\ | |
1318 s.append(#x ## " "); \ | |
1319 flags &= ~x; \ | |
1320 } | |
1321 | |
1322 std::string s = " flags "; | |
1323 ADD_BSCF_FLAG(BSCF_FIRSTDATANOTIFICATION) | |
1324 ADD_BSCF_FLAG(BSCF_INTERMEDIATEDATANOTIFICATION) | |
1325 ADD_BSCF_FLAG(BSCF_LASTDATANOTIFICATION) | |
1326 ADD_BSCF_FLAG(BSCF_DATAFULLYAVAILABLE) | |
1327 ADD_BSCF_FLAG(BSCF_AVAILABLEDATASIZEUNKNOWN) | |
1328 ADD_BSCF_FLAG(BSCF_SKIPDRAINDATAFORFILEURLS) | |
1329 ADD_BSCF_FLAG(BSCF_64BITLENGTHDOWNLOAD) | |
1330 | |
1331 if (flags) | |
1332 s += base::StringPrintf("+UnDoc[%#x]", flags); | |
1333 return s; | |
1334 #undef ADD_BSCF_FLAG | |
1335 } | |
1336 | |
1337 // Reads data from a stream into a string. | |
1338 HRESULT ReadStream(IStream* stream, size_t size, std::string* data) { | |
1339 DCHECK(stream); | |
1340 DCHECK_GT(size, 0u); | |
1341 DCHECK(data); | |
1342 | |
1343 DWORD read = 0; | |
1344 HRESULT hr = stream->Read(WriteInto(data, size + 1), size, &read); | |
1345 DCHECK(hr == S_OK || hr == S_FALSE || hr == E_PENDING); | |
1346 if (read) { | |
1347 data->erase(read); | |
1348 DCHECK_EQ(read, data->length()); | |
1349 } else { | |
1350 data->clear(); | |
1351 // Return S_FALSE if the underlying stream returned S_OK and zero bytes. | |
1352 if (hr == S_OK) | |
1353 hr = S_FALSE; | |
1354 } | |
1355 | |
1356 return hr; | |
1357 } | |
1358 | |
1359 ChromeFrameUrl::ChromeFrameUrl() { | |
1360 Reset(); | |
1361 } | |
1362 | |
1363 bool ChromeFrameUrl::Parse(const std::wstring& url) { | |
1364 Reset(); | |
1365 parsed_url_ = GURL(url); | |
1366 | |
1367 if (parsed_url_.is_empty()) | |
1368 return false; | |
1369 | |
1370 is_chrome_protocol_ = parsed_url_.SchemeIs(kGCFProtocol); | |
1371 if (is_chrome_protocol_) { | |
1372 parsed_url_ = GURL(url.c_str() + lstrlen(kChromeProtocolPrefix)); | |
1373 return true; | |
1374 } | |
1375 | |
1376 return ParseAttachExternalTabUrl(); | |
1377 } | |
1378 | |
1379 bool ChromeFrameUrl::ParseAttachExternalTabUrl() { | |
1380 std::string query = parsed_url_.query(); | |
1381 if (!StartsWithASCII(query, kAttachExternalTabPrefix, false)) { | |
1382 return parsed_url_.is_valid(); | |
1383 } | |
1384 | |
1385 attach_to_external_tab_ = true; | |
1386 base::StringTokenizer tokenizer(query, "&"); | |
1387 // Skip over kChromeAttachExternalTabPrefix | |
1388 tokenizer.GetNext(); | |
1389 // Read the following items in order. | |
1390 // 1. cookie | |
1391 // 2. disposition | |
1392 // 3. dimension.x | |
1393 // 4. dimension.y | |
1394 // 5. dimension.width | |
1395 // 6. dimension.height. | |
1396 if (tokenizer.GetNext()) { | |
1397 char* end_ptr = 0; | |
1398 cookie_ = _strtoui64(tokenizer.token().c_str(), &end_ptr, 10); | |
1399 } else { | |
1400 return false; | |
1401 } | |
1402 | |
1403 if (tokenizer.GetNext()) { | |
1404 disposition_ = atoi(tokenizer.token().c_str()); | |
1405 } else { | |
1406 return false; | |
1407 } | |
1408 | |
1409 if (tokenizer.GetNext()) { | |
1410 dimensions_.set_x(atoi(tokenizer.token().c_str())); | |
1411 } else { | |
1412 return false; | |
1413 } | |
1414 | |
1415 if (tokenizer.GetNext()) { | |
1416 dimensions_.set_y(atoi(tokenizer.token().c_str())); | |
1417 } else { | |
1418 return false; | |
1419 } | |
1420 | |
1421 if (tokenizer.GetNext()) { | |
1422 dimensions_.set_width(atoi(tokenizer.token().c_str())); | |
1423 } else { | |
1424 return false; | |
1425 } | |
1426 | |
1427 if (tokenizer.GetNext()) { | |
1428 dimensions_.set_height(atoi(tokenizer.token().c_str())); | |
1429 } else { | |
1430 return false; | |
1431 } | |
1432 | |
1433 if (tokenizer.GetNext()) { | |
1434 profile_name_ = tokenizer.token(); | |
1435 // Escape out special characters like %20, etc. | |
1436 profile_name_ = net::UnescapeURLComponent(profile_name_, | |
1437 net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS); | |
1438 } else { | |
1439 return false; | |
1440 } | |
1441 | |
1442 return true; | |
1443 } | |
1444 | |
1445 void ChromeFrameUrl::Reset() { | |
1446 attach_to_external_tab_ = false; | |
1447 is_chrome_protocol_ = false; | |
1448 cookie_ = 0; | |
1449 dimensions_.SetRect(0, 0, 0, 0); | |
1450 disposition_ = 0; | |
1451 profile_name_.clear(); | |
1452 } | |
1453 | |
1454 bool CanNavigate(const GURL& url, | |
1455 NavigationConstraints* navigation_constraints) { | |
1456 if (!url.is_valid()) { | |
1457 DLOG(ERROR) << "Invalid URL passed to InitiateNavigation: " << url; | |
1458 return false; | |
1459 } | |
1460 | |
1461 if (!navigation_constraints) { | |
1462 NOTREACHED() << "Invalid NavigationConstraints passed in"; | |
1463 return false; | |
1464 } | |
1465 | |
1466 // No sanity checks if unsafe URLs are allowed | |
1467 if (navigation_constraints->AllowUnsafeUrls()) | |
1468 return true; | |
1469 | |
1470 if (!navigation_constraints->IsSchemeAllowed(url)) { | |
1471 DLOG(WARNING) << __FUNCTION__ << " Disallowing navigation to url: " << url; | |
1472 return false; | |
1473 } | |
1474 | |
1475 if (!navigation_constraints->IsZoneAllowed(url)) { | |
1476 DLOG(WARNING) << __FUNCTION__ | |
1477 << " Disallowing navigation to restricted url: " << url; | |
1478 return false; | |
1479 } | |
1480 return true; | |
1481 } | |
1482 | |
1483 void WaitWithMessageLoop(HANDLE* handles, int count, DWORD timeout) { | |
1484 base::Time now = base::Time::Now(); | |
1485 base::Time wait_until = now + base::TimeDelta::FromMilliseconds(timeout); | |
1486 | |
1487 while (wait_until >= now) { | |
1488 base::TimeDelta wait_time = wait_until - now; | |
1489 DWORD wait = MsgWaitForMultipleObjects( | |
1490 count, handles, FALSE, static_cast<DWORD>(wait_time.InMilliseconds()), | |
1491 QS_ALLINPUT); | |
1492 switch (wait) { | |
1493 case WAIT_OBJECT_0: | |
1494 case WAIT_TIMEOUT: | |
1495 return; | |
1496 | |
1497 case WAIT_OBJECT_0 + 1: { | |
1498 MSG msg = {0}; | |
1499 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { | |
1500 TranslateMessage(&msg); | |
1501 DispatchMessage(&msg); | |
1502 } | |
1503 break; | |
1504 } | |
1505 | |
1506 default: { | |
1507 NOTREACHED() << "Unexpected return from MsgWaitForMultipleObjects :" | |
1508 << wait; | |
1509 return; | |
1510 } | |
1511 } | |
1512 now = base::Time::Now(); | |
1513 } | |
1514 } | |
1515 | |
1516 // Returns -1 if no directive is found, std::numeric_limits<int>::max() if the | |
1517 // directive matches all IE versions ('Chrome=1') or the maximum IE version | |
1518 // matched ('Chrome=IE7' => 7) | |
1519 int GetXUaCompatibleDirective(const std::string& directive, char delimiter) { | |
1520 net::HttpUtil::NameValuePairsIterator name_value_pairs(directive.begin(), | |
1521 directive.end(), | |
1522 delimiter); | |
1523 | |
1524 // Loop through the values until a valid 'Chrome=<FILTER>' entry is found | |
1525 while (name_value_pairs.GetNext()) { | |
1526 if (!LowerCaseEqualsASCII(name_value_pairs.name_begin(), | |
1527 name_value_pairs.name_end(), | |
1528 "chrome")) { | |
1529 continue; | |
1530 } | |
1531 std::string::const_iterator filter_begin = name_value_pairs.value_begin(); | |
1532 std::string::const_iterator filter_end = name_value_pairs.value_end(); | |
1533 | |
1534 size_t filter_length = filter_end - filter_begin; | |
1535 | |
1536 if (filter_length == 1 && *filter_begin == '1') { | |
1537 return std::numeric_limits<int>::max(); | |
1538 } | |
1539 | |
1540 if (filter_length < 3 || | |
1541 !LowerCaseEqualsASCII(filter_begin, filter_begin + 2, "ie") || | |
1542 !isdigit(*(filter_begin + 2))) { // ensure no leading +/- | |
1543 continue; | |
1544 } | |
1545 | |
1546 int header_ie_version = 0; | |
1547 if (!base::StringToInt(base::StringPiece(filter_begin + 2, | |
1548 filter_end), | |
1549 &header_ie_version) || | |
1550 header_ie_version == 0) { // ensure it's not a sequence of 0's | |
1551 continue; | |
1552 } | |
1553 | |
1554 // The first valid directive we find wins, whether it matches or not | |
1555 return header_ie_version; | |
1556 } | |
1557 return -1; | |
1558 } | |
1559 | |
1560 bool CheckXUaCompatibleDirective(const std::string& directive, | |
1561 int ie_major_version) { | |
1562 int header_ie_version = GetXUaCompatibleDirective(directive, ';'); | |
1563 if (header_ie_version == -1) { | |
1564 header_ie_version = GetXUaCompatibleDirective(directive, ','); | |
1565 } | |
1566 return header_ie_version >= ie_major_version; | |
1567 } | |
1568 | |
1569 void EnumerateKeyValues(HKEY parent_key, const wchar_t* sub_key_name, | |
1570 std::vector<std::wstring>* values) { | |
1571 DCHECK(values); | |
1572 base::win::RegistryValueIterator url_list(parent_key, sub_key_name); | |
1573 while (url_list.Valid()) { | |
1574 values->push_back(url_list.Value()); | |
1575 ++url_list; | |
1576 } | |
1577 } | |
1578 | |
1579 std::wstring GetCurrentModuleVersion() { | |
1580 scoped_ptr<FileVersionInfo> module_version_info( | |
1581 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); | |
1582 DCHECK(module_version_info.get() != NULL); | |
1583 return module_version_info->file_version(); | |
1584 } | |
1585 | |
1586 bool IsChromeFrameDocument(IWebBrowser2* web_browser) { | |
1587 if (!web_browser) | |
1588 return false; | |
1589 | |
1590 base::win::ScopedComPtr<IDispatch> doc; | |
1591 web_browser->get_Document(doc.Receive()); | |
1592 if (doc) { | |
1593 // Detect if CF is rendering based on whether the document is a | |
1594 // ChromeActiveDocument. Detecting based on hwnd is problematic as | |
1595 // the CF Active Document window may not have been created yet. | |
1596 base::win::ScopedComPtr<IChromeFrame> chrome_frame; | |
1597 chrome_frame.QueryFrom(doc); | |
1598 return chrome_frame.get() != NULL; | |
1599 } | |
1600 return false; | |
1601 } | |
1602 | |
1603 bool IncreaseWinInetConnections(DWORD connections) { | |
1604 static bool wininet_connection_count_updated = false; | |
1605 if (wininet_connection_count_updated) { | |
1606 return true; | |
1607 } | |
1608 | |
1609 static int connection_options[] = { | |
1610 INTERNET_OPTION_MAX_CONNS_PER_SERVER, | |
1611 INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER, | |
1612 }; | |
1613 | |
1614 BOOL ret = FALSE; | |
1615 | |
1616 for (int option_index = 0; option_index < arraysize(connection_options); | |
1617 ++option_index) { | |
1618 DWORD connection_value_size = sizeof(DWORD); | |
1619 DWORD current_connection_limit = 0; | |
1620 InternetQueryOption(NULL, connection_options[option_index], | |
1621 ¤t_connection_limit, &connection_value_size); | |
1622 if (current_connection_limit > connections) { | |
1623 continue; | |
1624 } | |
1625 | |
1626 ret = InternetSetOption(NULL, connection_options[option_index], | |
1627 &connections, connection_value_size); | |
1628 if (!ret) { | |
1629 return false; | |
1630 } | |
1631 } | |
1632 wininet_connection_count_updated = true; | |
1633 return true; | |
1634 } | |
1635 | |
1636 void GetChromeFrameProfilePath(const base::string16& profile_name, | |
1637 base::FilePath* profile_path) { | |
1638 chrome::GetChromeFrameUserDataDirectory(profile_path); | |
1639 *profile_path = profile_path->Append(profile_name); | |
1640 DVLOG(1) << __FUNCTION__ << ": " << profile_path->value(); | |
1641 } | |
OLD | NEW |