1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/utility/importer/firefox_importer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/common/importer/firefox_importer_utils.h"
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/common/importer/firefox_importer_utils.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/importer/imported_bookmark_entry.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/importer/imported_favicon_usage.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/common/importer/importer_bridge.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/importer/importer_url_row.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/utility/importer/bookmark_html_reader.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/utility/importer/favicon_reencode.h"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/utility/importer/nss_decryptor.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/password_form.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/connection.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h"
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Original definition is in http://mxr.mozilla.org/firefox/source/toolkit/
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  components/places/public/nsINavBookmarksService.idl
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum BookmarkItemType {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TYPE_BOOKMARK = 1,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TYPE_FOLDER = 2,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TYPE_SEPARATOR = 3,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TYPE_DYNAMIC_CONTAINER = 4
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Loads the default bookmarks in the Firefox installed at |app_path|,
43a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// and stores their locations in |urls|.
44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void LoadDefaultBookmarks(const base::FilePath& app_path,
45a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                          std::set<GURL>* urls) {
46a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::FilePath file = app_path.AppendASCII("defaults")
47a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      .AppendASCII("profile")
48a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      .AppendASCII("bookmarks.html");
49a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  urls->clear();
50a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  std::vector<ImportedBookmarkEntry> bookmarks;
52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  bookmark_html_reader::ImportBookmarksFile(base::Callback<bool(void)>(),
53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                            base::Callback<bool(const GURL&)>(),
54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                            file,
55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                            &bookmarks,
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                            NULL);
57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  for (size_t i = 0; i < bookmarks.size(); ++i)
58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    urls->insert(bookmarks[i].url);
59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
60a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
61558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Returns true if |url| has a valid scheme that we allow to import. We
62558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// filter out the URL with a unsupported scheme.
63558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochbool CanImportURL(const GURL& url) {
64558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // The URL is not valid.
65558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!url.is_valid())
66558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return false;
67558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
68558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Filter out the URLs with unsupported schemes.
69558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const char* const kInvalidSchemes[] = {"wyciwyg", "place", "about", "chrome"};
70558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  for (size_t i = 0; i < arraysize(kInvalidSchemes); ++i) {
71558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    if (url.SchemeIs(kInvalidSchemes[i]))
72558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      return false;
73558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
74558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
75558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return true;
76558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
77558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstruct FirefoxImporter::BookmarkItem {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int parent;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int id;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 title;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkItemType type;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string keyword;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time date_added;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 favicon;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool empty_folder;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochFirefoxImporter::FirefoxImporter() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochFirefoxImporter::~FirefoxImporter() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::StartImport(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const importer::SourceProfile& source_profile,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16 items,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImporterBridge* bridge) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bridge_ = bridge;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_path_ = source_profile.source_path;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  app_path_ = source_profile.app_path;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_POSIX)
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  locale_ = source_profile.locale;
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The order here is important!
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bridge_->NotifyStarted();
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if ((items & importer::HOME_PAGE) && !cancelled()) {
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bridge_->NotifyItemStarted(importer::HOME_PAGE);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImportHomepage();  // Doesn't have a UI item.
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bridge_->NotifyItemEnded(importer::HOME_PAGE);
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note history should be imported before bookmarks because bookmark import
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will also import favicons and we store favicon for a URL only if the URL
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exist in history or bookmarks.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((items & importer::HISTORY) && !cancelled()) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->NotifyItemStarted(importer::HISTORY);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImportHistory();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->NotifyItemEnded(importer::HISTORY);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((items & importer::FAVORITES) && !cancelled()) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->NotifyItemStarted(importer::FAVORITES);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImportBookmarks();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->NotifyItemEnded(importer::FAVORITES);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((items & importer::SEARCH_ENGINES) && !cancelled()) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->NotifyItemStarted(importer::SEARCH_ENGINES);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImportSearchEngines();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->NotifyItemEnded(importer::SEARCH_ENGINES);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((items & importer::PASSWORDS) && !cancelled()) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->NotifyItemStarted(importer::PASSWORDS);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImportPasswords();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->NotifyItemEnded(importer::PASSWORDS);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bridge_->NotifyEnded();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::ImportHistory() {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file = source_path_.AppendASCII("places.sqlite");
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::PathExists(file))
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Connection db;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db.Open(file))
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |visit_type| represent the transition type of URLs (typed, click,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // redirect, bookmark, etc.) We eliminate some URLs like sub-frames and
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // redirects, since we don't want them to appear in history.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Firefox transition types are defined in:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   toolkit/components/places/public/nsINavHistoryService.idl
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* query = "SELECT h.url, h.title, h.visit_count, "
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "h.hidden, h.typed, v.visit_date "
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "FROM moz_places h JOIN moz_historyvisits v "
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "ON h.id = v.place_id "
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "WHERE v.visit_type <= 3";
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db.GetUniqueStatement(query));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<ImporterURLRow> rows;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (s.Step() && !cancelled()) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL url(s.ColumnString(0));
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Filter out unwanted URLs.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!CanImportURL(url))
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ImporterURLRow row(url);
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    row.title = s.ColumnString16(1);
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    row.visit_count = s.ColumnInt(2);
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    row.hidden = s.ColumnInt(3) == 1;
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    row.typed_count = s.ColumnInt(4);
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    row.last_visit = base::Time::FromTimeT(s.ColumnInt64(5)/1000000);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rows.push_back(row);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!rows.empty() && !cancelled())
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bridge_->SetHistoryItems(rows, importer::VISIT_SOURCE_FIREFOX_IMPORTED);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::ImportBookmarks() {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file = source_path_.AppendASCII("places.sqlite");
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::PathExists(file))
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Connection db;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db.Open(file))
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the bookmark folders that we are interested in.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int toolbar_folder_id = -1;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int menu_folder_id = -1;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int unsorted_folder_id = -1;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadRootNodeID(&db, &toolbar_folder_id, &menu_folder_id, &unsorted_folder_id);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load livemark IDs.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<int> livemark_id;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadLivemarkIDs(&db, &livemark_id);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
208a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Load the default bookmarks.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<GURL> default_urls;
210a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  LoadDefaultBookmarks(app_path_, &default_urls);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkList list;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetTopBookmarkFolder(&db, toolbar_folder_id, &list);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetTopBookmarkFolder(&db, menu_folder_id, &list);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetTopBookmarkFolder(&db, unsorted_folder_id, &list);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t count = list.size();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < count; ++i)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetWholeBookmarkFolder(&db, &list, i, NULL);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
220a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  std::vector<ImportedBookmarkEntry> bookmarks;
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<importer::URLKeywordInfo> url_keywords;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FaviconMap favicon_map;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jcampan): http://b/issue?id=1196285 we do not support POST based
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                keywords yet.  We won't include them in the list.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<int> post_keyword_ids;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* query = "SELECT b.id FROM moz_bookmarks b "
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "INNER JOIN moz_items_annos ia ON ia.item_id = b.id "
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "INNER JOIN moz_anno_attributes aa ON ia.anno_attribute_id = aa.id "
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "WHERE aa.name = 'bookmarkProperties/POSTData'";
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db.GetUniqueStatement(query));
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!s.is_valid())
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (s.Step() && !cancelled())
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    post_keyword_ids.insert(s.ColumnInt(0));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < list.size(); ++i) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BookmarkItem* item = list[i];
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->type == TYPE_FOLDER) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Folders are added implicitly on adding children, so we only explicitly
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // add empty folders.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!item->empty_folder)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (item->type == TYPE_BOOKMARK) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Import only valid bookmarks
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!CanImportURL(item->url))
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Skip the default bookmarks and unwanted URLs.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (default_urls.find(item->url) != default_urls.end() ||
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        post_keyword_ids.find(item->id) != post_keyword_ids.end())
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find the bookmark path by tracing their links to parent folders.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<string16> path;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BookmarkItem* child = item;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool found_path = false;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_in_toolbar = false;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (child->parent >= 0) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BookmarkItem* parent = list[child->parent];
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (livemark_id.find(parent->id) != livemark_id.end()) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Don't import live bookmarks.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (parent->id != menu_folder_id) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // To avoid excessive nesting, omit the name for the bookmarks menu
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // folder.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        path.insert(path.begin(), parent->title);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (parent->id == toolbar_folder_id)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        is_in_toolbar = true;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (parent->id == toolbar_folder_id ||
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          parent->id == menu_folder_id ||
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          parent->id == unsorted_folder_id) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We've reached a root node, hooray!
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_path = true;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      child = parent;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!found_path)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ImportedBookmarkEntry entry;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.creation_time = item->date_added;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.title = item->title;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.url = item->url;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.path = path;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.in_toolbar = is_in_toolbar;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.is_folder = item->type == TYPE_FOLDER;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmarks.push_back(entry);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->type == TYPE_BOOKMARK) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (item->favicon)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        favicon_map[item->favicon].insert(item->url);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // This bookmark has a keyword, we should import it.
310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (!item->keyword.empty() && item->url.is_valid()) {
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        importer::URLKeywordInfo url_keyword_info;
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        url_keyword_info.url = item->url;
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        url_keyword_info.keyword.assign(UTF8ToUTF16(item->keyword));
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        url_keyword_info.display_name = item->title;
315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        url_keywords.push_back(url_keyword_info);
316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&list);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write into profile.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bookmarks.empty() && !cancelled()) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& first_folder_name =
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_FIREFOX);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->AddBookmarks(bookmarks, first_folder_name);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!url_keywords.empty() && !cancelled()) {
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    bridge_->SetKeywords(url_keywords, false);
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!favicon_map.empty() && !cancelled()) {
332a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    std::vector<ImportedFaviconUsage> favicons;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadFavicons(&db, favicon_map, &favicons);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->SetFavicons(favicons);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::ImportPasswords() {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initializes NSS3.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSSDecryptor decryptor;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!decryptor.Init(source_path_, source_path_) &&
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !decryptor.Init(app_path_, source_path_)) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<content::PasswordForm> forms;
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath source_path = source_path_;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file = source_path.AppendASCII("signons.sqlite");
3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (base::PathExists(file)) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since Firefox 3.1, passwords are in signons.sqlite db.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decryptor.ReadAndParseSignons(file, &forms);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Firefox 3.0 uses signons3.txt to store the passwords.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file = source_path.AppendASCII("signons3.txt");
3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!base::PathExists(file))
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file = source_path.AppendASCII("signons2.txt");
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string content;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_util::ReadFileToString(file, &content);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decryptor.ParseSignons(content, &forms);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cancelled()) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < forms.size(); ++i) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bridge_->SetPasswordForm(forms[i]);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::ImportSearchEngines() {
371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<std::string> search_engine_data;
372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GetSearchEnginesXMLData(&search_engine_data);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bridge_->SetFirefoxSearchEnginesXMLData(search_engine_data);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
377ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::ImportHomepage() {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL home_page = GetHomepage(source_path_);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (home_page.is_valid() && !IsDefaultHomepage(home_page, app_path_)) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bridge_->AddHomePage(home_page);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
384ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::GetSearchEnginesXMLData(
385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::vector<std::string>* search_engine_data) {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file = source_path_.AppendASCII("search.sqlite");
3877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::PathExists(file))
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Connection db;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db.Open(file))
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* query = "SELECT engineid FROM engine_data "
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "WHERE engineid NOT IN "
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "(SELECT engineid FROM engine_data "
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "WHERE name='hidden') "
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "ORDER BY value ASC";
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db.GetUniqueStatement(query));
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!s.is_valid())
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath app_path = app_path_.AppendASCII("searchplugins");
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath profile_path = source_path_.AppendASCII("searchplugins");
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Firefox doesn't store a search engine in its sqlite database unless the
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // user has added a engine. So we get search engines from sqlite db as well
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as from the file system.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s.Step()) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string kAppPrefix("[app]/");
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string kProfilePrefix("[profile]/");
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath file;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string engine(s.ColumnString(0));
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The string contains [app]/<name>.xml or [profile]/<name>.xml where
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the [app] and [profile] need to be replaced with the actual app or
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // profile path.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t index = engine.find(kAppPrefix);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index != std::string::npos) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Remove '[app]/'.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file = app_path.AppendASCII(engine.substr(index + kAppPrefix.length()));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if ((index = engine.find(kProfilePrefix)) != std::string::npos) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Remove '[profile]/'.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          file = profile_path.AppendASCII(
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              engine.substr(index + kProfilePrefix.length()));
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Looks like absolute path to the file.
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        file = base::FilePath::FromUTF8Unsafe(engine);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::string file_data;
433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      file_util::ReadFileToString(file, &file_data);
434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      search_engine_data->push_back(file_data);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (s.Step() && !cancelled());
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_POSIX)
439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Ubuntu-flavored Firefox supports locale-specific search engines via
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // locale-named subdirectories. They fall back to en-US.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See http://crbug.com/53899
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jshin): we need to make sure our locale code matches that of
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Firefox.
444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!locale_.empty());
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath locale_app_path = app_path.AppendASCII(locale_);
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath default_locale_app_path = app_path.AppendASCII("en-US");
4477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (base::DirectoryExists(locale_app_path))
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_path = locale_app_path;
4497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  else if (base::DirectoryExists(default_locale_app_path))
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_path = default_locale_app_path;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get search engine definition from file system.
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::FileEnumerator engines(app_path, false, base::FileEnumerator::FILES);
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (base::FilePath engine_path = engines.Next();
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       !engine_path.value().empty(); engine_path = engines.Next()) {
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string file_data;
458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    file_util::ReadFileToString(file, &file_data);
459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    search_engine_data->push_back(file_data);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
463ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::LoadRootNodeID(sql::Connection* db,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int* toolbar_folder_id,
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int* menu_folder_id,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int* unsorted_folder_id) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* kToolbarFolderName = "toolbar";
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* kMenuFolderName = "menu";
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* kUnsortedFolderName = "unfiled";
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* query = "SELECT root_name, folder_id FROM moz_bookmarks_roots";
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db->GetUniqueStatement(query));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (s.Step()) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string folder = s.ColumnString(0);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int id = s.ColumnInt(1);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (folder == kToolbarFolderName)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *toolbar_folder_id = id;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (folder == kMenuFolderName)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *menu_folder_id = id;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (folder == kUnsortedFolderName)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *unsorted_folder_id = id;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::LoadLivemarkIDs(sql::Connection* db,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       std::set<int>* livemark) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* kFeedAnnotation = "livemark/feedURI";
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  livemark->clear();
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* query = "SELECT b.item_id "
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "FROM moz_anno_attributes a "
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "JOIN moz_items_annos b ON a.id = b.anno_attribute_id "
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "WHERE a.name = ? ";
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db->GetUniqueStatement(query));
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.BindString(0, kFeedAnnotation);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (s.Step() && !cancelled())
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    livemark->insert(s.ColumnInt(0));
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::GetTopBookmarkFolder(sql::Connection* db,
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int folder_id,
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            BookmarkList* list) {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* query = "SELECT b.title "
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "FROM moz_bookmarks b "
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "WHERE b.type = 2 AND b.id = ? "
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "ORDER BY b.position";
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db->GetUniqueStatement(query));
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.BindInt(0, folder_id);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s.Step()) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BookmarkItem* item = new BookmarkItem;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->parent = -1;  // The top level folder has no parent.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->id = folder_id;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->title = s.ColumnString16(0);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->type = TYPE_FOLDER;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->favicon = 0;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->empty_folder = true;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list->push_back(item);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::GetWholeBookmarkFolder(sql::Connection* db,
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              BookmarkList* list,
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              size_t position,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              bool* empty_folder) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (position >= list->size()) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* query = "SELECT b.id, h.url, COALESCE(b.title, h.title), "
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "b.type, k.keyword, b.dateAdded, h.favicon_id "
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "FROM moz_bookmarks b "
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "LEFT JOIN moz_places h ON b.fk = h.id "
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "LEFT JOIN moz_keywords k ON k.id = b.keyword_id "
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "WHERE b.type IN (1,2) AND b.parent = ? "
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "ORDER BY b.position";
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db->GetUniqueStatement(query));
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.BindInt(0, (*list)[position]->id);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkList temp_list;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (s.Step()) {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BookmarkItem* item = new BookmarkItem;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->parent = static_cast<int>(position);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->id = s.ColumnInt(0);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->url = GURL(s.ColumnString(1));
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->title = s.ColumnString16(2);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->type = static_cast<BookmarkItemType>(s.ColumnInt(3));
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->keyword = s.ColumnString(4);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->date_added = base::Time::FromTimeT(s.ColumnInt64(5)/1000000);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->favicon = s.ColumnInt64(6);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->empty_folder = true;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    temp_list.push_back(item);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (empty_folder != NULL)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *empty_folder = false;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Appends all items to the list.
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (BookmarkList::iterator i = temp_list.begin();
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != temp_list.end(); ++i) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list->push_back(*i);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Recursive add bookmarks in sub-folders.
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*i)->type == TYPE_FOLDER)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetWholeBookmarkFolder(db, list, list->size() - 1, &(*i)->empty_folder);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
571ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid FirefoxImporter::LoadFavicons(
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Connection* db,
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FaviconMap& favicon_map,
574a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    std::vector<ImportedFaviconUsage>* favicons) {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* query = "SELECT url, data FROM moz_favicons WHERE id=?";
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db->GetUniqueStatement(query));
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!s.is_valid())
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (FaviconMap::const_iterator i = favicon_map.begin();
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != favicon_map.end(); ++i) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s.BindInt64(0, i->first);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (s.Step()) {
585a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      ImportedFaviconUsage usage;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      usage.favicon_url = GURL(s.ColumnString(0));
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!usage.favicon_url.is_valid())
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;  // Don't bother importing favicons with invalid URLs.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<unsigned char> data;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      s.ColumnBlobAsVector(1, &data);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (data.empty())
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;  // Data definitely invalid.
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (!importer::ReencodeFavicon(&data[0], data.size(), &usage.png_data))
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;  // Unable to decode.
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      usage.urls = i->second;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      favicons->push_back(usage);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s.Reset(true);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605