| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <Cocoa/Cocoa.h> | 5 #include <Cocoa/Cocoa.h> |
| 6 | 6 |
| 7 #include "chrome/browser/importer/safari_importer.h" | 7 #include "chrome/browser/importer/safari_importer.h" |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
| 13 #include "base/mac/mac_util.h" | 13 #include "base/mac/mac_util.h" |
| 14 #include "base/memory/scoped_nsobject.h" | 14 #include "base/memory/scoped_nsobject.h" |
| 15 #include "base/string16.h" | 15 #include "base/string16.h" |
| 16 #include "base/strings/sys_string_conversions.h" | 16 #include "base/strings/sys_string_conversions.h" |
| 17 #include "base/time.h" | 17 #include "base/time.h" |
| 18 #include "base/utf_string_conversions.h" | 18 #include "base/utf_string_conversions.h" |
| 19 #include "chrome/browser/history/history_types.h" | 19 #include "chrome/browser/bookmarks/imported_bookmark_entry.h" |
| 20 #include "chrome/browser/favicon/favicon_util.h" |
| 21 #include "chrome/browser/favicon/imported_favicon_usage.h" |
| 20 #include "chrome/browser/importer/importer_bridge.h" | 22 #include "chrome/browser/importer/importer_bridge.h" |
| 21 #include "chrome/browser/importer/importer_util.h" | |
| 22 #include "chrome/common/url_constants.h" | 23 #include "chrome/common/url_constants.h" |
| 23 #include "googleurl/src/gurl.h" | 24 #include "googleurl/src/gurl.h" |
| 24 #include "grit/generated_resources.h" | 25 #include "grit/generated_resources.h" |
| 25 #include "net/base/data_url.h" | 26 #include "net/base/data_url.h" |
| 26 #include "sql/statement.h" | 27 #include "sql/statement.h" |
| 27 | 28 |
| 28 namespace { | 29 namespace { |
| 29 | 30 |
| 30 // A function like this is used by other importers in order to filter out | 31 // A function like this is used by other importers in order to filter out |
| 31 // URLS we don't want to import. | 32 // URLS we don't want to import. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 bridge_->NotifyItemStarted(importer::PASSWORDS); | 94 bridge_->NotifyItemStarted(importer::PASSWORDS); |
| 94 ImportPasswords(); | 95 ImportPasswords(); |
| 95 bridge_->NotifyItemEnded(importer::PASSWORDS); | 96 bridge_->NotifyItemEnded(importer::PASSWORDS); |
| 96 } | 97 } |
| 97 bridge_->NotifyEnded(); | 98 bridge_->NotifyEnded(); |
| 98 } | 99 } |
| 99 | 100 |
| 100 void SafariImporter::ImportBookmarks() { | 101 void SafariImporter::ImportBookmarks() { |
| 101 string16 toolbar_name = | 102 string16 toolbar_name = |
| 102 bridge_->GetLocalizedString(IDS_BOOKMARK_BAR_FOLDER_NAME); | 103 bridge_->GetLocalizedString(IDS_BOOKMARK_BAR_FOLDER_NAME); |
| 103 std::vector<ProfileWriter::BookmarkEntry> bookmarks; | 104 std::vector<ImportedBookmarkEntry> bookmarks; |
| 104 ParseBookmarks(toolbar_name, &bookmarks); | 105 ParseBookmarks(toolbar_name, &bookmarks); |
| 105 | 106 |
| 106 // Write bookmarks into profile. | 107 // Write bookmarks into profile. |
| 107 if (!bookmarks.empty() && !cancelled()) { | 108 if (!bookmarks.empty() && !cancelled()) { |
| 108 const string16& first_folder_name = | 109 const string16& first_folder_name = |
| 109 bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_SAFARI); | 110 bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_SAFARI); |
| 110 bridge_->AddBookmarks(bookmarks, first_folder_name); | 111 bridge_->AddBookmarks(bookmarks, first_folder_name); |
| 111 } | 112 } |
| 112 | 113 |
| 113 // Import favicons. | 114 // Import favicons. |
| 114 sql::Connection db; | 115 sql::Connection db; |
| 115 if (!OpenDatabase(&db)) | 116 if (!OpenDatabase(&db)) |
| 116 return; | 117 return; |
| 117 | 118 |
| 118 FaviconMap favicon_map; | 119 FaviconMap favicon_map; |
| 119 ImportFaviconURLs(&db, &favicon_map); | 120 ImportFaviconURLs(&db, &favicon_map); |
| 120 // Write favicons into profile. | 121 // Write favicons into profile. |
| 121 if (!favicon_map.empty() && !cancelled()) { | 122 if (!favicon_map.empty() && !cancelled()) { |
| 122 std::vector<history::ImportedFaviconUsage> favicons; | 123 std::vector<ImportedFaviconUsage> favicons; |
| 123 LoadFaviconData(&db, favicon_map, &favicons); | 124 LoadFaviconData(&db, favicon_map, &favicons); |
| 124 bridge_->SetFavicons(favicons); | 125 bridge_->SetFavicons(favicons); |
| 125 } | 126 } |
| 126 } | 127 } |
| 127 | 128 |
| 128 bool SafariImporter::OpenDatabase(sql::Connection* db) { | 129 bool SafariImporter::OpenDatabase(sql::Connection* db) { |
| 129 // Construct ~/Library/Safari/WebIcons.db path. | 130 // Construct ~/Library/Safari/WebIcons.db path. |
| 130 NSString* library_dir = [NSString | 131 NSString* library_dir = [NSString |
| 131 stringWithUTF8String:library_dir_.value().c_str()]; | 132 stringWithUTF8String:library_dir_.value().c_str()]; |
| 132 NSString* safari_dir = [library_dir | 133 NSString* safari_dir = [library_dir |
| (...skipping 13 matching lines...) Expand all Loading... |
| 146 while (s.Step() && !cancelled()) { | 147 while (s.Step() && !cancelled()) { |
| 147 int64 icon_id = s.ColumnInt64(0); | 148 int64 icon_id = s.ColumnInt64(0); |
| 148 GURL url = GURL(s.ColumnString(1)); | 149 GURL url = GURL(s.ColumnString(1)); |
| 149 (*favicon_map)[icon_id].insert(url); | 150 (*favicon_map)[icon_id].insert(url); |
| 150 } | 151 } |
| 151 } | 152 } |
| 152 | 153 |
| 153 void SafariImporter::LoadFaviconData( | 154 void SafariImporter::LoadFaviconData( |
| 154 sql::Connection* db, | 155 sql::Connection* db, |
| 155 const FaviconMap& favicon_map, | 156 const FaviconMap& favicon_map, |
| 156 std::vector<history::ImportedFaviconUsage>* favicons) { | 157 std::vector<ImportedFaviconUsage>* favicons) { |
| 157 const char* query = "SELECT i.url, d.data " | 158 const char* query = "SELECT i.url, d.data " |
| 158 "FROM IconInfo i JOIN IconData d " | 159 "FROM IconInfo i JOIN IconData d " |
| 159 "ON i.iconID = d.iconID " | 160 "ON i.iconID = d.iconID " |
| 160 "WHERE i.iconID = ?;"; | 161 "WHERE i.iconID = ?;"; |
| 161 sql::Statement s(db->GetUniqueStatement(query)); | 162 sql::Statement s(db->GetUniqueStatement(query)); |
| 162 | 163 |
| 163 for (FaviconMap::const_iterator i = favicon_map.begin(); | 164 for (FaviconMap::const_iterator i = favicon_map.begin(); |
| 164 i != favicon_map.end(); ++i) { | 165 i != favicon_map.end(); ++i) { |
| 165 s.Reset(true); | 166 s.Reset(true); |
| 166 s.BindInt64(0, i->first); | 167 s.BindInt64(0, i->first); |
| 167 if (s.Step()) { | 168 if (s.Step()) { |
| 168 history::ImportedFaviconUsage usage; | 169 ImportedFaviconUsage usage; |
| 169 | 170 |
| 170 usage.favicon_url = GURL(s.ColumnString(0)); | 171 usage.favicon_url = GURL(s.ColumnString(0)); |
| 171 if (!usage.favicon_url.is_valid()) | 172 if (!usage.favicon_url.is_valid()) |
| 172 continue; // Don't bother importing favicons with invalid URLs. | 173 continue; // Don't bother importing favicons with invalid URLs. |
| 173 | 174 |
| 174 std::vector<unsigned char> data; | 175 std::vector<unsigned char> data; |
| 175 s.ColumnBlobAsVector(1, &data); | 176 s.ColumnBlobAsVector(1, &data); |
| 176 if (data.empty()) | 177 if (data.empty()) |
| 177 continue; // Data definitely invalid. | 178 continue; // Data definitely invalid. |
| 178 | 179 |
| 179 if (!importer::ReencodeFavicon(&data[0], data.size(), &usage.png_data)) | 180 if (!FaviconUtil::ReencodeFavicon(&data[0], data.size(), &usage.png_data)) |
| 180 continue; // Unable to decode. | 181 continue; // Unable to decode. |
| 181 | 182 |
| 182 usage.urls = i->second; | 183 usage.urls = i->second; |
| 183 favicons->push_back(usage); | 184 favicons->push_back(usage); |
| 184 } | 185 } |
| 185 } | 186 } |
| 186 } | 187 } |
| 187 | 188 |
| 188 void SafariImporter::RecursiveReadBookmarksFolder( | 189 void SafariImporter::RecursiveReadBookmarksFolder( |
| 189 NSDictionary* bookmark_folder, | 190 NSDictionary* bookmark_folder, |
| 190 const std::vector<string16>& parent_path_elements, | 191 const std::vector<string16>& parent_path_elements, |
| 191 bool is_in_toolbar, | 192 bool is_in_toolbar, |
| 192 const string16& toolbar_name, | 193 const string16& toolbar_name, |
| 193 std::vector<ProfileWriter::BookmarkEntry>* out_bookmarks) { | 194 std::vector<ImportedBookmarkEntry>* out_bookmarks) { |
| 194 DCHECK(bookmark_folder); | 195 DCHECK(bookmark_folder); |
| 195 | 196 |
| 196 NSString* type = [bookmark_folder objectForKey:@"WebBookmarkType"]; | 197 NSString* type = [bookmark_folder objectForKey:@"WebBookmarkType"]; |
| 197 NSString* title = [bookmark_folder objectForKey:@"Title"]; | 198 NSString* title = [bookmark_folder objectForKey:@"Title"]; |
| 198 | 199 |
| 199 // Are we the dictionary that contains all other bookmarks? | 200 // Are we the dictionary that contains all other bookmarks? |
| 200 // We need to know this so we don't add it to the path. | 201 // We need to know this so we don't add it to the path. |
| 201 bool is_top_level_bookmarks_container = [bookmark_folder | 202 bool is_top_level_bookmarks_container = [bookmark_folder |
| 202 objectForKey:@"WebBookmarkFileVersion"] != nil; | 203 objectForKey:@"WebBookmarkFileVersion"] != nil; |
| 203 | 204 |
| 204 // We're expecting a list of bookmarks here, if that isn't what we got, fail. | 205 // We're expecting a list of bookmarks here, if that isn't what we got, fail. |
| 205 if (!is_top_level_bookmarks_container) { | 206 if (!is_top_level_bookmarks_container) { |
| 206 // Top level containers sometimes don't have title attributes. | 207 // Top level containers sometimes don't have title attributes. |
| 207 if (![type isEqualToString:@"WebBookmarkTypeList"] || !title) { | 208 if (![type isEqualToString:@"WebBookmarkTypeList"] || !title) { |
| 208 NOTREACHED() << "Type=(" | 209 NOTREACHED() << "Type=(" |
| 209 << (type ? base::SysNSStringToUTF8(type) : "Null type") | 210 << (type ? base::SysNSStringToUTF8(type) : "Null type") |
| 210 << ") Title=(" | 211 << ") Title=(" |
| 211 << (title ? base::SysNSStringToUTF8(title) : "Null title") | 212 << (title ? base::SysNSStringToUTF8(title) : "Null title") |
| 212 << ")"; | 213 << ")"; |
| 213 return; | 214 return; |
| 214 } | 215 } |
| 215 } | 216 } |
| 216 | 217 |
| 217 NSArray* elements = [bookmark_folder objectForKey:@"Children"]; | 218 NSArray* elements = [bookmark_folder objectForKey:@"Children"]; |
| 218 if (!elements && (!parent_path_elements.empty() || !is_in_toolbar)) { | 219 if (!elements && (!parent_path_elements.empty() || !is_in_toolbar)) { |
| 219 // This is an empty folder, so add it explicitly; but don't add the toolbar | 220 // This is an empty folder, so add it explicitly; but don't add the toolbar |
| 220 // folder if it is empty. Note that all non-empty folders are added | 221 // folder if it is empty. Note that all non-empty folders are added |
| 221 // implicitly when their children are added. | 222 // implicitly when their children are added. |
| 222 ProfileWriter::BookmarkEntry entry; | 223 ImportedBookmarkEntry entry; |
| 223 // Safari doesn't specify a creation time for the folder. | 224 // Safari doesn't specify a creation time for the folder. |
| 224 entry.creation_time = base::Time::Now(); | 225 entry.creation_time = base::Time::Now(); |
| 225 entry.title = base::SysNSStringToUTF16(title); | 226 entry.title = base::SysNSStringToUTF16(title); |
| 226 entry.path = parent_path_elements; | 227 entry.path = parent_path_elements; |
| 227 entry.in_toolbar = is_in_toolbar; | 228 entry.in_toolbar = is_in_toolbar; |
| 228 entry.is_folder = true; | 229 entry.is_folder = true; |
| 229 | 230 |
| 230 out_bookmarks->push_back(entry); | 231 out_bookmarks->push_back(entry); |
| 231 return; | 232 return; |
| 232 } | 233 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 continue; | 265 continue; |
| 265 | 266 |
| 266 NSString* url = [bookmark objectForKey:@"URLString"]; | 267 NSString* url = [bookmark objectForKey:@"URLString"]; |
| 267 NSString* title = [[bookmark objectForKey:@"URIDictionary"] | 268 NSString* title = [[bookmark objectForKey:@"URIDictionary"] |
| 268 objectForKey:@"title"]; | 269 objectForKey:@"title"]; |
| 269 | 270 |
| 270 if (!url || !title) | 271 if (!url || !title) |
| 271 continue; | 272 continue; |
| 272 | 273 |
| 273 // Output Bookmark. | 274 // Output Bookmark. |
| 274 ProfileWriter::BookmarkEntry entry; | 275 ImportedBookmarkEntry entry; |
| 275 // Safari doesn't specify a creation time for the bookmark. | 276 // Safari doesn't specify a creation time for the bookmark. |
| 276 entry.creation_time = base::Time::Now(); | 277 entry.creation_time = base::Time::Now(); |
| 277 entry.title = base::SysNSStringToUTF16(title); | 278 entry.title = base::SysNSStringToUTF16(title); |
| 278 entry.url = GURL(base::SysNSStringToUTF8(url)); | 279 entry.url = GURL(base::SysNSStringToUTF8(url)); |
| 279 entry.path = path_elements; | 280 entry.path = path_elements; |
| 280 entry.in_toolbar = is_in_toolbar; | 281 entry.in_toolbar = is_in_toolbar; |
| 281 | 282 |
| 282 out_bookmarks->push_back(entry); | 283 out_bookmarks->push_back(entry); |
| 283 } | 284 } |
| 284 } | 285 } |
| 285 | 286 |
| 286 void SafariImporter::ParseBookmarks( | 287 void SafariImporter::ParseBookmarks( |
| 287 const string16& toolbar_name, | 288 const string16& toolbar_name, |
| 288 std::vector<ProfileWriter::BookmarkEntry>* bookmarks) { | 289 std::vector<ImportedBookmarkEntry>* bookmarks) { |
| 289 DCHECK(bookmarks); | 290 DCHECK(bookmarks); |
| 290 | 291 |
| 291 // Construct ~/Library/Safari/Bookmarks.plist path | 292 // Construct ~/Library/Safari/Bookmarks.plist path |
| 292 NSString* library_dir = [NSString | 293 NSString* library_dir = [NSString |
| 293 stringWithUTF8String:library_dir_.value().c_str()]; | 294 stringWithUTF8String:library_dir_.value().c_str()]; |
| 294 NSString* safari_dir = [library_dir | 295 NSString* safari_dir = [library_dir |
| 295 stringByAppendingPathComponent:@"Safari"]; | 296 stringByAppendingPathComponent:@"Safari"]; |
| 296 NSString* bookmarks_plist = [safari_dir | 297 NSString* bookmarks_plist = [safari_dir |
| 297 stringByAppendingPathComponent:@"Bookmarks.plist"]; | 298 stringByAppendingPathComponent:@"Bookmarks.plist"]; |
| 298 | 299 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 if (!last_visit_str) | 390 if (!last_visit_str) |
| 390 continue; | 391 continue; |
| 391 | 392 |
| 392 // Convert Safari's last visit time to Unix Epoch time. | 393 // Convert Safari's last visit time to Unix Epoch time. |
| 393 double seconds_since_unix_epoch = HistoryTimeToEpochTime(last_visit_str); | 394 double seconds_since_unix_epoch = HistoryTimeToEpochTime(last_visit_str); |
| 394 row.set_last_visit(base::Time::FromDoubleT(seconds_since_unix_epoch)); | 395 row.set_last_visit(base::Time::FromDoubleT(seconds_since_unix_epoch)); |
| 395 | 396 |
| 396 history_items->push_back(row); | 397 history_items->push_back(row); |
| 397 } | 398 } |
| 398 } | 399 } |
| OLD | NEW |