// 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/utility/importer/ie_importer_win.h"

#include <ole2.h>
#include <intshcut.h>
#include <shlobj.h>
#include <urlhist.h>
#include <wininet.h>

#include <algorithm>
#include <map>
#include <string>
#include <vector>

#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/strings/string16.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/win/registry.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_handle.h"
#include "base/win/scoped_propvariant.h"
#include "base/win/windows_version.h"
#include "chrome/common/importer/ie_importer_utils_win.h"
#include "chrome/common/importer/imported_bookmark_entry.h"
#include "chrome/common/importer/imported_favicon_usage.h"
#include "chrome/common/importer/importer_bridge.h"
#include "chrome/common/importer/importer_data_types.h"
#include "chrome/common/importer/importer_url_row.h"
#include "chrome/common/importer/pstore_declarations.h"
#include "chrome/common/url_constants.h"
#include "chrome/utility/importer/favicon_reencode.h"
#include "content/public/common/password_form.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

namespace {

// Registry key paths from which we import IE settings.
const char16 kSearchScopePath[] =
  L"Software\\Microsoft\\Internet Explorer\\SearchScopes";
const char16 kIEVersionKey[] =
  L"Software\\Microsoft\\Internet Explorer";
const char16 kIEToolbarKey[] =
  L"Software\\Microsoft\\Internet Explorer\\Toolbar";

// NTFS stream name of favicon image data.
const char16 kFaviconStreamName[] = L":favicon:$DATA";

// A struct that hosts the information of AutoComplete data in PStore.
struct AutoCompleteInfo {
  string16 key;
  std::vector<string16> data;
  bool is_url;
};

// Gets the creation time of the given file or directory.
base::Time GetFileCreationTime(const string16& file) {
  base::Time creation_time;
  base::win::ScopedHandle file_handle(
      CreateFile(file.c_str(), GENERIC_READ,
                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                 NULL, OPEN_EXISTING,
                 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL));
  FILETIME creation_filetime;
  if (GetFileTime(file_handle, &creation_filetime, NULL, NULL))
    creation_time = base::Time::FromFileTime(creation_filetime);
  return creation_time;
}

// Safely read an object of type T from a raw sequence of bytes.
template<typename T>
bool BinaryRead(T* data, size_t offset, const std::vector<uint8>& blob) {
  if (offset + sizeof(T) > blob.size())
    return false;
  memcpy(data, &blob[offset], sizeof(T));
  return true;
}

// Safely read an ITEMIDLIST from a raw sequence of bytes.
//
// An ITEMIDLIST is a list of SHITEMIDs, terminated by a SHITEMID with
// .cb = 0. Here, before simply casting &blob[offset] to LPITEMIDLIST,
// we verify that the list structure is not overrunning the boundary of
// the binary blob.
LPCITEMIDLIST BinaryReadItemIDList(size_t offset, size_t idlist_size,
                                   const std::vector<uint8>& blob) {
  size_t head = 0;
  while (true) {
    // Use a USHORT instead of SHITEMID to avoid buffer over read.
    USHORT id_cb;
    if (head >= idlist_size || !BinaryRead(&id_cb, offset + head, blob))
      return NULL;
    if (id_cb == 0)
      break;
    head += id_cb;
  }
  return reinterpret_cast<LPCITEMIDLIST>(&blob[offset]);
}

// Compares the two bookmarks in the order of IE's Favorites menu.
// Returns true if rhs should come later than lhs (lhs < rhs).
struct IEOrderBookmarkComparator {
  bool operator()(const ImportedBookmarkEntry& lhs,
                  const ImportedBookmarkEntry& rhs) const {
    static const uint32 kNotSorted = 0xfffffffb; // IE uses this magic value.
    base::FilePath lhs_prefix;
    base::FilePath rhs_prefix;
    for (size_t i = 0; i <= lhs.path.size() && i <= rhs.path.size(); ++i) {
      const base::FilePath::StringType lhs_i =
        (i < lhs.path.size() ? lhs.path[i] : lhs.title + L".url");
      const base::FilePath::StringType rhs_i =
        (i < rhs.path.size() ? rhs.path[i] : rhs.title + L".url");
      lhs_prefix = lhs_prefix.Append(lhs_i);
      rhs_prefix = rhs_prefix.Append(rhs_i);
      if (lhs_i == rhs_i)
        continue;
      // The first path element that differs between the two.
      std::map<base::FilePath, uint32>::const_iterator lhs_iter =
        sort_index_->find(lhs_prefix);
      std::map<base::FilePath, uint32>::const_iterator rhs_iter =
        sort_index_->find(rhs_prefix);
      uint32 lhs_sort_index = (lhs_iter == sort_index_->end() ? kNotSorted
        : lhs_iter->second);
      uint32 rhs_sort_index = (rhs_iter == sort_index_->end() ? kNotSorted
        : rhs_iter->second);
      if (lhs_sort_index != rhs_sort_index)
        return lhs_sort_index < rhs_sort_index;
      // If they have the same sort order, sort alphabetically.
      return lhs_i < rhs_i;
    }
    return lhs.path.size() < rhs.path.size();
  }
  const std::map<base::FilePath, uint32>* sort_index_;
};

// IE stores the order of the Favorites menu in registry under:
// HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites.
// The folder hierarchy of Favorites menu is directly mapped to the key
// hierarchy in the registry.
//
// If the order of the items in a folder is customized by user, the order is
// recorded in the REG_BINARY value named "Order" of the corresponding key.
// The content of the "Order" value is a raw binary dump of an array of the
// following data structure
//   struct {
//     uint32 size;  // Note that ITEMIDLIST is variably-sized.
//     uint32 sort_index;  // 0 means this is the first item, 1 the second, ...
//     ITEMIDLIST item_id;
//   };
// where each item_id should correspond to a favorites link file (*.url) in
// the current folder.
bool ParseFavoritesOrderBlob(
    const Importer* importer,
    const std::vector<uint8>& blob,
    const base::FilePath& path,
    std::map<base::FilePath, uint32>* sort_index) WARN_UNUSED_RESULT {
  static const int kItemCountOffset = 16;
  static const int kItemListStartOffset = 20;

  // Read the number of items.
  uint32 item_count = 0;
  if (!BinaryRead(&item_count, kItemCountOffset, blob))
    return false;

  // Traverse over the items.
  size_t base_offset = kItemListStartOffset;
  for (uint32 i = 0; i < item_count && !importer->cancelled(); ++i) {
    static const int kSizeOffset = 0;
    static const int kSortIndexOffset = 4;
    static const int kItemIDListOffset = 8;

    // Read the size (number of bytes) of the current item.
    uint32 item_size = 0;
    if (!BinaryRead(&item_size, base_offset + kSizeOffset, blob) ||
        base_offset + item_size <= base_offset || // checking overflow
        base_offset + item_size > blob.size())
      return false;

    // Read the sort index of the current item.
    uint32 item_sort_index = 0;
    if (!BinaryRead(&item_sort_index, base_offset + kSortIndexOffset, blob))
      return false;

    // Read the file name from the ITEMIDLIST structure.
    LPCITEMIDLIST idlist = BinaryReadItemIDList(
      base_offset + kItemIDListOffset, item_size - kItemIDListOffset, blob);
    TCHAR item_filename[MAX_PATH];
    if (!idlist || FAILED(SHGetPathFromIDList(idlist, item_filename)))
      return false;
    base::FilePath item_relative_path =
      path.Append(base::FilePath(item_filename).BaseName());

    // Record the retrieved information and go to the next item.
    sort_index->insert(std::make_pair(item_relative_path, item_sort_index));
    base_offset += item_size;
  }
  return true;
}

bool ParseFavoritesOrderRegistryTree(
    const Importer* importer,
    const base::win::RegKey& key,
    const base::FilePath& path,
    std::map<base::FilePath, uint32>* sort_index) WARN_UNUSED_RESULT {
  // Parse the order information of the current folder.
  DWORD blob_length = 0;
  if (key.ReadValue(L"Order", NULL, &blob_length, NULL) == ERROR_SUCCESS) {
    std::vector<uint8> blob(blob_length);
    if (blob_length > 0 &&
        key.ReadValue(L"Order", reinterpret_cast<DWORD*>(&blob[0]),
                      &blob_length, NULL) == ERROR_SUCCESS) {
      if (!ParseFavoritesOrderBlob(importer, blob, path, sort_index))
        return false;
    }
  }

  // Recursively parse subfolders.
  for (base::win::RegistryKeyIterator child(key.Handle(), L"");
       child.Valid() && !importer->cancelled();
       ++child) {
    base::win::RegKey subkey(key.Handle(), child.Name(), KEY_READ);
    if (subkey.Valid()) {
      base::FilePath subpath(path.Append(child.Name()));
      if (!ParseFavoritesOrderRegistryTree(importer, subkey, subpath,
                                           sort_index)) {
        return false;
      }
    }
  }
  return true;
}

bool ParseFavoritesOrderInfo(
    const Importer* importer,
    std::map<base::FilePath, uint32>* sort_index) WARN_UNUSED_RESULT {
  base::string16 key_path(importer::GetIEFavoritesOrderKey());
  base::win::RegKey key(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ);
  if (!key.Valid())
    return false;
  return ParseFavoritesOrderRegistryTree(importer, key, base::FilePath(),
                                         sort_index);
}

// Reads the sort order from registry. If failed, we don't touch the list
// and use the default (alphabetical) order.
void SortBookmarksInIEOrder(
    const Importer* importer,
    std::vector<ImportedBookmarkEntry>* bookmarks) {
  std::map<base::FilePath, uint32> sort_index;
  if (!ParseFavoritesOrderInfo(importer, &sort_index))
    return;
  IEOrderBookmarkComparator compare = {&sort_index};
  std::sort(bookmarks->begin(), bookmarks->end(), compare);
}

// Reads an internet shortcut (*.url) |file| and returns a COM object
// representing it.
bool LoadInternetShortcut(
    const string16& file,
    base::win::ScopedComPtr<IUniformResourceLocator>* shortcut) {
  base::win::ScopedComPtr<IUniformResourceLocator> url_locator;
  if (FAILED(url_locator.CreateInstance(CLSID_InternetShortcut, NULL,
                                        CLSCTX_INPROC_SERVER)))
    return false;

  base::win::ScopedComPtr<IPersistFile> persist_file;
  if (FAILED(persist_file.QueryFrom(url_locator)))
    return false;

  // Loads the Internet Shortcut from persistent storage.
  if (FAILED(persist_file->Load(file.c_str(), STGM_READ)))
    return false;

  std::swap(url_locator, *shortcut);
  return true;
}

// Reads the URL stored in the internet shortcut.
GURL ReadURLFromInternetShortcut(IUniformResourceLocator* url_locator) {
  base::win::ScopedCoMem<wchar_t> url;
  // GetURL can return S_FALSE (FAILED(S_FALSE) is false) when url == NULL.
  return (FAILED(url_locator->GetURL(&url)) || !url) ?
      GURL() : GURL(WideToUTF16(std::wstring(url)));
}

// Reads the URL of the favicon of the internet shortcut.
GURL ReadFaviconURLFromInternetShortcut(IUniformResourceLocator* url_locator) {
  base::win::ScopedComPtr<IPropertySetStorage> property_set_storage;
  if (FAILED(property_set_storage.QueryFrom(url_locator)))
    return GURL();

  base::win::ScopedComPtr<IPropertyStorage> property_storage;
  if (FAILED(property_set_storage->Open(FMTID_Intshcut, STGM_READ,
                                        property_storage.Receive()))) {
    return GURL();
  }

  PROPSPEC properties[] = {{PRSPEC_PROPID, PID_IS_ICONFILE}};
  // ReadMultiple takes a non-const array of PROPVARIANTs, but since this code
  // only needs an array of size 1: a non-const pointer to |output| is
  // equivalent.
  base::win::ScopedPropVariant output;
  // ReadMultiple can return S_FALSE (FAILED(S_FALSE) is false) when the
  // property is not found, in which case output[0].vt is set to VT_EMPTY.
  if (FAILED(property_storage->ReadMultiple(1, properties, output.Receive())) ||
      output.get().vt != VT_LPWSTR)
    return GURL();
  return GURL(WideToUTF16(output.get().pwszVal));
}

// Reads the favicon imaga data in an NTFS alternate data stream. This is where
// IE7 and above store the data.
bool ReadFaviconDataFromInternetShortcut(const string16& file,
                                         std::string* data) {
  return file_util::ReadFileToString(
      base::FilePath(file + kFaviconStreamName), data);
}

// Reads the favicon imaga data in the Internet cache. IE6 doesn't hold the data
// explicitly, but it might be found in the cache.
bool ReadFaviconDataFromCache(const GURL& favicon_url, std::string* data) {
  std::wstring url_wstring(UTF8ToWide(favicon_url.spec()));
  DWORD info_size = 0;
  GetUrlCacheEntryInfoEx(url_wstring.c_str(), NULL, &info_size, NULL, NULL,
                         NULL, 0);
  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    return false;

  std::vector<char> buf(info_size);
  INTERNET_CACHE_ENTRY_INFO* cache =
      reinterpret_cast<INTERNET_CACHE_ENTRY_INFO*>(&buf[0]);
  if (!GetUrlCacheEntryInfoEx(url_wstring.c_str(), cache, &info_size, NULL,
                              NULL, NULL, 0)) {
    return false;
  }
  return file_util::ReadFileToString(base::FilePath(cache->lpszLocalFileName),
                                     data);
}

// Reads the binary image data of favicon of an internet shortcut file |file|.
// |favicon_url| read by ReadFaviconURLFromInternetShortcut is also needed to
// examine the IE cache.
bool ReadReencodedFaviconData(const string16& file,
                              const GURL& favicon_url,
                              std::vector<unsigned char>* data) {
  std::string image_data;
  if (!ReadFaviconDataFromInternetShortcut(file, &image_data) &&
      !ReadFaviconDataFromCache(favicon_url, &image_data)) {
    return false;
  }

  const unsigned char* ptr =
      reinterpret_cast<const unsigned char*>(image_data.c_str());
  return importer::ReencodeFavicon(ptr, image_data.size(), data);
}

// Loads favicon image data and registers to |favicon_map|.
void UpdateFaviconMap(
    const string16& url_file,
    const GURL& url,
    IUniformResourceLocator* url_locator,
    std::map<GURL, ImportedFaviconUsage>* favicon_map) {
  GURL favicon_url = ReadFaviconURLFromInternetShortcut(url_locator);
  if (!favicon_url.is_valid())
    return;

  std::map<GURL, ImportedFaviconUsage>::iterator it =
    favicon_map->find(favicon_url);
  if (it != favicon_map->end()) {
    // Known favicon URL.
    it->second.urls.insert(url);
  } else {
    // New favicon URL. Read the image data and store.
    ImportedFaviconUsage usage;
    if (ReadReencodedFaviconData(url_file, favicon_url, &usage.png_data)) {
      usage.favicon_url = favicon_url;
      usage.urls.insert(url);
      favicon_map->insert(std::make_pair(favicon_url, usage));
    }
  }
}

}  // namespace

