diff options
author | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-07 04:31:35 +0000 |
---|---|---|
committer | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-07 04:31:35 +0000 |
commit | b504899244b4264994d4daae2bee660706dba652 (patch) | |
tree | eda190cb35dfff7f700a4c636730ff2487cb35d8 /chrome/browser/importer | |
parent | e562de106eeab2667eeb6922ddf2d771a0efa55d (diff) | |
download | chromium_src-b504899244b4264994d4daae2bee660706dba652.zip chromium_src-b504899244b4264994d4daae2bee660706dba652.tar.gz chromium_src-b504899244b4264994d4daae2bee660706dba652.tar.bz2 |
Adds import/export of bookmarks to bookmarks.html file.
BUG=1649
TEST=bring up bookmark manager and try out import/export from the
tools menu. Note that import ALWAYS creates a new folder under
the 'Other bookmarks folder' with the name of Imported (x). This
is by design.
Review URL: http://codereview.chromium.org/9471
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4968 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/importer')
-rw-r--r-- | chrome/browser/importer/firefox2_importer.cc | 96 | ||||
-rw-r--r-- | chrome/browser/importer/firefox2_importer.h | 16 | ||||
-rw-r--r-- | chrome/browser/importer/firefox3_importer.cc | 4 | ||||
-rw-r--r-- | chrome/browser/importer/ie_importer.cc | 5 | ||||
-rw-r--r-- | chrome/browser/importer/importer.cc | 134 | ||||
-rw-r--r-- | chrome/browser/importer/importer.h | 56 | ||||
-rw-r--r-- | chrome/browser/importer/importer_unittest.cc | 13 | ||||
-rw-r--r-- | chrome/browser/importer/toolbar_importer.cc | 8 |
8 files changed, 237 insertions, 95 deletions
diff --git a/chrome/browser/importer/firefox2_importer.cc b/chrome/browser/importer/firefox2_importer.cc index e85d347..aef2ba2 100644 --- a/chrome/browser/importer/firefox2_importer.cc +++ b/chrome/browser/importer/firefox2_importer.cc @@ -22,7 +22,7 @@ using base::Time; // Firefox2Importer. -Firefox2Importer::Firefox2Importer() { +Firefox2Importer::Firefox2Importer() : parsing_bookmarks_html_file_(false) { } Firefox2Importer::~Firefox2Importer() { @@ -37,6 +37,8 @@ void Firefox2Importer::StartImport(ProfileInfo profile_info, app_path_ = profile_info.app_path; importer_host_ = host; + parsing_bookmarks_html_file_ = (profile_info.browser_type == BOOKMARKS_HTML); + // The order here is important! NotifyStarted(); if ((items & HOME_PAGE) && !cancelled()) @@ -120,30 +122,29 @@ TemplateURL* Firefox2Importer::CreateTemplateURL(const std::wstring& title, return t_url; } -void Firefox2Importer::ImportBookmarks() { - // Read the whole file. - std::wstring file = source_path_; - file_util::AppendToPath(&file, L"bookmarks.html"); +// static +void Firefox2Importer::ImportBookmarksFile( + const std::wstring& file_path, + const std::set<GURL>& default_urls, + bool first_run, + const std::wstring& first_folder_name, + Importer* importer, + std::vector<ProfileWriter::BookmarkEntry>* bookmarks, + std::vector<TemplateURL*>* template_urls, + std::vector<history::ImportedFavIconUsage>* favicons) { std::string content; - file_util::ReadFileToString(file, &content); + file_util::ReadFileToString(file_path, &content); std::vector<std::string> lines; SplitString(content, '\n', &lines); - - // Load the default bookmarks. - std::set<GURL> default_urls; - LoadDefaultBookmarks(app_path_, &default_urls); - - // Parse the bookmarks.html file. - std::vector<ProfileWriter::BookmarkEntry> bookmarks, toolbar_bookmarks; - std::vector<TemplateURL*> template_urls; - std::vector<history::ImportedFavIconUsage> favicons; - std::wstring last_folder - = l10n_util::GetString(IDS_BOOKMARK_GROUP_FROM_FIREFOX); + + std::vector<ProfileWriter::BookmarkEntry> toolbar_bookmarks; + std::wstring last_folder = first_folder_name; bool last_folder_on_toolbar = false; std::vector<std::wstring> path; size_t toolbar_folder = 0; std::string charset; - for (size_t i = 0; i < lines.size() && !cancelled(); ++i) { + for (size_t i = 0; i < lines.size() && (!importer || !importer->cancelled()); + ++i) { std::string line; TrimString(lines[i], " ", &line); @@ -179,7 +180,7 @@ void Firefox2Importer::ImportBookmarks() { entry.url = url; entry.title = title; - if (first_run() && toolbar_folder) { + if (first_run && toolbar_folder) { // Flatten the items in toolbar. entry.in_toolbar = true; entry.path.assign(path.begin() + toolbar_folder, path.end()); @@ -188,20 +189,23 @@ void Firefox2Importer::ImportBookmarks() { // Insert the item into the "Imported from Firefox" folder after // the first run. entry.path.assign(path.begin(), path.end()); - if (first_run()) + if (first_run) entry.path.erase(entry.path.begin()); - bookmarks.push_back(entry); + bookmarks->push_back(entry); } // Save the favicon. DataURLToFaviconUsage will handle the case where // there is no favicon. - DataURLToFaviconUsage(url, favicon, &favicons); - - // If there is a SHORTCUT attribute for this bookmark, we - // add it as our keywords. - TemplateURL* t_url = CreateTemplateURL(title, shortcut, url); - if (t_url) - template_urls.push_back(t_url); + if (favicons) + DataURLToFaviconUsage(url, favicon, favicons); + + if (template_urls) { + // If there is a SHORTCUT attribute for this bookmark, we + // add it as our keywords. + TemplateURL* t_url = CreateTemplateURL(title, shortcut, url); + if (t_url) + template_urls->push_back(t_url); + } continue; } @@ -221,14 +225,42 @@ void Firefox2Importer::ImportBookmarks() { } } + bookmarks->insert(bookmarks->begin(), toolbar_bookmarks.begin(), + toolbar_bookmarks.end()); +} + +void Firefox2Importer::ImportBookmarks() { + // Load the default bookmarks. + std::set<GURL> default_urls; + if (!parsing_bookmarks_html_file_) + LoadDefaultBookmarks(app_path_, &default_urls); + + // Parse the bookmarks.html file. + std::vector<ProfileWriter::BookmarkEntry> bookmarks, toolbar_bookmarks; + std::vector<TemplateURL*> template_urls; + std::vector<history::ImportedFavIconUsage> favicons; + std::wstring file = source_path_; + if (!parsing_bookmarks_html_file_) + file_util::AppendToPath(&file, L"bookmarks.html"); + std::wstring first_folder_name; + if (parsing_bookmarks_html_file_) + first_folder_name = l10n_util::GetString(IDS_BOOKMARK_GROUP); + else + first_folder_name = l10n_util::GetString(IDS_BOOKMARK_GROUP_FROM_FIREFOX); + + ImportBookmarksFile(file, default_urls, first_run(), + first_folder_name, this, &bookmarks, &template_urls, + &favicons); + // Write data into profile. - bookmarks.insert(bookmarks.begin(), toolbar_bookmarks.begin(), - toolbar_bookmarks.end()); if (!bookmarks.empty() && !cancelled()) { main_loop_->PostTask(FROM_HERE, NewRunnableMethod(writer_, - &ProfileWriter::AddBookmarkEntry, bookmarks, false)); + &ProfileWriter::AddBookmarkEntry, bookmarks, + first_folder_name, + first_run() ? ProfileWriter::FIRST_RUN : 0)); } - if (!template_urls.empty() && !cancelled()) { + if (!parsing_bookmarks_html_file_ && !template_urls.empty() && + !cancelled()) { main_loop_->PostTask(FROM_HERE, NewRunnableMethod(writer_, &ProfileWriter::AddKeywords, template_urls, -1, false)); } else { diff --git a/chrome/browser/importer/firefox2_importer.h b/chrome/browser/importer/firefox2_importer.h index f14438d..eb02cb7 100644 --- a/chrome/browser/importer/firefox2_importer.h +++ b/chrome/browser/importer/firefox2_importer.h @@ -33,6 +33,19 @@ class Firefox2Importer : public Importer { const std::wstring& keyword, const GURL& url); + // Imports the bookmarks from the specified file. |template_urls| and + // |favicons| may be null, in which case TemplateURLs and favicons are + // not parsed. Any bookmarks in |default_urls| are ignored. + static void ImportBookmarksFile( + const std::wstring& file_path, + const std::set<GURL>& default_urls, + bool first_run, + const std::wstring& first_folder_name, + Importer* importer, + std::vector<ProfileWriter::BookmarkEntry>* bookmarks, + std::vector<TemplateURL*>* template_urls, + std::vector<history::ImportedFavIconUsage>* favicons); + private: FRIEND_TEST(FirefoxImporterTest, Firefox2BookmarkParse); FRIEND_TEST(FirefoxImporterTest, Firefox2CookesParse); @@ -105,9 +118,10 @@ class Firefox2Importer : public Importer { ProfileWriter* writer_; std::wstring source_path_; std::wstring app_path_; + // If true, we only parse the bookmarks.html file specified as source_path_. + bool parsing_bookmarks_html_file_; DISALLOW_EVIL_CONSTRUCTORS(Firefox2Importer); }; #endif // CHROME_BROWSER_IMPORTER_FIREFOX2_IMPORTER_H_ - diff --git a/chrome/browser/importer/firefox3_importer.cc b/chrome/browser/importer/firefox3_importer.cc index 965ba15..ea470d5 100644 --- a/chrome/browser/importer/firefox3_importer.cc +++ b/chrome/browser/importer/firefox3_importer.cc @@ -247,7 +247,9 @@ void Firefox3Importer::ImportBookmarks() { // Write into profile. if (!bookmarks.empty() && !cancelled()) { main_loop_->PostTask(FROM_HERE, NewRunnableMethod(writer_, - &ProfileWriter::AddBookmarkEntry, bookmarks, false)); + &ProfileWriter::AddBookmarkEntry, bookmarks, + l10n_util::GetString(IDS_BOOKMARK_GROUP_FROM_FIREFOX), + first_run() ? ProfileWriter::FIRST_RUN : 0)); } if (!template_urls.empty() && !cancelled()) { main_loop_->PostTask(FROM_HERE, NewRunnableMethod(writer_, diff --git a/chrome/browser/importer/ie_importer.cc b/chrome/browser/importer/ie_importer.cc index c952603..2e5d919 100644 --- a/chrome/browser/importer/ie_importer.cc +++ b/chrome/browser/importer/ie_importer.cc @@ -109,7 +109,9 @@ void IEImporter::ImportFavorites() { if (!bookmarks.empty() && !cancelled()) { main_loop_->PostTask(FROM_HERE, NewRunnableMethod(writer_, - &ProfileWriter::AddBookmarkEntry, bookmarks, false)); + &ProfileWriter::AddBookmarkEntry, bookmarks, + l10n_util::GetString(IDS_BOOKMARK_GROUP_FROM_IE), + first_run() ? ProfileWriter::FIRST_RUN : 0)); } } @@ -552,4 +554,3 @@ int IEImporter::CurrentIEVersion() const { } return version; } - diff --git a/chrome/browser/importer/importer.cc b/chrome/browser/importer/importer.cc index 16552e3..3ce8996 100644 --- a/chrome/browser/importer/importer.cc +++ b/chrome/browser/importer/importer.cc @@ -5,6 +5,7 @@ #include "chrome/browser/importer/importer.h" #include <map> +#include <set> #include "base/file_util.h" #include "base/gfx/image_operations.h" @@ -81,10 +82,15 @@ void ProfileWriter::AddHomepage(const GURL& home_page) { void ProfileWriter::AddBookmarkEntry( const std::vector<BookmarkEntry>& bookmark, - bool check_uniqueness) { + const std::wstring& first_folder_name, + int options) { BookmarkModel* model = profile_->GetBookmarkModel(); DCHECK(model->IsLoaded()); + bool first_run = (options & FIRST_RUN) != 0; + std::wstring real_first_folder = first_run ? first_folder_name : + GenerateUniqueFolderName(model, first_folder_name); + bool show_bookmark_toolbar = false; std::set<BookmarkNode*> groups_added_to; for (std::vector<BookmarkEntry>::const_iterator it = bookmark.begin(); @@ -92,49 +98,13 @@ void ProfileWriter::AddBookmarkEntry( // Don't insert this url if it isn't valid. if (!it->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 (check_uniqueness) { - std::vector<BookmarkModel::TitleMatch> matches; - model->GetBookmarksMatchingText((*it).title, 32, &matches); // 32 enough? - if (!matches.empty()) { - bool found_match = false; - for (std::vector<BookmarkModel::TitleMatch>::iterator match_it = - matches.begin(); - match_it != matches.end() && !found_match; - ++match_it) { - if ((*it).title != (*match_it).node->GetTitle()) - continue; - if ((*it).url != (*match_it).node->GetURL()) - continue; - - // Check the folder path for uniqueness as well - found_match = true; - BookmarkNode* node = (*match_it).node->GetParent(); - for(std::vector<std::wstring>::const_reverse_iterator path_it = - (*it).path.rbegin(); - (path_it != (*it).path.rend()) && found_match; - ++path_it) { - if (NULL == node || (*path_it != node->GetTitle())) - found_match = false; - if (found_match) - node = node->GetParent(); - } - - // We need a post test to differentiate checks such as - // /home/hello and /hello. Note that here the current parent - // should be the "Other bookmarks" node, its parent should be the - // root with title "", and it's parent is finally NULL. - if (NULL == node->GetParent() || - NULL != node->GetParent()->GetParent()) - found_match = false; - } - - if (found_match) - continue; - } + if (options & ADD_IF_UNIQUE && + DoesBookmarkExist(model, *it, real_first_folder, first_run)) { + continue; } // Set up groups in BookmarkModel in such a way that path[i] is @@ -146,17 +116,21 @@ void ProfileWriter::AddBookmarkEntry( for (std::vector<std::wstring>::const_iterator i = it->path.begin(); i != it->path.end(); ++i) { BookmarkNode* child = NULL; + const std::wstring& folder_name = + (!first_run && !it->in_toolbar && (i == it->path.begin())) ? + real_first_folder : *i; + for (int index = 0; index < parent->GetChildCount(); ++index) { BookmarkNode* node = parent->GetChild(index); if ((node->GetType() == history::StarredEntry::BOOKMARK_BAR || node->GetType() == history::StarredEntry::USER_GROUP) && - node->GetTitle() == *i) { + node->GetTitle() == folder_name) { child = node; break; } } if (child == NULL) - child = model->AddGroup(parent, parent->GetChildCount(), *i); + child = model->AddGroup(parent, parent->GetChildCount(), folder_name); parent = child; } groups_added_to.insert(parent); @@ -321,6 +295,79 @@ void ProfileWriter::ShowBookmarkBar() { } } +std::wstring ProfileWriter::GenerateUniqueFolderName( + BookmarkModel* model, + const std::wstring& folder_name) { + // Build a set containing the folder names of the other folder. + std::set<std::wstring> other_folder_names; + BookmarkNode* other = model->other_node(); + for (int i = 0; i < other->GetChildCount(); ++i) { + 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) { + std::wstring name = folder_name + StringPrintf(L" (%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 std::wstring& first_folder_name, + bool first_run) { + std::vector<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) { + BookmarkNode* node = nodes_with_same_url[i]; + if (entry.title != node->GetTitle()) + continue; + + // Does the path match? + bool found_match = true; + BookmarkNode* parent = node->GetParent(); + for (std::vector<std::wstring>::const_reverse_iterator path_it = + entry.path.rbegin(); + (path_it != entry.path.rend()) && found_match; ++path_it) { + const std::wstring& folder_name = + (!first_run && path_it + 1 == entry.path.rend()) ? + first_folder_name : *path_it; + if (NULL == parent || *path_it != folder_name) + found_match = false; + else + parent = parent->GetParent(); + } + + // 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 first_run and + // entry.in_toolbar. + if (found_match && + ((first_run && entry.in_toolbar && parent != + model->GetBookmarkBarNode()) || + ((!first_run || !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; +} + // Importer. // static @@ -539,6 +586,7 @@ Importer* ImporterHost::CreateImporterByType(ProfileType type) { switch (type) { case MS_IE: return new IEImporter(); + case BOOKMARKS_HTML: case FIREFOX2: return new Firefox2Importer(); case FIREFOX3: diff --git a/chrome/browser/importer/importer.h b/chrome/browser/importer/importer.h index a597879..4e57b64 100644 --- a/chrome/browser/importer/importer.h +++ b/chrome/browser/importer/importer.h @@ -27,7 +27,9 @@ enum ProfileType { MS_IE = 0, FIREFOX2, FIREFOX3, - GOOGLE_TOOLBAR5 + GOOGLE_TOOLBAR5, + // Identifies a 'bookmarks.html' file. + BOOKMARKS_HTML }; // An enumeration of the type of data we want to import. @@ -57,6 +59,18 @@ class Importer; // This object must be invoked on UI thread. class ProfileWriter : public base::RefCounted<ProfileWriter> { public: + // Used to identify how the bookmarks are added. + enum BookmarkOptions { + // Indicates the bookmark should only be added if unique. Uniqueness + // is done by title, url and path. That is, if this is passed to + // AddBookmarkEntry the bookmark is added only if there is no other + // URL with the same url, path and title. + ADD_IF_UNIQUE = 1 << 0, + + // Indicates the bookmarks are being added during first run. + FIRST_RUN = 1 << 1 + }; + explicit ProfileWriter(Profile* profile) : profile_(profile) { } virtual ~ProfileWriter() { } @@ -86,9 +100,21 @@ class ProfileWriter : public base::RefCounted<ProfileWriter> { virtual void AddIE7PasswordInfo(const IE7PasswordInfo& info); virtual void AddHistoryPage(const std::vector<history::URLRow>& page); virtual void AddHomepage(const GURL& homepage); - virtual void AddBookmarkEntry( - const std::vector<BookmarkEntry>& bookmark, - bool check_uniqueness); + // Adds the bookmarks to the BookmarkModel. + // |options| is a bitmask of BookmarkOptions and dictates how and + // which bookmarks are added. If the bitmask contains FIRST_RUN, + // then any entries with a value of true for in_toolbar are added to + // the bookmark bar. If the bitmask does not contain FIRST_RUN then + // the folder name the bookmarks are added to is uniqued based on + // |first_folder_name|. For example, if |first_folder_name| is 'foo' + // and a folder with the name 'foo' already exists in the other + // bookmarks folder, then the folder name 'foo 2' is used. + // If |options| contains ADD_IF_UNIQUE, then the bookmark is added only + // if another bookmarks does not exist with the same title, path and + // url. + virtual void AddBookmarkEntry(const std::vector<BookmarkEntry>& bookmark, + const std::wstring& first_folder_name, + int options); virtual void AddFavicons( const std::vector<history::ImportedFavIconUsage>& favicons); // Add the TemplateURLs in |template_urls| to the local store and make the @@ -111,6 +137,19 @@ class ProfileWriter : public base::RefCounted<ProfileWriter> { Profile* GetProfile() const { return profile_; } private: + // 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. + std::wstring GenerateUniqueFolderName(BookmarkModel* model, + const std::wstring& folder_name); + + // Returns true if a bookmark exists with the same url, title and path + // as |entry|. |first_folder_name| is the name to use for the first + // path entry if |first_run| is true. + bool DoesBookmarkExist(BookmarkModel* model, + const BookmarkEntry& entry, + const std::wstring& first_folder_name, + bool first_run); + Profile* profile_; DISALLOW_EVIL_CONSTRUCTORS(ProfileWriter); @@ -290,12 +329,15 @@ class Importer : public base::RefCounted<Importer> { void set_first_run(bool first_run) { first_run_ = first_run; } + bool cancelled() const { return cancelled_; } + protected: Importer() : main_loop_(MessageLoop::current()), delagate_loop_(NULL), importer_host_(NULL), - cancelled_(false) {} + cancelled_(false), + first_run_(false) {} // Notifies the coordinator that the collection of data for the specified // item has begun. @@ -329,8 +371,6 @@ class Importer : public base::RefCounted<Importer> { static bool ReencodeFavicon(const unsigned char* src_data, size_t src_len, std::vector<unsigned char>* png_data); - bool cancelled() const { return cancelled_; } - bool first_run() const { return first_run_; } // The importer should know the main thread so that ProfileWriter @@ -359,6 +399,7 @@ class ImportObserver { public: virtual ~ImportObserver() {} // The import operation was canceled by the user. + // TODO (4164): this is never invoked, either rip it out or invoke it. virtual void ImportCanceled() = 0; // The import operation was completed successfully. @@ -380,4 +421,3 @@ void StartImportingWithUI(HWND parent_window, bool first_run); #endif // CHROME_BROWSER_IMPORTER_IMPORTER_H_ - diff --git a/chrome/browser/importer/importer_unittest.cc b/chrome/browser/importer/importer_unittest.cc index f75aa4f..a6094fc 100644 --- a/chrome/browser/importer/importer_unittest.cc +++ b/chrome/browser/importer/importer_unittest.cc @@ -189,9 +189,9 @@ class TestObserver : public ProfileWriter, ++history_count_; } - virtual void AddBookmarkEntry( - const std::vector<BookmarkEntry>& bookmark, - bool check_duplicates) { + virtual void AddBookmarkEntry(const std::vector<BookmarkEntry>& bookmark, + const std::wstring& first_folder_name, + int options) { // Importer should import the IE Favorites folder the same as the list. for (size_t i = 0; i < bookmark.size(); ++i) { if (FindBookmarkEntry(bookmark[i], kIEBookmarks, @@ -545,7 +545,8 @@ class FirefoxObserver : public ProfileWriter, } virtual void AddBookmarkEntry(const std::vector<BookmarkEntry>& bookmark, - bool check_duplicates) { + const std::wstring& first_folder_name, + int options) { for (size_t i = 0; i < bookmark.size(); ++i) { if (FindBookmarkEntry(bookmark[i], kFirefox2Bookmarks, arraysize(kFirefox2Bookmarks))) @@ -745,7 +746,8 @@ class Firefox3Observer : public ProfileWriter, } virtual void AddBookmarkEntry(const std::vector<BookmarkEntry>& bookmark, - bool check_duplicates) { + const std::wstring& first_folder_name, + int options) { for (size_t i = 0; i < bookmark.size(); ++i) { if (FindBookmarkEntry(bookmark[i], kFirefox3Bookmarks, arraysize(kFirefox3Bookmarks))) @@ -829,4 +831,3 @@ TEST_F(ImporterTest, Firefox3Importer) { HISTORY | PASSWORDS | FAVORITES | SEARCH_ENGINES, observer, true)); loop->Run(); } - diff --git a/chrome/browser/importer/toolbar_importer.cc b/chrome/browser/importer/toolbar_importer.cc index 8813807..e96435f 100644 --- a/chrome/browser/importer/toolbar_importer.cc +++ b/chrome/browser/importer/toolbar_importer.cc @@ -568,7 +568,11 @@ bool Toolbar5Importer::ExtractFoldersFromXmlReader( void Toolbar5Importer::AddBookMarksToChrome( const std::vector<ProfileWriter::BookmarkEntry>& bookmarks) { if (!bookmarks.empty() && !cancelled()) { - main_loop_->PostTask(FROM_HERE, NewRunnableMethod(writer_, - &ProfileWriter::AddBookmarkEntry, bookmarks, true)); + int options = ProfileWriter::ADD_IF_UNIQUE | + (first_run() ? ProfileWriter::FIRST_RUN : 0); + main_loop_->PostTask(FROM_HERE, NewRunnableMethod(writer_, + &ProfileWriter::AddBookmarkEntry, bookmarks, + l10n_util::GetString(IDS_BOOKMARK_GROUP_FROM_GOOGLE_TOOLBAR), + options)); } } |