| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/bookmarks/browser/bookmark_pasteboard_helper_mac.h" | 5 #include "components/bookmarks/browser/bookmark_pasteboard_helper_mac.h" |
| 6 | 6 |
| 7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| 11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
| 12 #include "base/strings/sys_string_conversions.h" | 12 #include "base/strings/sys_string_conversions.h" |
| 13 #include "components/bookmarks/browser/bookmark_node.h" | 13 #include "components/bookmarks/browser/bookmark_node.h" |
| 14 #include "ui/base/clipboard/clipboard.h" | 14 #include "ui/base/clipboard/clipboard.h" |
| 15 #include "ui/base/clipboard/clipboard_util_mac.h" |
| 15 | 16 |
| 16 NSString* const kBookmarkDictionaryListPboardType = | 17 NSString* const kBookmarkDictionaryListPboardType = |
| 17 @"BookmarkDictionaryListPboardType"; | 18 @"com.google.chrome.BookmarkDictionaryListPboardType"; |
| 18 | 19 |
| 19 namespace bookmarks { | 20 namespace bookmarks { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 // An unofficial standard pasteboard title type to be provided alongside the | |
| 24 // |NSURLPboardType|. | |
| 25 NSString* const kNSURLTitlePboardType = @"public.url-name"; | |
| 26 | |
| 27 // Pasteboard type used to store profile path to determine which profile | 24 // Pasteboard type used to store profile path to determine which profile |
| 28 // a set of bookmarks came from. | 25 // a set of bookmarks came from. |
| 29 NSString* const kChromiumProfilePathPboardType = | 26 NSString* const kChromiumProfilePathPboardType = |
| 30 @"ChromiumProfilePathPboardType"; | 27 @"com.google.chrome.ChromiumProfilePathPboardType"; |
| 31 | 28 |
| 32 // Internal bookmark ID for a bookmark node. Used only when moving inside | 29 // Internal bookmark ID for a bookmark node. Used only when moving inside |
| 33 // of one profile. | 30 // of one profile. |
| 34 NSString* const kChromiumBookmarkId = @"ChromiumBookmarkId"; | 31 NSString* const kChromiumBookmarkId = @"ChromiumBookmarkId"; |
| 35 | 32 |
| 36 // Internal bookmark meta info dictionary for a bookmark node. | 33 // Internal bookmark meta info dictionary for a bookmark node. |
| 37 NSString* const kChromiumBookmarkMetaInfo = @"ChromiumBookmarkMetaInfo"; | 34 NSString* const kChromiumBookmarkMetaInfo = @"ChromiumBookmarkMetaInfo"; |
| 38 | 35 |
| 39 // Mac WebKit uses this type, declared in | |
| 40 // WebKit/mac/History/WebURLsWithTitles.h. | |
| 41 NSString* const kCrWebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType"; | |
| 42 | |
| 43 // Keys for the type of node in BookmarkDictionaryListPboardType. | 36 // Keys for the type of node in BookmarkDictionaryListPboardType. |
| 44 NSString* const kWebBookmarkType = @"WebBookmarkType"; | 37 NSString* const kWebBookmarkType = @"WebBookmarkType"; |
| 45 | 38 |
| 46 NSString* const kWebBookmarkTypeList = @"WebBookmarkTypeList"; | 39 NSString* const kWebBookmarkTypeList = @"WebBookmarkTypeList"; |
| 47 | 40 |
| 48 NSString* const kWebBookmarkTypeLeaf = @"WebBookmarkTypeLeaf"; | 41 NSString* const kWebBookmarkTypeLeaf = @"WebBookmarkTypeLeaf"; |
| 49 | 42 |
| 50 BookmarkNode::MetaInfoMap MetaInfoMapFromDictionary(NSDictionary* dictionary) { | 43 BookmarkNode::MetaInfoMap MetaInfoMapFromDictionary(NSDictionary* dictionary) { |
| 51 BookmarkNode::MetaInfoMap meta_info_map; | 44 BookmarkNode::MetaInfoMap meta_info_map; |
| 52 | 45 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 ConvertPlistToElements([pboardBookmark objectForKey:@"Children"], | 86 ConvertPlistToElements([pboardBookmark objectForKey:@"Children"], |
| 94 e.children); | 87 e.children); |
| 95 } | 88 } |
| 96 elements.push_back(e); | 89 elements.push_back(e); |
| 97 } | 90 } |
| 98 } | 91 } |
| 99 | 92 |
| 100 bool ReadBookmarkDictionaryListPboardType( | 93 bool ReadBookmarkDictionaryListPboardType( |
| 101 NSPasteboard* pb, | 94 NSPasteboard* pb, |
| 102 std::vector<BookmarkNodeData::Element>& elements) { | 95 std::vector<BookmarkNodeData::Element>& elements) { |
| 103 NSArray* bookmarks = | 96 NSString* uti = ui::ClipboardUtil::UTIForPasteboardType( |
| 104 [pb propertyListForType:kBookmarkDictionaryListPboardType]; | 97 kBookmarkDictionaryListPboardType); |
| 98 NSArray* bookmarks = [pb propertyListForType:uti]; |
| 105 if (!bookmarks) | 99 if (!bookmarks) |
| 106 return false; | 100 return false; |
| 107 ConvertPlistToElements(bookmarks, elements); | 101 ConvertPlistToElements(bookmarks, elements); |
| 108 return true; | 102 return true; |
| 109 } | 103 } |
| 110 | 104 |
| 111 bool ReadWebURLsWithTitlesPboardType( | 105 bool ReadWebURLsWithTitlesPboardType( |
| 112 NSPasteboard* pb, | 106 NSPasteboard* pb, |
| 113 std::vector<BookmarkNodeData::Element>& elements) { | 107 std::vector<BookmarkNodeData::Element>& elements) { |
| 114 NSArray* bookmarkPairs = | 108 NSArray* urlsArr = nil; |
| 115 [pb propertyListForType:kCrWebURLsWithTitlesPboardType]; | 109 NSArray* titlesArr = nil; |
| 116 if (![bookmarkPairs isKindOfClass:[NSArray class]]) | 110 if (!ui::ClipboardUtil::URLsAndTitlesFromPasteboard(pb, &urlsArr, &titlesArr)) |
| 117 return false; | |
| 118 | |
| 119 NSArray* urlsArr = [bookmarkPairs objectAtIndex:0]; | |
| 120 NSArray* titlesArr = [bookmarkPairs objectAtIndex:1]; | |
| 121 if ([urlsArr count] < 1) | |
| 122 return false; | |
| 123 if ([urlsArr count] != [titlesArr count]) | |
| 124 return false; | 111 return false; |
| 125 | 112 |
| 126 NSUInteger len = [titlesArr count]; | 113 NSUInteger len = [titlesArr count]; |
| 127 for (NSUInteger i = 0; i < len; ++i) { | 114 for (NSUInteger i = 0; i < len; ++i) { |
| 128 base::string16 title = | 115 base::string16 title = |
| 129 base::SysNSStringToUTF16([titlesArr objectAtIndex:i]); | 116 base::SysNSStringToUTF16([titlesArr objectAtIndex:i]); |
| 130 std::string url = base::SysNSStringToUTF8([urlsArr objectAtIndex:i]); | 117 std::string url = base::SysNSStringToUTF8([urlsArr objectAtIndex:i]); |
| 131 if (!url.empty()) { | 118 if (!url.empty()) { |
| 132 BookmarkNodeData::Element element; | 119 BookmarkNodeData::Element element; |
| 133 element.is_url = true; | 120 element.is_url = true; |
| 134 element.url = GURL(url); | 121 element.url = GURL(url); |
| 135 element.title = title; | 122 element.title = title; |
| 136 elements.push_back(element); | 123 elements.push_back(element); |
| 137 } | 124 } |
| 138 } | 125 } |
| 139 return true; | 126 return true; |
| 140 } | 127 } |
| 141 | 128 |
| 142 bool ReadNSURLPboardType(NSPasteboard* pb, | |
| 143 std::vector<BookmarkNodeData::Element>& elements) { | |
| 144 NSURL* url = [NSURL URLFromPasteboard:pb]; | |
| 145 if (url == nil) | |
| 146 return false; | |
| 147 | |
| 148 std::string urlString = base::SysNSStringToUTF8([url absoluteString]); | |
| 149 NSString* title = [pb stringForType:kNSURLTitlePboardType]; | |
| 150 if (!title) | |
| 151 title = [pb stringForType:NSStringPboardType]; | |
| 152 | |
| 153 BookmarkNodeData::Element element; | |
| 154 element.is_url = true; | |
| 155 element.url = GURL(urlString); | |
| 156 element.title = base::SysNSStringToUTF16(title); | |
| 157 elements.push_back(element); | |
| 158 return true; | |
| 159 } | |
| 160 | |
| 161 NSDictionary* DictionaryFromBookmarkMetaInfo( | 129 NSDictionary* DictionaryFromBookmarkMetaInfo( |
| 162 const BookmarkNode::MetaInfoMap& meta_info_map) { | 130 const BookmarkNode::MetaInfoMap& meta_info_map) { |
| 163 NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; | 131 NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; |
| 164 | 132 |
| 165 for (BookmarkNode::MetaInfoMap::const_iterator it = meta_info_map.begin(); | 133 for (BookmarkNode::MetaInfoMap::const_iterator it = meta_info_map.begin(); |
| 166 it != meta_info_map.end(); ++it) { | 134 it != meta_info_map.end(); ++it) { |
| 167 [dictionary setObject:base::SysUTF8ToNSString(it->second) | 135 [dictionary setObject:base::SysUTF8ToNSString(it->second) |
| 168 forKey:base::SysUTF8ToNSString(it->first)]; | 136 forKey:base::SysUTF8ToNSString(it->first)]; |
| 169 } | 137 } |
| 170 | 138 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 [plist addObject:object]; | 176 [plist addObject:object]; |
| 209 } | 177 } |
| 210 } | 178 } |
| 211 return plist; | 179 return plist; |
| 212 } | 180 } |
| 213 | 181 |
| 214 void WriteBookmarkDictionaryListPboardType( | 182 void WriteBookmarkDictionaryListPboardType( |
| 215 NSPasteboard* pb, | 183 NSPasteboard* pb, |
| 216 const std::vector<BookmarkNodeData::Element>& elements) { | 184 const std::vector<BookmarkNodeData::Element>& elements) { |
| 217 NSArray* plist = GetPlistForBookmarkList(elements); | 185 NSArray* plist = GetPlistForBookmarkList(elements); |
| 218 [pb setPropertyList:plist forType:kBookmarkDictionaryListPboardType]; | 186 NSString* uti = ui::ClipboardUtil::UTIForPasteboardType( |
| 187 kBookmarkDictionaryListPboardType); |
| 188 [pb addTypes:@[ uti ] owner:nil]; |
| 189 [pb setPropertyList:plist forType:uti]; |
| 219 } | 190 } |
| 220 | 191 |
| 221 void FillFlattenedArraysForBookmarks( | 192 void FillFlattenedArraysForBookmarks( |
| 222 const std::vector<BookmarkNodeData::Element>& elements, | 193 const std::vector<BookmarkNodeData::Element>& elements, |
| 223 NSMutableArray* url_titles, | 194 NSMutableArray* url_titles, |
| 224 NSMutableArray* urls, | 195 NSMutableArray* urls, |
| 225 NSMutableArray* toplevel_string_data) { | 196 NSMutableArray* toplevel_string_data) { |
| 226 for (const BookmarkNodeData::Element& element : elements) { | 197 for (const BookmarkNodeData::Element& element : elements) { |
| 227 NSString* title = base::SysUTF16ToNSString(element.title); | 198 NSString* title = base::SysUTF16ToNSString(element.title); |
| 228 if (element.is_url) { | 199 if (element.is_url) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 241 | 212 |
| 242 void WriteSimplifiedBookmarkTypes( | 213 void WriteSimplifiedBookmarkTypes( |
| 243 NSPasteboard* pb, | 214 NSPasteboard* pb, |
| 244 const std::vector<BookmarkNodeData::Element>& elements) { | 215 const std::vector<BookmarkNodeData::Element>& elements) { |
| 245 NSMutableArray* url_titles = [NSMutableArray array]; | 216 NSMutableArray* url_titles = [NSMutableArray array]; |
| 246 NSMutableArray* urls = [NSMutableArray array]; | 217 NSMutableArray* urls = [NSMutableArray array]; |
| 247 NSMutableArray* toplevel_string_data = [NSMutableArray array]; | 218 NSMutableArray* toplevel_string_data = [NSMutableArray array]; |
| 248 FillFlattenedArraysForBookmarks( | 219 FillFlattenedArraysForBookmarks( |
| 249 elements, url_titles, urls, toplevel_string_data); | 220 elements, url_titles, urls, toplevel_string_data); |
| 250 | 221 |
| 222 if ([urls count] > 0) { |
| 223 base::scoped_nsobject<NSPasteboardItem> item; |
| 224 if ([urls count] == 1) { |
| 225 item = ui::ClipboardUtil::PasteboardItemFromUrl([urls firstObject], |
| 226 [url_titles firstObject]); |
| 227 } else { |
| 228 item = ui::ClipboardUtil::PasteboardItemFromUrls(urls, url_titles); |
| 229 } |
| 230 |
| 231 ui::ClipboardUtil::AddDataToPasteboard(pb, item); |
| 232 } |
| 233 |
| 251 // Write NSStringPboardType. | 234 // Write NSStringPboardType. |
| 235 [pb addTypes:@[ NSStringPboardType ] owner:nil]; |
| 252 [pb setString:[toplevel_string_data componentsJoinedByString:@"\n"] | 236 [pb setString:[toplevel_string_data componentsJoinedByString:@"\n"] |
| 253 forType:NSStringPboardType]; | 237 forType:NSStringPboardType]; |
| 254 | |
| 255 // The following pasteboard types only act on urls, not folders. | |
| 256 if ([urls count] < 1) | |
| 257 return; | |
| 258 | |
| 259 // Write WebURLsWithTitlesPboardType. | |
| 260 [pb setPropertyList:[NSArray arrayWithObjects:urls, url_titles, nil] | |
| 261 forType:kCrWebURLsWithTitlesPboardType]; | |
| 262 | |
| 263 // Write NSURLPboardType (with title). | |
| 264 NSURL* url = [NSURL URLWithString:[urls objectAtIndex:0]]; | |
| 265 [url writeToPasteboard:pb]; | |
| 266 NSString* titleString = [url_titles objectAtIndex:0]; | |
| 267 [pb setString:titleString forType:kNSURLTitlePboardType]; | |
| 268 } | 238 } |
| 269 | 239 |
| 270 NSPasteboard* PasteboardFromType(ui::ClipboardType type) { | 240 NSPasteboard* PasteboardFromType(ui::ClipboardType type) { |
| 271 NSString* type_string = nil; | 241 NSString* type_string = nil; |
| 272 switch (type) { | 242 switch (type) { |
| 273 case ui::CLIPBOARD_TYPE_COPY_PASTE: | 243 case ui::CLIPBOARD_TYPE_COPY_PASTE: |
| 274 type_string = NSGeneralPboard; | 244 type_string = NSGeneralPboard; |
| 275 break; | 245 break; |
| 276 case ui::CLIPBOARD_TYPE_DRAG: | 246 case ui::CLIPBOARD_TYPE_DRAG: |
| 277 type_string = NSDragPboard; | 247 type_string = NSDragPboard; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 288 | 258 |
| 289 void WriteBookmarksToPasteboard( | 259 void WriteBookmarksToPasteboard( |
| 290 ui::ClipboardType type, | 260 ui::ClipboardType type, |
| 291 const std::vector<BookmarkNodeData::Element>& elements, | 261 const std::vector<BookmarkNodeData::Element>& elements, |
| 292 const base::FilePath& profile_path) { | 262 const base::FilePath& profile_path) { |
| 293 if (elements.empty()) | 263 if (elements.empty()) |
| 294 return; | 264 return; |
| 295 | 265 |
| 296 NSPasteboard* pb = PasteboardFromType(type); | 266 NSPasteboard* pb = PasteboardFromType(type); |
| 297 | 267 |
| 298 NSArray* types = [NSArray arrayWithObjects:kBookmarkDictionaryListPboardType, | 268 NSString* uti = |
| 299 kCrWebURLsWithTitlesPboardType, | 269 ui::ClipboardUtil::UTIForPasteboardType(kChromiumProfilePathPboardType); |
| 300 NSStringPboardType, | 270 [pb declareTypes:@[ uti ] owner:nil]; |
| 301 NSURLPboardType, | 271 [pb setString:base::SysUTF8ToNSString(profile_path.value()) forType:uti]; |
| 302 kNSURLTitlePboardType, | |
| 303 kChromiumProfilePathPboardType, | |
| 304 nil]; | |
| 305 [pb declareTypes:types owner:nil]; | |
| 306 [pb setString:base::SysUTF8ToNSString(profile_path.value()) | |
| 307 forType:kChromiumProfilePathPboardType]; | |
| 308 WriteBookmarkDictionaryListPboardType(pb, elements); | 272 WriteBookmarkDictionaryListPboardType(pb, elements); |
| 309 WriteSimplifiedBookmarkTypes(pb, elements); | 273 WriteSimplifiedBookmarkTypes(pb, elements); |
| 310 } | 274 } |
| 311 | 275 |
| 312 bool ReadBookmarksFromPasteboard( | 276 bool ReadBookmarksFromPasteboard( |
| 313 ui::ClipboardType type, | 277 ui::ClipboardType type, |
| 314 std::vector<BookmarkNodeData::Element>& elements, | 278 std::vector<BookmarkNodeData::Element>& elements, |
| 315 base::FilePath* profile_path) { | 279 base::FilePath* profile_path) { |
| 316 NSPasteboard* pb = PasteboardFromType(type); | 280 NSPasteboard* pb = PasteboardFromType(type); |
| 317 | 281 |
| 318 elements.clear(); | 282 elements.clear(); |
| 319 NSString* profile = [pb stringForType:kChromiumProfilePathPboardType]; | 283 NSString* uti = |
| 284 ui::ClipboardUtil::UTIForPasteboardType(kChromiumProfilePathPboardType); |
| 285 NSString* profile = [pb stringForType:uti]; |
| 320 *profile_path = base::FilePath(base::SysNSStringToUTF8(profile)); | 286 *profile_path = base::FilePath(base::SysNSStringToUTF8(profile)); |
| 321 return ReadBookmarkDictionaryListPboardType(pb, elements) || | 287 return ReadBookmarkDictionaryListPboardType(pb, elements) || |
| 322 ReadWebURLsWithTitlesPboardType(pb, elements) || | 288 ReadWebURLsWithTitlesPboardType(pb, elements); |
| 323 ReadNSURLPboardType(pb, elements); | |
| 324 } | 289 } |
| 325 | 290 |
| 326 bool PasteboardContainsBookmarks(ui::ClipboardType type) { | 291 bool PasteboardContainsBookmarks(ui::ClipboardType type) { |
| 327 NSPasteboard* pb = PasteboardFromType(type); | 292 NSPasteboard* pb = PasteboardFromType(type); |
| 328 | 293 |
| 329 NSArray* availableTypes = | 294 NSArray* availableTypes = @[ |
| 330 [NSArray arrayWithObjects:kBookmarkDictionaryListPboardType, | 295 ui::ClipboardUtil::UTIForWebURLsAndTitles(), |
| 331 kCrWebURLsWithTitlesPboardType, | 296 ui::ClipboardUtil::UTIForPasteboardType(kBookmarkDictionaryListPboardType) |
| 332 NSURLPboardType, | 297 ]; |
| 333 nil]; | |
| 334 return [pb availableTypeFromArray:availableTypes] != nil; | 298 return [pb availableTypeFromArray:availableTypes] != nil; |
| 335 } | 299 } |
| 336 | 300 |
| 337 } // namespace bookmarks | 301 } // namespace bookmarks |
| OLD | NEW |