// static
// {E161255A-37C3-11D2-BCAA-00C04fD929DB}
const GUID IEImporter::kPStoreAutocompleteGUID = {
    0xe161255a, 0x37c3, 0x11d2,
    { 0xbc, 0xaa, 0x00, 0xc0, 0x4f, 0xd9, 0x29, 0xdb }
};
// {A79029D6-753E-4e27-B807-3D46AB1545DF}
const GUID IEImporter::kUnittestGUID = {
    0xa79029d6, 0x753e, 0x4e27,
    { 0xb8, 0x7, 0x3d, 0x46, 0xab, 0x15, 0x45, 0xdf }
};

IEImporter::IEImporter() {
}

void IEImporter::StartImport(const importer::SourceProfile& source_profile,
                             uint16 items,
                             ImporterBridge* bridge) {
  bridge_ = bridge;
  source_path_ = source_profile.source_path;

  bridge_->NotifyStarted();

  if ((items & importer::HOME_PAGE) && !cancelled()) {
    bridge_->NotifyItemStarted(importer::HOME_PAGE);
    ImportHomepage();  // Doesn't have a UI item.
    bridge_->NotifyItemEnded(importer::HOME_PAGE);
  }
  // The order here is important!
  if ((items & importer::HISTORY) && !cancelled()) {
    bridge_->NotifyItemStarted(importer::HISTORY);
    ImportHistory();
    bridge_->NotifyItemEnded(importer::HISTORY);
  }
  if ((items & importer::FAVORITES) && !cancelled()) {
    bridge_->NotifyItemStarted(importer::FAVORITES);
    ImportFavorites();
    bridge_->NotifyItemEnded(importer::FAVORITES);
  }
  if ((items & importer::SEARCH_ENGINES) && !cancelled()) {
    bridge_->NotifyItemStarted(importer::SEARCH_ENGINES);
    ImportSearchEngines();
    bridge_->NotifyItemEnded(importer::SEARCH_ENGINES);
  }
  if ((items & importer::PASSWORDS) && !cancelled()) {
    bridge_->NotifyItemStarted(importer::PASSWORDS);
    // Always import IE6 passwords.
    ImportPasswordsIE6();

    if (CurrentIEVersion() >= 7)
      ImportPasswordsIE7();
    bridge_->NotifyItemEnded(importer::PASSWORDS);
  }
  bridge_->NotifyEnded();
}

