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

Side by Side Diff: chrome/browser/importer/safari_importer.mm

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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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>
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 } 90 }
91 if ((items & importer::PASSWORDS) && !cancelled()) { 91 if ((items & importer::PASSWORDS) && !cancelled()) {
92 bridge_->NotifyItemStarted(importer::PASSWORDS); 92 bridge_->NotifyItemStarted(importer::PASSWORDS);
93 ImportPasswords(); 93 ImportPasswords();
94 bridge_->NotifyItemEnded(importer::PASSWORDS); 94 bridge_->NotifyItemEnded(importer::PASSWORDS);
95 } 95 }
96 bridge_->NotifyEnded(); 96 bridge_->NotifyEnded();
97 } 97 }
98 98
99 void SafariImporter::ImportBookmarks() { 99 void SafariImporter::ImportBookmarks() {
100 string16 toolbar_name =
101 bridge_->GetLocalizedString(IDS_BOOMARK_BAR_FOLDER_NAME);
100 std::vector<ProfileWriter::BookmarkEntry> bookmarks; 102 std::vector<ProfileWriter::BookmarkEntry> bookmarks;
101 ParseBookmarks(&bookmarks); 103 ParseBookmarks(toolbar_name, &bookmarks);
102 104
103 // Write bookmarks into profile. 105 // Write bookmarks into profile.
104 if (!bookmarks.empty() && !cancelled()) { 106 if (!bookmarks.empty() && !cancelled()) {
105 const string16& first_folder_name = 107 const string16& first_folder_name =
106 bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_SAFARI); 108 bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_SAFARI);
107 int options = 0; 109 bridge_->AddBookmarks(bookmarks, first_folder_name);
108 if (import_to_bookmark_bar())
109 options = ProfileWriter::IMPORT_TO_BOOKMARK_BAR;
110 bridge_->AddBookmarks(bookmarks, first_folder_name, options);
111 } 110 }
112 111
113 // Import favicons. 112 // Import favicons.
114 sql::Connection db; 113 sql::Connection db;
115 if (!OpenDatabase(&db)) 114 if (!OpenDatabase(&db))
116 return; 115 return;
117 116
118 FaviconMap favicon_map; 117 FaviconMap favicon_map;
119 ImportFaviconURLs(&db, &favicon_map); 118 ImportFaviconURLs(&db, &favicon_map);
120 // Write favicons into profile. 119 // Write favicons into profile.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 usage.urls = i->second; 185 usage.urls = i->second;
187 favicons->push_back(usage); 186 favicons->push_back(usage);
188 } 187 }
189 } 188 }
190 } 189 }
191 190
192 void SafariImporter::RecursiveReadBookmarksFolder( 191 void SafariImporter::RecursiveReadBookmarksFolder(
193 NSDictionary* bookmark_folder, 192 NSDictionary* bookmark_folder,
194 const std::vector<string16>& parent_path_elements, 193 const std::vector<string16>& parent_path_elements,
195 bool is_in_toolbar, 194 bool is_in_toolbar,
195 const string16& toolbar_name,
196 std::vector<ProfileWriter::BookmarkEntry>* out_bookmarks) { 196 std::vector<ProfileWriter::BookmarkEntry>* out_bookmarks) {
197 DCHECK(bookmark_folder); 197 DCHECK(bookmark_folder);
198 198
199 NSString* type = [bookmark_folder objectForKey:@"WebBookmarkType"]; 199 NSString* type = [bookmark_folder objectForKey:@"WebBookmarkType"];
200 NSString* title = [bookmark_folder objectForKey:@"Title"]; 200 NSString* title = [bookmark_folder objectForKey:@"Title"];
201 201
202 // Are we the dictionary that contains all other bookmarks? 202 // Are we the dictionary that contains all other bookmarks?
203 // We need to know this so we don't add it to the path. 203 // We need to know this so we don't add it to the path.
204 bool is_top_level_bookmarks_container = [bookmark_folder 204 bool is_top_level_bookmarks_container = [bookmark_folder
205 objectForKey:@"WebBookmarkFileVersion"] != nil; 205 objectForKey:@"WebBookmarkFileVersion"] != nil;
206 206
207 // We're expecting a list of bookmarks here, if that isn't what we got, fail. 207 // We're expecting a list of bookmarks here, if that isn't what we got, fail.
208 if (!is_top_level_bookmarks_container) { 208 if (!is_top_level_bookmarks_container) {
209 // Top level containers sometimes don't have title attributes. 209 // Top level containers sometimes don't have title attributes.
210 if (![type isEqualToString:@"WebBookmarkTypeList"] || !title) { 210 if (![type isEqualToString:@"WebBookmarkTypeList"] || !title) {
211 DCHECK(false) << "Type =(" 211 NOTREACHED() << "Type=("
212 << (type ? base::SysNSStringToUTF8(type) : "Null Type") 212 << (type ? base::SysNSStringToUTF8(type) : "Null type")
213 << ") Title=(" << (title ? base::SysNSStringToUTF8(title) : "Null title") 213 << ") Title=("
214 << ")"; 214 << (title ? base::SysNSStringToUTF8(title) : "Null title")
215 << ")";
215 return; 216 return;
216 } 217 }
217 } 218 }
218 219
220 NSArray* elements = [bookmark_folder objectForKey:@"Children"];
221 if (!elements && (!parent_path_elements.empty() || !is_in_toolbar)) {
222 // This is an empty folder, so add it explicitly; but don't add the toolbar
223 // folder if it is empty. Note that all non-empty folders are added
224 // implicitly when their children are added.
225 ProfileWriter::BookmarkEntry entry;
226 // Safari doesn't specify a creation time for the folder.
227 entry.creation_time = base::Time::Now();
228 entry.title = base::SysNSStringToUTF16(title);
229 entry.path = parent_path_elements;
230 entry.in_toolbar = is_in_toolbar;
231 entry.is_folder = true;
232
233 out_bookmarks->push_back(entry);
234 return;
235 }
236
219 std::vector<string16> path_elements(parent_path_elements); 237 std::vector<string16> path_elements(parent_path_elements);
220 // Is this the toolbar folder? 238 // Create a folder for the toolbar, but not for the bookmarks menu.
221 if ([title isEqualToString:@"BookmarksBar"]) { 239 if (path_elements.empty() && [title isEqualToString:@"BookmarksBar"]) {
222 // Be defensive, the toolbar items shouldn't have a prepended path.
223 path_elements.clear();
224 is_in_toolbar = true; 240 is_in_toolbar = true;
225 } else if ([title isEqualToString:@"BookmarksMenu"]) { 241 path_elements.push_back(toolbar_name);
226 // top level container for normal bookmarks. 242 } else if (!is_top_level_bookmarks_container &&
227 path_elements.clear(); 243 !(path_elements.empty() &&
228 } else if (!is_top_level_bookmarks_container) { 244 [title isEqualToString:@"BookmarksMenu"])) {
229 if (title) 245 if (title)
230 path_elements.push_back(base::SysNSStringToUTF16(title)); 246 path_elements.push_back(base::SysNSStringToUTF16(title));
231 } 247 }
232 248
233 NSArray* elements = [bookmark_folder objectForKey:@"Children"];
234 // TODO(jeremy) Does Chrome support importing empty folders?
235 if (!elements)
236 return;
237
238 // Iterate over individual bookmarks. 249 // Iterate over individual bookmarks.
239 for (NSDictionary* bookmark in elements) { 250 for (NSDictionary* bookmark in elements) {
240 NSString* type = [bookmark objectForKey:@"WebBookmarkType"]; 251 NSString* type = [bookmark objectForKey:@"WebBookmarkType"];
241 if (!type) 252 if (!type)
242 continue; 253 continue;
243 254
244 // If this is a folder, recurse. 255 // If this is a folder, recurse.
245 if ([type isEqualToString:@"WebBookmarkTypeList"]) { 256 if ([type isEqualToString:@"WebBookmarkTypeList"]) {
246 RecursiveReadBookmarksFolder(bookmark, 257 RecursiveReadBookmarksFolder(bookmark,
247 path_elements, 258 path_elements,
248 is_in_toolbar, 259 is_in_toolbar,
260 toolbar_name,
249 out_bookmarks); 261 out_bookmarks);
250 } 262 }
251 263
252 // If we didn't see a bookmark folder, then we're expecting a bookmark 264 // If we didn't see a bookmark folder, then we're expecting a bookmark
253 // item, if that's not what we got then ignore it. 265 // item. If that's not what we got then ignore it.
254 if (![type isEqualToString:@"WebBookmarkTypeLeaf"]) 266 if (![type isEqualToString:@"WebBookmarkTypeLeaf"])
255 continue; 267 continue;
256 268
257 NSString* url = [bookmark objectForKey:@"URLString"]; 269 NSString* url = [bookmark objectForKey:@"URLString"];
258 NSString* title = [[bookmark objectForKey:@"URIDictionary"] 270 NSString* title = [[bookmark objectForKey:@"URIDictionary"]
259 objectForKey:@"title"]; 271 objectForKey:@"title"];
260 272
261 if (!url || !title) 273 if (!url || !title)
262 continue; 274 continue;
263 275
264 // Output Bookmark. 276 // Output Bookmark.
265 ProfileWriter::BookmarkEntry entry; 277 ProfileWriter::BookmarkEntry entry;
266 // Safari doesn't specify a creation time for the bookmark. 278 // Safari doesn't specify a creation time for the bookmark.
267 entry.creation_time = base::Time::Now(); 279 entry.creation_time = base::Time::Now();
268 entry.title = base::SysNSStringToUTF16(title); 280 entry.title = base::SysNSStringToUTF16(title);
269 entry.url = GURL(base::SysNSStringToUTF8(url)); 281 entry.url = GURL(base::SysNSStringToUTF8(url));
270 entry.path = path_elements; 282 entry.path = path_elements;
271 entry.in_toolbar = is_in_toolbar; 283 entry.in_toolbar = is_in_toolbar;
272 284
273 out_bookmarks->push_back(entry); 285 out_bookmarks->push_back(entry);
274 } 286 }
275 } 287 }
276 288
277 void SafariImporter::ParseBookmarks( 289 void SafariImporter::ParseBookmarks(
290 const string16& toolbar_name,
278 std::vector<ProfileWriter::BookmarkEntry>* bookmarks) { 291 std::vector<ProfileWriter::BookmarkEntry>* bookmarks) {
279 DCHECK(bookmarks); 292 DCHECK(bookmarks);
280 293
281 // Construct ~/Library/Safari/Bookmarks.plist path 294 // Construct ~/Library/Safari/Bookmarks.plist path
282 NSString* library_dir = [NSString 295 NSString* library_dir = [NSString
283 stringWithUTF8String:library_dir_.value().c_str()]; 296 stringWithUTF8String:library_dir_.value().c_str()];
284 NSString* safari_dir = [library_dir 297 NSString* safari_dir = [library_dir
285 stringByAppendingPathComponent:@"Safari"]; 298 stringByAppendingPathComponent:@"Safari"];
286 NSString* bookmarks_plist = [safari_dir 299 NSString* bookmarks_plist = [safari_dir
287 stringByAppendingPathComponent:@"Bookmarks.plist"]; 300 stringByAppendingPathComponent:@"Bookmarks.plist"];
288 301
289 // Load the plist file. 302 // Load the plist file.
290 NSDictionary* bookmarks_dict = [NSDictionary 303 NSDictionary* bookmarks_dict = [NSDictionary
291 dictionaryWithContentsOfFile:bookmarks_plist]; 304 dictionaryWithContentsOfFile:bookmarks_plist];
292 if (!bookmarks_dict) 305 if (!bookmarks_dict)
293 return; 306 return;
294 307
295 // Recursively read in bookmarks. 308 // Recursively read in bookmarks.
296 std::vector<string16> parent_path_elements; 309 std::vector<string16> parent_path_elements;
297 RecursiveReadBookmarksFolder(bookmarks_dict, parent_path_elements, false, 310 RecursiveReadBookmarksFolder(bookmarks_dict, parent_path_elements, false,
298 bookmarks); 311 toolbar_name, bookmarks);
299 } 312 }
300 313
301 void SafariImporter::ImportPasswords() { 314 void SafariImporter::ImportPasswords() {
302 // Safari stores it's passwords in the Keychain, same as us so we don't need 315 // Safari stores it's passwords in the Keychain, same as us so we don't need
303 // to import them. 316 // to import them.
304 // Note: that we don't automatically pick them up, there is some logic around 317 // Note: that we don't automatically pick them up, there is some logic around
305 // the user needing to explicitly input his username in a page and blurring 318 // the user needing to explicitly input his username in a page and blurring
306 // the field before we pick it up, but the details of that are beyond the 319 // the field before we pick it up, but the details of that are beyond the
307 // scope of this comment. 320 // scope of this comment.
308 } 321 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 if (!last_visit_str) 393 if (!last_visit_str)
381 continue; 394 continue;
382 395
383 // Convert Safari's last visit time to Unix Epoch time. 396 // Convert Safari's last visit time to Unix Epoch time.
384 double seconds_since_unix_epoch = HistoryTimeToEpochTime(last_visit_str); 397 double seconds_since_unix_epoch = HistoryTimeToEpochTime(last_visit_str);
385 row.set_last_visit(base::Time::FromDoubleT(seconds_since_unix_epoch)); 398 row.set_last_visit(base::Time::FromDoubleT(seconds_since_unix_epoch));
386 399
387 history_items->push_back(row); 400 history_items->push_back(row);
388 } 401 }
389 } 402 }
OLDNEW
« no previous file with comments | « chrome/browser/importer/safari_importer.h ('k') | chrome/browser/importer/safari_importer_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698