// Copyright 2013 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/firefox_importer.h"

#include <memory>
#include <set>

#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/json/json_file_value_serializer.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/common/importer/firefox_importer_utils.h"
#include "chrome/common/importer/imported_bookmark_entry.h"
#include "chrome/common/importer/importer_autofill_form_data_entry.h"
#include "chrome/common/importer/importer_bridge.h"
#include "chrome/common/importer/importer_url_row.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/utility/importer/bookmark_html_reader.h"
#include "chrome/utility/importer/favicon_reencode.h"
#include "chrome/utility/importer/nss_decryptor.h"
#include "components/autofill/core/common/password_form.h"
#include "sql/connection.h"
#include "sql/statement.h"
#include "url/gurl.h"

namespace {

// Original definition is in http://mxr.mozilla.org/firefox/source/toolkit/
//  components/places/public/nsINavBookmarksService.idl
enum BookmarkItemType {
  TYPE_BOOKMARK = 1,
  TYPE_FOLDER = 2,
  TYPE_SEPARATOR = 3,
  TYPE_DYNAMIC_CONTAINER = 4
};

// Loads the default bookmarks in the Firefox installed at |app_path|,
// and stores their locations in |urls|.
void LoadDefaultBookmarks(const base::FilePath& app_path,
                          std::set<GURL>* urls) {
  base::FilePath file = app_path.AppendASCII("defaults")
      .AppendASCII("profile")
      .AppendASCII("bookmarks.html");
  urls->clear();

  std::vector<ImportedBookmarkEntry> bookmarks;
  std::vector<importer::SearchEngineInfo> search_engines;
  bookmark_html_reader::ImportBookmarksFile(base::Callback<bool(void)>(),
                                            base::Callback<bool(const GURL&)>(),
                                            file,
                                            &bookmarks,
                                            &search_engines,
                                            NULL);
  for (size_t i = 0; i < bookmarks.size(); ++i)
    urls->insert(bookmarks[i].url);
}

// Returns true if |url| has a valid scheme that we allow to import. We
// filter out the URL with a unsupported scheme.
bool CanImportURL(const GURL& url) {
  // The URL is not valid.
  if (!url.is_valid())
    return false;

  // Filter out the URLs with unsupported schemes.
  const char* const kInvalidSchemes[] = {"wyciwyg", "place", "about", "chrome"};
  for (size_t i = 0; i < arraysize(kInvalidSchemes); ++i) {
    if (url.SchemeIs(kInvalidSchemes[i]))
      return false;
  }

  return true;
}

}  // namespace

struct FirefoxImporter::BookmarkItem {
  int parent;
  int id;
  GURL url;
  base::string16 title;
  BookmarkItemType type;
  std::string keyword;
  base::Time date_added;
  int64_t favicon;
  bool empty_folder;
};

FirefoxImporter::FirefoxImporter() {
}

FirefoxImporter::~FirefoxImporter() {
}

void FirefoxImporter::StartImport(const importer::SourceProfile& source_profile,
                                  uint16_t items,
                                  ImporterBridge* bridge) {
  bridge_ = bridge;
  source_path_ = source_profile.source_path;
  app_path_ = source_profile.app_path;

#if defined(OS_POSIX)
  locale_ = source_profile.locale;
#endif

  // The order here is important!
  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);
  }

  // Note history should be imported before bookmarks because bookmark import
  // will also import favicons and we store favicon for a URL only if the URL
  // exist in history or bookmarks.
  if ((items & importer::HISTORY) && !cancelled()) {
    bridge_->NotifyItemStarted(importer::HISTORY);
    ImportHistory();
    bridge_->NotifyItemEnded(importer::HISTORY);
  }

  if ((items & importer::FAVORITES) && !cancelled()) {
    bridge_->NotifyItemStarted(importer::FAVORITES);
    ImportBookmarks();
    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);
    ImportPasswords();
    bridge_->NotifyItemEnded(importer::PASSWORDS);
  }
  if ((items & importer::AUTOFILL_FORM_DATA) && !cancelled()) {
    bridge_->NotifyItemStarted(importer::AUTOFILL_FORM_DATA);
    ImportAutofillFormData();
    bridge_->NotifyItemEnded(importer::AUTOFILL_FORM_DATA);
  }
  bridge_->NotifyEnded();
}