IEImporter::~IEImporter() {
}

void IEImporter::ImportFavorites() {
  FavoritesInfo info;
  if (!GetFavoritesInfo(&info))
    return;

  BookmarkVector bookmarks;
  std::vector<ImportedFaviconUsage> favicons;
  ParseFavoritesFolder(info, &bookmarks, &favicons);

  if (!bookmarks.empty() && !cancelled()) {
    const string16& first_folder_name =
        l10n_util::GetStringUTF16(IDS_BOOKMARK_GROUP_FROM_IE);
    bridge_->AddBookmarks(bookmarks, first_folder_name);
  }
  if (!favicons.empty() && !cancelled())
    bridge_->SetFavicons(favicons);
}

void IEImporter::ImportHistory() {
  const std::string kSchemes[] = {chrome::kHttpScheme,
                                  chrome::kHttpsScheme,
                                  chrome::kFtpScheme,
                                  chrome::kFileScheme};
  int total_schemes = arraysize(kSchemes);

  base::win::ScopedComPtr<IUrlHistoryStg2> url_history_stg2;
  HRESULT result;
  result = url_history_stg2.CreateInstance(CLSID_CUrlHistory, NULL,
                                           CLSCTX_INPROC_SERVER);
  if (FAILED(result))
    return;
  base::win::ScopedComPtr<IEnumSTATURL> enum_url;
  if (SUCCEEDED(result = url_history_stg2->EnumUrls(enum_url.Receive()))) {
    std::vector<ImporterURLRow> rows;
    STATURL stat_url;
    ULONG fetched;
    while (!cancelled() &&
           (result = enum_url->Next(1, &stat_url, &fetched)) == S_OK) {
      string16 url_string;
      if (stat_url.pwcsUrl) {
        url_string = stat_url.pwcsUrl;
        CoTaskMemFree(stat_url.pwcsUrl);
      }
      string16 title_string;
      if (stat_url.pwcsTitle) {
        title_string = stat_url.pwcsTitle;
        CoTaskMemFree(stat_url.pwcsTitle);
      }

      GURL url(url_string);
      // Skips the URLs that are invalid or have other schemes.
      if (!url.is_valid() ||
          (std::find(kSchemes, kSchemes + total_schemes, url.scheme()) ==
           kSchemes + total_schemes))
        continue;

      ImporterURLRow row(url);
      row.title = title_string;
      row.last_visit = base::Time::FromFileTime(stat_url.ftLastVisited);
      if (stat_url.dwFlags == STATURL_QUERYFLAG_TOPLEVEL) {
        row.visit_count = 1;
        row.hidden = false;
      } else {
        row.hidden = true;
      }

      rows.push_back(row);
    }

    if (!rows.empty() && !cancelled()) {
      bridge_->SetHistoryItems(rows, importer::VISIT_SOURCE_IE_IMPORTED);
    }
  }
}

