// Copyright (c) 2012 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 "chrome_frame/utils.h"

#include <atlsafe.h>
#include <atlsecurity.h>
#include <htiframe.h>
#include <mshtml.h>
#include <shlobj.h>

#include "base/file_version_info.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_local.h"
#include "base/win/registry.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_variant.h"
#include "chrome/common/automation_messages.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/url_constants.h"
#include "chrome/installer/util/chrome_frame_distribution.h"
#include "chrome_frame/chrome_tab.h"
#include "chrome_frame/extra_system_apis.h"
#include "chrome_frame/html_utils.h"
#include "chrome_frame/navigation_constraints.h"
#include "chrome_frame/policy_settings.h"
#include "chrome_frame/registry_list_preferences_holder.h"
#include "chrome_frame/simple_resource_loader.h"
#include "extensions/common/constants.h"
#include "grit/chromium_strings.h"
#include "net/base/escape.h"
#include "net/http/http_util.h"
#include "ui/base/models/menu_model.h"
#include "url/gurl.h"
#include "url/url_canon.h"

using base::win::RegKey;

// Note that these values are all lower case and are compared to
// lower-case-transformed values.
const char kGCFProtocol[] = "gcf";
const wchar_t kBodyTag[] = L"body";
const wchar_t kContentAttribName[] = L"content";
const wchar_t kChromeContentPrefix[] = L"chrome=";
const wchar_t kChromeMimeType[] = L"application/chromepage";
const wchar_t kChromeProtocolPrefix[] = L"gcf:";
const wchar_t kHttpEquivAttribName[] = L"http-equiv";
const wchar_t kIexploreProfileName[] = L"iexplore";
const wchar_t kMetaTag[] = L"meta";
const wchar_t kRundllProfileName[] = L"rundll32";
const wchar_t kXUACompatValue[] = L"x-ua-compatible";

// Registry key and value names related to Chrome Frame configuration options.
const wchar_t kAllowUnsafeURLs[] = L"AllowUnsafeURLs";
const wchar_t kChromeFrameConfigKey[] = L"Software\\Google\\ChromeFrame";
const wchar_t kEnableBuggyBhoIntercept[] = L"EnableBuggyBhoIntercept";
const wchar_t kEnableGCFRendererByDefault[] = L"IsDefaultRenderer";
const wchar_t kExcludeUAFromDomainList[] = L"ExcludeUAFromDomain";
const wchar_t kPatchProtocols[] = L"PatchProtocols";
const wchar_t kRenderInGCFUrlList[] = L"RenderInGcfUrls";
const wchar_t kRenderInHostUrlList[] = L"RenderInHostUrls";

static const wchar_t kChromeFramePersistNPAPIReg[] = L"PersistNPAPIReg";

const char kAttachExternalTabPrefix[] = "attach_external_tab";

// Indicates that we are running in a test environment, where execptions, etc
// are handled by the chrome test crash server.
const wchar_t kChromeFrameHeadlessMode[] = L"ChromeFrameHeadlessMode";

// Indicates that we are running in an environment that expects chrome renderer
// accessibility to be enabled for use in automation tests.
const wchar_t kChromeFrameAccessibleMode[] = L"ChromeFrameAccessibleMode";

// Indicates that we are running in an environment that wishes to avoid
// DLL pinning, such as the perf tests.
const wchar_t kChromeFrameUnpinnedMode[] = L"kChromeFrameUnpinnedMode";

// Controls whether we download subresources, etc on the chrome frame page in
// the background worker thread. Defaults to true.
const wchar_t kUseBackgroundThreadForSubResources[]
    = L"BackgroundHTTPWorkerThread";

// {1AF32B6C-A3BA-48B9-B24E-8AA9C41F6ECD}
static const IID IID_IWebBrowserPriv2IE7 = { 0x1AF32B6C, 0xA3BA, 0x48B9,
    { 0xB2, 0x4E, 0x8A, 0xA9, 0xC4, 0x1F, 0x6E, 0xCD } };

// {3ED72303-6FFC-4214-BA90-FAF1862DEC8A}
static const IID IID_IWebBrowserPriv2IE8 = { 0x3ED72303, 0x6FFC, 0x4214,
    { 0xBA, 0x90, 0xFA, 0xF1, 0x86, 0x2D, 0xEC, 0x8A } };

// {486F6159-9F3F-4827-82D4-283CEF397733}
static const IID IID_IWebBrowserPriv2IE8XP = { 0x486F6159, 0x9F3F, 0x4827,
    { 0x82, 0xD4, 0x28, 0x3C, 0xEF, 0x39, 0x77, 0x33 } };

// {38339692-0BC9-46CB-8E5C-4677A5C83DD5}
static const IID IID_IWebBrowserPriv2IE8XPBeta = { 0x38339692, 0x0BC9, 0x46CB,
    { 0x8E, 0x5C, 0x46, 0x77, 0xA5, 0xC8, 0x3D, 0xD5 } };

namespace {

// A flag used to signal when an active browser instance on the current thread
// is loading a Chrome Frame document.  There's no reference stored with the
// pointer so it should not be dereferenced and used for comparison against a
// living instance only.
base::LazyInstance<base::ThreadLocalPointer<IBrowserService> >
    g_tls_browser_for_cf_navigation = LAZY_INSTANCE_INITIALIZER;

// Holds the cached preferences for the per-url render type settings.
base::LazyInstance<RegistryListPreferencesHolder>::Leaky
    g_render_type_for_url_holder;

// Holds the cached preferences for the per-url user agent filter.
base::LazyInstance<RegistryListPreferencesHolder>::Leaky
    g_user_agent_filter_holder;

}  // end anonymous namespace

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;
}

bool UtilRemovePersistentNPAPIMarker() {
  BrowserDistribution* cf_dist = BrowserDistribution::GetDistribution();
  std::wstring cf_state_key_path(cf_dist->GetStateKey());
  RegKey cf_state_key;

  LONG result = cf_state_key.Open(HKEY_LOCAL_MACHINE, cf_state_key_path.c_str(),
                                  KEY_SET_VALUE);
  if (result == ERROR_SUCCESS)
    result = cf_state_key.DeleteValue(kChromeFramePersistNPAPIReg);
  return (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
}

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;
}

