Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(775)

Side by Side Diff: chrome_frame/utils.cc

Issue 126143005: Remove Chrome Frame code and resources. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync to r244038 Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome_frame/utils.h ('k') | chrome_frame/vtable_patch_manager.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 &current_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 }
OLDNEW
« no previous file with comments | « chrome_frame/utils.h ('k') | chrome_frame/vtable_patch_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698