void IEImporter::ImportPasswordsIE6() {
  GUID AutocompleteGUID = kPStoreAutocompleteGUID;
  if (!source_path_.empty()) {
    // We supply a fake GUID for testting.
    AutocompleteGUID = kUnittestGUID;
  }

  // The PStoreCreateInstance function retrieves an interface pointer
  // to a storage provider. But this function has no associated import
  // library or header file, we must call it using the LoadLibrary()
  // and GetProcAddress() functions.
  typedef HRESULT (WINAPI *PStoreCreateFunc)(IPStore**, DWORD, DWORD, DWORD);
  HMODULE pstorec_dll = LoadLibrary(L"pstorec.dll");
  if (!pstorec_dll)
    return;
  PStoreCreateFunc PStoreCreateInstance =
      (PStoreCreateFunc)GetProcAddress(pstorec_dll, "PStoreCreateInstance");
  if (!PStoreCreateInstance) {
    FreeLibrary(pstorec_dll);
    return;
  }

  base::win::ScopedComPtr<IPStore, &IID_IPStore> pstore;
  HRESULT result = PStoreCreateInstance(pstore.Receive(), 0, 0, 0);
  if (result != S_OK) {
    FreeLibrary(pstorec_dll);
    return;
  }

  std::vector<AutoCompleteInfo> ac_list;

  // Enumerates AutoComplete items in the protected database.
  base::win::ScopedComPtr<IEnumPStoreItems, &IID_IEnumPStoreItems> item;
  result = pstore->EnumItems(0, &AutocompleteGUID,
                             &AutocompleteGUID, 0, item.Receive());
  if (result != PST_E_OK) {
    pstore.Release();
    FreeLibrary(pstorec_dll);
    return;
  }

  wchar_t* item_name;
  while (!cancelled() && SUCCEEDED(item->Next(1, &item_name, 0))) {
    DWORD length = 0;
    unsigned char* buffer = NULL;
    result = pstore->ReadItem(0, &AutocompleteGUID, &AutocompleteGUID,
                              item_name, &length, &buffer, NULL, 0);
    if (SUCCEEDED(result)) {
      AutoCompleteInfo ac;
      ac.key = item_name;
      string16 data;
      data.insert(0, reinterpret_cast<wchar_t*>(buffer),
                  length / sizeof(wchar_t));

      // The key name is always ended with ":StringData".
      const wchar_t kDataSuffix[] = L":StringData";
      size_t i = ac.key.rfind(kDataSuffix);
      if (i != string16::npos && ac.key.substr(i) == kDataSuffix) {
        ac.key.erase(i);
        ac.is_url = (ac.key.find(L"://") != string16::npos);
        ac_list.push_back(ac);
        base::SplitString(data, L'\0', &ac_list[ac_list.size() - 1].data);
      }
      CoTaskMemFree(buffer);
    }
    CoTaskMemFree(item_name);
  }
  // Releases them before unload the dll.
  item.Release();
  pstore.Release();
  FreeLibrary(pstorec_dll);

  size_t i;
  for (i = 0; i < ac_list.size(); i++) {
    if (!ac_list[i].is_url || ac_list[i].data.size() < 2)
      continue;

    GURL url(ac_list[i].key.c_str());
    if (!(LowerCaseEqualsASCII(url.scheme(), chrome::kHttpScheme) ||
        LowerCaseEqualsASCII(url.scheme(), chrome::kHttpsScheme))) {
      continue;
    }

    content::PasswordForm form;
    GURL::Replacements rp;
    rp.ClearUsername();
    rp.ClearPassword();
    rp.ClearQuery();
    rp.ClearRef();
    form.origin = url.ReplaceComponents(rp);
    form.username_value = ac_list[i].data[0];
    form.password_value = ac_list[i].data[1];
    form.signon_realm = url.GetOrigin().spec();

    // This is not precise, because a scheme of https does not imply a valid
    // certificate was presented; however we assign it this way so that if we
    // import a password from IE whose scheme is https, we give it the benefit
    // of the doubt and DONT auto-fill it unless the form appears under
    // valid SSL conditions.
    form.ssl_valid = url.SchemeIsSecure();

    // Goes through the list to find out the username field
    // of the web page.
    size_t list_it, item_it;
    for (list_it = 0; list_it < ac_list.size(); ++list_it) {
      if (ac_list[list_it].is_url)
        continue;

      for (item_it = 0; item_it < ac_list[list_it].data.size(); ++item_it)
        if (ac_list[list_it].data[item_it] == form.username_value) {
          form.username_element = ac_list[list_it].key;
          break;
        }
    }

    bridge_->SetPasswordForm(form);
  }
}