void DisplayVersionMismatchWarning(HWND parent,
                                   const std::string& server_version) {
  // Obtain the current module version.
  scoped_ptr<FileVersionInfo> module_version_info(
      FileVersionInfo::CreateFileVersionInfoForCurrentModule());
  string16 version_string(module_version_info->file_version());
  std::wstring wide_server_version;
  if (server_version.empty()) {
    wide_server_version = SimpleResourceLoader::Get(IDS_VERSIONUNKNOWN);
  } else {
    wide_server_version = ASCIIToWide(server_version);
  }
  std::wstring title = SimpleResourceLoader::Get(IDS_VERSIONMISMATCH_HEADER);
  std::wstring message;
  base::SStringPrintf(&message,
                      SimpleResourceLoader::Get(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();
}

bool IsChrome(RendererType renderer_type) {
  DCHECK_GE(renderer_type, RENDERER_TYPE_UNDETERMINED);
  DCHECK_LE(renderer_type, RENDERER_TYPE_OTHER);
  return renderer_type >= RENDERER_TYPE_CHROME_MIN &&
    renderer_type <= RENDERER_TYPE_CHROME_MAX;
}

namespace {
const char kIEImageName[] = "iexplore.exe";
}  // namespace

std::wstring GetHostProcessName(bool include_extension) {
  base::FilePath exe;
  if (PathService::Get(base::FILE_EXE, &exe))
    exe = exe.BaseName();
  if (!include_extension) {
    exe = exe.RemoveExtension();
  }
  return exe.value();
}

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 {
        browser_type = BROWSER_UNKNOWN;
      }
    } else {
      NOTREACHED();
    }
  }

  return browser_type;
}

uint32 GetIEMajorVersion() {
  static uint32 ie_major_version = UINT_MAX;

  if (ie_major_version == UINT_MAX) {
    wchar_t exe_path[MAX_PATH];
    HMODULE mod = GetModuleHandle(NULL);
    GetModuleFileName(mod, exe_path, arraysize(exe_path) - 1);
    std::wstring exe_name = base::FilePath(exe_path).BaseName().value();
    if (!LowerCaseEqualsASCII(exe_name, kIEImageName)) {
      ie_major_version = 0;
    } else {
      uint32 high = 0;
      uint32 low  = 0;
      if (GetModuleVersion(mod, &high, &low)) {
        ie_major_version = HIWORD(high);
      } else {
        ie_major_version = 0;
      }
    }
  }

  return ie_major_version;
}

IEVersion GetIEVersion() {
  static IEVersion ie_version = IE_INVALID;

  if (ie_version == IE_INVALID) {
    uint32 major_version = GetIEMajorVersion();
    switch (major_version) {
      case 0:
        ie_version = NON_IE;
        break;
      case 6:
        ie_version = IE_6;
        break;
      case 7:
        ie_version = IE_7;
        break;
      case 8:
        ie_version = IE_8;
        break;
      case 9:
        ie_version = IE_9;
        break;
      default:
        ie_version = (major_version >= 10) ? IE_10 : IE_UNSUPPORTED;
        break;
    }
  }

  return ie_version;
}

base::FilePath GetIETemporaryFilesFolder() {
  LPITEMIDLIST tif_pidl = NULL;
  HRESULT hr = SHGetFolderLocation(NULL, CSIDL_INTERNET_CACHE, NULL,
                                   SHGFP_TYPE_CURRENT, &tif_pidl);
  if (SUCCEEDED(hr) && tif_pidl) {
    base::win::ScopedComPtr<IShellFolder> parent_folder;
    LPITEMIDLIST relative_pidl = NULL;
    hr = SHBindToParent(tif_pidl, IID_IShellFolder,
                        reinterpret_cast<void**>(parent_folder.Receive()),
                        const_cast<LPCITEMIDLIST*>(&relative_pidl));
    if (SUCCEEDED(hr) && relative_pidl) {
      STRRET path = {0};
      hr = parent_folder->GetDisplayNameOf(relative_pidl,
                                           SHGDN_NORMAL | SHGDN_FORPARSING,
                                           &path);
      DCHECK(SUCCEEDED(hr));
      base::win::ScopedBstr temp_internet_files_bstr;
      StrRetToBSTR(&path, relative_pidl, temp_internet_files_bstr.Receive());
      base::FilePath temp_internet_files(
          static_cast<BSTR>(temp_internet_files_bstr));
      ILFree(tif_pidl);
      return temp_internet_files;
    } else {
      NOTREACHED() << "SHBindToParent failed with Error:" << hr;
      ILFree(tif_pidl);
    }
  } else {
    NOTREACHED() << "SHGetFolderLocation for internet cache failed. Error:"
                 << hr;
  }
  // As a last ditch effort we use the SHGetFolderPath function to retrieve the
  // path. This function has a limitation of MAX_PATH.
  wchar_t path[MAX_PATH + 1] = {0};
  hr = SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL, SHGFP_TYPE_CURRENT,
                       path);
  if (SUCCEEDED(hr)) {
    return base::FilePath(path);
  } else {
    NOTREACHED() << "SHGetFolderPath for internet cache failed. Error:"
                 << hr;
  }
  return base::FilePath();
}

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;
}

HRESULT DoFileDownloadInIE(const wchar_t* url) {
  DCHECK(url);

  HMODULE mod = ::GetModuleHandleA("ieframe.dll");
  if (!mod)
    mod = ::GetModuleHandleA("shdocvw.dll");

  if (!mod) {
    NOTREACHED();
    return E_UNEXPECTED;
  }

  typedef HRESULT (WINAPI* DoFileDownloadFn)(const wchar_t*);
  DoFileDownloadFn fn = reinterpret_cast<DoFileDownloadFn>(
      ::GetProcAddress(mod, "DoFileDownload"));
  DCHECK(fn);
  return fn ? fn(url) : E_UNEXPECTED;
}

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]);
      if (data.get()) {
        memcpy(data.get(), readonly_resource_data, version_resource_size);
        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;

// Builds a Windows menu from the menu model sent from Chrome.  The
// caller is responsible for closing the returned HMENU.  This does
// not currently handle 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.
HMENU BuildContextMenuImpl(const ContextMenuModel* menu_model, int depth) {
  if (depth >= kMaxSubmenuDepth)
    return NULL;

  HMENU menu = CreatePopupMenu();
  for (size_t i = 0; i < menu_model->items.size(); i++) {
    const ContextMenuModel::Item& item = menu_model->items[i];

    MENUITEMINFO item_info = { 0 };
    item_info.cbSize = sizeof(MENUITEMINFO);
    switch (item.type) {
      case ui::MenuModel::TYPE_COMMAND:
      case ui::MenuModel::TYPE_CHECK:
        item_info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
        item_info.fType = MFT_STRING;
        item_info.wID = item.item_id;
        item_info.dwTypeData = const_cast<LPWSTR>(item.label.c_str());
        break;
      case ui::MenuModel::TYPE_RADIO:
        item_info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
        item_info.fType = MFT_STRING | MFT_RADIOCHECK;
        item_info.wID = item.item_id;
        item_info.dwTypeData = const_cast<LPWSTR>(item.label.c_str());
        break;
      case ui::MenuModel::TYPE_SEPARATOR:
        item_info.fMask = MIIM_FTYPE;
        item_info.fType = MFT_SEPARATOR;
        break;
      case ui::MenuModel::TYPE_SUBMENU:
        item_info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_SUBMENU;
        item_info.fType = MFT_STRING;
        item_info.wID = item.item_id;
        item_info.dwTypeData = const_cast<LPWSTR>(item.label.c_str());
        item_info.hSubMenu = BuildContextMenuImpl(item.submenu, depth + 1);
        break;
      default:
        NOTREACHED() << "Unsupported MenuModel::ItemType " << item.type;
        break;
    }

    item_info.fMask |= MIIM_STATE;
    item_info.fState =
        (item.checked ? MFS_CHECKED : MFS_UNCHECKED) |
        (item.enabled ? MFS_ENABLED : (MFS_DISABLED | MFS_GRAYED));

    InsertMenuItem(menu, i, TRUE, &item_info);
  }

  return menu;
}

}  // namespace