void FirefoxImporter::ImportHistory() {
  base::FilePath file = source_path_.AppendASCII("places.sqlite");
  if (!base::PathExists(file))
    return;

  sql::Connection db;
  if (!db.Open(file))
    return;

  // |visit_type| represent the transition type of URLs (typed, click,
  // redirect, bookmark, etc.) We eliminate some URLs like sub-frames and
  // redirects, since we don't want them to appear in history.
  // Firefox transition types are defined in:
  //   toolkit/components/places/public/nsINavHistoryService.idl
  const char query[] =
      "SELECT h.url, h.title, h.visit_count, "
      "h.hidden, h.typed, v.visit_date "
      "FROM moz_places h JOIN moz_historyvisits v "
      "ON h.id = v.place_id "
      "WHERE v.visit_type <= 3";

  sql::Statement s(db.GetUniqueStatement(query));

  std::vector<ImporterURLRow> rows;
  while (s.Step() && !cancelled()) {
    GURL url(s.ColumnString(0));

    // Filter out unwanted URLs.
    if (!CanImportURL(url))
      continue;

    ImporterURLRow row(url);
    row.title = s.ColumnString16(1);
    row.visit_count = s.ColumnInt(2);
    row.hidden = s.ColumnInt(3) == 1;
    row.typed_count = s.ColumnInt(4);
    row.last_visit = base::Time::FromTimeT(s.ColumnInt64(5)/1000000);

    rows.push_back(row);
  }

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

void FirefoxImporter::ImportBookmarks() {
  base::FilePath file = source_path_.AppendASCII("places.sqlite");
  if (!base::PathExists(file))
    return;

  sql::Connection db;
  if (!db.Open(file))
    return;

  // Get the bookmark folders that we are interested in.
  int toolbar_folder_id = LoadNodeIDByGUID(&db, "toolbar_____");
  int menu_folder_id = LoadNodeIDByGUID(&db, "menu________");
  int unsorted_folder_id = LoadNodeIDByGUID(&db, "unfiled_____");

  // Load livemark IDs.
  std::set<int> livemark_id;
  LoadLivemarkIDs(&db, &livemark_id);

  // Load the default bookmarks.
  std::set<GURL> default_urls;
  LoadDefaultBookmarks(app_path_, &default_urls);

  BookmarkList list;
  GetTopBookmarkFolder(&db, toolbar_folder_id, &list);
  GetTopBookmarkFolder(&db, menu_folder_id, &list);
  GetTopBookmarkFolder(&db, unsorted_folder_id, &list);
  size_t count = list.size();
  for (size_t i = 0; i < count; ++i)
    GetWholeBookmarkFolder(&db, &list, i, NULL);

  std::vector<ImportedBookmarkEntry> bookmarks;
  std::vector<importer::SearchEngineInfo> search_engines;
  FaviconMap favicon_map;

  // TODO(jcampan): http://b/issue?id=1196285 we do not support POST based
  //                keywords yet.  We won't include them in the list.
  std::set<int> post_keyword_ids;
  const char query[] =
      "SELECT b.id FROM moz_bookmarks b "
      "INNER JOIN moz_items_annos ia ON ia.item_id = b.id "
      "INNER JOIN moz_anno_attributes aa ON ia.anno_attribute_id = aa.id "
      "WHERE aa.name = 'bookmarkProperties/POSTData'";
  sql::Statement s(db.GetUniqueStatement(query));

  if (!s.is_valid())
    return;

  while (s.Step() && !cancelled())
    post_keyword_ids.insert(s.ColumnInt(0));

  for (const auto& item : list) {
    // Folders are added implicitly on adding children, so we only explicitly
    // add empty folders.
    if (item->type != TYPE_BOOKMARK &&
        ((item->type != TYPE_FOLDER) || !item->empty_folder))
      continue;

    if (CanImportURL(item->url)) {
      // Skip the default bookmarks and unwanted URLs.
      if (default_urls.find(item->url) != default_urls.end() ||
          post_keyword_ids.find(item->id) != post_keyword_ids.end())
        continue;

      // Find the bookmark path by tracing their links to parent folders.
      std::vector<base::string16> path;
      BookmarkItem* child = item.get();
      bool found_path = false;
      bool is_in_toolbar = false;
      while (child->parent >= 0) {
        BookmarkItem* parent = list[child->parent].get();
        if (livemark_id.find(parent->id) != livemark_id.end()) {
          // Don't import live bookmarks.
          break;
        }

        if (parent->id != menu_folder_id) {
          // To avoid excessive nesting, omit the name for the bookmarks menu
          // folder.
          path.insert(path.begin(), parent->title);
        }

        if (parent->id == toolbar_folder_id)
          is_in_toolbar = true;

        if (parent->id == toolbar_folder_id ||
            parent->id == menu_folder_id ||
            parent->id == unsorted_folder_id) {
          // We've reached a root node, hooray!
          found_path = true;
          break;
        }

        child = parent;
      }

      if (!found_path)
        continue;

      ImportedBookmarkEntry entry;
      entry.creation_time = item->date_added;
      entry.title = item->title;
      entry.url = item->url;
      entry.path = path;
      entry.in_toolbar = is_in_toolbar;
      entry.is_folder = item->type == TYPE_FOLDER;

      bookmarks.push_back(entry);
    }

    if (item->type == TYPE_BOOKMARK) {
      if (item->favicon)
        favicon_map[item->favicon].insert(item->url);

      // Import this bookmark as a search engine if it has a keyword and its URL
      // is usable as a search engine URL. (Even if the URL doesn't allow
      // substitution, importing as a "search engine" allows users to trigger
      // the bookmark by entering its keyword in the omnibox.)
      if (item->keyword.empty())
        continue;
      importer::SearchEngineInfo search_engine_info;
      std::string search_engine_url;
      if (item->url.is_valid())
        search_engine_info.url = base::UTF8ToUTF16(item->url.spec());
      else if (bookmark_html_reader::CanImportURLAsSearchEngine(
                   item->url,
                   &search_engine_url))
        search_engine_info.url = base::UTF8ToUTF16(search_engine_url);
      else
        continue;
      search_engine_info.keyword = base::UTF8ToUTF16(item->keyword);
      search_engine_info.display_name = item->title;
      search_engines.push_back(search_engine_info);
    }
  }

  // Write into profile.
  if (!bookmarks.empty() && !cancelled()) {
    const base::string16& first_folder_name =
        bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_FIREFOX);
    bridge_->AddBookmarks(bookmarks, first_folder_name);
  }
  if (!search_engines.empty() && !cancelled()) {
    bridge_->SetKeywords(search_engines, false);
  }
  if (!favicon_map.empty() && !cancelled()) {
    favicon_base::FaviconUsageDataList favicons;
    LoadFavicons(&db, favicon_map, &favicons);
    bridge_->SetFavicons(favicons);
  }
}

