// 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 <limits>

#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 kSkipGCFMetadataCheck[] = L"SkipGCFMetadataCheck";
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;
      case 10:
        ie_version = IE_10;
        break;
      default:
        ie_version = (major_version >= 11) ? IE_11 : 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;
}

// Check for the registry key 'SkipGCFMetadataCheck' and if true, then
// ignore presence of <meta http-equiv="X-UA-Compatible" content="chrome=1">
bool SkipMetadataCheck() {
  // Check policy settings
  PolicySettings::SkipMetadataCheck metadataCheck =
      PolicySettings::GetInstance()->skip_metadata_check();
  if (metadataCheck != PolicySettings::SKIP_METADATA_CHECK_NOT_SPECIFIED)
    return (metadataCheck == PolicySettings::SKIP_METADATA_CHECK_YES);

  DWORD skip = 0;
  RegKey config_key;
  if (config_key.Open(HKEY_CURRENT_USER, kChromeFrameConfigKey,
                      KEY_READ) == ERROR_SUCCESS) {
    config_key.ReadValueDW(kSkipGCFMetadataCheck, &skip);
  }
  return skip != 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(content::kHttpScheme) ||
      url.SchemeIs(content::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(content::kHttpScheme) ||
        sub_url.SchemeIs(content::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();
}