HMENU BuildContextMenu(const ContextMenuModel& menu_model) {
  return BuildContextMenuImpl(&menu_model, 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) == ERROR_SUCCESS) {
    config_key.ReadValueDW(value_name, reinterpret_cast<DWORD*>(&ret));
  }

  return ret;
}

int64 GetConfigInt64(int64 default_value, const wchar_t* value_name) {
  int64 ret = default_value;
  RegKey config_key;
  if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey,
                      KEY_QUERY_VALUE) == ERROR_SUCCESS) {
    config_key.ReadInt64(value_name, &ret);
  }

  return ret;
}

bool GetConfigBool(bool default_value, const wchar_t* value_name) {
  DWORD value = GetConfigInt(default_value, value_name);
  return (value != FALSE);
}

bool SetConfigInt(const wchar_t* value_name, int value) {
  RegKey config_key;
  if (config_key.Create(HKEY_CURRENT_USER, kChromeFrameConfigKey,
                        KEY_SET_VALUE) == ERROR_SUCCESS) {
    if (config_key.WriteValue(value_name, value) == ERROR_SUCCESS) {
      return true;
    }
  }

  return false;
}

bool SetConfigBool(const wchar_t* value_name, bool value) {
  return SetConfigInt(value_name, value);
}

bool SetConfigInt64(const wchar_t* value_name, int64 value) {
  RegKey config_key;
  if (config_key.Create(HKEY_CURRENT_USER, kChromeFrameConfigKey,
                        KEY_SET_VALUE) == ERROR_SUCCESS) {
    if (config_key.WriteValue(value_name, &value, sizeof(value),
                              REG_QWORD) == ERROR_SUCCESS) {
      return true;
    }
  }

  return false;
}

bool DeleteConfigValue(const wchar_t* value_name) {
  RegKey config_key;
  if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey,
                      KEY_WRITE) == ERROR_SUCCESS) {
    if (config_key.DeleteValue(value_name) == ERROR_SUCCESS) {
      return true;
    }
  }
  return false;
}

bool IsGcfDefaultRenderer() {
  DWORD is_default = 0;  // NOLINT

  // First check policy settings
  PolicySettings::RendererForUrl renderer =
      PolicySettings::GetInstance()->default_renderer();
  if (renderer != PolicySettings::RENDERER_NOT_SPECIFIED) {
    is_default = (renderer == PolicySettings::RENDER_IN_CHROME_FRAME);
  } else {
    // TODO(tommi): Implement caching for this config value as it gets
    // checked frequently.
    RegKey config_key;
    if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey,
                        KEY_READ) == ERROR_SUCCESS) {
      config_key.ReadValueDW(kEnableGCFRendererByDefault, &is_default);
    }
  }

  return is_default != 0;
}

RendererType RendererTypeForUrl(const std::wstring& url) {
  // First check if the default renderer settings are specified by policy.
  // If so, then that overrides the user settings.
  PolicySettings::RendererForUrl renderer =
      PolicySettings::GetInstance()->GetRendererForUrl(url.c_str());
  if (renderer != PolicySettings::RENDERER_NOT_SPECIFIED) {
    // We may know at this point that policy says do NOT render in Chrome Frame.
    // To maintain consistency, we return RENDERER_TYPE_UNDETERMINED so that
    // content sniffing, etc. still take place.
    // TODO(tommi): Clarify the intent here.
    return (renderer == PolicySettings::RENDER_IN_CHROME_FRAME) ?
        RENDERER_TYPE_CHROME_OPT_IN_URL : RENDERER_TYPE_UNDETERMINED;
  }

  // TODO(robertshield): Move this into a holder-type class that listens
  // for reg change events as well.
  static int render_in_cf_by_default = FALSE;

  RegistryListPreferencesHolder& render_type_for_url_holder =
      g_render_type_for_url_holder.Get();
  if (!render_type_for_url_holder.Valid()) {
    const wchar_t* url_list_name = kRenderInGCFUrlList;
    if (IsGcfDefaultRenderer()) {
      url_list_name = kRenderInHostUrlList;
      render_in_cf_by_default = TRUE;
    } else {
      render_in_cf_by_default = FALSE;
    }

    render_type_for_url_holder.Init(HKEY_CURRENT_USER,
                                    kChromeFrameConfigKey,
                                    url_list_name);
  }
  DCHECK(render_type_for_url_holder.Valid());

  RendererType renderer_type =
      render_in_cf_by_default ? RENDERER_TYPE_CHROME_DEFAULT_RENDERER :
                                RENDERER_TYPE_UNDETERMINED;

  if (render_type_for_url_holder.ListMatches(url)) {
    renderer_type = render_in_cf_by_default ?
      RENDERER_TYPE_UNDETERMINED :
      RENDERER_TYPE_CHROME_OPT_IN_URL;
  }

  return renderer_type;
}

bool ShouldRemoveUAForUrl(const string16& url) {
  // TODO(robertshield): Wire up the stuff in PolicySettings here so the value
  // can be specified via group policy.
  // TODO(robertshield): Add a default list of exclusions here for site with
  // known bad UA parsing.
  RegistryListPreferencesHolder& user_agent_filter_holder =
      g_user_agent_filter_holder.Get();
  if (!user_agent_filter_holder.Valid()) {
    user_agent_filter_holder.Init(HKEY_CURRENT_USER,
                                  kChromeFrameConfigKey,
                                  kExcludeUAFromDomainList);
  }
  DCHECK(user_agent_filter_holder.Valid());

  return user_agent_filter_holder.ListMatches(url);
}

