| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/utility/importer/firefox_importer.h" | 5 #include "chrome/utility/importer/firefox_importer.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/files/file_enumerator.h" | 10 #include "base/files/file_enumerator.h" |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/json/json_file_value_serializer.h" | 12 #include "base/json/json_file_value_serializer.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 18 #include "build/build_config.h" | 18 #include "build/build_config.h" |
| 19 #include "chrome/common/importer/firefox_importer_utils.h" | 19 #include "chrome/common/importer/firefox_importer_utils.h" |
| 20 #include "chrome/common/importer/imported_bookmark_entry.h" | 20 #include "chrome/common/importer/imported_bookmark_entry.h" |
| 21 #include "chrome/common/importer/importer_autofill_form_data_entry.h" | 21 #include "chrome/common/importer/importer_autofill_form_data_entry.h" |
| 22 #include "chrome/common/importer/importer_bridge.h" | 22 #include "chrome/common/importer/importer_bridge.h" |
| 23 #include "chrome/common/importer/importer_url_row.h" | 23 #include "chrome/common/importer/importer_url_row.h" |
| 24 #include "chrome/grit/generated_resources.h" | 24 #include "chrome/grit/generated_resources.h" |
| 25 #include "chrome/utility/importer/bookmark_html_reader.h" | 25 #include "chrome/utility/importer/bookmark_html_reader.h" |
| 26 #include "chrome/utility/importer/favicon_reencode.h" | 26 #include "chrome/utility/importer/firefox_places_factory.h" |
| 27 #include "chrome/utility/importer/nss_decryptor.h" | 27 #include "chrome/utility/importer/nss_decryptor.h" |
| 28 #include "components/autofill/core/common/password_form.h" | 28 #include "components/autofill/core/common/password_form.h" |
| 29 #include "sql/connection.h" | 29 #include "sql/connection.h" |
| 30 #include "sql/statement.h" | 30 #include "sql/statement.h" |
| 31 #include "url/gurl.h" | 31 #include "url/gurl.h" |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 // Original definition is in http://mxr.mozilla.org/firefox/source/toolkit/ | |
| 36 // components/places/public/nsINavBookmarksService.idl | |
| 37 enum BookmarkItemType { | |
| 38 TYPE_BOOKMARK = 1, | |
| 39 TYPE_FOLDER = 2, | |
| 40 TYPE_SEPARATOR = 3, | |
| 41 TYPE_DYNAMIC_CONTAINER = 4 | |
| 42 }; | |
| 43 | |
| 44 // Loads the default bookmarks in the Firefox installed at |app_path|, | 35 // Loads the default bookmarks in the Firefox installed at |app_path|, |
| 45 // and stores their locations in |urls|. | 36 // and stores their locations in |urls|. |
| 46 void LoadDefaultBookmarks(const base::FilePath& app_path, | 37 void LoadDefaultBookmarks(const base::FilePath& app_path, |
| 47 std::set<GURL>* urls) { | 38 std::set<GURL>* urls) { |
| 48 base::FilePath file = app_path.AppendASCII("defaults") | 39 base::FilePath file = app_path.AppendASCII("defaults") |
| 49 .AppendASCII("profile") | 40 .AppendASCII("profile") |
| 50 .AppendASCII("bookmarks.html"); | 41 .AppendASCII("bookmarks.html"); |
| 51 urls->clear(); | 42 urls->clear(); |
| 52 | 43 |
| 53 std::vector<ImportedBookmarkEntry> bookmarks; | 44 std::vector<ImportedBookmarkEntry> bookmarks; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 74 for (size_t i = 0; i < arraysize(kInvalidSchemes); ++i) { | 65 for (size_t i = 0; i < arraysize(kInvalidSchemes); ++i) { |
| 75 if (url.SchemeIs(kInvalidSchemes[i])) | 66 if (url.SchemeIs(kInvalidSchemes[i])) |
| 76 return false; | 67 return false; |
| 77 } | 68 } |
| 78 | 69 |
| 79 return true; | 70 return true; |
| 80 } | 71 } |
| 81 | 72 |
| 82 } // namespace | 73 } // namespace |
| 83 | 74 |
| 84 struct FirefoxImporter::BookmarkItem { | |
| 85 int parent; | |
| 86 int id; | |
| 87 GURL url; | |
| 88 base::string16 title; | |
| 89 BookmarkItemType type; | |
| 90 std::string keyword; | |
| 91 base::Time date_added; | |
| 92 int64_t favicon; | |
| 93 bool empty_folder; | |
| 94 }; | |
| 95 | |
| 96 FirefoxImporter::FirefoxImporter() { | 75 FirefoxImporter::FirefoxImporter() { |
| 97 } | 76 } |
| 98 | 77 |
| 99 FirefoxImporter::~FirefoxImporter() { | 78 FirefoxImporter::~FirefoxImporter() { |
| 100 } | 79 } |
| 101 | 80 |
| 102 void FirefoxImporter::StartImport(const importer::SourceProfile& source_profile, | 81 void FirefoxImporter::StartImport(const importer::SourceProfile& source_profile, |
| 103 uint16_t items, | 82 uint16_t items, |
| 104 ImporterBridge* bridge) { | 83 ImporterBridge* bridge) { |
| 105 bridge_ = bridge; | 84 bridge_ = bridge; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 } | 123 } |
| 145 if ((items & importer::AUTOFILL_FORM_DATA) && !cancelled()) { | 124 if ((items & importer::AUTOFILL_FORM_DATA) && !cancelled()) { |
| 146 bridge_->NotifyItemStarted(importer::AUTOFILL_FORM_DATA); | 125 bridge_->NotifyItemStarted(importer::AUTOFILL_FORM_DATA); |
| 147 ImportAutofillFormData(); | 126 ImportAutofillFormData(); |
| 148 bridge_->NotifyItemEnded(importer::AUTOFILL_FORM_DATA); | 127 bridge_->NotifyItemEnded(importer::AUTOFILL_FORM_DATA); |
| 149 } | 128 } |
| 150 bridge_->NotifyEnded(); | 129 bridge_->NotifyEnded(); |
| 151 } | 130 } |
| 152 | 131 |
| 153 void FirefoxImporter::ImportHistory() { | 132 void FirefoxImporter::ImportHistory() { |
| 154 base::FilePath file = source_path_.AppendASCII("places.sqlite"); | 133 auto places = FirefoxPlacesFactory::GetForProfile(source_path_); |
| 155 if (!base::PathExists(file)) | 134 if (!places) |
| 156 return; | 135 return; |
| 157 | 136 |
| 158 sql::Connection db; | |
| 159 if (!db.Open(file)) | |
| 160 return; | |
| 161 | |
| 162 // |visit_type| represent the transition type of URLs (typed, click, | |
| 163 // redirect, bookmark, etc.) We eliminate some URLs like sub-frames and | |
| 164 // redirects, since we don't want them to appear in history. | |
| 165 // Firefox transition types are defined in: | |
| 166 // toolkit/components/places/public/nsINavHistoryService.idl | |
| 167 const char query[] = | |
| 168 "SELECT h.url, h.title, h.visit_count, " | |
| 169 "h.hidden, h.typed, v.visit_date " | |
| 170 "FROM moz_places h JOIN moz_historyvisits v " | |
| 171 "ON h.id = v.place_id " | |
| 172 "WHERE v.visit_type <= 3"; | |
| 173 | |
| 174 sql::Statement s(db.GetUniqueStatement(query)); | |
| 175 | |
| 176 std::vector<ImporterURLRow> rows; | 137 std::vector<ImporterURLRow> rows; |
| 177 while (s.Step() && !cancelled()) { | 138 places->LoadHistory(&rows); |
| 178 GURL url(s.ColumnString(0)); | 139 rows.erase(begin(rows), |
| 179 | 140 std::remove_if(begin(rows), end(rows), [](const ImporterURLRow& row
) { |
| 180 // Filter out unwanted URLs. | 141 return CanImportURL(row.url); |
| 181 if (!CanImportURL(url)) | 142 })); |
| 182 continue; | |
| 183 | |
| 184 ImporterURLRow row(url); | |
| 185 row.title = s.ColumnString16(1); | |
| 186 row.visit_count = s.ColumnInt(2); | |
| 187 row.hidden = s.ColumnInt(3) == 1; | |
| 188 row.typed_count = s.ColumnInt(4); | |
| 189 row.last_visit = base::Time::FromTimeT(s.ColumnInt64(5)/1000000); | |
| 190 | |
| 191 rows.push_back(row); | |
| 192 } | |
| 193 | |
| 194 if (!rows.empty() && !cancelled()) | 143 if (!rows.empty() && !cancelled()) |
| 195 bridge_->SetHistoryItems(rows, importer::VISIT_SOURCE_FIREFOX_IMPORTED); | 144 bridge_->SetHistoryItems(rows, importer::VISIT_SOURCE_FIREFOX_IMPORTED); |
| 196 } | 145 } |
| 197 | 146 |
| 198 void FirefoxImporter::ImportBookmarks() { | 147 void FirefoxImporter::ImportBookmarks() { |
| 199 base::FilePath file = source_path_.AppendASCII("places.sqlite"); | 148 auto places = FirefoxPlacesFactory::GetForProfile(source_path_); |
| 200 if (!base::PathExists(file)) | 149 if (!places) |
| 150 return; |
| 151 BookmarkList list; |
| 152 if (!places->LoadBookmarks(&list)) |
| 153 return; |
| 154 // TODO(jcampan): http://b/issue?id=1196285 we do not support POST based |
| 155 // keywords yet. We won't include them in the list. |
| 156 PostKeywordIds post_keyword_ids; |
| 157 if (!places->LoadPostKeywordIds(&post_keyword_ids)) |
| 201 return; | 158 return; |
| 202 | 159 |
| 203 sql::Connection db; | 160 // Load livemark IDs. |
| 204 if (!db.Open(file)) | 161 LivemarkIds livemark_ids; |
| 162 if (!places->LoadLivemarkIds(&livemark_ids)) |
| 205 return; | 163 return; |
| 206 | 164 |
| 207 // Get the bookmark folders that we are interested in. | |
| 208 int toolbar_folder_id = -1; | |
| 209 int menu_folder_id = -1; | |
| 210 int unsorted_folder_id = -1; | |
| 211 LoadRootNodeID(&db, &toolbar_folder_id, &menu_folder_id, &unsorted_folder_id); | |
| 212 | |
| 213 // Load livemark IDs. | |
| 214 std::set<int> livemark_id; | |
| 215 LoadLivemarkIDs(&db, &livemark_id); | |
| 216 | |
| 217 // Load the default bookmarks. | 165 // Load the default bookmarks. |
| 218 std::set<GURL> default_urls; | 166 std::set<GURL> default_urls; |
| 219 LoadDefaultBookmarks(app_path_, &default_urls); | 167 LoadDefaultBookmarks(app_path_, &default_urls); |
| 220 | 168 |
| 221 BookmarkList list; | 169 auto toolbar_folder_id = places->GetFolderId(FirefoxPlaces::FolderType::TOOLBA
R); |
| 222 GetTopBookmarkFolder(&db, toolbar_folder_id, &list); | 170 auto menu_folder_id = places->GetFolderId(FirefoxPlaces::FolderType::MENU); |
| 223 GetTopBookmarkFolder(&db, menu_folder_id, &list); | 171 auto unsorted_folder_id = places->GetFolderId(FirefoxPlaces::FolderType::UNSOR
TED); |
| 224 GetTopBookmarkFolder(&db, unsorted_folder_id, &list); | |
| 225 size_t count = list.size(); | |
| 226 for (size_t i = 0; i < count; ++i) | |
| 227 GetWholeBookmarkFolder(&db, &list, i, NULL); | |
| 228 | 172 |
| 229 std::vector<ImportedBookmarkEntry> bookmarks; | 173 std::vector<ImportedBookmarkEntry> bookmarks; |
| 230 std::vector<importer::SearchEngineInfo> search_engines; | 174 std::vector<importer::SearchEngineInfo> search_engines; |
| 231 FaviconMap favicon_map; | 175 FaviconMap favicon_map; |
| 232 | 176 |
| 233 // TODO(jcampan): http://b/issue?id=1196285 we do not support POST based | |
| 234 // keywords yet. We won't include them in the list. | |
| 235 std::set<int> post_keyword_ids; | |
| 236 const char query[] = | |
| 237 "SELECT b.id FROM moz_bookmarks b " | |
| 238 "INNER JOIN moz_items_annos ia ON ia.item_id = b.id " | |
| 239 "INNER JOIN moz_anno_attributes aa ON ia.anno_attribute_id = aa.id " | |
| 240 "WHERE aa.name = 'bookmarkProperties/POSTData'"; | |
| 241 sql::Statement s(db.GetUniqueStatement(query)); | |
| 242 | |
| 243 if (!s.is_valid()) | |
| 244 return; | |
| 245 | |
| 246 while (s.Step() && !cancelled()) | |
| 247 post_keyword_ids.insert(s.ColumnInt(0)); | |
| 248 | |
| 249 for (size_t i = 0; i < list.size(); ++i) { | 177 for (size_t i = 0; i < list.size(); ++i) { |
| 250 BookmarkItem* item = list[i]; | 178 BookmarkItem* item = list[i]; |
| 251 | |
| 252 // Folders are added implicitly on adding children, so we only explicitly | 179 // Folders are added implicitly on adding children, so we only explicitly |
| 253 // add empty folders. | 180 // add empty folders. |
| 254 if (item->type != TYPE_BOOKMARK && | 181 if (item->type != TYPE_BOOKMARK && |
| 255 ((item->type != TYPE_FOLDER) || !item->empty_folder)) | 182 ((item->type != TYPE_FOLDER) || !item->empty_folder)) |
| 256 continue; | 183 continue; |
| 257 | 184 |
| 258 if (CanImportURL(item->url)) { | 185 if (CanImportURL(item->url)) { |
| 259 // Skip the default bookmarks and unwanted URLs. | 186 // Skip the default bookmarks and unwanted URLs. |
| 260 if (default_urls.find(item->url) != default_urls.end() || | 187 if (default_urls.find(item->url) != default_urls.end() || |
| 261 post_keyword_ids.find(item->id) != post_keyword_ids.end()) | 188 post_keyword_ids.find(item->id) != post_keyword_ids.end()) |
| 262 continue; | 189 continue; |
| 263 | 190 |
| 264 // Find the bookmark path by tracing their links to parent folders. | 191 // Find the bookmark path by tracing their links to parent folders. |
| 265 std::vector<base::string16> path; | 192 std::vector<base::string16> path; |
| 266 BookmarkItem* child = item; | 193 BookmarkItem* child = item; |
| 267 bool found_path = false; | 194 bool found_path = false; |
| 268 bool is_in_toolbar = false; | 195 bool is_in_toolbar = false; |
| 269 while (child->parent >= 0) { | 196 while (child->parent >= 0) { |
| 270 BookmarkItem* parent = list[child->parent]; | 197 BookmarkItem* parent = list[child->parent]; |
| 271 if (livemark_id.find(parent->id) != livemark_id.end()) { | 198 if (livemark_ids.find(parent->id) != livemark_ids.end()) { |
| 272 // Don't import live bookmarks. | 199 // Don't import live bookmarks. |
| 273 break; | 200 break; |
| 274 } | 201 } |
| 275 | 202 |
| 276 if (parent->id != menu_folder_id) { | 203 if (parent->id != menu_folder_id) { |
| 277 // To avoid excessive nesting, omit the name for the bookmarks menu | 204 // To avoid excessive nesting, omit the name for the bookmarks menu |
| 278 // folder. | 205 // folder. |
| 279 path.insert(path.begin(), parent->title); | 206 path.insert(path.begin(), parent->title); |
| 280 } | 207 } |
| 281 | 208 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 if (!bookmarks.empty() && !cancelled()) { | 266 if (!bookmarks.empty() && !cancelled()) { |
| 340 const base::string16& first_folder_name = | 267 const base::string16& first_folder_name = |
| 341 bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_FIREFOX); | 268 bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_FIREFOX); |
| 342 bridge_->AddBookmarks(bookmarks, first_folder_name); | 269 bridge_->AddBookmarks(bookmarks, first_folder_name); |
| 343 } | 270 } |
| 344 if (!search_engines.empty() && !cancelled()) { | 271 if (!search_engines.empty() && !cancelled()) { |
| 345 bridge_->SetKeywords(search_engines, false); | 272 bridge_->SetKeywords(search_engines, false); |
| 346 } | 273 } |
| 347 if (!favicon_map.empty() && !cancelled()) { | 274 if (!favicon_map.empty() && !cancelled()) { |
| 348 favicon_base::FaviconUsageDataList favicons; | 275 favicon_base::FaviconUsageDataList favicons; |
| 349 LoadFavicons(&db, favicon_map, &favicons); | 276 if (places->LoadFavicons(favicon_map, &favicons)) |
| 350 bridge_->SetFavicons(favicons); | 277 bridge_->SetFavicons(favicons); |
| 351 } | 278 } |
| 352 } | 279 } |
| 353 | 280 |
| 354 void FirefoxImporter::ImportPasswords() { | 281 void FirefoxImporter::ImportPasswords() { |
| 355 // Initializes NSS3. | 282 // Initializes NSS3. |
| 356 NSSDecryptor decryptor; | 283 NSSDecryptor decryptor; |
| 357 if (!decryptor.Init(source_path_, source_path_) && | 284 if (!decryptor.Init(source_path_, source_path_) && |
| 358 !decryptor.Init(app_path_, source_path_)) { | 285 !decryptor.Init(app_path_, source_path_)) { |
| 359 return; | 286 return; |
| 360 } | 287 } |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 // Add <Alias> element as the last child element. | 566 // Add <Alias> element as the last child element. |
| 640 size_t end_of_parent = file_data.find("</SearchPlugin>"); | 567 size_t end_of_parent = file_data.find("</SearchPlugin>"); |
| 641 if (end_of_parent != std::string::npos && !alias.empty()) | 568 if (end_of_parent != std::string::npos && !alias.empty()) |
| 642 file_data.insert(end_of_parent, "<Alias>" + alias + "</Alias> \n"); | 569 file_data.insert(end_of_parent, "<Alias>" + alias + "</Alias> \n"); |
| 643 } | 570 } |
| 644 search_engine_data->push_back(file_data); | 571 search_engine_data->push_back(file_data); |
| 645 } | 572 } |
| 646 } | 573 } |
| 647 } | 574 } |
| 648 } | 575 } |
| 649 | |
| 650 void FirefoxImporter::LoadRootNodeID(sql::Connection* db, | |
| 651 int* toolbar_folder_id, | |
| 652 int* menu_folder_id, | |
| 653 int* unsorted_folder_id) { | |
| 654 static const char kToolbarFolderName[] = "toolbar"; | |
| 655 static const char kMenuFolderName[] = "menu"; | |
| 656 static const char kUnsortedFolderName[] = "unfiled"; | |
| 657 | |
| 658 const char query[] = "SELECT root_name, folder_id FROM moz_bookmarks_roots"; | |
| 659 sql::Statement s(db->GetUniqueStatement(query)); | |
| 660 | |
| 661 while (s.Step()) { | |
| 662 std::string folder = s.ColumnString(0); | |
| 663 int id = s.ColumnInt(1); | |
| 664 if (folder == kToolbarFolderName) | |
| 665 *toolbar_folder_id = id; | |
| 666 else if (folder == kMenuFolderName) | |
| 667 *menu_folder_id = id; | |
| 668 else if (folder == kUnsortedFolderName) | |
| 669 *unsorted_folder_id = id; | |
| 670 } | |
| 671 } | |
| 672 | |
| 673 void FirefoxImporter::LoadLivemarkIDs(sql::Connection* db, | |
| 674 std::set<int>* livemark) { | |
| 675 static const char kFeedAnnotation[] = "livemark/feedURI"; | |
| 676 livemark->clear(); | |
| 677 | |
| 678 const char query[] = | |
| 679 "SELECT b.item_id " | |
| 680 "FROM moz_anno_attributes a " | |
| 681 "JOIN moz_items_annos b ON a.id = b.anno_attribute_id " | |
| 682 "WHERE a.name = ? "; | |
| 683 sql::Statement s(db->GetUniqueStatement(query)); | |
| 684 s.BindString(0, kFeedAnnotation); | |
| 685 | |
| 686 while (s.Step() && !cancelled()) | |
| 687 livemark->insert(s.ColumnInt(0)); | |
| 688 } | |
| 689 | |
| 690 void FirefoxImporter::GetTopBookmarkFolder(sql::Connection* db, | |
| 691 int folder_id, | |
| 692 BookmarkList* list) { | |
| 693 const char query[] = | |
| 694 "SELECT b.title " | |
| 695 "FROM moz_bookmarks b " | |
| 696 "WHERE b.type = 2 AND b.id = ? " | |
| 697 "ORDER BY b.position"; | |
| 698 sql::Statement s(db->GetUniqueStatement(query)); | |
| 699 s.BindInt(0, folder_id); | |
| 700 | |
| 701 if (s.Step()) { | |
| 702 BookmarkItem* item = new BookmarkItem; | |
| 703 item->parent = -1; // The top level folder has no parent. | |
| 704 item->id = folder_id; | |
| 705 item->title = s.ColumnString16(0); | |
| 706 item->type = TYPE_FOLDER; | |
| 707 item->favicon = 0; | |
| 708 item->empty_folder = true; | |
| 709 list->push_back(item); | |
| 710 } | |
| 711 } | |
| 712 | |
| 713 void FirefoxImporter::GetWholeBookmarkFolder(sql::Connection* db, | |
| 714 BookmarkList* list, | |
| 715 size_t position, | |
| 716 bool* empty_folder) { | |
| 717 if (position >= list->size()) { | |
| 718 NOTREACHED(); | |
| 719 return; | |
| 720 } | |
| 721 | |
| 722 const char query[] = | |
| 723 "SELECT b.id, h.url, COALESCE(b.title, h.title), " | |
| 724 "b.type, k.keyword, b.dateAdded, h.favicon_id " | |
| 725 "FROM moz_bookmarks b " | |
| 726 "LEFT JOIN moz_places h ON b.fk = h.id " | |
| 727 "LEFT JOIN moz_keywords k ON k.id = b.keyword_id " | |
| 728 "WHERE b.type IN (1,2) AND b.parent = ? " | |
| 729 "ORDER BY b.position"; | |
| 730 sql::Statement s(db->GetUniqueStatement(query)); | |
| 731 s.BindInt(0, (*list)[position]->id); | |
| 732 | |
| 733 BookmarkList temp_list; | |
| 734 while (s.Step()) { | |
| 735 BookmarkItem* item = new BookmarkItem; | |
| 736 item->parent = static_cast<int>(position); | |
| 737 item->id = s.ColumnInt(0); | |
| 738 item->url = GURL(s.ColumnString(1)); | |
| 739 item->title = s.ColumnString16(2); | |
| 740 item->type = static_cast<BookmarkItemType>(s.ColumnInt(3)); | |
| 741 item->keyword = s.ColumnString(4); | |
| 742 item->date_added = base::Time::FromTimeT(s.ColumnInt64(5)/1000000); | |
| 743 item->favicon = s.ColumnInt64(6); | |
| 744 item->empty_folder = true; | |
| 745 | |
| 746 temp_list.push_back(item); | |
| 747 if (empty_folder != NULL) | |
| 748 *empty_folder = false; | |
| 749 } | |
| 750 | |
| 751 // Appends all items to the list. | |
| 752 for (BookmarkList::iterator i = temp_list.begin(); | |
| 753 i != temp_list.end(); ++i) { | |
| 754 list->push_back(*i); | |
| 755 // Recursive add bookmarks in sub-folders. | |
| 756 if ((*i)->type == TYPE_FOLDER) | |
| 757 GetWholeBookmarkFolder(db, list, list->size() - 1, &(*i)->empty_folder); | |
| 758 } | |
| 759 } | |
| 760 | |
| 761 void FirefoxImporter::LoadFavicons( | |
| 762 sql::Connection* db, | |
| 763 const FaviconMap& favicon_map, | |
| 764 favicon_base::FaviconUsageDataList* favicons) { | |
| 765 const char query[] = "SELECT url, data FROM moz_favicons WHERE id=?"; | |
| 766 sql::Statement s(db->GetUniqueStatement(query)); | |
| 767 | |
| 768 if (!s.is_valid()) | |
| 769 return; | |
| 770 | |
| 771 for (FaviconMap::const_iterator i = favicon_map.begin(); | |
| 772 i != favicon_map.end(); ++i) { | |
| 773 s.BindInt64(0, i->first); | |
| 774 if (s.Step()) { | |
| 775 favicon_base::FaviconUsageData usage; | |
| 776 | |
| 777 usage.favicon_url = GURL(s.ColumnString(0)); | |
| 778 if (!usage.favicon_url.is_valid()) | |
| 779 continue; // Don't bother importing favicons with invalid URLs. | |
| 780 | |
| 781 std::vector<unsigned char> data; | |
| 782 s.ColumnBlobAsVector(1, &data); | |
| 783 if (data.empty()) | |
| 784 continue; // Data definitely invalid. | |
| 785 | |
| 786 if (!importer::ReencodeFavicon(&data[0], data.size(), &usage.png_data)) | |
| 787 continue; // Unable to decode. | |
| 788 | |
| 789 usage.urls = i->second; | |
| 790 favicons->push_back(usage); | |
| 791 } | |
| 792 s.Reset(true); | |
| 793 } | |
| 794 } | |
| OLD | NEW |