void IEImporter::ImportPasswordsIE7() {
  base::string16 key_path(importer::GetIE7PasswordsKey());
  base::win::RegKey key(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ);
  base::win::RegistryValueIterator reg_iterator(HKEY_CURRENT_USER,
                                                key_path.c_str());
  importer::ImporterIE7PasswordInfo password_info;
  while (reg_iterator.Valid() && !cancelled()) {
    // Get the size of the encrypted data.
    DWORD value_len = 0;
    key.ReadValue(reg_iterator.Name(), NULL, &value_len, NULL);
    if (value_len) {
      // Query the encrypted data.
      password_info.encrypted_data.resize(value_len);
      if (key.ReadValue(reg_iterator.Name(),
                        &password_info.encrypted_data.front(),
                        &value_len, NULL) == ERROR_SUCCESS) {
        password_info.url_hash = reg_iterator.Name();
        password_info.date_created = base::Time::Now();

        bridge_->AddIE7PasswordInfo(password_info);
      }
    }

    ++reg_iterator;
  }
}

void IEImporter::ImportSearchEngines() {
  // On IE, search engines are stored in the registry, under:
  // Software\Microsoft\Internet Explorer\SearchScopes
  // Each key represents a search engine. The URL value contains the URL and
  // the DisplayName the name.
  typedef std::map<std::string, string16> SearchEnginesMap;
  SearchEnginesMap search_engines_map;
  for (base::win::RegistryKeyIterator key_iter(HKEY_CURRENT_USER,
       kSearchScopePath); key_iter.Valid(); ++key_iter) {
    string16 sub_key_name = kSearchScopePath;
    sub_key_name.append(L"\\").append(key_iter.Name());
    base::win::RegKey sub_key(HKEY_CURRENT_USER, sub_key_name.c_str(),
                              KEY_READ);
    string16 wide_url;
    if ((sub_key.ReadValue(L"URL", &wide_url) != ERROR_SUCCESS) ||
        wide_url.empty()) {
      VLOG(1) << "No URL for IE search engine at " << key_iter.Name();
      continue;
    }
    // For the name, we try the default value first (as Live Search uses a
    // non displayable name in DisplayName, and the readable name under the
    // default value).
    string16 name;
    if ((sub_key.ReadValue(NULL, &name) != ERROR_SUCCESS) || name.empty()) {
      // Try the displayable name.
      if ((sub_key.ReadValue(L"DisplayName", &name) != ERROR_SUCCESS) ||
          name.empty()) {
        VLOG(1) << "No name for IE search engine at " << key_iter.Name();
        continue;
      }
    }

    std::string url(WideToUTF8(wide_url));
    SearchEnginesMap::iterator t_iter = search_engines_map.find(url);
    if (t_iter == search_engines_map.end()) {
      // First time we see that URL.
      GURL gurl(url);
      if (gurl.is_valid()) {
        t_iter = search_engines_map.insert(std::make_pair(url, name)).first;
      }
    }
  }
  // ProfileWriter::AddKeywords() requires a vector and we have a map.
  std::vector<importer::URLKeywordInfo> url_keywords;
  for (SearchEnginesMap::iterator i = search_engines_map.begin();
       i != search_engines_map.end(); ++i) {
    importer::URLKeywordInfo url_keyword_info;
    url_keyword_info.url = GURL(i->first);
    url_keyword_info.display_name = i->second;
    url_keywords.push_back(url_keyword_info);
  }
  bridge_->SetKeywords(url_keywords, true);
}

