| Index: chrome/browser/history/starred_url_database.cc
|
| diff --git a/chrome/browser/history/starred_url_database.cc b/chrome/browser/history/starred_url_database.cc
|
| deleted file mode 100644
|
| index 7b981668adbc4fb3489be1dfbcea905f0f509e2d..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/history/starred_url_database.cc
|
| +++ /dev/null
|
| @@ -1,661 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/history/starred_url_database.h"
|
| -
|
| -#include "base/file_util.h"
|
| -#include "base/json/json_writer.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/scoped_vector.h"
|
| -#include "base/stl_util.h"
|
| -#include "base/string_util.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "base/values.h"
|
| -#include "chrome/browser/bookmarks/bookmark_codec.h"
|
| -#include "chrome/browser/bookmarks/bookmark_model.h"
|
| -#include "chrome/browser/history/history.h"
|
| -#include "sql/statement.h"
|
| -
|
| -// The following table is used to store star (aka bookmark) information. This
|
| -// class derives from URLDatabase, which has its own schema.
|
| -//
|
| -// starred
|
| -// id Unique identifier (primary key) for the entry.
|
| -// type Type of entry, if 0 this corresponds to a URL, 1 for
|
| -// a system folder, 2 for a user created folder, 3 for
|
| -// other. Note that 4 (synced) will never appear in the
|
| -// database because it was added after this storage was
|
| -// deprecated.
|
| -// url_id ID of the url, only valid if type == 0
|
| -// group_id ID of the folder, only valid if type != 0. This id comes
|
| -// from the UI and is NOT the same as id.
|
| -// title User assigned title.
|
| -// date_added Creation date.
|
| -// visual_order Visual order within parent.
|
| -// parent_id Folder ID of the parent this entry is contained in, if 0
|
| -// entry is not in a folder.
|
| -// date_modified Time the folder was last modified. See comments in
|
| -// StarredEntry::date_folder_modified
|
| -// NOTE: group_id and parent_id come from the UI, id is assigned by the
|
| -// db.
|
| -
|
| -namespace history {
|
| -
|
| -namespace {
|
| -
|
| -// Fields used by FillInStarredEntry.
|
| -#define STAR_FIELDS \
|
| - " starred.id, starred.type, starred.title, starred.date_added, " \
|
| - "starred.visual_order, starred.parent_id, urls.url, urls.id, " \
|
| - "starred.group_id, starred.date_modified "
|
| -const char kHistoryStarFields[] = STAR_FIELDS;
|
| -
|
| -void FillInStarredEntry(const sql::Statement& s, StarredEntry* entry) {
|
| - DCHECK(entry);
|
| - entry->id = s.ColumnInt64(0);
|
| - switch (s.ColumnInt(1)) {
|
| - case 0:
|
| - entry->type = history::StarredEntry::URL;
|
| - entry->url = GURL(s.ColumnString(6));
|
| - break;
|
| - case 1:
|
| - entry->type = history::StarredEntry::BOOKMARK_BAR;
|
| - break;
|
| - case 2:
|
| - entry->type = history::StarredEntry::USER_FOLDER;
|
| - break;
|
| - case 3:
|
| - entry->type = history::StarredEntry::OTHER;
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - break;
|
| - }
|
| - entry->title = s.ColumnString16(2);
|
| - entry->date_added = base::Time::FromInternalValue(s.ColumnInt64(3));
|
| - entry->visual_order = s.ColumnInt(4);
|
| - entry->parent_folder_id = s.ColumnInt64(5);
|
| - entry->url_id = s.ColumnInt64(7);
|
| - entry->folder_id = s.ColumnInt64(8);
|
| - entry->date_folder_modified = base::Time::FromInternalValue(s.ColumnInt64(9));
|
| -}
|
| -
|
| -// Resets the properties of |node| from the supplied |entry|.
|
| -void ResetBookmarkNode(const history::StarredEntry& entry,
|
| - BookmarkNode* node) {
|
| - DCHECK(entry.type != history::StarredEntry::URL ||
|
| - entry.url == node->url());
|
| -
|
| - node->set_date_added(entry.date_added);
|
| - node->set_date_folder_modified(entry.date_folder_modified);
|
| - node->SetTitle(entry.title);
|
| -
|
| - switch (entry.type) {
|
| - case history::StarredEntry::URL:
|
| - node->set_type(BookmarkNode::URL);
|
| - break;
|
| - case history::StarredEntry::USER_FOLDER:
|
| - node->set_type(BookmarkNode::FOLDER);
|
| - break;
|
| - case history::StarredEntry::BOOKMARK_BAR:
|
| - node->set_type(BookmarkNode::BOOKMARK_BAR);
|
| - break;
|
| - case history::StarredEntry::OTHER:
|
| - node->set_type(BookmarkNode::OTHER_NODE);
|
| - break;
|
| - case history::StarredEntry::MOBILE:
|
| - node->set_type(BookmarkNode::MOBILE);
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - break;
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// static
|
| -const int64 StarredURLDatabase::kBookmarkBarID = 1;
|
| -
|
| -StarredURLDatabase::StarredURLDatabase(sql::Connection* db)
|
| - : db_(db) {
|
| -}
|
| -
|
| -StarredURLDatabase::~StarredURLDatabase() {
|
| -}
|
| -
|
| -bool StarredURLDatabase::MigrateBookmarksToFile(const FilePath& path) {
|
| - if (!GetDB().DoesTableExist("starred"))
|
| - return true;
|
| -
|
| - if (EnsureStarredIntegrity() && !MigrateBookmarksToFileImpl(path)) {
|
| - NOTREACHED() << " Bookmarks migration failed";
|
| - return false;
|
| - }
|
| -
|
| - if (!GetDB().Execute("DROP TABLE starred")) {
|
| - NOTREACHED() << "Unable to drop starred table";
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool StarredURLDatabase::GetAllStarredEntries(
|
| - std::vector<StarredEntry>* entries) {
|
| - DCHECK(entries);
|
| - std::string sql = "SELECT ";
|
| - sql.append(kHistoryStarFields);
|
| - sql.append("FROM starred LEFT JOIN urls ON starred.url_id = urls.id ");
|
| - sql += "ORDER BY parent_id, visual_order";
|
| -
|
| - sql::Statement s(GetDB().GetUniqueStatement(sql.c_str()));
|
| - if (!s.is_valid())
|
| - return false;
|
| -
|
| - history::StarredEntry entry;
|
| - while (s.Step()) {
|
| - FillInStarredEntry(s, &entry);
|
| - // Reset the url for non-url types. This is needed as we're reusing the
|
| - // same entry for the loop.
|
| - if (entry.type != history::StarredEntry::URL)
|
| - entry.url = GURL();
|
| - entries->push_back(entry);
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -sql::Connection& StarredURLDatabase::GetDB() {
|
| - return *db_;
|
| -}
|
| -
|
| -bool StarredURLDatabase::EnsureStarredIntegrity() {
|
| - std::set<StarredNode*> roots;
|
| - std::set<StarID> folders_with_duplicate_ids;
|
| - std::set<StarredNode*> unparented_urls;
|
| - std::set<StarID> empty_url_ids;
|
| -
|
| - if (!BuildStarNodes(&roots, &folders_with_duplicate_ids, &unparented_urls,
|
| - &empty_url_ids)) {
|
| - return false;
|
| - }
|
| -
|
| - bool valid = EnsureStarredIntegrityImpl(&roots, folders_with_duplicate_ids,
|
| - &unparented_urls, empty_url_ids);
|
| -
|
| - STLDeleteElements(&roots);
|
| - STLDeleteElements(&unparented_urls);
|
| - return valid;
|
| -}
|
| -
|
| -bool StarredURLDatabase::UpdateStarredEntryRow(StarID star_id,
|
| - const string16& title,
|
| - UIStarID parent_folder_id,
|
| - int visual_order,
|
| - base::Time date_modified) {
|
| - DCHECK(star_id && visual_order >= 0);
|
| - sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| - "UPDATE starred SET title=?, parent_id=?, visual_order=?, "
|
| - "date_modified=? WHERE id=?"));
|
| - statement.BindString16(0, title);
|
| - statement.BindInt64(1, parent_folder_id);
|
| - statement.BindInt(2, visual_order);
|
| - statement.BindInt64(3, date_modified.ToInternalValue());
|
| - statement.BindInt64(4, star_id);
|
| -
|
| - return statement.Run();
|
| -}
|
| -
|
| -bool StarredURLDatabase::AdjustStarredVisualOrder(UIStarID parent_folder_id,
|
| - int start_visual_order,
|
| - int delta) {
|
| - DCHECK(parent_folder_id && start_visual_order >= 0);
|
| - sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| - "UPDATE starred SET visual_order=visual_order+? "
|
| - "WHERE parent_id=? AND visual_order >= ?"));
|
| - statement.BindInt(0, delta);
|
| - statement.BindInt64(1, parent_folder_id);
|
| - statement.BindInt(2, start_visual_order);
|
| -
|
| - return statement.Run();
|
| -}
|
| -
|
| -StarID StarredURLDatabase::CreateStarredEntryRow(URLID url_id,
|
| - UIStarID folder_id,
|
| - UIStarID parent_folder_id,
|
| - const string16& title,
|
| - const base::Time& date_added,
|
| - int visual_order,
|
| - StarredEntry::Type type) {
|
| - DCHECK(visual_order >= 0 &&
|
| - (type != history::StarredEntry::URL || url_id));
|
| - sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| - "INSERT INTO starred "
|
| - "(type, url_id, group_id, title, date_added, visual_order, parent_id, "
|
| - "date_modified) VALUES (?,?,?,?,?,?,?,?)"));
|
| -
|
| - switch (type) {
|
| - case history::StarredEntry::URL:
|
| - statement.BindInt(0, 0);
|
| - break;
|
| - case history::StarredEntry::BOOKMARK_BAR:
|
| - statement.BindInt(0, 1);
|
| - break;
|
| - case history::StarredEntry::USER_FOLDER:
|
| - statement.BindInt(0, 2);
|
| - break;
|
| - case history::StarredEntry::OTHER:
|
| - statement.BindInt(0, 3);
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - }
|
| - statement.BindInt64(1, url_id);
|
| - statement.BindInt64(2, folder_id);
|
| - statement.BindString16(3, title);
|
| - statement.BindInt64(4, date_added.ToInternalValue());
|
| - statement.BindInt(5, visual_order);
|
| - statement.BindInt64(6, parent_folder_id);
|
| - statement.BindInt64(7, base::Time().ToInternalValue());
|
| -
|
| - if (statement.Run())
|
| - return GetDB().GetLastInsertRowId();
|
| - return 0;
|
| -}
|
| -
|
| -bool StarredURLDatabase::DeleteStarredEntryRow(StarID star_id) {
|
| - sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| - "DELETE FROM starred WHERE id=?"));
|
| - statement.BindInt64(0, star_id);
|
| -
|
| - return statement.Run();
|
| -}
|
| -
|
| -bool StarredURLDatabase::GetStarredEntry(StarID star_id, StarredEntry* entry) {
|
| - DCHECK(entry && star_id);
|
| - sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| - "SELECT" STAR_FIELDS "FROM starred LEFT JOIN urls ON "
|
| - "starred.url_id = urls.id WHERE starred.id=?"));
|
| - statement.BindInt64(0, star_id);
|
| -
|
| - if (statement.Step()) {
|
| - FillInStarredEntry(statement, entry);
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -StarID StarredURLDatabase::CreateStarredEntry(StarredEntry* entry) {
|
| - entry->id = 0; // Ensure 0 for failure case.
|
| -
|
| - // Adjust the visual order when we are inserting it somewhere.
|
| - if (entry->parent_folder_id)
|
| - AdjustStarredVisualOrder(entry->parent_folder_id, entry->visual_order, 1);
|
| -
|
| - // Insert the new entry.
|
| - switch (entry->type) {
|
| - case StarredEntry::USER_FOLDER:
|
| - entry->id = CreateStarredEntryRow(0, entry->folder_id,
|
| - entry->parent_folder_id, entry->title, entry->date_added,
|
| - entry->visual_order, entry->type);
|
| - break;
|
| -
|
| - case StarredEntry::URL: {
|
| - // Get the row for this URL.
|
| - URLRow url_row;
|
| - if (!GetRowForURL(entry->url, &url_row)) {
|
| - // Create a new URL row for this entry.
|
| - url_row = URLRow(entry->url);
|
| - url_row.set_title(entry->title);
|
| - url_row.set_hidden(false);
|
| - entry->url_id = this->AddURL(url_row);
|
| - } else {
|
| - entry->url_id = url_row.id(); // The caller doesn't have to set this.
|
| - }
|
| -
|
| - // Create the star entry referring to the URL row.
|
| - entry->id = CreateStarredEntryRow(entry->url_id, entry->folder_id,
|
| - entry->parent_folder_id, entry->title, entry->date_added,
|
| - entry->visual_order, entry->type);
|
| -
|
| - // Update the URL row to refer to this new starred entry.
|
| - UpdateURLRow(entry->url_id, url_row);
|
| - break;
|
| - }
|
| -
|
| - default:
|
| - NOTREACHED();
|
| - break;
|
| - }
|
| - return entry->id;
|
| -}
|
| -
|
| -UIStarID StarredURLDatabase::GetMaxFolderID() {
|
| - sql::Statement max_folder_id_statement(GetDB().GetUniqueStatement(
|
| - "SELECT MAX(group_id) FROM starred"));
|
| -
|
| - if (!max_folder_id_statement.Step()) {
|
| - return 0;
|
| - }
|
| - return max_folder_id_statement.ColumnInt64(0);
|
| -}
|
| -
|
| -bool StarredURLDatabase::BuildStarNodes(
|
| - std::set<StarredURLDatabase::StarredNode*>* roots,
|
| - std::set<StarID>* folders_with_duplicate_ids,
|
| - std::set<StarredNode*>* unparented_urls,
|
| - std::set<StarID>* empty_url_ids) {
|
| - std::vector<StarredEntry> star_entries;
|
| - if (!GetAllStarredEntries(&star_entries)) {
|
| - NOTREACHED() << "Unable to get bookmarks from database";
|
| - return false;
|
| - }
|
| -
|
| - // Create the folder/bookmark-bar/other nodes.
|
| - std::map<UIStarID, StarredNode*> folder_id_to_node_map;
|
| - for (size_t i = 0; i < star_entries.size(); ++i) {
|
| - if (star_entries[i].type != StarredEntry::URL) {
|
| - if (folder_id_to_node_map.find(star_entries[i].folder_id) !=
|
| - folder_id_to_node_map.end()) {
|
| - // There's already a folder with this ID.
|
| - folders_with_duplicate_ids->insert(star_entries[i].id);
|
| - } else {
|
| - // Create the node and update the mapping.
|
| - StarredNode* node = new StarredNode(star_entries[i]);
|
| - folder_id_to_node_map[star_entries[i].folder_id] = node;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Iterate again, creating nodes for URL bookmarks and parenting all
|
| - // bookmarks/folders. In addition populate the empty_url_ids with all entries
|
| - // of type URL that have an empty URL.
|
| - std::map<StarID, StarredNode*> id_to_node_map;
|
| - for (size_t i = 0; i < star_entries.size(); ++i) {
|
| - if (star_entries[i].type == StarredEntry::URL) {
|
| - if (star_entries[i].url.is_empty()) {
|
| - empty_url_ids->insert(star_entries[i].id);
|
| - } else if (!star_entries[i].parent_folder_id ||
|
| - folder_id_to_node_map.find(star_entries[i].parent_folder_id) ==
|
| - folder_id_to_node_map.end()) {
|
| - // This entry has no parent, or we couldn't find the parent.
|
| - StarredNode* node = new StarredNode(star_entries[i]);
|
| - unparented_urls->insert(node);
|
| - } else {
|
| - // Add the node to its parent.
|
| - StarredNode* parent =
|
| - folder_id_to_node_map[star_entries[i].parent_folder_id];
|
| - StarredNode* node = new StarredNode(star_entries[i]);
|
| - parent->Add(node, parent->child_count());
|
| - }
|
| - } else if (folders_with_duplicate_ids->find(star_entries[i].id) ==
|
| - folders_with_duplicate_ids->end()) {
|
| - // The entry is a folder (or bookmark bar/other node) that isn't
|
| - // marked as a duplicate.
|
| - if (!star_entries[i].parent_folder_id ||
|
| - folder_id_to_node_map.find(star_entries[i].parent_folder_id) ==
|
| - folder_id_to_node_map.end()) {
|
| - // Entry has no parent, or the parent wasn't found.
|
| - roots->insert(folder_id_to_node_map[star_entries[i].folder_id]);
|
| - } else {
|
| - // Parent the folder node.
|
| - StarredNode* parent =
|
| - folder_id_to_node_map[star_entries[i].parent_folder_id];
|
| - StarredNode* node = folder_id_to_node_map[star_entries[i].folder_id];
|
| - if (!node->HasAncestor(parent) && !parent->HasAncestor(node)) {
|
| - parent->Add(node, parent->child_count());
|
| - } else {
|
| - // The node has a cycle. Add it to the list of roots so the cycle is
|
| - // broken.
|
| - roots->insert(node);
|
| - }
|
| - }
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -StarredURLDatabase::StarredNode* StarredURLDatabase::GetNodeByType(
|
| - const std::set<StarredURLDatabase::StarredNode*>& nodes,
|
| - StarredEntry::Type type) {
|
| - for (std::set<StarredNode*>::const_iterator i = nodes.begin();
|
| - i != nodes.end(); ++i) {
|
| - if ((*i)->value.type == type)
|
| - return *i;
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -bool StarredURLDatabase::EnsureVisualOrder(
|
| - StarredURLDatabase::StarredNode* node) {
|
| - for (int i = 0; i < node->child_count(); ++i) {
|
| - if (node->GetChild(i)->value.visual_order != i) {
|
| - StarredEntry& entry = node->GetChild(i)->value;
|
| - entry.visual_order = i;
|
| - LOG(WARNING) << "Bookmark visual order is wrong";
|
| - if (!UpdateStarredEntryRow(entry.id, entry.title, entry.parent_folder_id,
|
| - i, entry.date_folder_modified)) {
|
| - NOTREACHED() << "Unable to update visual order";
|
| - return false;
|
| - }
|
| - }
|
| - if (!EnsureVisualOrder(node->GetChild(i)))
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool StarredURLDatabase::EnsureStarredIntegrityImpl(
|
| - std::set<StarredURLDatabase::StarredNode*>* roots,
|
| - const std::set<StarID>& folders_with_duplicate_ids,
|
| - std::set<StarredNode*>* unparented_urls,
|
| - const std::set<StarID>& empty_url_ids) {
|
| - // Make sure the bookmark bar entry exists.
|
| - StarredNode* bookmark_node =
|
| - GetNodeByType(*roots, StarredEntry::BOOKMARK_BAR);
|
| - if (!bookmark_node) {
|
| - LOG(WARNING) << "No bookmark bar folder in database";
|
| - // If there is no bookmark bar entry in the db things are really
|
| - // screwed. Return false, which won't trigger migration and we'll just
|
| - // drop the tables.
|
| - return false;
|
| - }
|
| -
|
| - // Make sure the other node exists.
|
| - StarredNode* other_node = GetNodeByType(*roots, StarredEntry::OTHER);
|
| - if (!other_node) {
|
| - LOG(WARNING) << "No bookmark other folder in database";
|
| - StarredEntry entry;
|
| - entry.folder_id = GetMaxFolderID() + 1;
|
| - if (entry.folder_id == 1) {
|
| - NOTREACHED() << "Unable to get new id for other bookmarks folder";
|
| - return false;
|
| - }
|
| - entry.id = CreateStarredEntryRow(
|
| - 0, entry.folder_id, 0, UTF8ToUTF16("other"), base::Time::Now(), 0,
|
| - history::StarredEntry::OTHER);
|
| - if (!entry.id) {
|
| - NOTREACHED() << "Unable to create other bookmarks folder";
|
| - return false;
|
| - }
|
| - entry.type = StarredEntry::OTHER;
|
| - StarredNode* other_node = new StarredNode(entry);
|
| - roots->insert(other_node);
|
| - }
|
| -
|
| - // We could potentially make sure only one folder with type
|
| - // BOOKMARK_BAR/OTHER, but history backend enforces this.
|
| -
|
| - // Nuke any entries with no url.
|
| - for (std::set<StarID>::const_iterator i = empty_url_ids.begin();
|
| - i != empty_url_ids.end(); ++i) {
|
| - LOG(WARNING) << "Bookmark exists with no URL";
|
| - if (!DeleteStarredEntryRow(*i)) {
|
| - NOTREACHED() << "Unable to delete bookmark";
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - // Make sure the visual order of the nodes is correct.
|
| - for (std::set<StarredNode*>::const_iterator i = roots->begin();
|
| - i != roots->end(); ++i) {
|
| - if (!EnsureVisualOrder(*i))
|
| - return false;
|
| - }
|
| -
|
| - // Move any unparented bookmarks to the bookmark bar.
|
| - {
|
| - std::set<StarredNode*>::iterator i = unparented_urls->begin();
|
| - while (i != unparented_urls->end()) {
|
| - LOG(WARNING) << "Bookmark not in a bookmark folder found";
|
| - if (!Move(*i, bookmark_node))
|
| - return false;
|
| - unparented_urls->erase(i++);
|
| - }
|
| - }
|
| -
|
| - // Nuke any folders with duplicate ids. A duplicate id means there are two
|
| - // folders in the starred table with the same folder_id. We only keep the
|
| - // first folder, all other folders are removed.
|
| - for (std::set<StarID>::const_iterator i = folders_with_duplicate_ids.begin();
|
| - i != folders_with_duplicate_ids.end(); ++i) {
|
| - LOG(WARNING) << "Duplicate folder id in bookmark database";
|
| - if (!DeleteStarredEntryRow(*i)) {
|
| - NOTREACHED() << "Unable to delete folder";
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - // Move unparented user folders back to the bookmark bar.
|
| - {
|
| - std::set<StarredNode*>::iterator i = roots->begin();
|
| - while (i != roots->end()) {
|
| - if ((*i)->value.type == StarredEntry::USER_FOLDER) {
|
| - LOG(WARNING) << "Bookmark folder not on bookmark bar found";
|
| - if (!Move(*i, bookmark_node))
|
| - return false;
|
| - roots->erase(i++);
|
| - } else {
|
| - ++i;
|
| - }
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool StarredURLDatabase::Move(StarredNode* source, StarredNode* new_parent) {
|
| - history::StarredEntry& entry = source->value;
|
| - entry.visual_order = new_parent->child_count();
|
| - entry.parent_folder_id = new_parent->value.folder_id;
|
| - if (!UpdateStarredEntryRow(entry.id, entry.title,
|
| - entry.parent_folder_id, entry.visual_order,
|
| - entry.date_folder_modified)) {
|
| - NOTREACHED() << "Unable to move folder";
|
| - return false;
|
| - }
|
| - new_parent->Add(source, new_parent->child_count());
|
| - return true;
|
| -}
|
| -
|
| -bool StarredURLDatabase::MigrateBookmarksToFileImpl(const FilePath& path) {
|
| - std::vector<history::StarredEntry> entries;
|
| - if (!GetAllStarredEntries(&entries))
|
| - return false;
|
| -
|
| - // Create the bookmark bar and other folder nodes.
|
| - history::StarredEntry entry;
|
| - entry.type = history::StarredEntry::BOOKMARK_BAR;
|
| - BookmarkNode bookmark_bar_node(0, GURL());
|
| - ResetBookmarkNode(entry, &bookmark_bar_node);
|
| - entry.type = history::StarredEntry::OTHER;
|
| - BookmarkNode other_node(0, GURL());
|
| - ResetBookmarkNode(entry, &other_node);
|
| - // NOTE(yfriedman): We don't do anything with the mobile node because it won't
|
| - // ever exist in the starred node DB. We only need to create it to pass to
|
| - // "encode".
|
| - entry.type = history::StarredEntry::MOBILE;
|
| - BookmarkNode mobile_node(0, GURL());
|
| - ResetBookmarkNode(entry, &mobile_node);
|
| -
|
| - std::map<history::UIStarID, history::StarID> folder_id_to_id_map;
|
| - typedef std::map<history::StarID, BookmarkNode*> IDToNodeMap;
|
| - IDToNodeMap id_to_node_map;
|
| -
|
| - history::UIStarID other_folder_folder_id = 0;
|
| - history::StarID other_folder_id = 0;
|
| -
|
| - // Iterate through the entries building a mapping between folder_id and id.
|
| - for (std::vector<history::StarredEntry>::const_iterator i = entries.begin();
|
| - i != entries.end(); ++i) {
|
| - if (i->type != history::StarredEntry::URL) {
|
| - folder_id_to_id_map[i->folder_id] = i->id;
|
| - if (i->type == history::StarredEntry::OTHER) {
|
| - other_folder_id = i->id;
|
| - other_folder_folder_id = i->folder_id;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Register the bookmark bar and other folder nodes in the maps.
|
| - id_to_node_map[kBookmarkBarID] = &bookmark_bar_node;
|
| - folder_id_to_id_map[kBookmarkBarID] = kBookmarkBarID;
|
| - if (other_folder_folder_id) {
|
| - id_to_node_map[other_folder_id] = &other_node;
|
| - folder_id_to_id_map[other_folder_folder_id] = other_folder_id;
|
| - }
|
| -
|
| - // Iterate through the entries again creating the nodes.
|
| - for (std::vector<history::StarredEntry>::iterator i = entries.begin();
|
| - i != entries.end(); ++i) {
|
| - if (!i->parent_folder_id) {
|
| - DCHECK(i->type == history::StarredEntry::BOOKMARK_BAR ||
|
| - i->type == history::StarredEntry::MOBILE ||
|
| - i->type == history::StarredEntry::OTHER);
|
| - // Only entries with no parent should be the bookmark bar and other
|
| - // bookmarks folders.
|
| - continue;
|
| - }
|
| -
|
| - BookmarkNode* node = id_to_node_map[i->id];
|
| - if (!node) {
|
| - // Creating a node results in creating the parent. As such, it is
|
| - // possible for the node representing a folder to have been created before
|
| - // encountering the details.
|
| -
|
| - // The created nodes are owned by the root node.
|
| - node = new BookmarkNode(i->url);
|
| - id_to_node_map[i->id] = node;
|
| - }
|
| - ResetBookmarkNode(*i, node);
|
| -
|
| - DCHECK(folder_id_to_id_map.find(i->parent_folder_id) !=
|
| - folder_id_to_id_map.end());
|
| - history::StarID parent_id = folder_id_to_id_map[i->parent_folder_id];
|
| - BookmarkNode* parent = id_to_node_map[parent_id];
|
| - if (!parent) {
|
| - // Haven't encountered the parent yet, create it now.
|
| - parent = new BookmarkNode(GURL());
|
| - id_to_node_map[parent_id] = parent;
|
| - }
|
| -
|
| - // Add the node to its parent. |entries| is ordered by parent then
|
| - // visual order so that we know we maintain visual order by always adding
|
| - // to the end.
|
| - parent->Add(node, parent->child_count());
|
| - }
|
| -
|
| - // Save to file.
|
| - BookmarkCodec encoder;
|
| - scoped_ptr<Value> encoded_bookmarks(
|
| - encoder.Encode(&bookmark_bar_node, &other_node, &mobile_node));
|
| - std::string content;
|
| - base::JSONWriter::WriteWithOptions(encoded_bookmarks.get(),
|
| - base::JSONWriter::OPTIONS_PRETTY_PRINT,
|
| - &content);
|
| -
|
| - return (file_util::WriteFile(path, content.c_str(),
|
| - static_cast<int>(content.length())) != -1);
|
| -}
|
| -
|
| -} // namespace history
|
|
|