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 "chrome/browser/ui/select_file_dialog.h" | 5 #include "chrome/browser/ui/select_file_dialog.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 #include <CoreServices/CoreServices.h> | 8 #include <CoreServices/CoreServices.h> |
9 | 9 |
10 #include <map> | 10 #include <map> |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "base/sys_string_conversions.h" | 22 #include "base/sys_string_conversions.h" |
23 #include "base/threading/thread_restrictions.h" | 23 #include "base/threading/thread_restrictions.h" |
24 #include "grit/generated_resources.h" | 24 #include "grit/generated_resources.h" |
25 #import "ui/base/cocoa/nib_loading.h" | 25 #import "ui/base/cocoa/nib_loading.h" |
26 #include "ui/base/l10n/l10n_util_mac.h" | 26 #include "ui/base/l10n/l10n_util_mac.h" |
27 | 27 |
28 namespace { | 28 namespace { |
29 | 29 |
30 const int kFileTypePopupTag = 1234; | 30 const int kFileTypePopupTag = 1234; |
31 | 31 |
32 CFStringRef CreateUTIFromExtensionList( | 32 CFStringRef CreateUTIFromExtension(const FilePath::StringType& ext) { |
33 const std::vector<FilePath::StringType>& ext_list) { | 33 base::mac::ScopedCFTypeRef<CFStringRef> ext_cf( |
34 // The extensions specified in FileTypeInfo contains a list of lists; the | 34 base::SysUTF8ToCFStringRef(ext)); |
35 // example given there is: | 35 return UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, |
36 // { { "htm", "html" }, { "txt" } } | 36 ext_cf.get(), |
37 // In that case, each extension list holds synonym extensions for the same | 37 NULL); |
38 // file type. With Uniform Type Identifiers there is one identifier that | |
39 // covers all those extensions, so if they are all synonymous anyway, just | |
40 // make a UTI from the first. | |
41 DCHECK(!ext_list.empty()); | |
42 base::mac::ScopedCFTypeRef<CFStringRef> type_extension( | |
43 base::SysUTF8ToCFStringRef(ext_list[0])); | |
44 return UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, | |
45 type_extension.get(), | |
46 NULL); | |
47 } | 38 } |
48 | 39 |
49 } // namespace | 40 } // namespace |
50 | 41 |
51 class SelectFileDialogImpl; | 42 class SelectFileDialogImpl; |
52 | 43 |
53 // A bridge class to act as the modal delegate to the save/open sheet and send | 44 // A bridge class to act as the modal delegate to the save/open sheet and send |
54 // the results to the C++ class. | 45 // the results to the C++ class. |
55 @interface SelectFileDialogBridge : NSObject<NSOpenSavePanelDelegate> { | 46 @interface SelectFileDialogBridge : NSObject<NSOpenSavePanelDelegate> { |
56 @private | 47 @private |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 base::ThreadRestrictions::ScopedAllowIO allow_io; | 210 base::ThreadRestrictions::ScopedAllowIO allow_io; |
220 if (file_util::DirectoryExists(default_path)) { | 211 if (file_util::DirectoryExists(default_path)) { |
221 default_dir = base::SysUTF8ToNSString(default_path.value()); | 212 default_dir = base::SysUTF8ToNSString(default_path.value()); |
222 } else { | 213 } else { |
223 default_dir = base::SysUTF8ToNSString(default_path.DirName().value()); | 214 default_dir = base::SysUTF8ToNSString(default_path.DirName().value()); |
224 default_filename = | 215 default_filename = |
225 base::SysUTF8ToNSString(default_path.BaseName().value()); | 216 base::SysUTF8ToNSString(default_path.BaseName().value()); |
226 } | 217 } |
227 } | 218 } |
228 | 219 |
229 NSMutableArray* allowed_file_types = nil; | 220 NSArray* allowed_file_types = nil; |
230 if (file_types) { | 221 if (file_types) { |
231 if (!file_types->extensions.empty()) { | 222 if (!file_types->extensions.empty()) { |
232 allowed_file_types = [NSMutableArray array]; | 223 // While the example given in the header for FileTypeInfo lists an example |
| 224 // |file_types->extensions| value as |
| 225 // { { "htm", "html" }, { "txt" } } |
| 226 // it is not always the case that the given extensions in one of the sub- |
| 227 // lists are all synonyms. In fact, in the case of a <select> element with |
| 228 // multiple "accept" types, all the extensions allowed for all the types |
| 229 // will be part of one list. To be safe, allow the types of all the |
| 230 // specified extensions. |
| 231 NSMutableSet* file_type_set = [NSMutableSet set]; |
233 for (size_t i = 0; i < file_types->extensions.size(); ++i) { | 232 for (size_t i = 0; i < file_types->extensions.size(); ++i) { |
234 base::mac::ScopedCFTypeRef<CFStringRef> uti( | 233 const std::vector<FilePath::StringType>& ext_list = |
235 CreateUTIFromExtensionList(file_types->extensions[i])); | 234 file_types->extensions[i]; |
236 [allowed_file_types addObject:base::mac::CFToNSCast(uti.get())]; | 235 for (size_t j = 0; j < ext_list.size(); ++j) { |
| 236 base::mac::ScopedCFTypeRef<CFStringRef> uti( |
| 237 CreateUTIFromExtension(ext_list[j])); |
| 238 [file_type_set addObject:base::mac::CFToNSCast(uti.get())]; |
| 239 } |
237 } | 240 } |
| 241 allowed_file_types = [file_type_set allObjects]; |
238 } | 242 } |
239 if (type == SELECT_SAVEAS_FILE) | 243 if (type == SELECT_SAVEAS_FILE) |
240 [dialog setAllowedFileTypes:allowed_file_types]; | 244 [dialog setAllowedFileTypes:allowed_file_types]; |
241 // else we'll pass it in when we run the open panel | 245 // else we'll pass it in when we run the open panel |
242 | 246 |
243 if (file_types->include_all_files) | 247 if (file_types->include_all_files) |
244 [dialog setAllowsOtherFileTypes:YES]; | 248 [dialog setAllowsOtherFileTypes:YES]; |
245 | 249 |
246 if (file_types->extension_description_overrides.size() > 1) { | 250 if (file_types->extension_description_overrides.size() > 1) { |
247 NSView* accessory_view = GetAccessoryView(file_types, file_type_index); | 251 NSView* accessory_view = GetAccessoryView(file_types, file_type_index); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 NSPopUpButton* popup = [accessory_view viewWithTag:kFileTypePopupTag]; | 337 NSPopUpButton* popup = [accessory_view viewWithTag:kFileTypePopupTag]; |
334 DCHECK(popup); | 338 DCHECK(popup); |
335 | 339 |
336 size_t type_count = file_types->extensions.size(); | 340 size_t type_count = file_types->extensions.size(); |
337 for (size_t type = 0; type < type_count; ++type) { | 341 for (size_t type = 0; type < type_count; ++type) { |
338 NSString* type_description; | 342 NSString* type_description; |
339 if (type < file_types->extension_description_overrides.size()) { | 343 if (type < file_types->extension_description_overrides.size()) { |
340 type_description = base::SysUTF16ToNSString( | 344 type_description = base::SysUTF16ToNSString( |
341 file_types->extension_description_overrides[type]); | 345 file_types->extension_description_overrides[type]); |
342 } else { | 346 } else { |
| 347 // No description given for a list of extensions; pick the first one from |
| 348 // the list (arbitrarily) and use its description. |
| 349 const std::vector<FilePath::StringType>& ext_list = |
| 350 file_types->extensions[type]; |
| 351 DCHECK(!ext_list.empty()); |
343 base::mac::ScopedCFTypeRef<CFStringRef> uti( | 352 base::mac::ScopedCFTypeRef<CFStringRef> uti( |
344 CreateUTIFromExtensionList(file_types->extensions[type])); | 353 CreateUTIFromExtension(ext_list[0])); |
345 base::mac::ScopedCFTypeRef<CFStringRef> description( | 354 base::mac::ScopedCFTypeRef<CFStringRef> description( |
346 UTTypeCopyDescription(uti.get())); | 355 UTTypeCopyDescription(uti.get())); |
347 | 356 |
348 type_description = | 357 type_description = |
349 [[base::mac::CFToNSCast(description.get()) retain] autorelease]; | 358 [[base::mac::CFToNSCast(description.get()) retain] autorelease]; |
350 } | 359 } |
351 [popup addItemWithTitle:type_description]; | 360 [popup addItemWithTitle:type_description]; |
352 } | 361 } |
353 | 362 |
354 [popup selectItemAtIndex:file_type_index - 1]; // 1-based | 363 [popup selectItemAtIndex:file_type_index - 1]; // 1-based |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 paths, | 427 paths, |
419 index); | 428 index); |
420 [panel release]; | 429 [panel release]; |
421 } | 430 } |
422 | 431 |
423 - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename { | 432 - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename { |
424 return selectFileDialogImpl_->ShouldEnableFilename(sender, filename); | 433 return selectFileDialogImpl_->ShouldEnableFilename(sender, filename); |
425 } | 434 } |
426 | 435 |
427 @end | 436 @end |
OLD | NEW |