| Index: chrome_frame/utils.cc
|
| ===================================================================
|
| --- chrome_frame/utils.cc (revision 0)
|
| +++ chrome_frame/utils.cc (revision 0)
|
| @@ -0,0 +1,643 @@
|
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <shlobj.h>
|
| +
|
| +#include "chrome_frame/html_utils.h"
|
| +#include "chrome_frame/utils.h"
|
| +
|
| +#include "base/file_util.h"
|
| +#include "base/file_version_info.h"
|
| +#include "base/logging.h"
|
| +#include "base/path_service.h"
|
| +#include "base/registry.h"
|
| +#include "base/scoped_comptr_win.h"
|
| +#include "base/string_util.h"
|
| +#include "chrome/common/chrome_constants.h"
|
| +#include "chrome/installer/util/google_update_constants.h"
|
| +#include "googleurl/src/gurl.h"
|
| +#include "grit/chrome_frame_resources.h"
|
| +#include "chrome_frame/resource.h"
|
| +
|
| +// Note that these values are all lower case and are compared to
|
| +// lower-case-transformed values.
|
| +const wchar_t kMetaTag[] = L"meta";
|
| +const wchar_t kHttpEquivAttribName[] = L"http-equiv";
|
| +const wchar_t kContentAttribName[] = L"content";
|
| +const wchar_t kXUACompatValue[] = L"x-ua-compatible";
|
| +const wchar_t kBodyTag[] = L"body";
|
| +const wchar_t kChromeContentPrefix[] = L"chrome=";
|
| +const wchar_t kChromeProtocolPrefix[] = L"cf:";
|
| +
|
| +static const wchar_t kChromeFrameConfigKey[] =
|
| + L"Software\\Google\\ChromeFrame";
|
| +static const wchar_t kChromeFrameOptinUrlsKey[] = L"OptinUrls";
|
| +
|
| +// Used to isolate chrome frame builds from google chrome release channels.
|
| +const wchar_t kChromeFrameOmahaSuffix[] = L"-cf";
|
| +const wchar_t kDevChannelName[] = L"-dev";
|
| +
|
| +const wchar_t kChromeAttachExternalTabPrefix[] = L"attach_external_tab";
|
| +
|
| +HRESULT UtilRegisterTypeLib(HINSTANCE tlb_instance,
|
| + LPCOLESTR index,
|
| + bool for_current_user_only) {
|
| + CComBSTR path;
|
| + CComPtr<ITypeLib> type_lib;
|
| + HRESULT hr = AtlLoadTypeLib(tlb_instance, index, &path, &type_lib);
|
| + if (SUCCEEDED(hr)) {
|
| + hr = UtilRegisterTypeLib(type_lib, path, NULL, for_current_user_only);
|
| + }
|
| + return hr;
|
| +}
|
| +
|
| +HRESULT UtilUnRegisterTypeLib(HINSTANCE tlb_instance,
|
| + LPCOLESTR index,
|
| + bool for_current_user_only) {
|
| + CComBSTR path;
|
| + CComPtr<ITypeLib> type_lib;
|
| + HRESULT hr = AtlLoadTypeLib(tlb_instance, index, &path, &type_lib);
|
| + if (SUCCEEDED(hr)) {
|
| + hr = UtilUnRegisterTypeLib(type_lib, for_current_user_only);
|
| + }
|
| + return hr;
|
| +}
|
| +
|
| +HRESULT UtilRegisterTypeLib(LPCWSTR typelib_path,
|
| + bool for_current_user_only) {
|
| + if (NULL == typelib_path) {
|
| + return E_INVALIDARG;
|
| + }
|
| + CComBSTR path;
|
| + CComPtr<ITypeLib> type_lib;
|
| + HRESULT hr = ::LoadTypeLib(typelib_path, &type_lib);
|
| + if (SUCCEEDED(hr)) {
|
| + hr = UtilRegisterTypeLib(type_lib,
|
| + typelib_path,
|
| + NULL,
|
| + for_current_user_only);
|
| + }
|
| + return hr;
|
| +}
|
| +
|
| +HRESULT UtilUnRegisterTypeLib(LPCWSTR typelib_path,
|
| + bool for_current_user_only) {
|
| + CComPtr<ITypeLib> type_lib;
|
| + HRESULT hr = ::LoadTypeLib(typelib_path, &type_lib);
|
| + if (SUCCEEDED(hr)) {
|
| + hr = UtilUnRegisterTypeLib(type_lib, for_current_user_only);
|
| + }
|
| + return hr;
|
| +}
|
| +
|
| +HRESULT UtilRegisterTypeLib(ITypeLib* typelib,
|
| + LPCWSTR typelib_path,
|
| + LPCWSTR help_dir,
|
| + bool for_current_user_only) {
|
| + typedef HRESULT(WINAPI *RegisterTypeLibPrototype)(ITypeLib FAR* type_lib,
|
| + OLECHAR FAR* full_path,
|
| + OLECHAR FAR* help_dir);
|
| + LPCSTR function_name =
|
| + for_current_user_only ? "RegisterTypeLibForUser" : "RegisterTypeLib";
|
| + RegisterTypeLibPrototype reg_tlb =
|
| + reinterpret_cast<RegisterTypeLibPrototype>(
|
| + GetProcAddress(GetModuleHandle(_T("oleaut32.dll")),
|
| + function_name));
|
| + if (NULL == reg_tlb) {
|
| + return E_FAIL;
|
| + }
|
| + return reg_tlb(typelib,
|
| + const_cast<OLECHAR*>(typelib_path),
|
| + const_cast<OLECHAR*>(help_dir));
|
| +}
|
| +
|
| +HRESULT UtilUnRegisterTypeLib(ITypeLib* typelib,
|
| + bool for_current_user_only) {
|
| + if (NULL == typelib) {
|
| + return E_INVALIDARG;
|
| + }
|
| + typedef HRESULT(WINAPI *UnRegisterTypeLibPrototype)(
|
| + REFGUID libID,
|
| + unsigned short wVerMajor, // NOLINT
|
| + unsigned short wVerMinor, // NOLINT
|
| + LCID lcid,
|
| + SYSKIND syskind);
|
| + LPCSTR function_name =
|
| + for_current_user_only ? "UnRegisterTypeLibForUser" : "UnRegisterTypeLib";
|
| +
|
| + UnRegisterTypeLibPrototype unreg_tlb =
|
| + reinterpret_cast<UnRegisterTypeLibPrototype>(
|
| + GetProcAddress(GetModuleHandle(_T("oleaut32.dll")),
|
| + function_name));
|
| + if (NULL == unreg_tlb) {
|
| + return E_FAIL;
|
| + }
|
| + TLIBATTR* tla = NULL;
|
| + HRESULT hr = typelib->GetLibAttr(&tla);
|
| + if (SUCCEEDED(hr)) {
|
| + hr = unreg_tlb(tla->guid,
|
| + tla->wMajorVerNum,
|
| + tla->wMinorVerNum,
|
| + tla->lcid,
|
| + tla->syskind);
|
| + typelib->ReleaseTLibAttr(tla);
|
| + }
|
| + return hr;
|
| +}
|
| +
|
| +HRESULT UtilGetXUACompatContentValue(const std::wstring& html_string,
|
| + std::wstring* content_value) {
|
| + if (!content_value) {
|
| + return E_POINTER;
|
| + }
|
| +
|
| + // Fail fast if the string X-UA-Compatible isn't in html_string
|
| + if (StringToLowerASCII(html_string).find(kXUACompatValue) ==
|
| + std::wstring::npos) {
|
| + return E_FAIL;
|
| + }
|
| +
|
| + HTMLScanner scanner(html_string.c_str());
|
| +
|
| + // Build the list of meta tags that occur before the body tag is hit.
|
| + HTMLScanner::StringRangeList tag_list;
|
| + scanner.GetTagsByName(kMetaTag, &tag_list, kBodyTag);
|
| +
|
| + // Search the list of meta tags for one with an http-equiv="X-UA-Compatible"
|
| + // attribute.
|
| + HTMLScanner::StringRange attribute;
|
| + std::string search_attribute_ascii(WideToASCII(kXUACompatValue));
|
| + HTMLScanner::StringRangeList::const_iterator tag_list_iter(tag_list.begin());
|
| + for (; tag_list_iter != tag_list.end(); tag_list_iter++) {
|
| + if (!tag_list_iter->GetTagAttribute(kHttpEquivAttribName, &attribute)) {
|
| + continue;
|
| + }
|
| +
|
| + // We found an http-equiv meta tag, check its value using the ascii
|
| + // case-insensitive comparison method.
|
| + if (!attribute.LowerCaseEqualsASCII(search_attribute_ascii.c_str())) {
|
| + continue;
|
| + }
|
| +
|
| + // We found our X-UA-Compatible meta tag so look for and extract
|
| + // the value of the content attribute.
|
| + if (!tag_list_iter->GetTagAttribute(kContentAttribName, &attribute)) {
|
| + continue;
|
| + }
|
| +
|
| + // Found the content string, copy and return.
|
| + content_value->assign(attribute.Copy());
|
| + return S_OK;
|
| + }
|
| +
|
| + return E_FAIL;
|
| +}
|
| +
|
| +bool AppendSuffixToChannelName(std::wstring* string,
|
| + const std::wstring& channel_name,
|
| + const std::wstring& suffix) {
|
| + size_t pos = string->find(channel_name);
|
| + // Append the suffix only if we find the channel name.
|
| + if (pos != std::wstring::npos) {
|
| + pos += channel_name.size();
|
| + // Append the suffix only to the channel name only if the name is not
|
| + // already followed by suffix.
|
| + if (string->find(suffix, pos) != pos) {
|
| + string->insert(pos, suffix);
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool RemoveSuffixFromChannelName(std::wstring* string,
|
| + const std::wstring& channel_name,
|
| + const std::wstring& suffix) {
|
| + std::wstring decorated_channel(channel_name + suffix);
|
| + size_t pos = string->find(decorated_channel);
|
| + // TODO(robertshield): Remove the suffix iff the suffix is the last thing in
|
| + // the string or is followed by another suffix that starts with '-'.
|
| + if (pos != std::wstring::npos) {
|
| + pos += channel_name.size();
|
| + string->erase(pos, suffix.size());
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +HRESULT UtilUpdateOmahaConfig(bool add_cf_suffix) {
|
| + HKEY reg_root = HKEY_LOCAL_MACHINE;
|
| +
|
| + RegKey key;
|
| + std::wstring ap_key_value;
|
| + std::wstring reg_key(google_update::kRegPathClientState);
|
| + reg_key.append(L"\\");
|
| + reg_key.append(google_update::kChromeGuid);
|
| + if (!key.Open(reg_root, reg_key.c_str(), KEY_READ | KEY_WRITE) ||
|
| + !key.ReadValue(google_update::kRegApField, &ap_key_value)) {
|
| + // Can't read the Omaha config.
|
| + return REGDB_E_READREGDB;
|
| + }
|
| +
|
| + HRESULT result = S_OK;
|
| + // We've read the key in, try and modify it then write it back.
|
| + if (add_cf_suffix && AppendSuffixToChannelName(&ap_key_value,
|
| + kDevChannelName,
|
| + kChromeFrameOmahaSuffix)) {
|
| + if (!key.WriteValue(google_update::kRegApField, ap_key_value.c_str())) {
|
| + DLOG(ERROR) << "Failed to add suffix to omaha ap key value.";
|
| + result = REGDB_E_WRITEREGDB;
|
| + }
|
| + } else if (!add_cf_suffix &&
|
| + RemoveSuffixFromChannelName(&ap_key_value,
|
| + kDevChannelName,
|
| + kChromeFrameOmahaSuffix)) {
|
| + if (!key.WriteValue(google_update::kRegApField, ap_key_value.c_str())) {
|
| + DLOG(ERROR) << "Failed to remove suffix from omaha ap key value.";
|
| + result = REGDB_E_WRITEREGDB;
|
| + }
|
| + } else {
|
| + // Getting here means that no modifications needed to be made.
|
| + result = S_FALSE;
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +std::wstring GetResourceString(int resource_id) {
|
| + std::wstring resource_string;
|
| + HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
|
| + const ATLSTRINGRESOURCEIMAGE* image = AtlGetStringResourceImage(
|
| + this_module, resource_id);
|
| + if (image) {
|
| + resource_string.assign(image->achString, image->nLength);
|
| + } else {
|
| + NOTREACHED() << "Unable to find resource id " << resource_id;
|
| + }
|
| + return resource_string;
|
| +}
|
| +
|
| +void DisplayVersionMismatchWarning(HWND parent,
|
| + const std::string& server_version) {
|
| + // Obtain the current module version.
|
| + FileVersionInfo* file_version_info =
|
| + FileVersionInfo::CreateFileVersionInfoForCurrentModule();
|
| + DCHECK(file_version_info);
|
| + std::wstring version_string(file_version_info->file_version());
|
| + std::wstring wide_server_version;
|
| + if (server_version.empty()) {
|
| + wide_server_version = GetResourceString(IDS_VERSIONUNKNOWN);
|
| + } else {
|
| + wide_server_version = ASCIIToWide(server_version);
|
| + }
|
| + std::wstring title = GetResourceString(IDS_VERSIONMISMATCH_HEADER);
|
| + std::wstring message;
|
| + SStringPrintf(&message, GetResourceString(IDS_VERSIONMISMATCH).c_str(),
|
| + wide_server_version.c_str(), version_string.c_str());
|
| +
|
| + ::MessageBox(parent, message.c_str(), title.c_str(), MB_OK);
|
| +}
|
| +
|
| +std::string CreateJavascript(const std::string& function_name,
|
| + const std::string args) {
|
| + std::string script_string = "javascript:";
|
| + script_string += function_name + "(";
|
| + if (!args.empty()) {
|
| + script_string += "'";
|
| + script_string += args;
|
| + script_string += "'";
|
| + }
|
| + script_string += ")";
|
| + return script_string;
|
| +}
|
| +
|
| +AddRefModule::AddRefModule() {
|
| + // TODO(tommi): Override the module's Lock/Unlock methods to call
|
| + // npapi::SetValue(NPPVpluginKeepLibraryInMemory) and keep the dll loaded
|
| + // while the module's refcount is > 0. Only do this when we're being
|
| + // used as an NPAPI module.
|
| + _pAtlModule->Lock();
|
| +}
|
| +
|
| +
|
| +AddRefModule::~AddRefModule() {
|
| + _pAtlModule->Unlock();
|
| +}
|
| +
|
| +namespace {
|
| +const char kIEImageName[] = "iexplore.exe";
|
| +const char kFirefoxImageName[] = "firefox.exe";
|
| +const char kOperaImageName[] = "opera.exe";
|
| +} // namespace
|
| +
|
| +std::wstring GetHostProcessName(bool include_extension) {
|
| + FilePath exe;
|
| + if (PathService::Get(base::FILE_EXE, &exe))
|
| + exe = exe.BaseName();
|
| + if (!include_extension) {
|
| + exe = exe.RemoveExtension();
|
| + }
|
| + return exe.ToWStringHack();
|
| +}
|
| +
|
| +BrowserType GetBrowserType() {
|
| + static BrowserType browser_type = BROWSER_INVALID;
|
| +
|
| + if (browser_type == BROWSER_INVALID) {
|
| + std::wstring exe(GetHostProcessName(true));
|
| + if (!exe.empty()) {
|
| + std::wstring::const_iterator begin = exe.begin();
|
| + std::wstring::const_iterator end = exe.end();
|
| + if (LowerCaseEqualsASCII(begin, end, kIEImageName)) {
|
| + browser_type = BROWSER_IE;
|
| + } else if (LowerCaseEqualsASCII(begin, end, kFirefoxImageName)) {
|
| + browser_type = BROWSER_FIREFOX;
|
| + } else if (LowerCaseEqualsASCII(begin, end, kOperaImageName)) {
|
| + browser_type = BROWSER_OPERA;
|
| + } else {
|
| + browser_type = BROWSER_UNKNOWN;
|
| + }
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +
|
| + return browser_type;
|
| +}
|
| +
|
| +IEVersion GetIEVersion() {
|
| + static IEVersion ie_version = IE_INVALID;
|
| +
|
| + if (ie_version == IE_INVALID) {
|
| + wchar_t exe_path[MAX_PATH];
|
| + HMODULE mod = GetModuleHandle(NULL);
|
| + GetModuleFileName(mod, exe_path, arraysize(exe_path) - 1);
|
| + std::wstring exe_name(file_util::GetFilenameFromPath(exe_path));
|
| + if (!LowerCaseEqualsASCII(exe_name, kIEImageName)) {
|
| + ie_version = NON_IE;
|
| + } else {
|
| + uint32 high = 0;
|
| + uint32 low = 0;
|
| + if (GetModuleVersion(mod, &high, &low)) {
|
| + switch (HIWORD(high)) {
|
| + case 6:
|
| + ie_version = IE_6;
|
| + break;
|
| + case 7:
|
| + ie_version = IE_7;
|
| + break;
|
| + default:
|
| + ie_version = HIWORD(high) >= 8 ? IE_8 : IE_UNSUPPORTED;
|
| + break;
|
| + }
|
| + } else {
|
| + NOTREACHED() << "Can't get IE version";
|
| + }
|
| + }
|
| + }
|
| +
|
| + return ie_version;
|
| +}
|
| +
|
| +bool IsIEInPrivate() {
|
| + typedef BOOL (WINAPI* IEIsInPrivateBrowsingPtr)();
|
| + bool incognito_mode = false;
|
| + HMODULE h = GetModuleHandle(L"ieframe.dll");
|
| + if (h) {
|
| + IEIsInPrivateBrowsingPtr IsInPrivate =
|
| + reinterpret_cast<IEIsInPrivateBrowsingPtr>(GetProcAddress(h,
|
| + "IEIsInPrivateBrowsing"));
|
| + if (IsInPrivate) {
|
| + incognito_mode = !!IsInPrivate();
|
| + }
|
| + }
|
| +
|
| + return incognito_mode;
|
| +}
|
| +
|
| +bool GetModuleVersion(HMODULE module, uint32* high, uint32* low) {
|
| + DCHECK(module != NULL)
|
| + << "Please use GetModuleHandle(NULL) to get the process name";
|
| + DCHECK(high);
|
| +
|
| + bool ok = false;
|
| +
|
| + HRSRC res = FindResource(module,
|
| + reinterpret_cast<const wchar_t*>(VS_VERSION_INFO), RT_VERSION);
|
| + if (res) {
|
| + HGLOBAL res_data = LoadResource(module, res);
|
| + DWORD version_resource_size = SizeofResource(module, res);
|
| + const void* readonly_resource_data = LockResource(res_data);
|
| + if (readonly_resource_data && version_resource_size) {
|
| + // Copy data as VerQueryValue tries to modify the data. This causes
|
| + // exceptions and heap corruption errors if debugger is attached.
|
| + scoped_ptr<char> data(new char[version_resource_size]);
|
| + memcpy(data.get(), readonly_resource_data, version_resource_size);
|
| + if (data.get()) {
|
| + VS_FIXEDFILEINFO* ver_info = NULL;
|
| + UINT info_size = 0;
|
| + if (VerQueryValue(data.get(), L"\\",
|
| + reinterpret_cast<void**>(&ver_info), &info_size)) {
|
| + *high = ver_info->dwFileVersionMS;
|
| + if (low != NULL)
|
| + *low = ver_info->dwFileVersionLS;
|
| + ok = true;
|
| + }
|
| +
|
| + UnlockResource(res_data);
|
| + }
|
| + FreeResource(res_data);
|
| + }
|
| + }
|
| +
|
| + return ok;
|
| +}
|
| +
|
| +namespace {
|
| +
|
| +const int kMaxSubmenuDepth = 10;
|
| +
|
| +// Copies original_menu and returns the copy. The caller is responsible for
|
| +// closing the returned HMENU. This does not currently copy over bitmaps
|
| +// (e.g. hbmpChecked, hbmpUnchecked or hbmpItem), so checkmarks, radio buttons,
|
| +// and custom icons won't work.
|
| +// It also copies over submenus up to a maximum depth of kMaxSubMenuDepth.
|
| +//
|
| +// TODO(robertshield): Add support for the bitmap fields if need be.
|
| +HMENU UtilCloneContextMenuImpl(HMENU original_menu, int depth) {
|
| + DCHECK(IsMenu(original_menu));
|
| +
|
| + if (depth >= kMaxSubmenuDepth)
|
| + return NULL;
|
| +
|
| + HMENU new_menu = CreatePopupMenu();
|
| + int item_count = GetMenuItemCount(original_menu);
|
| + if (item_count <= 0) {
|
| + NOTREACHED();
|
| + } else {
|
| + for (int i = 0; i < item_count; i++) {
|
| + MENUITEMINFO item_info = { 0 };
|
| + item_info.cbSize = sizeof(MENUITEMINFO);
|
| + item_info.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE |
|
| + MIIM_STATE | MIIM_DATA | MIIM_SUBMENU |
|
| + MIIM_CHECKMARKS | MIIM_BITMAP;
|
| +
|
| + // Call GetMenuItemInfo a first time to obtain the buffer size for
|
| + // the label.
|
| + if (GetMenuItemInfo(original_menu, i, TRUE, &item_info)) {
|
| + item_info.cch++; // Increment this as per MSDN
|
| + std::vector<wchar_t> buffer(item_info.cch, 0);
|
| + item_info.dwTypeData = &buffer[0];
|
| +
|
| + // Call GetMenuItemInfo a second time with dwTypeData set to a buffer
|
| + // of a correct size to get the label.
|
| + GetMenuItemInfo(original_menu, i, TRUE, &item_info);
|
| +
|
| + // Clone any submenus. Within reason.
|
| + if (item_info.hSubMenu) {
|
| + HMENU new_submenu = UtilCloneContextMenuImpl(item_info.hSubMenu,
|
| + depth + 1);
|
| + item_info.hSubMenu = new_submenu;
|
| + }
|
| +
|
| + // Now insert the item into the new menu.
|
| + InsertMenuItem(new_menu, i, TRUE, &item_info);
|
| + }
|
| + }
|
| + }
|
| + return new_menu;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +HMENU UtilCloneContextMenu(HMENU original_menu) {
|
| + return UtilCloneContextMenuImpl(original_menu, 0);
|
| +}
|
| +
|
| +std::string ResolveURL(const std::string& document,
|
| + const std::string& relative) {
|
| + if (document.empty()) {
|
| + return GURL(relative).spec();
|
| + } else {
|
| + return GURL(document).Resolve(relative).spec();
|
| + }
|
| +}
|
| +
|
| +bool HaveSameOrigin(const std::string& url1, const std::string& url2) {
|
| + GURL a(url1), b(url2);
|
| + bool ret;
|
| + if (a.is_valid() != b.is_valid()) {
|
| + // Either (but not both) url is invalid, so they can't match.
|
| + ret = false;
|
| + } else if (!a.is_valid()) {
|
| + // Both URLs are invalid (see first check). Just check if the opaque
|
| + // strings match exactly.
|
| + ret = url1.compare(url2) == 0;
|
| + } else if (a.GetOrigin() != b.GetOrigin()) {
|
| + // The origins don't match.
|
| + ret = false;
|
| + } else {
|
| + // we have a match.
|
| + ret = true;
|
| + }
|
| +
|
| + return ret;
|
| +}
|
| +
|
| +int GetConfigInt(int default_value, const wchar_t* value_name) {
|
| + int ret = default_value;
|
| + RegKey config_key;
|
| + if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey,
|
| + KEY_QUERY_VALUE)) {
|
| + int value = FALSE;
|
| + if (config_key.ReadValueDW(value_name, reinterpret_cast<DWORD*>(&value))) {
|
| + ret = value;
|
| + }
|
| + }
|
| +
|
| + return ret;
|
| +}
|
| +
|
| +bool GetConfigBool(bool default_value, const wchar_t* value_name) {
|
| + DWORD value = GetConfigInt(default_value, value_name);
|
| + return (value != FALSE);
|
| +}
|
| +
|
| +bool IsOptInUrl(const wchar_t* url) {
|
| + RegKey config_key;
|
| + if (!config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey, KEY_READ))
|
| + return false;
|
| +
|
| + RegistryValueIterator optin_urls_list(config_key.Handle(),
|
| + kChromeFrameOptinUrlsKey);
|
| + while (optin_urls_list.Valid()) {
|
| + if (MatchPattern(url, optin_urls_list.Name()))
|
| + return true;
|
| + ++optin_urls_list;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +HRESULT GetUrlFromMoniker(IMoniker* moniker, IBindCtx* bind_context,
|
| + std::wstring* url) {
|
| + if (!moniker || !url) {
|
| + NOTREACHED();
|
| + return E_INVALIDARG;
|
| + }
|
| +
|
| + ScopedComPtr<IBindCtx> temp_bind_context;
|
| + if (!bind_context) {
|
| + CreateBindCtx(0, temp_bind_context.Receive());
|
| + bind_context = temp_bind_context;
|
| + }
|
| +
|
| + CComHeapPtr<WCHAR> display_name;
|
| + HRESULT hr = moniker->GetDisplayName(bind_context, NULL, &display_name);
|
| + if (display_name)
|
| + *url = display_name;
|
| +
|
| + return hr;
|
| +}
|
| +
|
| +bool IsValidUrlScheme(const std::wstring& url) {
|
| + if (url.empty())
|
| + return false;
|
| +
|
| + GURL crack_url(url);
|
| +
|
| + if (crack_url.SchemeIs("http") || crack_url.SchemeIs("https") ||
|
| + crack_url.SchemeIs("about") || crack_url.SchemeIs("view-source"))
|
| + return true;
|
| +
|
| + if (StartsWith(url, kChromeAttachExternalTabPrefix, false))
|
| + return true;
|
| +
|
| + return false;
|
| +}
|
| +
|
| +// TODO(robertshield): Register and use Chrome's PathProviders.
|
| +// - Note that this function is used by unit tests as well to override
|
| +// PathService paths, so please test when addressing todo.
|
| +bool GetUserProfileBaseDirectory(std::wstring* path) {
|
| + DCHECK(path);
|
| + wchar_t path_buffer[MAX_PATH * 4];
|
| + path_buffer[0] = 0;
|
| + // TODO(robertshield): Ideally we should use SHGetFolderLocation and then
|
| + // get a path via PIDL.
|
| + HRESULT hr = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL,
|
| + SHGFP_TYPE_CURRENT, path_buffer);
|
| +
|
| + if (SUCCEEDED(hr)) {
|
| + *path = path_buffer;
|
| +#if defined(GOOGLE_CHROME_BUILD)
|
| + file_util::AppendToPath(path, FILE_PATH_LITERAL("Google"));
|
| +#endif
|
| + file_util::AppendToPath(path, chrome::kBrowserAppName);
|
| + file_util::AppendToPath(path, chrome::kUserDataDirname);
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
|
|