RegistryListPreferencesHolder& GetRendererTypePreferencesHolderForTesting() {
  return g_render_type_for_url_holder.Get();
}

RegistryListPreferencesHolder& GetUserAgentPreferencesHolderForTesting() {
  return g_user_agent_filter_holder.Get();
}

HRESULT NavigateBrowserToMoniker(IUnknown* browser, IMoniker* moniker,
                                 const wchar_t* headers, IBindCtx* bind_ctx,
                                 const wchar_t* fragment, IStream* post_data,
                                 VARIANT* flags) {
  DCHECK(browser);
  DCHECK(moniker);
  DCHECK(bind_ctx);

  base::win::ScopedComPtr<IWebBrowser2> web_browser2;
  HRESULT hr = DoQueryService(SID_SWebBrowserApp, browser,
                              web_browser2.Receive());
  DCHECK(web_browser2);
  DLOG_IF(WARNING, FAILED(hr)) << base::StringPrintf(L"SWebBrowserApp 0x%08X",
                                                     hr);
  if (FAILED(hr))
    return hr;

  // If the data to be downloaded was received in response to a post request
  // then we need to reissue the post request.
  base::win::ScopedVariant post_data_variant;
  if (post_data) {
    RewindStream(post_data);

    CComSafeArray<uint8> safe_array_post;

    STATSTG stat;
    post_data->Stat(&stat, STATFLAG_NONAME);

    if (stat.cbSize.LowPart > 0) {
      std::string data;

      HRESULT hr = E_FAIL;
      while ((hr = ReadStream(post_data, 0xffff, &data)) == S_OK) {
        safe_array_post.Add(
            data.size(),
            reinterpret_cast<unsigned char*>(const_cast<char*>(data.data())));
        data.clear();
      }
    } else {
      // If we get here it means that the navigation is being reissued for a
      // POST request with no data. To ensure that the new window used as a
      // target to handle the new navigation issues a POST request
      // we need valid POST data. In this case we create a dummy 1 byte array.
      // May not work as expected with some web sites.
      DLOG(WARNING) << "Reissuing navigation with empty POST data. May not"
                    << " work as expected";
      safe_array_post.Create(1);
    }
    post_data_variant.Set(safe_array_post.Detach());
  }
  // Create a new bind context that's not associated with our callback.
  // Calling RevokeBindStatusCallback doesn't disassociate the callback with
  // the bind context in IE7.  The returned bind context has the same
  // implementation of GetRunningObjectTable as the bind context we held which
  // basically delegates to ole32's GetRunningObjectTable.  The object table
  // is then used to determine if the moniker is already running and via
  // that mechanism is associated with the same internet request as has already
  // been issued.

  // TODO(tommi): See if we can get HlinkSimpleNavigateToMoniker to work
  // instead.  Looks like we'll need to support IHTMLDocument2 (get_URL in
  // particular), access to IWebBrowser2 etc.
  // HlinkSimpleNavigateToMoniker(moniker, url, NULL, host, bind_context,
  //                              NULL, 0, 0);

  base::win::ScopedComPtr<IUriContainer> uri_container;
  hr = uri_container.QueryFrom(moniker);

  base::win::ScopedVariant headers_var;
  if (headers && headers[0])
    headers_var.Set(headers);

  if (uri_container) {
    // IE7 and IE8.
    const IID* interface_ids[] = {
      &IID_IWebBrowserPriv2IE7,
      &IID_IWebBrowserPriv2IE8,
      &IID_IWebBrowserPriv2IE8XP,
      &IID_IWebBrowserPriv2IE8XPBeta,
    };

    base::win::ScopedComPtr<IWebBrowserPriv2Common, NULL> browser_priv2;
    for (int i = 0; i < arraysize(interface_ids) && browser_priv2 == NULL;
         ++i) {
      hr = web_browser2.QueryInterface(*interface_ids[i],
          reinterpret_cast<void**>(browser_priv2.Receive()));
    }

    DCHECK(browser_priv2);

    if (browser_priv2) {
      base::win::ScopedComPtr<IUri> uri_obj;
      uri_container->GetIUri(uri_obj.Receive());
      DCHECK(uri_obj);

      if (GetIEVersion() < IE_9) {
        hr = browser_priv2->NavigateWithBindCtx2(
                uri_obj, flags, NULL, post_data_variant.AsInput(),
                headers_var.AsInput(), bind_ctx,
                const_cast<wchar_t*>(fragment));
      } else {
        IWebBrowserPriv2CommonIE9* browser_priv2_ie9 =
            reinterpret_cast<IWebBrowserPriv2CommonIE9*>(browser_priv2.get());
        hr = browser_priv2_ie9->NavigateWithBindCtx2(
                uri_obj, flags, NULL, post_data_variant.AsInput(),
                headers_var.AsInput(), bind_ctx,
                const_cast<wchar_t*>(fragment), 0);
      }
      DLOG_IF(WARNING, FAILED(hr))
          << base::StringPrintf(L"NavigateWithBindCtx2 0x%08X", hr);
    }
  } else {
    // IE6
    LPOLESTR url = NULL;
    if (SUCCEEDED(hr = moniker->GetDisplayName(bind_ctx, NULL, &url))) {
      DVLOG(1) << __FUNCTION__ << " " << url;
      base::win::ScopedComPtr<IWebBrowserPriv> browser_priv;
      if (SUCCEEDED(hr = browser_priv.QueryFrom(web_browser2))) {
        GURL target_url(url);
        // On IE6 if the original URL has a fragment then the navigation
        // attempt is ignored. To workaround this we strip the fragment from
        // the url and initiate the navigation. When the active document loads
        // we retrieve the original url with the fragment from the Navigation
        // manager and use it.
        if (target_url.has_ref()) {
          url_parse::Component comp;
          GURL::Replacements replacements;
          replacements.SetRef("", comp);

          target_url = target_url.ReplaceComponents(replacements);
          fragment = NULL;
        }

        base::win::ScopedVariant var_url(UTF8ToWide(target_url.spec()).c_str());
        hr = browser_priv->NavigateWithBindCtx(var_url.AsInput(), flags, NULL,
                                               post_data_variant.AsInput(),
                                               headers_var.AsInput(), bind_ctx,
                                               const_cast<wchar_t*>(fragment));
        DLOG_IF(WARNING, FAILED(hr))
            << base::StringPrintf(L"NavigateWithBindCtx 0x%08X", hr);
      } else {
        NOTREACHED();
      }
      ::CoTaskMemFree(url);
    } else {
      DLOG(ERROR) << base::StringPrintf("GetDisplayName: 0x%08X", hr);
    }
  }

  return hr;
}

