Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1114)

Unified Diff: chrome/utility/importer/firefox_places_factory.cc

Issue 2451223004: Improve Firefox importer to handle all Firefox profiles. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/utility/importer/firefox_places_factory.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/utility/importer/firefox_places_factory.cc
diff --git a/chrome/utility/importer/firefox_places_factory.cc b/chrome/utility/importer/firefox_places_factory.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e06093949d5e4af46e65da7d9ee09d3d6a48b5cc
--- /dev/null
+++ b/chrome/utility/importer/firefox_places_factory.cc
@@ -0,0 +1,310 @@
+// Copyright 2016 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/favicon_reencode.h"
+#include "chrome/utility/importer/firefox_places_factory.h"
+#include "firefox_places_factory.h"
+
+FirefoxPlaces::FirefoxPlaces(const base::FilePath& places_path)
+ : places_path_(places_path) {
+ db_.Open(places_path);
+}
+
+bool FirefoxPlaces::LoadBookmarks(BookmarkList* bookmarks) {
+ // Get the bookmark folders that we are interested in.
+ int toolbar_folder_id = GetFolderId(FolderType::TOOLBAR);
+ int menu_folder_id = GetFolderId(FolderType::MENU);
+ int unsorted_folder_id = GetFolderId(FolderType::UNSORTED);
+
+ GetTopBookmarkFolder(toolbar_folder_id, bookmarks);
+ GetTopBookmarkFolder(menu_folder_id, bookmarks);
+ GetTopBookmarkFolder(unsorted_folder_id, bookmarks);
+ auto num_folders = bookmarks->size();
+ for (size_t i = 0; i < num_folders; ++i)
+ GetWholeBookmarkFolder(bookmarks, i, NULL);
+ return true;
+}
+
+bool FirefoxPlaces::LoadHistory(std::vector<ImporterURLRow>* rows) {
+ // |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));
+
+ while (s.Step()) {
+ GURL url(s.ColumnString(0));
+
+ 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);
+ }
+ return true;
+}
+
+bool FirefoxPlaces::LoadPostKeywordIds(PostKeywordIds* 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 false;
+
+ while (s.Step())
+ post_keyword_ids->insert(s.ColumnInt(0));
+ return true;
+}
+
+bool FirefoxPlaces::LoadLivemarkIds(LivemarkIds* livemark_ids) {
+ static const char kFeedAnnotation[] = "livemark/feedURI";
+ livemark_ids->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())
+ livemark_ids->insert(s.ColumnInt(0));
+ return true;
+}
+
+int FirefoxPlaces::GetFolderId(FolderType folder_type) {
+ return -1;
+}
+
+bool FirefoxPlaces::LoadFavicons(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 false;
+
+ 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);
+ }
+ return true;
+}
+
+void FirefoxPlaces::GetTopBookmarkFolder(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()) {
+ BookmarkItem* item = new 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(item);
+ }
+}
+
+void FirefoxPlaces::GetWholeBookmarkFolder(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()) {
+ BookmarkItem* item = new 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(item);
+ if (empty_folder != NULL)
+ *empty_folder = false;
+ }
+
+ // Appends all items to the list.
+ for (BookmarkList::iterator i = temp_list.begin(); i != temp_list.end();
+ ++i) {
+ list->push_back(*i);
+ // Recursive add bookmarks in sub-folders.
+ if ((*i)->type == TYPE_FOLDER)
+ GetWholeBookmarkFolder(list, list->size() - 1, &(*i)->empty_folder);
+ }
+}
+
+// FirefoxPlacesV11
+FirefoxPlacesV11::FirefoxPlacesV11(const base::FilePath& places_path)
+ : FirefoxPlaces(places_path) {}
+
+int FirefoxPlacesV11::GetFolderId(FolderType folder_type) {
+ int folder_id = -1;
+ switch (folder_type) {
+ case FolderType::ROOT:
+ folder_id = LoadNodeIDByName("root");
+ break;
+ case FolderType::MENU:
+ folder_id = LoadNodeIDByName("menu");
+ break;
+ case FolderType::TOOLBAR:
+ folder_id = LoadNodeIDByName("toolbar");
+ break;
+ case FolderType::TAGS:
+ folder_id = LoadNodeIDByName("tags");
+ break;
+ case FolderType::UNSORTED:
+ folder_id = LoadNodeIDByName("unfiled");
+ break;
+ default:
+ folder_id = -1;
+ break;
+ }
+ return folder_id;
+}
+
+int FirefoxPlacesV11::LoadNodeIDByName(const std::string& name) {
+ const char query[] =
+ "SELECT folder_id "
+ "FROM moz_bookmarks_roots "
+ "WHERE root_name = ?";
+ sql::Statement s(db_.GetUniqueStatement(query));
+ s.BindString(0, name);
+ if (!s.Step())
+ return -1;
+ return s.ColumnInt(0);
+}
+
+// FirefoxPlacesV25
+FirefoxPlacesV25::FirefoxPlacesV25(const base::FilePath& places_path)
+ : FirefoxPlaces(places_path) {}
+
+int FirefoxPlacesV25::LoadNodeIDByGUID(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);
+}
+
+int FirefoxPlacesV25::GetFolderId(FolderType folder_type) {
+ int folder_id = -1;
+ switch (folder_type) {
+ case FolderType::ROOT:
+ folder_id = LoadNodeIDByGUID("root________");
+ break;
+ case FolderType::MENU:
+ folder_id = LoadNodeIDByGUID("menu________");
+ break;
+ case FolderType::TOOLBAR:
+ folder_id = LoadNodeIDByGUID("toolbar_____");
+ break;
+ case FolderType::TAGS:
+ folder_id = LoadNodeIDByGUID("tags________");
+ break;
+ case FolderType::UNSORTED:
+ folder_id = LoadNodeIDByGUID("unfiled_____");
+ break;
+ default:
+ folder_id = -1;
+ break;
+ }
+ return folder_id;
+}
+
+std::unique_ptr<FirefoxPlaces> FirefoxPlacesFactory::GetForProfile(
+ const base::FilePath& profile_path) {
+ base::FilePath places_path = profile_path.AppendASCII("places.sqlite");
+ if (!base::PathExists(places_path))
+ return std::unique_ptr<FirefoxPlaces>();
+
+ sql::Connection db;
+ if (!db.Open(places_path))
+ return std::unique_ptr<FirefoxPlaces>();
+
+ const std::string schema_version_query{"PRAGMA user_version"};
+ sql::Statement s(db.GetUniqueStatement(schema_version_query.c_str()));
+ if (!s.is_valid())
+ return std::unique_ptr<FirefoxPlaces>();
+
+ s.Step();
+ int schema_version = s.ColumnInt(0);
+ s.Clear();
+ db.Close();
+
+ if (schema_version >= 25) {
+ return std::unique_ptr<FirefoxPlaces>(new FirefoxPlacesV25(places_path));
+ } else if (schema_version >= 11) {
+ return std::unique_ptr<FirefoxPlaces>(new FirefoxPlacesV11(places_path));
+ } else {
+ return std::unique_ptr<FirefoxPlaces>(); // Same as Firefox, we don't
+ // support schemas earlier than
+ // 11.
+ }
+}
« no previous file with comments | « chrome/utility/importer/firefox_places_factory.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698