void FirefoxImporter::ImportPasswords() {
  // Initializes NSS3.
  NSSDecryptor decryptor;
  if (!decryptor.Init(source_path_, source_path_) &&
      !decryptor.Init(app_path_, source_path_)) {
    return;
  }

  std::vector<autofill::PasswordForm> forms;
  base::FilePath source_path = source_path_;
  const base::FilePath sqlite_file = source_path.AppendASCII("signons.sqlite");
  const base::FilePath json_file = source_path.AppendASCII("logins.json");
  const base::FilePath signon3_file = source_path.AppendASCII("signons3.txt");
  const base::FilePath signon2_file = source_path.AppendASCII("signons2.txt");
  if (base::PathExists(json_file)) {
    // Since Firefox 32, passwords are in logins.json.
    decryptor.ReadAndParseLogins(json_file, &forms);
  } else if (base::PathExists(sqlite_file)) {
    // Since Firefox 3.1, passwords are in signons.sqlite db.
    decryptor.ReadAndParseSignons(sqlite_file, &forms);
  } else if (base::PathExists(signon3_file)) {
    // Firefox 3.0 uses signons3.txt to store the passwords.
    decryptor.ParseSignons(signon3_file, &forms);
  } else {
    decryptor.ParseSignons(signon2_file, &forms);
  }

  if (!cancelled()) {
    for (size_t i = 0; i < forms.size(); ++i) {
      if (!forms[i].username_value.empty() ||
          !forms[i].password_value.empty() ||
          forms[i].blacklisted_by_user) {
        bridge_->SetPasswordForm(forms[i]);
      }
    }
  }
}

