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/platform_util.h" | 5 #include "chrome/browser/platform_util.h" |
6 | 6 |
7 #include <Carbon/Carbon.h> | 7 #include <Carbon/Carbon.h> |
8 #import <Cocoa/Cocoa.h> | 8 #import <Cocoa/Cocoa.h> |
9 #include <CoreServices/CoreServices.h> | 9 #include <CoreServices/CoreServices.h> |
10 | 10 |
11 #include "base/bind.h" | |
12 #include "base/files/file_util.h" | |
11 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
12 #include "base/logging.h" | 14 #include "base/logging.h" |
13 #include "base/mac/mac_logging.h" | 15 #include "base/mac/mac_logging.h" |
14 #import "base/mac/mac_util.h" | 16 #import "base/mac/mac_util.h" |
15 #import "base/mac/sdk_forward_declarations.h" | 17 #import "base/mac/sdk_forward_declarations.h" |
16 #include "base/mac/scoped_aedesc.h" | 18 #include "base/mac/scoped_aedesc.h" |
17 #include "base/strings/sys_string_conversions.h" | 19 #include "base/strings/sys_string_conversions.h" |
20 #include "chrome/browser/platform_util_internal.h" | |
21 #include "content/public/browser/browser_thread.h" | |
18 #include "url/gurl.h" | 22 #include "url/gurl.h" |
19 | 23 |
20 namespace platform_util { | 24 namespace platform_util { |
21 | 25 |
22 void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) { | 26 void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) { |
23 DCHECK([NSThread isMainThread]); | 27 DCHECK([NSThread isMainThread]); |
24 NSString* path_string = base::SysUTF8ToNSString(full_path.value()); | 28 NSString* path_string = base::SysUTF8ToNSString(full_path.value()); |
25 if (!path_string || ![[NSWorkspace sharedWorkspace] selectFile:path_string | 29 if (!path_string || ![[NSWorkspace sharedWorkspace] selectFile:path_string |
26 inFileViewerRootedAtPath:nil]) | 30 inFileViewerRootedAtPath:nil]) |
27 LOG(WARNING) << "NSWorkspace failed to select file " << full_path.value(); | 31 LOG(WARNING) << "NSWorkspace failed to select file " << full_path.value(); |
28 } | 32 } |
29 | 33 |
30 void OpenItem(Profile* profile, const base::FilePath& full_path) { | 34 // This function opens a file. This doesn't use LaunchServices or NSWorkspace |
Robert Sesek
2015/02/05 00:52:29
This comment isn't accurate anymore (c.f. lines 47
asanka
2015/02/05 18:07:25
Comment removed.
| |
35 // because of two bugs: | |
36 // 1. Incorrect app activation with com.apple.quarantine: | |
37 // http://crbug.com/32921 | |
38 // 2. Silent no-op for unassociated file types: http://crbug.com/50263 | |
39 // Instead, an AppleEvent is constructed to tell the Finder to open the | |
40 // document. | |
41 void OpenFileOnMainThread(const base::FilePath& full_path) { | |
31 DCHECK([NSThread isMainThread]); | 42 DCHECK([NSThread isMainThread]); |
32 NSString* path_string = base::SysUTF8ToNSString(full_path.value()); | 43 NSString* path_string = base::SysUTF8ToNSString(full_path.value()); |
33 if (!path_string) | 44 if (!path_string) |
34 return; | 45 return; |
35 | 46 |
36 // On Mavericks or later, NSWorkspaceLaunchWithErrorPresentation will | 47 // On Mavericks or later, NSWorkspaceLaunchWithErrorPresentation will |
37 // properly handle Finder activation for quarantined files | 48 // properly handle Finder activation for quarantined files |
38 // (http://crbug.com/32921) and unassociated file types | 49 // (http://crbug.com/32921) and unassociated file types |
39 // (http://crbug.com/50263). | 50 // (http://crbug.com/50263). |
40 if (base::mac::IsOSMavericksOrLater()) { | 51 if (base::mac::IsOSMavericksOrLater()) { |
(...skipping 16 matching lines...) Expand all Loading... | |
57 // instruct the Finder to open the file. | 68 // instruct the Finder to open the file. |
58 | 69 |
59 // Create the target of this AppleEvent, the Finder. | 70 // Create the target of this AppleEvent, the Finder. |
60 base::mac::ScopedAEDesc<AEAddressDesc> address; | 71 base::mac::ScopedAEDesc<AEAddressDesc> address; |
61 const OSType finderCreatorCode = 'MACS'; | 72 const OSType finderCreatorCode = 'MACS'; |
62 OSErr status = AECreateDesc(typeApplSignature, // type | 73 OSErr status = AECreateDesc(typeApplSignature, // type |
63 &finderCreatorCode, // data | 74 &finderCreatorCode, // data |
64 sizeof(finderCreatorCode), // dataSize | 75 sizeof(finderCreatorCode), // dataSize |
65 address.OutPointer()); // result | 76 address.OutPointer()); // result |
66 if (status != noErr) { | 77 if (status != noErr) { |
67 OSSTATUS_LOG(WARNING, status) << "Could not create OpenItem() AE target"; | 78 OSSTATUS_LOG(WARNING, status) << "Could not create OpenFile() AE target"; |
68 return; | 79 return; |
69 } | 80 } |
70 | 81 |
71 // Build the AppleEvent data structure that instructs Finder to open files. | 82 // Build the AppleEvent data structure that instructs Finder to open files. |
72 base::mac::ScopedAEDesc<AppleEvent> theEvent; | 83 base::mac::ScopedAEDesc<AppleEvent> theEvent; |
73 status = AECreateAppleEvent(kCoreEventClass, // theAEEventClass | 84 status = AECreateAppleEvent(kCoreEventClass, // theAEEventClass |
74 kAEOpenDocuments, // theAEEventID | 85 kAEOpenDocuments, // theAEEventID |
75 address, // target | 86 address, // target |
76 kAutoGenerateReturnID, // returnID | 87 kAutoGenerateReturnID, // returnID |
77 kAnyTransactionID, // transactionID | 88 kAnyTransactionID, // transactionID |
78 theEvent.OutPointer()); // result | 89 theEvent.OutPointer()); // result |
79 if (status != noErr) { | 90 if (status != noErr) { |
80 OSSTATUS_LOG(WARNING, status) << "Could not create OpenItem() AE event"; | 91 OSSTATUS_LOG(WARNING, status) << "Could not create OpenFile() AE event"; |
81 return; | 92 return; |
82 } | 93 } |
83 | 94 |
84 // Create the list of files (only ever one) to open. | 95 // Create the list of files (only ever one) to open. |
85 base::mac::ScopedAEDesc<AEDescList> fileList; | 96 base::mac::ScopedAEDesc<AEDescList> fileList; |
86 status = AECreateList(NULL, // factoringPtr | 97 status = AECreateList(NULL, // factoringPtr |
87 0, // factoredSize | 98 0, // factoredSize |
88 false, // isRecord | 99 false, // isRecord |
89 fileList.OutPointer()); // resultList | 100 fileList.OutPointer()); // resultList |
90 if (status != noErr) { | 101 if (status != noErr) { |
91 OSSTATUS_LOG(WARNING, status) << "Could not create OpenItem() AE file list"; | 102 OSSTATUS_LOG(WARNING, status) << "Could not create OpenFile() AE file list"; |
92 return; | 103 return; |
93 } | 104 } |
94 | 105 |
95 // Add the single path to the file list. C-style cast to avoid both a | 106 // Add the single path to the file list. C-style cast to avoid both a |
96 // static_cast and a const_cast to get across the toll-free bridge. | 107 // static_cast and a const_cast to get across the toll-free bridge. |
97 CFURLRef pathURLRef = (CFURLRef)[NSURL fileURLWithPath:path_string]; | 108 CFURLRef pathURLRef = (CFURLRef)[NSURL fileURLWithPath:path_string]; |
98 FSRef pathRef; | 109 FSRef pathRef; |
99 if (CFURLGetFSRef(pathURLRef, &pathRef)) { | 110 if (CFURLGetFSRef(pathURLRef, &pathRef)) { |
100 status = AEPutPtr(fileList.OutPointer(), // theAEDescList | 111 status = AEPutPtr(fileList.OutPointer(), // theAEDescList |
101 0, // index | 112 0, // index |
102 typeFSRef, // typeCode | 113 typeFSRef, // typeCode |
103 &pathRef, // dataPtr | 114 &pathRef, // dataPtr |
104 sizeof(pathRef)); // dataSize | 115 sizeof(pathRef)); // dataSize |
105 if (status != noErr) { | 116 if (status != noErr) { |
106 OSSTATUS_LOG(WARNING, status) | 117 OSSTATUS_LOG(WARNING, status) |
107 << "Could not add file path to AE list in OpenItem()"; | 118 << "Could not add file path to AE list in OpenFile()"; |
108 return; | 119 return; |
109 } | 120 } |
110 } else { | 121 } else { |
111 LOG(WARNING) << "Could not get FSRef for path URL in OpenItem()"; | 122 LOG(WARNING) << "Could not get FSRef for path URL in OpenFile()"; |
112 return; | 123 return; |
113 } | 124 } |
114 | 125 |
115 // Attach the file list to the AppleEvent. | 126 // Attach the file list to the AppleEvent. |
116 status = AEPutParamDesc(theEvent.OutPointer(), // theAppleEvent | 127 status = AEPutParamDesc(theEvent.OutPointer(), // theAppleEvent |
117 keyDirectObject, // theAEKeyword | 128 keyDirectObject, // theAEKeyword |
118 fileList); // theAEDesc | 129 fileList); // theAEDesc |
119 if (status != noErr) { | 130 if (status != noErr) { |
120 OSSTATUS_LOG(WARNING, status) | 131 OSSTATUS_LOG(WARNING, status) |
121 << "Could not put the AE file list the path in OpenItem()"; | 132 << "Could not put the AE file list the path in OpenFile()"; |
122 return; | 133 return; |
123 } | 134 } |
124 | 135 |
125 // Send the actual event. Do not care about the reply. | 136 // Send the actual event. Do not care about the reply. |
126 base::mac::ScopedAEDesc<AppleEvent> reply; | 137 base::mac::ScopedAEDesc<AppleEvent> reply; |
127 status = AESend(theEvent, // theAppleEvent | 138 status = AESend(theEvent, // theAppleEvent |
128 reply.OutPointer(), // reply | 139 reply.OutPointer(), // reply |
129 kAENoReply + kAEAlwaysInteract, // sendMode | 140 kAENoReply + kAEAlwaysInteract, // sendMode |
130 kAENormalPriority, // sendPriority | 141 kAENormalPriority, // sendPriority |
131 kAEDefaultTimeout, // timeOutInTicks | 142 kAEDefaultTimeout, // timeOutInTicks |
132 NULL, // idleProc | 143 NULL, // idleProc |
133 NULL); // filterProc | 144 NULL); // filterProc |
134 if (status != noErr) { | 145 if (status != noErr) { |
135 OSSTATUS_LOG(WARNING, status) | 146 OSSTATUS_LOG(WARNING, status) |
136 << "Could not send AE to Finder in OpenItem()"; | 147 << "Could not send AE to Finder in OpenFile()"; |
137 } | 148 } |
138 } | 149 } |
139 | 150 |
151 namespace internal { | |
152 | |
153 void PlatformOpenVerifiedItem(const base::FilePath& path, OpenItemType type) { | |
154 switch (type) { | |
155 case OPEN_FILE: | |
156 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | |
157 base::Bind(&OpenFileOnMainThread, path)); | |
158 return; | |
159 case OPEN_FOLDER: | |
160 NSString* path_string = base::SysUTF8ToNSString(path.value()); | |
161 if (!path_string) | |
162 return; | |
163 [[NSWorkspace sharedWorkspace] openFile:path_string | |
Robert Sesek
2015/02/05 00:52:29
Does:
NSURL* url = [NSURL fileURLWithPath:path_
asanka
2015/02/05 18:07:25
I tried this, but it doesn't have the intended eff
Robert Sesek
2015/02/05 23:37:55
I think the only difference between this method an
| |
164 withApplication:@"Finder"]; | |
165 return; | |
166 } | |
167 } | |
168 } | |
Robert Sesek
2015/02/05 00:52:29
nit: blank line before, and " // namespace intern
asanka
2015/02/05 18:07:25
Done.
| |
169 | |
140 void OpenExternal(Profile* profile, const GURL& url) { | 170 void OpenExternal(Profile* profile, const GURL& url) { |
141 DCHECK([NSThread isMainThread]); | 171 DCHECK([NSThread isMainThread]); |
142 NSString* url_string = base::SysUTF8ToNSString(url.spec()); | 172 NSString* url_string = base::SysUTF8ToNSString(url.spec()); |
143 NSURL* ns_url = [NSURL URLWithString:url_string]; | 173 NSURL* ns_url = [NSURL URLWithString:url_string]; |
144 if (!ns_url || ![[NSWorkspace sharedWorkspace] openURL:ns_url]) | 174 if (!ns_url || ![[NSWorkspace sharedWorkspace] openURL:ns_url]) |
145 LOG(WARNING) << "NSWorkspace failed to open URL " << url; | 175 LOG(WARNING) << "NSWorkspace failed to open URL " << url; |
146 } | 176 } |
147 | 177 |
148 gfx::NativeWindow GetTopLevel(gfx::NativeView view) { | 178 gfx::NativeWindow GetTopLevel(gfx::NativeView view) { |
149 return [view window]; | 179 return [view window]; |
(...skipping 25 matching lines...) Expand all Loading... | |
175 [[view window] isVisible]); | 205 [[view window] isVisible]); |
176 } | 206 } |
177 | 207 |
178 bool IsSwipeTrackingFromScrollEventsEnabled() { | 208 bool IsSwipeTrackingFromScrollEventsEnabled() { |
179 SEL selector = @selector(isSwipeTrackingFromScrollEventsEnabled); | 209 SEL selector = @selector(isSwipeTrackingFromScrollEventsEnabled); |
180 return [NSEvent respondsToSelector:selector] | 210 return [NSEvent respondsToSelector:selector] |
181 && [NSEvent performSelector:selector]; | 211 && [NSEvent performSelector:selector]; |
182 } | 212 } |
183 | 213 |
184 } // namespace platform_util | 214 } // namespace platform_util |
OLD | NEW |