void MarkBrowserOnThreadForCFNavigation(IBrowserService* browser) {
  DCHECK(browser != NULL);
  DCHECK(g_tls_browser_for_cf_navigation.Pointer()->Get() == NULL ||
         g_tls_browser_for_cf_navigation.Pointer()->Get() == browser);
  g_tls_browser_for_cf_navigation.Pointer()->Set(browser);
}

bool CheckForCFNavigation(IBrowserService* browser, bool clear_flag) {
  DCHECK(browser);
  bool ret = (g_tls_browser_for_cf_navigation.Pointer()->Get() == browser);
  if (ret && clear_flag)
    g_tls_browser_for_cf_navigation.Pointer()->Set(NULL);
  return ret;
}

bool IsValidUrlScheme(const GURL& url, bool is_privileged) {
  if (url.is_empty())
    return false;

  if (url.SchemeIs(chrome::kHttpScheme) ||
      url.SchemeIs(chrome::kHttpsScheme) ||
      url.SchemeIs(chrome::kAboutScheme))
    return true;

  // Additional checking for view-source. Allow only http and https
  // URLs in view source.
  if (url.SchemeIs(content::kViewSourceScheme)) {
    GURL sub_url(url.GetContent());
    if (sub_url.SchemeIs(chrome::kHttpScheme) ||
        sub_url.SchemeIs(chrome::kHttpsScheme))
      return true;
    else
      return false;
  }

  if (is_privileged &&
      (url.SchemeIs(chrome::kDataScheme) ||
       url.SchemeIs(extensions::kExtensionScheme)))
    return true;

  return false;
}

std::string GetRawHttpHeaders(IWinInetHttpInfo* info) {
  DCHECK(info);

  std::string buffer;

  DWORD size = 0;
  DWORD flags = 0;
  DWORD reserved = 0;
  HRESULT hr = info->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &size,
                               &flags, &reserved);
  if (!size) {
    DLOG(WARNING) << "Failed to query HTTP headers size. Error: " << hr;
  } else {
    buffer.resize(size + 1);
    hr = info->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, &buffer[0],
                         &size, &flags, &reserved);
    if (FAILED(hr)) {
      DLOG(WARNING) << "Failed to query HTTP headers. Error: " << hr;
    }
  }

  return buffer;
}

bool IsSubFrameRequest(IUnknown* service_provider) {
  DCHECK(service_provider);

  // We need to be able to get at an IWebBrowser2 if we are to decide whether
  // this request originates from a non-top-level frame.
  base::win::ScopedComPtr<IWebBrowser2> web_browser;
  HRESULT hr = DoQueryService(IID_ITargetFrame2, service_provider,
                              web_browser.Receive());

  bool is_sub_frame_request = false;
  if (web_browser) {
    // Now check to see if we are in a sub-frame.
    base::win::ScopedComPtr<IHTMLWindow2> current_frame, parent_frame;
    hr = DoQueryService(IID_IHTMLWindow2, service_provider,
                        current_frame.Receive());
    if (current_frame) {
      // Only the top level window will return self when get_parent is called.
      current_frame->get_parent(parent_frame.Receive());
      if (parent_frame != current_frame) {
        DVLOG(1) << "Sub frame detected";
        is_sub_frame_request = true;
      }
    }
  } else {
    DVLOG(1) << "IsSubFrameRequest - no IWebBrowser2";
    is_sub_frame_request = true;
  }

  return is_sub_frame_request;
}

bool IsHeadlessMode() {
  bool headless = GetConfigBool(false, kChromeFrameHeadlessMode);
  return headless;
}

bool IsAccessibleMode() {
  bool accessible = GetConfigBool(false, kChromeFrameAccessibleMode);
  return accessible;
}

bool IsUnpinnedMode() {
  // We only check this value once and then cache it since changing the registry
  // once we've pinned the DLL won't have any effect.
  static bool unpinned = GetConfigBool(false, kChromeFrameUnpinnedMode);
  return unpinned;
}

std::wstring GetActualUrlFromMoniker(IMoniker* moniker,
                                     IBindCtx* bind_context,
                                     const std::wstring& bho_url) {
  CComHeapPtr<WCHAR> display_name;
  moniker->GetDisplayName(bind_context, NULL, &display_name);
  std::wstring moniker_url = display_name;

  GURL parsed_url(WideToUTF8(bho_url));
  if (!parsed_url.has_ref())
    return moniker_url;

  if (StartsWith(bho_url, moniker_url, false) &&
      bho_url[moniker_url.length()] == L'#')
    return bho_url;

  return moniker_url;
}

bool IsTopLevelWindow(HWND window) {
  long style = GetWindowLong(window, GWL_STYLE);  // NOLINT
  if (!(style & WS_CHILD))
    return true;

  HWND parent = GetParent(window);
  return !parent || (parent == GetDesktopWindow());
}

HRESULT RewindStream(IStream* stream) {
  HRESULT hr = E_POINTER;
  if (stream) {
    LARGE_INTEGER zero = {0};
    ULARGE_INTEGER new_pos = {0};
    hr = stream->Seek(zero, STREAM_SEEK_SET, &new_pos);
  }

  return hr;
}

std::wstring GuidToString(const GUID& guid) {
  std::wstring ret;
  ::StringFromGUID2(guid, WriteInto(&ret, 39), 39);
  return ret;
}

int32 MapCookieStateToCookieAction(InternetCookieState cookie_state) {
  int32 cookie_action = COOKIEACTION_NONE;

  switch (cookie_state) {
    case COOKIE_STATE_UNKNOWN:
      cookie_action = COOKIEACTION_NONE;
      break;
    case COOKIE_STATE_ACCEPT:
      cookie_action = COOKIEACTION_ACCEPT;
      break;
    case COOKIE_STATE_LEASH:
      cookie_action = COOKIEACTION_LEASH;
      break;
    case COOKIE_STATE_DOWNGRADE:
      cookie_action = COOKIEACTION_DOWNGRADE;
      break;
    case COOKIE_STATE_REJECT:
      cookie_action = COOKIEACTION_REJECT;
      break;
    default:
      cookie_action = COOKIEACTION_REJECT;
      break;
  }
  return cookie_action;
}