void FirefoxImporter::ImportSearchEngines() {
  std::vector<std::string> search_engine_data;
  GetSearchEnginesXMLData(&search_engine_data);

  bridge_->SetFirefoxSearchEnginesXMLData(search_engine_data);
}

void FirefoxImporter::ImportHomepage() {
  GURL home_page = GetHomepage(source_path_);
  if (home_page.is_valid() && !IsDefaultHomepage(home_page, app_path_)) {
    bridge_->AddHomePage(home_page);
  }
}

void FirefoxImporter::ImportAutofillFormData() {
  base::FilePath file = source_path_.AppendASCII("formhistory.sqlite");
  if (!base::PathExists(file))
    return;

  sql::Connection db;
  if (!db.Open(file))
    return;

  const char query[] =
      "SELECT fieldname, value, timesUsed, firstUsed, lastUsed FROM "
      "moz_formhistory";

  sql::Statement s(db.GetUniqueStatement(query));

  std::vector<ImporterAutofillFormDataEntry> form_entries;
  while (s.Step() && !cancelled()) {
    ImporterAutofillFormDataEntry form_entry;
    form_entry.name = s.ColumnString16(0);
    form_entry.value = s.ColumnString16(1);
    form_entry.times_used = s.ColumnInt(2);
    form_entry.first_used = base::Time::FromTimeT(s.ColumnInt64(3) / 1000000);
    form_entry.last_used = base::Time::FromTimeT(s.ColumnInt64(4) / 1000000);

    // Don't import search bar history.
    if (base::UTF16ToUTF8(form_entry.name) == "searchbar-history")
      continue;

    form_entries.push_back(form_entry);
  }

  if (!form_entries.empty() && !cancelled())
    bridge_->SetAutofillFormData(form_entries);
}

