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

Unified Diff: chrome/browser/importer/profile_writer.cc

Issue 6979007: Many fixes to bookmark importing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Happy tests =) Created 9 years, 7 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/browser/importer/profile_writer.h ('k') | chrome/browser/importer/safari_importer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/importer/profile_writer.cc
diff --git a/chrome/browser/importer/profile_writer.cc b/chrome/browser/importer/profile_writer.cc
index 6f3d222e5f043c2a0509c9b557a45cf6a32e5982..da6397683ce8ef3c37c5c4d9e37892e019f254e5 100644
--- a/chrome/browser/importer/profile_writer.cc
+++ b/chrome/browser/importer/profile_writer.cc
@@ -4,6 +4,9 @@
#include "chrome/browser/importer/profile_writer.h"
+#include <string>
+
+#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/threading/thread.h"
#include "base/utf_string_conversions.h"
@@ -16,6 +19,54 @@
#include "chrome/common/pref_names.h"
#include "content/common/notification_service.h"
+namespace {
+
+// Generates a unique folder name. If |folder_name| is not unique, then this
+// repeatedly tests for '|folder_name| + (i)' until a unique name is found.
+string16 GenerateUniqueFolderName(BookmarkModel* model,
+ const string16& folder_name) {
+ // Build a set containing the bookmark bar folder names.
+ std::set<string16> existing_folder_names;
+ const BookmarkNode* bookmark_bar = model->GetBookmarkBarNode();
+ for (int i = 0; i < bookmark_bar->child_count(); ++i) {
+ const BookmarkNode* node = bookmark_bar->GetChild(i);
+ if (node->is_folder())
+ existing_folder_names.insert(node->GetTitle());
+ }
+
+ // If the given name is unique, use it.
+ if (existing_folder_names.find(folder_name) == existing_folder_names.end())
+ return folder_name;
+
+ // Otherwise iterate until we find a unique name.
+ for (size_t i = 1; i <= existing_folder_names.size(); ++i) {
+ string16 name = folder_name + ASCIIToUTF16(" (") + base::IntToString16(i) +
+ ASCIIToUTF16(")");
+ if (existing_folder_names.find(name) == existing_folder_names.end())
+ return name;
+ }
+
+ NOTREACHED();
+ return folder_name;
+}
+
+// Shows the bookmarks toolbar.
+void ShowBookmarkBar(Profile* profile) {
+ PrefService* prefs = profile->GetPrefs();
+ // Check whether the bookmark bar is shown in current pref.
+ if (!prefs->GetBoolean(prefs::kShowBookmarkBar)) {
+ // Set the pref and notify the notification service.
+ prefs->SetBoolean(prefs::kShowBookmarkBar, true);
+ prefs->ScheduleSavePersistentPrefs();
+ Source<Profile> source(profile);
+ NotificationService::current()->Notify(
+ NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED, source,
+ NotificationService::NoDetails());
+ }
+}
+
+} // namespace
+
ProfileWriter::BookmarkEntry::BookmarkEntry()
: in_toolbar(false),
is_folder(false) {}
@@ -61,72 +112,89 @@ void ProfileWriter::AddHomepage(const GURL& home_page) {
}
void ProfileWriter::AddBookmarks(const std::vector<BookmarkEntry>& bookmarks,
- const string16& first_folder_name,
- int options) {
+ const string16& top_level_folder_name) {
if (bookmarks.empty())
return;
BookmarkModel* model = profile_->GetBookmarkModel();
DCHECK(model->IsLoaded());
- bool import_to_bookmark_bar = ((options & IMPORT_TO_BOOKMARK_BAR) != 0);
- string16 real_first_folder = import_to_bookmark_bar ? first_folder_name :
- GenerateUniqueFolderName(model, first_folder_name);
+ // If the bookmark bar is currently empty, we should import directly to it.
+ // Otherwise, we should import everything to a subfolder.
+ const BookmarkNode* bookmark_bar = model->GetBookmarkBarNode();
+ bool import_to_top_level = bookmark_bar->child_count() == 0;
- bool show_bookmark_toolbar = false;
- std::set<const BookmarkNode*> folders_added_to;
+ // If the user currently has no bookmarks in the bookmark bar, make sure that
+ // at least some of the imported bookmarks end up there. Otherwise, we'll end
+ // up with just a single folder containing the imported bookmarks, which makes
+ // for unnecessary nesting.
+ bool add_all_to_top_level = import_to_top_level;
+ for (std::vector<BookmarkEntry>::const_iterator it = bookmarks.begin();
+ it != bookmarks.end() && add_all_to_top_level; ++it) {
+ if (it->in_toolbar)
+ add_all_to_top_level = false;
+ }
model->BeginImportMode();
- for (std::vector<BookmarkEntry>::const_iterator it = bookmarks.begin();
- it != bookmarks.end(); ++it) {
- // Don't insert this url if it isn't valid.
- if (!it->is_folder && !it->url.is_valid())
+ std::set<const BookmarkNode*> folders_added_to;
+ const BookmarkNode* top_level_folder = NULL;
+ for (std::vector<BookmarkEntry>::const_iterator bookmark = bookmarks.begin();
+ bookmark != bookmarks.end(); ++bookmark) {
+ // Disregard any bookmarks with invalid urls.
+ if (!bookmark->is_folder && !bookmark->url.is_valid())
continue;
- // We suppose that bookmarks are unique by Title, URL, and Folder. Since
- // checking for uniqueness may not be always the user's intention we have
- // this as an option.
- if (options & ADD_IF_UNIQUE && DoesBookmarkExist(model, *it,
- real_first_folder, import_to_bookmark_bar))
- continue;
+ const BookmarkNode* parent = NULL;
+ if (import_to_top_level && (add_all_to_top_level || bookmark->in_toolbar)) {
+ // Add directly to the bookmarks bar.
+ parent = bookmark_bar;
+ } else {
+ // Add to a folder that will contain all the imported bookmarks not added
+ // to the bar. The first time we do so, create the folder.
+ if (!top_level_folder) {
+ string16 name = GenerateUniqueFolderName(model, top_level_folder_name);
+ top_level_folder = model->AddFolder(bookmark_bar,
+ bookmark_bar->child_count(),
+ name);
+ }
+ parent = top_level_folder;
+ }
- // Set up folders in BookmarkModel in such a way that path[i] is
- // the subfolder of path[i-1]. Finally they construct a path in the
- // model:
- // path[0] \ path[1] \ ... \ path[size() - 1]
- const BookmarkNode* parent =
- (it->in_toolbar ? model->GetBookmarkBarNode() : model->other_node());
- for (std::vector<string16>::const_iterator i = it->path.begin();
- i != it->path.end(); ++i) {
- const BookmarkNode* child = NULL;
- const string16& folder_name = (!import_to_bookmark_bar &&
- !it->in_toolbar && (i == it->path.begin())) ? real_first_folder : *i;
+ // Ensure any enclosing folders are present in the model. The bookmark's
+ // enclosing folder structure should be
+ // path[0] > path[1] > ... > path[size() - 1]
+ for (std::vector<string16>::const_iterator folder_name =
+ bookmark->path.begin();
+ folder_name != bookmark->path.end(); ++folder_name) {
+ if (bookmark->in_toolbar && parent == bookmark_bar &&
+ folder_name == bookmark->path.begin()) {
+ // If we're importing directly to the bookmarks bar, skip over the
+ // folder named "Bookmarks Toolbar" (or any non-Firefox equivalent).
+ continue;
+ }
+ const BookmarkNode* child = NULL;
for (int index = 0; index < parent->child_count(); ++index) {
const BookmarkNode* node = parent->GetChild(index);
- if (node->is_folder() && node->GetTitle() == folder_name) {
+ if (node->is_folder() && node->GetTitle() == *folder_name) {
child = node;
break;
}
}
if (!child)
- child = model->AddFolder(parent, parent->child_count(), folder_name);
+ child = model->AddFolder(parent, parent->child_count(), *folder_name);
parent = child;
}
folders_added_to.insert(parent);
- if (it->is_folder) {
- model->AddFolder(parent, parent->child_count(), it->title);
+ if (bookmark->is_folder) {
+ model->AddFolder(parent, parent->child_count(), bookmark->title);
} else {
model->AddURLWithCreationTime(parent, parent->child_count(),
- it->title, it->url, it->creation_time);
+ bookmark->title, bookmark->url,
+ bookmark->creation_time);
}
-
- // If some items are put into toolbar, it looks like the user was using
- // it in their last browser. We turn on the bookmarks toolbar.
- if (it->in_toolbar)
- show_bookmark_toolbar = true;
}
// In order to keep the imported-to folders from appearing in the 'recently
@@ -139,8 +207,9 @@ void ProfileWriter::AddBookmarks(const std::vector<BookmarkEntry>& bookmarks,
model->EndImportMode();
- if (show_bookmark_toolbar && !(options & BOOKMARK_BAR_DISABLED))
- ShowBookmarkBar();
+ // If the user was previously using a toolbar, we should show the bar.
+ if (import_to_top_level && !add_all_to_top_level)
+ ShowBookmarkBar(profile_);
}
void ProfileWriter::AddFavicons(
@@ -265,94 +334,4 @@ void ProfileWriter::AddKeywords(const std::vector<TemplateURL*>& template_urls,
}
}
-void ProfileWriter::ShowBookmarkBar() {
- DCHECK(profile_);
-
- PrefService* prefs = profile_->GetPrefs();
- // Check whether the bookmark bar is shown in current pref.
- if (!prefs->GetBoolean(prefs::kShowBookmarkBar)) {
- // Set the pref and notify the notification service.
- prefs->SetBoolean(prefs::kShowBookmarkBar, true);
- prefs->ScheduleSavePersistentPrefs();
- Source<Profile> source(profile_);
- NotificationService::current()->Notify(
- NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED, source,
- NotificationService::NoDetails());
- }
-}
-
ProfileWriter::~ProfileWriter() {}
-
-string16 ProfileWriter::GenerateUniqueFolderName(
- BookmarkModel* model,
- const string16& folder_name) {
- // Build a set containing the folder names of the other folder.
- std::set<string16> other_folder_names;
- const BookmarkNode* other = model->other_node();
-
- for (int i = 0, child_count = other->child_count(); i < child_count; ++i) {
- const BookmarkNode* node = other->GetChild(i);
- if (node->is_folder())
- other_folder_names.insert(node->GetTitle());
- }
-
- if (other_folder_names.find(folder_name) == other_folder_names.end())
- return folder_name; // Name is unique, use it.
-
- // Otherwise iterate until we find a unique name.
- for (int i = 1; i < 100; ++i) {
- string16 name = folder_name + UTF8ToUTF16(base::StringPrintf(" (%d)", i));
- if (other_folder_names.find(name) == other_folder_names.end())
- return name;
- }
-
- return folder_name;
-}
-
-bool ProfileWriter::DoesBookmarkExist(
- BookmarkModel* model,
- const BookmarkEntry& entry,
- const string16& first_folder_name,
- bool import_to_bookmark_bar) {
- std::vector<const BookmarkNode*> nodes_with_same_url;
- model->GetNodesByURL(entry.url, &nodes_with_same_url);
- if (nodes_with_same_url.empty())
- return false;
-
- for (size_t i = 0; i < nodes_with_same_url.size(); ++i) {
- const BookmarkNode* node = nodes_with_same_url[i];
- if (entry.title != node->GetTitle())
- continue;
-
- // Does the path match?
- bool found_match = true;
- const BookmarkNode* parent = node->parent();
- for (std::vector<string16>::const_reverse_iterator path_it =
- entry.path.rbegin();
- (path_it != entry.path.rend()) && found_match; ++path_it) {
- const string16& folder_name =
- (!import_to_bookmark_bar && path_it + 1 == entry.path.rend()) ?
- first_folder_name : *path_it;
- if (NULL == parent || *path_it != folder_name)
- found_match = false;
- else
- parent = parent->parent();
- }
-
- // We need a post test to differentiate checks such as
- // /home/hello and /hello. The parent should either by the other folder
- // node, or the bookmarks bar, depending upon import_to_bookmark_bar and
- // entry.in_toolbar.
- if (found_match &&
- ((import_to_bookmark_bar && entry.in_toolbar && parent !=
- model->GetBookmarkBarNode()) ||
- ((!import_to_bookmark_bar || !entry.in_toolbar) &&
- parent != model->other_node()))) {
- found_match = false;
- }
-
- if (found_match)
- return true; // Found a match with the same url path and title.
- }
- return false;
-}
« no previous file with comments | « chrome/browser/importer/profile_writer.h ('k') | chrome/browser/importer/safari_importer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698