GURL GetUrlWithoutFragment(const wchar_t* url) {
  GURL parsed_url(url);

  if (parsed_url.has_ref()) {
    url_parse::Component comp;
    GURL::Replacements replacements;
    replacements.SetRef("", comp);

    parsed_url = parsed_url.ReplaceComponents(replacements);
  }
  return parsed_url;
}

bool CompareUrlsWithoutFragment(const wchar_t* url1, const wchar_t* url2) {
  GURL parsed_url1 = GetUrlWithoutFragment(url1);
  GURL parsed_url2 = GetUrlWithoutFragment(url2);
  return parsed_url1 == parsed_url2;
}

std::string FindReferrerFromHeaders(const wchar_t* headers,
                                     const wchar_t* additional_headers) {
  std::string referrer;

  const wchar_t* both_headers[] = { headers, additional_headers };
  for (int i = 0; referrer.empty() && i < arraysize(both_headers); ++i) {
    if (!both_headers[i])
      continue;
    std::string raw_headers_utf8 = WideToUTF8(both_headers[i]);
    net::HttpUtil::HeadersIterator it(raw_headers_utf8.begin(),
                                      raw_headers_utf8.end(), "\r\n");
    while (it.GetNext()) {
      if (LowerCaseEqualsASCII(it.name(), "referer")) {
        referrer = it.values();
        break;
      }
    }
  }

  return referrer;
}

std::string GetHttpHeadersFromBinding(IBinding* binding) {
  if (binding == NULL) {
    DLOG(WARNING) << "GetHttpResponseStatus - no binding_";
    return std::string();
  }

  base::win::ScopedComPtr<IWinInetHttpInfo> info;
  if (FAILED(info.QueryFrom(binding))) {
    DLOG(WARNING) << "Failed to QI for IWinInetHttpInfo";
    return std::string();
  }

  return GetRawHttpHeaders(info);
}

int GetHttpResponseStatusFromBinding(IBinding* binding) {
  DVLOG(1) << __FUNCTION__;
  if (binding == NULL) {
    DLOG(WARNING) << "GetHttpResponseStatus - no binding_";
    return 0;
  }

  int http_status = 0;

  base::win::ScopedComPtr<IWinInetHttpInfo> info;
  if (SUCCEEDED(info.QueryFrom(binding))) {
    char status[10] = {0};
    DWORD buf_size = sizeof(status);
    DWORD flags = 0;
    DWORD reserved = 0;
    if (SUCCEEDED(info->QueryInfo(HTTP_QUERY_STATUS_CODE, status, &buf_size,
                                  &flags, &reserved))) {
      base::StringToInt(status, &http_status);
    } else {
      NOTREACHED() << "Failed to get HTTP status";
    }
  } else {
    NOTREACHED() << "failed to get IWinInetHttpInfo from binding_";
  }

  return http_status;
}

CLIPFORMAT GetTextHtmlClipboardFormat() {
  static const CLIPFORMAT text_html = RegisterClipboardFormat(CFSTR_MIME_HTML);
  return text_html;
}

bool IsTextHtmlMimeType(const wchar_t* mime_type) {
  return IsTextHtmlClipFormat(RegisterClipboardFormatW(mime_type));
}

bool IsTextHtmlClipFormat(CLIPFORMAT cf) {
  return cf == GetTextHtmlClipboardFormat();
}

bool IsSystemProcess() {
  bool is_system = false;
  CAccessToken process_token;
  if (process_token.GetProcessToken(TOKEN_QUERY, GetCurrentProcess())) {
    CSid logon_sid;
    if (process_token.GetUser(&logon_sid)) {
      is_system = logon_sid == Sids::System();
    }
  }
  return is_system;
}


std::string BindStatus2Str(ULONG bind_status) {
  std::string s;
  static const char* const bindstatus_txt[] = {
    "BINDSTATUS_FINDINGRESOURCE",
    "BINDSTATUS_CONNECTING",
    "BINDSTATUS_REDIRECTING",
    "BINDSTATUS_BEGINDOWNLOADDATA",
    "BINDSTATUS_DOWNLOADINGDATA",
    "BINDSTATUS_ENDDOWNLOADDATA",
    "BINDSTATUS_BEGINDOWNLOADCOMPONENTS",
    "BINDSTATUS_INSTALLINGCOMPONENTS",
    "BINDSTATUS_ENDDOWNLOADCOMPONENTS",
    "BINDSTATUS_USINGCACHEDCOPY",
    "BINDSTATUS_SENDINGREQUEST",
    "BINDSTATUS_CLASSIDAVAILABLE",
    "BINDSTATUS_MIMETYPEAVAILABLE",
    "BINDSTATUS_CACHEFILENAMEAVAILABLE",
    "BINDSTATUS_BEGINSYNCOPERATION",
    "BINDSTATUS_ENDSYNCOPERATION",
    "BINDSTATUS_BEGINUPLOADDATA",
    "BINDSTATUS_UPLOADINGDATA",
    "BINDSTATUS_ENDUPLOADINGDATA",
    "BINDSTATUS_PROTOCOLCLASSID",
    "BINDSTATUS_ENCODING",
    "BINDSTATUS_VERFIEDMIMETYPEAVAILABLE",
    "BINDSTATUS_CLASSINSTALLLOCATION",
    "BINDSTATUS_DECODING",
    "BINDSTATUS_LOADINGMIMEHANDLER",
    "BINDSTATUS_CONTENTDISPOSITIONATTACH",
    "BINDSTATUS_FILTERREPORTMIMETYPE",
    "BINDSTATUS_CLSIDCANINSTANTIATE",
    "BINDSTATUS_IUNKNOWNAVAILABLE",
    "BINDSTATUS_DIRECTBIND",
    "BINDSTATUS_RAWMIMETYPE",
    "BINDSTATUS_PROXYDETECTING",
    "BINDSTATUS_ACCEPTRANGES",
    "BINDSTATUS_COOKIE_SENT",
    "BINDSTATUS_COMPACT_POLICY_RECEIVED",
    "BINDSTATUS_COOKIE_SUPPRESSED",
    "BINDSTATUS_COOKIE_STATE_UNKNOWN",
    "BINDSTATUS_COOKIE_STATE_ACCEPT",
    "BINDSTATUS_COOKIE_STATE_REJECT",
    "BINDSTATUS_COOKIE_STATE_PROMPT",
    "BINDSTATUS_COOKIE_STATE_LEASH",
    "BINDSTATUS_COOKIE_STATE_DOWNGRADE",
    "BINDSTATUS_POLICY_HREF",
    "BINDSTATUS_P3P_HEADER",
    "BINDSTATUS_SESSION_COOKIE_RECEIVED",
    "BINDSTATUS_PERSISTENT_COOKIE_RECEIVED",
    "BINDSTATUS_SESSION_COOKIES_ALLOWED",
    "BINDSTATUS_CACHECONTROL",
    "BINDSTATUS_CONTENTDISPOSITIONFILENAME",
    "BINDSTATUS_MIMETEXTPLAINMISMATCH",
    "BINDSTATUS_PUBLISHERAVAILABLE",
    "BINDSTATUS_DISPLAYNAMEAVAILABLE",
    "BINDSTATUS_SSLUX_NAVBLOCKED",
    "BINDSTATUS_SERVER_MIMETYPEAVAILABLE",
    "BINDSTATUS_SNIFFED_CLASSIDAVAILABLE",
    "BINDSTATUS_64BIT_PROGRESS"
  };
  if (bind_status >= 1 && bind_status <= BINDSTATUS_64BIT_PROGRESS)
    s = bindstatus_txt[bind_status - 1];
  else
    s = base::StringPrintf("UnDoc[%#x]", bind_status);
  return s;
}