void FirefoxImporter::GetSearchEnginesXMLData(
    std::vector<std::string>* search_engine_data) {
  base::FilePath file = source_path_.AppendASCII("search.sqlite");
  if (!base::PathExists(file)) {
    // Since Firefox 3.5, search engines are no longer stored in search.sqlite.
    // Instead, search.json is used for storing search engines.
    GetSearchEnginesXMLDataFromJSON(search_engine_data);
    return;
  }

  sql::Connection db;
  if (!db.Open(file))
    return;

  const char query[] =
      "SELECT engineid FROM engine_data "
      "WHERE engineid NOT IN "
      "(SELECT engineid FROM engine_data "
      "WHERE name='hidden') "
      "ORDER BY value ASC";

  sql::Statement s(db.GetUniqueStatement(query));
  if (!s.is_valid())
    return;

  const base::FilePath searchplugins_path(FILE_PATH_LITERAL("searchplugins"));
  // Search engine definitions are XMLs stored in two directories. Default
  // engines are in the app directory (app_path_) and custom engines are
  // in the profile directory (source_path_).

  // Since Firefox 21, app_path_ engines are in 'browser' subdirectory:
  base::FilePath app_path =
      app_path_.AppendASCII("browser").Append(searchplugins_path);
  if (!base::PathExists(app_path)) {
    // This might be an older Firefox, try old location without the 'browser'
    // path component:
    app_path = app_path_.Append(searchplugins_path);
  }

  base::FilePath profile_path = source_path_.Append(searchplugins_path);

  // Firefox doesn't store a search engine in its sqlite database unless the
  // user has added a engine. So we get search engines from sqlite db as well
  // as from the file system.
  if (s.Step()) {
    const std::string kAppPrefix("[app]/");
    const std::string kProfilePrefix("[profile]/");
    do {
      base::FilePath file;
      std::string engine(s.ColumnString(0));

      // The string contains [app]/<name>.xml or [profile]/<name>.xml where
      // the [app] and [profile] need to be replaced with the actual app or
      // profile path.
      size_t index = engine.find(kAppPrefix);
      if (index != std::string::npos) {
        // Remove '[app]/'.
        file = app_path.AppendASCII(engine.substr(index + kAppPrefix.length()));
      } else if ((index = engine.find(kProfilePrefix)) != std::string::npos) {
        // Remove '[profile]/'.
          file = profile_path.AppendASCII(
              engine.substr(index + kProfilePrefix.length()));
      } else {
        // Looks like absolute path to the file.
        file = base::FilePath::FromUTF8Unsafe(engine);
      }
      std::string file_data;
      base::ReadFileToString(file, &file_data);
      search_engine_data->push_back(file_data);
    } while (s.Step() && !cancelled());
  }

#if defined(OS_POSIX)
  // Ubuntu-flavored Firefox supports locale-specific search engines via
  // locale-named subdirectories. They fall back to en-US.
  // See http://crbug.com/53899
  // TODO(jshin): we need to make sure our locale code matches that of
  // Firefox.
  DCHECK(!locale_.empty());
  base::FilePath locale_app_path = app_path.AppendASCII(locale_);
  base::FilePath default_locale_app_path = app_path.AppendASCII("en-US");
  if (base::DirectoryExists(locale_app_path))
    app_path = locale_app_path;
  else if (base::DirectoryExists(default_locale_app_path))
    app_path = default_locale_app_path;
#endif

  // Get search engine definition from file system.
  base::FileEnumerator engines(app_path, false, base::FileEnumerator::FILES);
  for (base::FilePath engine_path = engines.Next();
       !engine_path.value().empty(); engine_path = engines.Next()) {
    std::string file_data;
    base::ReadFileToString(file, &file_data);
    search_engine_data->push_back(file_data);
  }
}

