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( | |
33 const std::vector<FilePath::StringType>& ext_list) { | |
34 // The extensions specified in FileTypeInfo contains a list of lists; the | |
35 // example given there is: | |
36 // { { "htm", "html" }, { "txt" } } | |
37 // In that case, each extension list holds synonym extensions for the same | |
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 } | |
48 | |
49 } // namespace | 32 } // namespace |
50 | 33 |
51 class SelectFileDialogImpl; | 34 class SelectFileDialogImpl; |
52 | 35 |
53 // A bridge class to act as the modal delegate to the save/open sheet and send | 36 // A bridge class to act as the modal delegate to the save/open sheet and send |
54 // the results to the C++ class. | 37 // the results to the C++ class. |
55 @interface SelectFileDialogBridge : NSObject<NSOpenSavePanelDelegate> { | 38 @interface SelectFileDialogBridge : NSObject<NSOpenSavePanelDelegate> { |
56 @private | 39 @private |
57 SelectFileDialogImpl* selectFileDialogImpl_; // WEAK; owns us | 40 SelectFileDialogImpl* selectFileDialogImpl_; // WEAK; owns us |
58 } | 41 } |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 base::ThreadRestrictions::ScopedAllowIO allow_io; | 202 base::ThreadRestrictions::ScopedAllowIO allow_io; |
220 if (file_util::DirectoryExists(default_path)) { | 203 if (file_util::DirectoryExists(default_path)) { |
221 default_dir = base::SysUTF8ToNSString(default_path.value()); | 204 default_dir = base::SysUTF8ToNSString(default_path.value()); |
222 } else { | 205 } else { |
223 default_dir = base::SysUTF8ToNSString(default_path.DirName().value()); | 206 default_dir = base::SysUTF8ToNSString(default_path.DirName().value()); |
224 default_filename = | 207 default_filename = |
225 base::SysUTF8ToNSString(default_path.BaseName().value()); | 208 base::SysUTF8ToNSString(default_path.BaseName().value()); |
226 } | 209 } |
227 } | 210 } |
228 | 211 |
229 NSMutableArray* allowed_file_types = nil; | 212 NSArray* allowed_file_types = nil; |
230 if (file_types) { | 213 if (file_types) { |
231 if (!file_types->extensions.empty()) { | 214 if (!file_types->extensions.empty()) { |
232 allowed_file_types = [NSMutableArray array]; | 215 // While the example given in the header for FileTypeInfo lists an example |
216 // |file_types->extensions| value as | |
217 // { { "htm", "html" }, { "txt" } } | |
218 // it is not always the case that the given extensions in one of the sub- | |
219 // lists are all synonyms. In fact, in the case of a <select> element with | |
220 // multiple "accept" types, all the extensions allowed for all the types | |
221 // will be part of one list. To be safe, allow the types of all the | |
222 // specified extensions. | |
223 NSMutableSet* file_type_set = [NSMutableSet set]; | |
233 for (size_t i = 0; i < file_types->extensions.size(); ++i) { | 224 for (size_t i = 0; i < file_types->extensions.size(); ++i) { |
234 base::mac::ScopedCFTypeRef<CFStringRef> uti( | 225 const std::vector<FilePath::StringType>& ext_list = |
235 CreateUTIFromExtensionList(file_types->extensions[i])); | 226 file_types->extensions[i]; |
236 [allowed_file_types addObject:base::mac::CFToNSCast(uti.get())]; | 227 for (size_t j = 0; j < ext_list.size(); ++j) { |
228 NSString* type_extension = base::SysUTF8ToNSString(ext_list[j]); | |
Nico
2012/05/15 15:38:50
nit: it might be worth it to have a function that
Avi (use Gerrit)
2012/05/15 15:54:13
Done.
| |
229 base::mac::ScopedCFTypeRef<CFStringRef> uti( | |
230 UTTypeCreatePreferredIdentifierForTag( | |
231 kUTTagClassFilenameExtension, | |
232 base::mac::NSToCFCast(type_extension), | |
233 NULL)); | |
234 [file_type_set addObject:base::mac::CFToNSCast(uti.get())]; | |
235 } | |
237 } | 236 } |
237 allowed_file_types = [file_type_set allObjects]; | |
238 } | 238 } |
239 if (type == SELECT_SAVEAS_FILE) | 239 if (type == SELECT_SAVEAS_FILE) |
240 [dialog setAllowedFileTypes:allowed_file_types]; | 240 [dialog setAllowedFileTypes:allowed_file_types]; |
241 // else we'll pass it in when we run the open panel | 241 // else we'll pass it in when we run the open panel |
242 | 242 |
243 if (file_types->include_all_files) | 243 if (file_types->include_all_files) |
244 [dialog setAllowsOtherFileTypes:YES]; | 244 [dialog setAllowsOtherFileTypes:YES]; |
245 | 245 |
246 if (file_types->extension_description_overrides.size() > 1) { | 246 if (file_types->extension_description_overrides.size() > 1) { |
247 NSView* accessory_view = GetAccessoryView(file_types, file_type_index); | 247 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]; | 333 NSPopUpButton* popup = [accessory_view viewWithTag:kFileTypePopupTag]; |
334 DCHECK(popup); | 334 DCHECK(popup); |
335 | 335 |
336 size_t type_count = file_types->extensions.size(); | 336 size_t type_count = file_types->extensions.size(); |
337 for (size_t type = 0; type < type_count; ++type) { | 337 for (size_t type = 0; type < type_count; ++type) { |
338 NSString* type_description; | 338 NSString* type_description; |
339 if (type < file_types->extension_description_overrides.size()) { | 339 if (type < file_types->extension_description_overrides.size()) { |
340 type_description = base::SysUTF16ToNSString( | 340 type_description = base::SysUTF16ToNSString( |
341 file_types->extension_description_overrides[type]); | 341 file_types->extension_description_overrides[type]); |
342 } else { | 342 } else { |
343 // No description given for a list of extensions; pick the first one from | |
344 // the list (arbitrarily) and use its description. | |
345 const std::vector<FilePath::StringType>& ext_list = | |
346 file_types->extensions[type]; | |
347 DCHECK(!ext_list.empty()); | |
348 NSString* type_extension = base::SysUTF8ToNSString(ext_list[0]); | |
343 base::mac::ScopedCFTypeRef<CFStringRef> uti( | 349 base::mac::ScopedCFTypeRef<CFStringRef> uti( |
344 CreateUTIFromExtensionList(file_types->extensions[type])); | 350 UTTypeCreatePreferredIdentifierForTag( |
351 kUTTagClassFilenameExtension, | |
352 base::mac::NSToCFCast(type_extension), | |
353 NULL)); | |
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 |