std::string PiFlags2Str(DWORD flags) {
#define ADD_PI_FLAG(x)  \
  if (flags & x) { \
    s.append(#x ## " "); \
    flags &= ~x; \
  }

  std::string s = " flags ";
  ADD_PI_FLAG(PI_PARSE_URL);
  ADD_PI_FLAG(PI_FILTER_MODE);
  ADD_PI_FLAG(PI_FORCE_ASYNC);
  ADD_PI_FLAG(PI_USE_WORKERTHREAD);
  ADD_PI_FLAG(PI_MIMEVERIFICATION);
  ADD_PI_FLAG(PI_CLSIDLOOKUP);
  ADD_PI_FLAG(PI_DATAPROGRESS);
  ADD_PI_FLAG(PI_SYNCHRONOUS);
  ADD_PI_FLAG(PI_APARTMENTTHREADED);
  ADD_PI_FLAG(PI_CLASSINSTALL);
  ADD_PI_FLAG(PI_PASSONBINDCTX);
  ADD_PI_FLAG(PI_NOMIMEHANDLER);
  ADD_PI_FLAG(PI_LOADAPPDIRECT);
  ADD_PI_FLAG(PD_FORCE_SWITCH);
  ADD_PI_FLAG(PI_PREFERDEFAULTHANDLER);

  if (flags)
    s += base::StringPrintf("+UnDoc[%#x]", flags);
  return s;
#undef ADD_PI_FLAG
}

std::string Bscf2Str(DWORD flags) {
#define ADD_BSCF_FLAG(x)  \
  if (flags & x) {\
    s.append(#x ## " "); \
    flags &= ~x; \
  }

  std::string s = " flags ";
  ADD_BSCF_FLAG(BSCF_FIRSTDATANOTIFICATION)
  ADD_BSCF_FLAG(BSCF_INTERMEDIATEDATANOTIFICATION)
  ADD_BSCF_FLAG(BSCF_LASTDATANOTIFICATION)
  ADD_BSCF_FLAG(BSCF_DATAFULLYAVAILABLE)
  ADD_BSCF_FLAG(BSCF_AVAILABLEDATASIZEUNKNOWN)
  ADD_BSCF_FLAG(BSCF_SKIPDRAINDATAFORFILEURLS)
  ADD_BSCF_FLAG(BSCF_64BITLENGTHDOWNLOAD)

  if (flags)
    s += base::StringPrintf("+UnDoc[%#x]", flags);
  return s;
#undef ADD_BSCF_FLAG
}

// Reads data from a stream into a string.
HRESULT ReadStream(IStream* stream, size_t size, std::string* data) {
  DCHECK(stream);
  DCHECK_GT(size, 0u);
  DCHECK(data);

  DWORD read = 0;
  HRESULT hr = stream->Read(WriteInto(data, size + 1), size, &read);
  DCHECK(hr == S_OK || hr == S_FALSE || hr == E_PENDING);
  if (read) {
    data->erase(read);
    DCHECK_EQ(read, data->length());
  } else {
    data->clear();
    // Return S_FALSE if the underlying stream returned S_OK and zero bytes.
    if (hr == S_OK)
      hr = S_FALSE;
  }

  return hr;
}

ChromeFrameUrl::ChromeFrameUrl() {
  Reset();
}

bool ChromeFrameUrl::Parse(const std::wstring& url) {
  Reset();
  parsed_url_ = GURL(url);

  if (parsed_url_.is_empty())
    return false;

  is_chrome_protocol_ = parsed_url_.SchemeIs(kGCFProtocol);
  if (is_chrome_protocol_) {
    parsed_url_ = GURL(url.c_str() + lstrlen(kChromeProtocolPrefix));
    return true;
  }

  return ParseAttachExternalTabUrl();
}

bool ChromeFrameUrl::ParseAttachExternalTabUrl() {
  std::string query = parsed_url_.query();
  if (!StartsWithASCII(query, kAttachExternalTabPrefix, false)) {
    return parsed_url_.is_valid();
  }

  attach_to_external_tab_ = true;
  base::StringTokenizer tokenizer(query, "&");
  // Skip over kChromeAttachExternalTabPrefix
  tokenizer.GetNext();
  // Read the following items in order.
  // 1. cookie
  // 2. disposition
  // 3. dimension.x
  // 4. dimension.y
  // 5. dimension.width
  // 6. dimension.height.
  if (tokenizer.GetNext()) {
    char* end_ptr = 0;
    cookie_ = _strtoui64(tokenizer.token().c_str(), &end_ptr, 10);
  } else {
    return false;
  }

  if (tokenizer.GetNext()) {
    disposition_ = atoi(tokenizer.token().c_str());
  } else {
    return false;
  }

  if (tokenizer.GetNext()) {
    dimensions_.set_x(atoi(tokenizer.token().c_str()));
  } else {
    return false;
  }

  if (tokenizer.GetNext()) {
    dimensions_.set_y(atoi(tokenizer.token().c_str()));
  } else {
    return false;
  }

  if (tokenizer.GetNext()) {
    dimensions_.set_width(atoi(tokenizer.token().c_str()));
  } else {
    return false;
  }

  if (tokenizer.GetNext()) {
    dimensions_.set_height(atoi(tokenizer.token().c_str()));
  } else {
    return false;
  }

  if (tokenizer.GetNext()) {
    profile_name_ = tokenizer.token();
    // Escape out special characters like %20, etc.
    profile_name_ = net::UnescapeURLComponent(profile_name_,
        net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS);
  } else {
    return false;
  }

  return true;
}

void ChromeFrameUrl::Reset() {
  attach_to_external_tab_ = false;
  is_chrome_protocol_ = false;
  cookie_ = 0;
  dimensions_.SetRect(0, 0, 0, 0);
  disposition_ = 0;
  profile_name_.clear();
}

bool CanNavigate(const GURL& url,
                 NavigationConstraints* navigation_constraints) {
  if (!url.is_valid()) {
    DLOG(ERROR) << "Invalid URL passed to InitiateNavigation: " << url;
    return false;
  }

  if (!navigation_constraints) {
    NOTREACHED() << "Invalid NavigationConstraints passed in";
    return false;
  }

  // No sanity checks if unsafe URLs are allowed
  if (navigation_constraints->AllowUnsafeUrls())
    return true;

  if (!navigation_constraints->IsSchemeAllowed(url)) {
    DLOG(WARNING) << __FUNCTION__ << " Disallowing navigation to url: " << url;
    return false;
  }

  if (!navigation_constraints->IsZoneAllowed(url)) {
    DLOG(WARNING) << __FUNCTION__
                  << " Disallowing navigation to restricted url: " << url;
    return false;
  }
  return true;
}

void WaitWithMessageLoop(HANDLE* handles, int count, DWORD timeout) {
  base::Time now = base::Time::Now();
  base::Time wait_until = now + base::TimeDelta::FromMilliseconds(timeout);

  while (wait_until >= now) {
    base::TimeDelta wait_time = wait_until - now;
    DWORD wait = MsgWaitForMultipleObjects(
        count, handles, FALSE, static_cast<DWORD>(wait_time.InMilliseconds()),
        QS_ALLINPUT);
    switch (wait) {
      case WAIT_OBJECT_0:
      case WAIT_TIMEOUT:
       return;

      case WAIT_OBJECT_0 + 1: {
        MSG msg = {0};
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
        }
        break;
      }

      default: {
        NOTREACHED() << "Unexpected return from MsgWaitForMultipleObjects :"
                     << wait;
        return;
      }
    }
    now = base::Time::Now();
  }
}

// Returns -1 if no directive is found, std::numeric_limits<int>::max() if the
// directive matches all IE versions ('Chrome=1') or the maximum IE version
// matched ('Chrome=IE7' => 7)
int GetXUaCompatibleDirective(const std::string& directive, char delimiter) {
  net::HttpUtil::NameValuePairsIterator name_value_pairs(directive.begin(),
                                                         directive.end(),
                                                         delimiter);

  // Loop through the values until a valid 'Chrome=<FILTER>' entry is found
  while (name_value_pairs.GetNext()) {
    if (!LowerCaseEqualsASCII(name_value_pairs.name_begin(),
                             name_value_pairs.name_end(),
                             "chrome")) {
      continue;
    }
    std::string::const_iterator filter_begin = name_value_pairs.value_begin();
    std::string::const_iterator filter_end = name_value_pairs.value_end();

    size_t filter_length = filter_end - filter_begin;

    if (filter_length == 1 && *filter_begin == '1') {
      return std::numeric_limits<int>::max();
    }

    if (filter_length < 3 ||
        !LowerCaseEqualsASCII(filter_begin, filter_begin + 2, "ie") ||
        !isdigit(*(filter_begin + 2))) {  // ensure no leading +/-
      continue;
    }

    int header_ie_version = 0;
    if (!base::StringToInt(base::StringPiece(filter_begin + 2,
                                             filter_end),
                           &header_ie_version) ||
        header_ie_version == 0) {  // ensure it's not a sequence of 0's
      continue;
    }

    // The first valid directive we find wins, whether it matches or not
    return header_ie_version;
  }
  return -1;
}

bool CheckXUaCompatibleDirective(const std::string& directive,
                                 int ie_major_version) {
  int header_ie_version = GetXUaCompatibleDirective(directive, ';');
  if (header_ie_version == -1) {
    header_ie_version = GetXUaCompatibleDirective(directive, ',');
  }
  return header_ie_version >= ie_major_version;
}

void EnumerateKeyValues(HKEY parent_key, const wchar_t* sub_key_name,
                        std::vector<std::wstring>* values) {
  DCHECK(values);
  base::win::RegistryValueIterator url_list(parent_key, sub_key_name);
  while (url_list.Valid()) {
    values->push_back(url_list.Value());
    ++url_list;
  }
}

std::wstring GetCurrentModuleVersion() {
  scoped_ptr<FileVersionInfo> module_version_info(
      FileVersionInfo::CreateFileVersionInfoForCurrentModule());
  DCHECK(module_version_info.get() != NULL);
  return module_version_info->file_version();
}

bool IsChromeFrameDocument(IWebBrowser2* web_browser) {
  if (!web_browser)
    return false;

  base::win::ScopedComPtr<IDispatch> doc;
  web_browser->get_Document(doc.Receive());
  if (doc) {
    // Detect if CF is rendering based on whether the document is a
    // ChromeActiveDocument. Detecting based on hwnd is problematic as
    // the CF Active Document window may not have been created yet.
    base::win::ScopedComPtr<IChromeFrame> chrome_frame;
    chrome_frame.QueryFrom(doc);
    return chrome_frame.get() != NULL;
  }
  return false;
}

bool IncreaseWinInetConnections(DWORD connections) {
  static bool wininet_connection_count_updated = false;
  if (wininet_connection_count_updated) {
    return true;
  }

  static int connection_options[] = {
    INTERNET_OPTION_MAX_CONNS_PER_SERVER,
    INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER,
  };

  BOOL ret = FALSE;

  for (int option_index = 0; option_index < arraysize(connection_options);
       ++option_index) {
    DWORD connection_value_size = sizeof(DWORD);
    DWORD current_connection_limit = 0;
    InternetQueryOption(NULL, connection_options[option_index],
                        &current_connection_limit, &connection_value_size);
    if (current_connection_limit > connections) {
      continue;
    }

    ret = InternetSetOption(NULL, connection_options[option_index],
                            &connections, connection_value_size);
    if (!ret) {
      return false;
    }
  }
  wininet_connection_count_updated = true;
  return true;
}

void GetChromeFrameProfilePath(const string16& profile_name,
                               base::FilePath* profile_path) {
  chrome::GetChromeFrameUserDataDirectory(profile_path);
  *profile_path = profile_path->Append(profile_name);
  DVLOG(1) << __FUNCTION__ << ": " << profile_path->value();
}