void FirefoxImporter::GetSearchEnginesXMLDataFromJSON(
    std::vector<std::string>* search_engine_data) {
  // search-metadata.json contains keywords for search engines. This
  // file exists only if the user has set keywords for search engines.
  base::FilePath search_metadata_json_file =
      source_path_.AppendASCII("search-metadata.json");
  JSONFileValueDeserializer metadata_deserializer(search_metadata_json_file);
  std::unique_ptr<base::Value> metadata_root =
      metadata_deserializer.Deserialize(NULL, NULL);
  const base::DictionaryValue* search_metadata_root = NULL;
  if (metadata_root)
    metadata_root->GetAsDictionary(&search_metadata_root);

  // search.json contains information about search engines to import.
  base::FilePath search_json_file = source_path_.AppendASCII("search.json");
  if (!base::PathExists(search_json_file))
    return;

  JSONFileValueDeserializer deserializer(search_json_file);
  std::unique_ptr<base::Value> root = deserializer.Deserialize(NULL, NULL);
  const base::DictionaryValue* search_root = NULL;
  if (!root || !root->GetAsDictionary(&search_root))
    return;

  const std::string kDirectories("directories");
  const base::DictionaryValue* search_directories = NULL;
  if (!search_root->GetDictionary(kDirectories, &search_directories))
    return;

  // Dictionary |search_directories| contains a list of search engines
  // (default and installed). The list can be found from key <engines>
  // of the dictionary. Key <engines> is a grandchild of key <directories>.
  // However, key <engines> parent's key is dynamic which depends on
  // operating systems. For example,
  //   Ubuntu (for default search engine):
  //     /usr/lib/firefox/distribution/searchplugins/locale/en-US
  //   Ubuntu (for installed search engines):
  //     /home/<username>/.mozilla/firefox/lcd50n4n.default/searchplugins
  //   Windows (for default search engine):
  //     C:\\Program Files (x86)\\Mozilla Firefox\\browser\\searchplugins
  // Therefore, it needs to be retrieved by searching.

  for (base::DictionaryValue::Iterator it(*search_directories); !it.IsAtEnd();
       it.Advance()) {
    // The key of |it| may contains dot (.) which cannot be used as <key>
    // for retrieving <engines>. Hence, it is needed to get |it| as dictionary.
    // The resulted dictionary can be used for retrieving <engines>.
    const std::string kEngines("engines");
    const base::DictionaryValue* search_directory = NULL;
    if (!it.value().GetAsDictionary(&search_directory))
      continue;

    const base::ListValue* search_engines = NULL;
    if (!search_directory->GetList(kEngines, &search_engines))
      continue;

    const std::string kFilePath("filePath");
    const std::string kHidden("_hidden");
    for (size_t i = 0; i < search_engines->GetSize(); ++i) {
      const base::DictionaryValue* engine_info = NULL;
      if (!search_engines->GetDictionary(i, &engine_info))
        continue;

      bool is_hidden = false;
      std::string file_path;
      if (!engine_info->GetBoolean(kHidden, &is_hidden) ||
          !engine_info->GetString(kFilePath, &file_path))
        continue;

      if (!is_hidden) {
        const std::string kAppPrefix("[app]/");
        const std::string kProfilePrefix("[profile]/");
        base::FilePath xml_file = base::FilePath::FromUTF8Unsafe(file_path);

        // If |file_path| contains [app] or [profile] then they need to be
        // replaced with the actual app or profile path.
        size_t index = file_path.find(kAppPrefix);
        if (index != std::string::npos) {
          // Replace '[app]/' with actual app path.
          xml_file = app_path_.AppendASCII("searchplugins").AppendASCII(
              file_path.substr(index + kAppPrefix.length()));
        } else if ((index = file_path.find(kProfilePrefix)) !=
                   std::string::npos) {
          // Replace '[profile]/' with actual profile path.
          xml_file = source_path_.AppendASCII("searchplugins").AppendASCII(
              file_path.substr(index + kProfilePrefix.length()));
        }

        std::string file_data;
        base::ReadFileToString(xml_file, &file_data);

        // If a keyword is mentioned for this search engine, then add
        // it to the XML string as an <Alias> element and use this updated
        // string.
        const base::DictionaryValue* search_xml_path = NULL;
        if (search_metadata_root && search_metadata_root->HasKey(file_path) &&
            search_metadata_root->GetDictionaryWithoutPathExpansion(
                file_path, &search_xml_path)) {
          std::string alias;
          search_xml_path->GetString("alias", &alias);

          // Add <Alias> element as the last child element.
          size_t end_of_parent = file_data.find("</SearchPlugin>");
          if (end_of_parent != std::string::npos && !alias.empty())
            file_data.insert(end_of_parent, "<Alias>" + alias + "</Alias> \n");
        }
        search_engine_data->push_back(file_data);
      }
    }
  }
}

int FirefoxImporter::LoadNodeIDByGUID(sql::Connection* db,
                                      const std::string& GUID) {
  const char query[] =
      "SELECT id "
      "FROM moz_bookmarks "
      "WHERE guid == ?";
  sql::Statement s(db->GetUniqueStatement(query));
  s.BindString(0, GUID);

  if (!s.Step())
    return -1;
  return s.ColumnInt(0);
}

void FirefoxImporter::LoadLivemarkIDs(sql::Connection* db,
                                      std::set<int>* livemark) {
  static const char kFeedAnnotation[] = "livemark/feedURI";
  livemark->clear();

  const char query[] =
      "SELECT b.item_id "
      "FROM moz_anno_attributes a "
      "JOIN moz_items_annos b ON a.id = b.anno_attribute_id "
      "WHERE a.name = ? ";
  sql::Statement s(db->GetUniqueStatement(query));
  s.BindString(0, kFeedAnnotation);

  while (s.Step() && !cancelled())
    livemark->insert(s.ColumnInt(0));
}

