OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/platform_util.h" | 5 #include "chrome/browser/platform_util.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 #import <CoreServices/CoreServices.h> |
8 | 9 |
9 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
10 #include "app/l10n_util_mac.h" | 11 #include "app/l10n_util_mac.h" |
11 #include "base/file_path.h" | 12 #include "base/file_path.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/mac_util.h" | 14 #include "base/mac_util.h" |
| 15 #include "base/scoped_aedesc.h" |
14 #include "base/sys_string_conversions.h" | 16 #include "base/sys_string_conversions.h" |
15 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
16 #include "grit/generated_resources.h" | 18 #include "grit/generated_resources.h" |
17 | 19 |
18 namespace platform_util { | 20 namespace platform_util { |
19 | 21 |
20 void ShowItemInFolder(const FilePath& full_path) { | 22 void ShowItemInFolder(const FilePath& full_path) { |
21 DCHECK_EQ([NSThread currentThread], [NSThread mainThread]); | 23 DCHECK_EQ([NSThread currentThread], [NSThread mainThread]); |
22 NSString* path_string = base::SysUTF8ToNSString(full_path.value()); | 24 NSString* path_string = base::SysUTF8ToNSString(full_path.value()); |
23 if (!path_string || ![[NSWorkspace sharedWorkspace] selectFile:path_string | 25 if (!path_string || ![[NSWorkspace sharedWorkspace] selectFile:path_string |
24 inFileViewerRootedAtPath:nil]) | 26 inFileViewerRootedAtPath:nil]) |
25 LOG(WARNING) << "NSWorkspace failed to select file " << full_path.value(); | 27 LOG(WARNING) << "NSWorkspace failed to select file " << full_path.value(); |
26 } | 28 } |
27 | 29 |
| 30 // This function opens a file. This doesn't use LaunchServices or NSWorkspace |
| 31 // because of two bugs: |
| 32 // 1. Incorrect app activation with com.apple.quarantine: |
| 33 // http://crbug.com/32921 |
| 34 // 2. Silent no-op for unassociated file types: http://crbug.com/50263 |
| 35 // Instead, an AppleEvent is constructed to tell the Finder to open the |
| 36 // document. |
28 void OpenItem(const FilePath& full_path) { | 37 void OpenItem(const FilePath& full_path) { |
29 DCHECK_EQ([NSThread currentThread], [NSThread mainThread]); | 38 DCHECK_EQ([NSThread currentThread], [NSThread mainThread]); |
30 NSString* path_string = base::SysUTF8ToNSString(full_path.value()); | 39 NSString* path_string = base::SysUTF8ToNSString(full_path.value()); |
31 if (!path_string || ![[NSWorkspace sharedWorkspace] openFile:path_string]) | 40 if (!path_string) |
32 LOG(WARNING) << "NSWorkspace failed to open file " << full_path.value(); | 41 return; |
| 42 |
| 43 OSErr status; |
| 44 |
| 45 // Create the target of this AppleEvent, the Finder. |
| 46 scoped_aedesc<AEAddressDesc> address; |
| 47 const OSType finderCreatorCode = 'MACS'; |
| 48 status = AECreateDesc(typeApplSignature, // type |
| 49 &finderCreatorCode, // data |
| 50 sizeof(finderCreatorCode), // dataSize |
| 51 address.OutPointer()); // result |
| 52 if (status != noErr) { |
| 53 LOG(WARNING) << "Could not create OpenItem() AE target"; |
| 54 return; |
| 55 } |
| 56 |
| 57 // Build the AppleEvent data structure that instructs Finder to open files. |
| 58 scoped_aedesc<AppleEvent> theEvent; |
| 59 status = AECreateAppleEvent(kCoreEventClass, // theAEEventClass |
| 60 kAEOpenDocuments, // theAEEventID |
| 61 address, // target |
| 62 kAutoGenerateReturnID, // returnID |
| 63 kAnyTransactionID, // transactionID |
| 64 theEvent.OutPointer()); // result |
| 65 if (status != noErr) { |
| 66 LOG(WARNING) << "Could not create OpenItem() AE event"; |
| 67 return; |
| 68 } |
| 69 |
| 70 // Create the list of files (only ever one) to open. |
| 71 scoped_aedesc<AEDescList> fileList; |
| 72 status = AECreateList(NULL, // factoringPtr |
| 73 0, // factoredSize |
| 74 false, // isRecord |
| 75 fileList.OutPointer()); // resultList |
| 76 if (status != noErr) { |
| 77 LOG(WARNING) << "Could not create OpenItem() AE file list"; |
| 78 return; |
| 79 } |
| 80 |
| 81 // Add the single path to the file list. C-style cast to avoid both a |
| 82 // static_cast and a const_cast to get across the toll-free bridge. |
| 83 CFURLRef pathURLRef = (CFURLRef)[NSURL fileURLWithPath:path_string]; |
| 84 FSRef pathRef; |
| 85 if (CFURLGetFSRef(pathURLRef, &pathRef)) { |
| 86 status = AEPutPtr(fileList.OutPointer(), // theAEDescList |
| 87 0, // index |
| 88 typeFSRef, // typeCode |
| 89 &pathRef, // dataPtr |
| 90 sizeof(pathRef)); // dataSize |
| 91 if (status != noErr) { |
| 92 LOG(WARNING) << "Could not add file path to AE list in OpenItem()"; |
| 93 return; |
| 94 } |
| 95 } else { |
| 96 LOG(WARNING) << "Could not get FSRef for path URL in OpenItem()"; |
| 97 return; |
| 98 } |
| 99 |
| 100 // Attach the file list to the AppleEvent. |
| 101 status = AEPutParamDesc(theEvent.OutPointer(), // theAppleEvent |
| 102 keyDirectObject, // theAEKeyword |
| 103 fileList); // theAEDesc |
| 104 if (status != noErr) { |
| 105 LOG(WARNING) << "Could not put the AE file list the path in OpenItem()"; |
| 106 return; |
| 107 } |
| 108 |
| 109 // Send the actual event. Do not care about the reply. |
| 110 scoped_aedesc<AppleEvent> reply; |
| 111 status = AESend(theEvent, // theAppleEvent |
| 112 reply.OutPointer(), // reply |
| 113 kAENoReply + kAEAlwaysInteract, // sendMode |
| 114 kAENormalPriority, // sendPriority |
| 115 kAEDefaultTimeout, // timeOutInTicks |
| 116 NULL, // idleProc |
| 117 NULL); // filterProc |
| 118 if (status != noErr) { |
| 119 LOG(WARNING) << "Could not send AE to Finder in OpenItem()"; |
| 120 } |
33 } | 121 } |
34 | 122 |
35 void OpenExternal(const GURL& url) { | 123 void OpenExternal(const GURL& url) { |
36 DCHECK_EQ([NSThread currentThread], [NSThread mainThread]); | 124 DCHECK_EQ([NSThread currentThread], [NSThread mainThread]); |
37 NSString* url_string = base::SysUTF8ToNSString(url.spec()); | 125 NSString* url_string = base::SysUTF8ToNSString(url.spec()); |
38 NSURL* ns_url = [NSURL URLWithString:url_string]; | 126 NSURL* ns_url = [NSURL URLWithString:url_string]; |
39 if (!ns_url || ![[NSWorkspace sharedWorkspace] openURL:ns_url]) | 127 if (!ns_url || ![[NSWorkspace sharedWorkspace] openURL:ns_url]) |
40 LOG(WARNING) << "NSWorkspace failed to open URL " << url; | 128 LOG(WARNING) << "NSWorkspace failed to open URL " << url; |
41 } | 129 } |
42 | 130 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 channel = @"unknown"; | 196 channel = @"unknown"; |
109 } | 197 } |
110 | 198 |
111 return base::SysNSStringToUTF16(channel); | 199 return base::SysNSStringToUTF16(channel); |
112 #else | 200 #else |
113 return string16(); | 201 return string16(); |
114 #endif | 202 #endif |
115 } | 203 } |
116 | 204 |
117 } // namespace platform_util | 205 } // namespace platform_util |
OLD | NEW |