void IEImporter::ImportHomepage() {
  const wchar_t* kIEHomepage = L"Start Page";
  const wchar_t* kIEDefaultHomepage = L"Default_Page_URL";

  base::string16 key_path(importer::GetIESettingsKey());

  base::win::RegKey key(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ);
  string16 homepage_url;
  if (key.ReadValue(kIEHomepage, &homepage_url) != ERROR_SUCCESS ||
      homepage_url.empty())
    return;

  GURL homepage = GURL(homepage_url);
  if (!homepage.is_valid())
    return;

  // Check to see if this is the default website and skip import.
  base::win::RegKey keyDefault(HKEY_LOCAL_MACHINE, key_path.c_str(), KEY_READ);
  string16 default_homepage_url;
  LONG result = keyDefault.ReadValue(kIEDefaultHomepage, &default_homepage_url);
  if (result == ERROR_SUCCESS && !default_homepage_url.empty()) {
    if (homepage.spec() == GURL(default_homepage_url).spec())
      return;
  }
  bridge_->AddHomePage(homepage);
}

bool IEImporter::GetFavoritesInfo(IEImporter::FavoritesInfo* info) {
  if (!source_path_.empty()) {
    // Source path exists during testing.
    info->path = source_path_;
    info->path = info->path.AppendASCII("Favorites");
    info->links_folder = L"Links";
    return true;
  }

  // IE stores the favorites in the Favorites under user profile's folder.
  wchar_t buffer[MAX_PATH];
  if (FAILED(SHGetFolderPath(NULL, CSIDL_FAVORITES, NULL,
                             SHGFP_TYPE_CURRENT, buffer)))
    return false;
  info->path = base::FilePath(buffer);

  // There is a Links folder under Favorites folder in Windows Vista, but it
  // is not recording in Vista's registry. So in Vista, we assume the Links
  // folder is under Favorites folder since it looks like there is not name
  // different in every language version of Windows Vista.
  if (base::win::GetVersion() < base::win::VERSION_VISTA) {
    // The Link folder name is stored in the registry.
    DWORD buffer_length = sizeof(buffer);
    base::win::RegKey reg_key(HKEY_CURRENT_USER, kIEToolbarKey, KEY_READ);
    if (reg_key.ReadValue(L"LinksFolderName", buffer,
                          &buffer_length, NULL) != ERROR_SUCCESS)
      return false;
    info->links_folder = buffer;
  } else {
    info->links_folder = L"Links";
  }

  return true;
}