void FirefoxImporter::GetTopBookmarkFolder(sql::Connection* db,
                                           int folder_id,
                                           BookmarkList* list) {
  const char query[] =
      "SELECT b.title "
      "FROM moz_bookmarks b "
      "WHERE b.type = 2 AND b.id = ? "
      "ORDER BY b.position";
  sql::Statement s(db->GetUniqueStatement(query));
  s.BindInt(0, folder_id);

  if (s.Step()) {
    std::unique_ptr<BookmarkItem> item = base::MakeUnique<BookmarkItem>();
    item->parent = -1;  // The top level folder has no parent.
    item->id = folder_id;
    item->title = s.ColumnString16(0);
    item->type = TYPE_FOLDER;
    item->favicon = 0;
    item->empty_folder = true;
    list->push_back(std::move(item));
  }
}

void FirefoxImporter::GetWholeBookmarkFolder(sql::Connection* db,
                                             BookmarkList* list,
                                             size_t position,
                                             bool* empty_folder) {
  if (position >= list->size()) {
    NOTREACHED();
    return;
  }

  const char query[] =
      "SELECT b.id, h.url, COALESCE(b.title, h.title), "
      "b.type, k.keyword, b.dateAdded, h.favicon_id "
      "FROM moz_bookmarks b "
      "LEFT JOIN moz_places h ON b.fk = h.id "
      "LEFT JOIN moz_keywords k ON k.id = b.keyword_id "
      "WHERE b.type IN (1,2) AND b.parent = ? "
      "ORDER BY b.position";
  sql::Statement s(db->GetUniqueStatement(query));
  s.BindInt(0, (*list)[position]->id);

  BookmarkList temp_list;
  while (s.Step()) {
    std::unique_ptr<BookmarkItem> item = base::MakeUnique<BookmarkItem>();
    item->parent = static_cast<int>(position);
    item->id = s.ColumnInt(0);
    item->url = GURL(s.ColumnString(1));
    item->title = s.ColumnString16(2);
    item->type = static_cast<BookmarkItemType>(s.ColumnInt(3));
    item->keyword = s.ColumnString(4);
    item->date_added = base::Time::FromTimeT(s.ColumnInt64(5)/1000000);
    item->favicon = s.ColumnInt64(6);
    item->empty_folder = true;

    temp_list.push_back(std::move(item));
    if (empty_folder != NULL)
      *empty_folder = false;
  }

  // Appends all items to the list.
  for (auto& bookmark : temp_list) {
    list->push_back(std::move(bookmark));
    // Recursive add bookmarks in sub-folders.
    if (list->back()->type == TYPE_FOLDER) {
      GetWholeBookmarkFolder(db, list, list->size() - 1,
                             &list->back()->empty_folder);
    }
  }
}

void FirefoxImporter::LoadFavicons(
    sql::Connection* db,
    const FaviconMap& favicon_map,
    favicon_base::FaviconUsageDataList* favicons) {
  const char query[] = "SELECT url, data FROM moz_favicons WHERE id=?";
  sql::Statement s(db->GetUniqueStatement(query));

  if (!s.is_valid())
    return;

  for (FaviconMap::const_iterator i = favicon_map.begin();
       i != favicon_map.end(); ++i) {
    s.BindInt64(0, i->first);
    if (s.Step()) {
      favicon_base::FaviconUsageData usage;

      usage.favicon_url = GURL(s.ColumnString(0));
      if (!usage.favicon_url.is_valid())
        continue;  // Don't bother importing favicons with invalid URLs.

      std::vector<unsigned char> data;
      s.ColumnBlobAsVector(1, &data);
      if (data.empty())
        continue;  // Data definitely invalid.

      if (!importer::ReencodeFavicon(&data[0], data.size(), &usage.png_data))
        continue;  // Unable to decode.

      usage.urls = i->second;
      favicons->push_back(usage);
    }
    s.Reset(true);
  }
}