void IEImporter::ParseFavoritesFolder(
    const FavoritesInfo& info,
    BookmarkVector* bookmarks,
    std::vector<ImportedFaviconUsage>* favicons) {
  base::FilePath file;
  std::vector<base::FilePath::StringType> file_list;
  base::FilePath favorites_path(info.path);
  // Favorites path length.  Make sure it doesn't include the trailing \.
  size_t favorites_path_len =
      favorites_path.StripTrailingSeparators().value().size();
  base::FileEnumerator file_enumerator(
      favorites_path, true, base::FileEnumerator::FILES);
  while (!(file = file_enumerator.Next()).value().empty() && !cancelled())
    file_list.push_back(file.value());

  // Keep the bookmarks in alphabetical order.
  std::sort(file_list.begin(), file_list.end());

  // Map from favicon URLs to the favicon data (the binary image data and the
  // set of bookmark URLs referring to the favicon).
  typedef std::map<GURL, ImportedFaviconUsage> FaviconMap;
  FaviconMap favicon_map;

  for (std::vector<base::FilePath::StringType>::iterator it = file_list.begin();
       it != file_list.end(); ++it) {
    base::FilePath shortcut(*it);
    if (!LowerCaseEqualsASCII(shortcut.Extension(), ".url"))
      continue;

    // Skip the bookmark with invalid URL.
    base::win::ScopedComPtr<IUniformResourceLocator> url_locator;
    if (!LoadInternetShortcut(*it, &url_locator))
      continue;
    GURL url = ReadURLFromInternetShortcut(url_locator);
    if (!url.is_valid())
      continue;
    // Skip default bookmarks. go.microsoft.com redirects to
    // search.microsoft.com, and http://go.microsoft.com/fwlink/?LinkId=XXX,
    // which URLs IE has as default, to some another sites.
    // We expect that users will never themselves create bookmarks having this
    // hostname.
    if (url.host() == "go.microsoft.com")
      continue;
    // Read favicon.
    UpdateFaviconMap(*it, url, url_locator, &favicon_map);

    // Make the relative path from the Favorites folder, without the basename.
    // ex. Suppose that the Favorites folder is C:\Users\Foo\Favorites.
    //   C:\Users\Foo\Favorites\Foo.url -> ""
    //   C:\Users\Foo\Favorites\Links\Bar\Baz.url -> "Links\Bar"
    base::FilePath::StringType relative_string =
        shortcut.DirName().value().substr(favorites_path_len);
    if (!relative_string.empty() &&
        base::FilePath::IsSeparator(relative_string[0]))
      relative_string = relative_string.substr(1);
    base::FilePath relative_path(relative_string);

    ImportedBookmarkEntry entry;
    // Remove the dot, the file extension, and the directory path.
    entry.title = shortcut.RemoveExtension().BaseName().value();
    entry.url = url;
    entry.creation_time = GetFileCreationTime(*it);
    if (!relative_path.empty())
      relative_path.GetComponents(&entry.path);

    // Add the bookmark.
    if (!entry.path.empty() && entry.path[0] == info.links_folder) {
      // Bookmarks in the Link folder should be imported to the toolbar.
      entry.in_toolbar = true;
    }
    bookmarks->push_back(entry);
  }

  // Reflect the menu order in IE.
  SortBookmarksInIEOrder(this, bookmarks);

  // Record favicon data.
  for (FaviconMap::iterator iter = favicon_map.begin();
       iter != favicon_map.end(); ++iter)
    favicons->push_back(iter->second);
}

int IEImporter::CurrentIEVersion() const {
  static int version = -1;
  if (version < 0) {
    wchar_t buffer[128];
    DWORD buffer_length = sizeof(buffer);
    base::win::RegKey reg_key(HKEY_LOCAL_MACHINE, kIEVersionKey, KEY_READ);
    LONG result = reg_key.ReadValue(L"Version", buffer, &buffer_length, NULL);
    version = ((result == ERROR_SUCCESS)? _wtoi(buffer) : 0);
  }
  return version;
}
