Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Unified Diff: chrome/browser/platform_util_mac.mm

Issue 3151011: [Mac] Use an AppleEvent to tell the Finder to open downloaded items, rather than NSWorkspace. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: Address comments Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/scoped_aedesc.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/platform_util_mac.mm
diff --git a/chrome/browser/platform_util_mac.mm b/chrome/browser/platform_util_mac.mm
index 3192fcc489b034f41807fda547e41ab339ba6df0..7c719501f3618047b190b4933e5dd3d003f5ef14 100644
--- a/chrome/browser/platform_util_mac.mm
+++ b/chrome/browser/platform_util_mac.mm
@@ -5,12 +5,14 @@
#include "chrome/browser/platform_util.h"
#import <Cocoa/Cocoa.h>
+#import <CoreServices/CoreServices.h>
#include "app/l10n_util.h"
#include "app/l10n_util_mac.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/mac_util.h"
+#include "base/scoped_aedesc.h"
#include "base/sys_string_conversions.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
@@ -25,11 +27,97 @@ void ShowItemInFolder(const FilePath& full_path) {
LOG(WARNING) << "NSWorkspace failed to select file " << full_path.value();
}
+// This function opens a file. This doesn't use LaunchServices or NSWorkspace
+// because of two bugs:
+// 1. Incorrect app activation with com.apple.quarantine:
+// http://crbug.com/32921
+// 2. Silent no-op for unassociated file types: http://crbug.com/50263
+// Instead, an AppleEvent is constructed to tell the Finder to open the
+// document.
void OpenItem(const FilePath& full_path) {
DCHECK_EQ([NSThread currentThread], [NSThread mainThread]);
NSString* path_string = base::SysUTF8ToNSString(full_path.value());
- if (!path_string || ![[NSWorkspace sharedWorkspace] openFile:path_string])
- LOG(WARNING) << "NSWorkspace failed to open file " << full_path.value();
+ if (!path_string)
+ return;
+
+ OSErr status;
+
+ // Create the target of this AppleEvent, the Finder.
+ scoped_aedesc<AEAddressDesc> address;
+ const OSType finderCreatorCode = 'MACS';
+ status = AECreateDesc(typeApplSignature, // type
+ &finderCreatorCode, // data
+ sizeof(finderCreatorCode), // dataSize
+ address.OutPointer()); // result
+ if (status != noErr) {
+ LOG(WARNING) << "Could not create OpenItem() AE target";
+ return;
+ }
+
+ // Build the AppleEvent data structure that instructs Finder to open files.
+ scoped_aedesc<AppleEvent> theEvent;
+ status = AECreateAppleEvent(kCoreEventClass, // theAEEventClass
+ kAEOpenDocuments, // theAEEventID
+ address, // target
+ kAutoGenerateReturnID, // returnID
+ kAnyTransactionID, // transactionID
+ theEvent.OutPointer()); // result
+ if (status != noErr) {
+ LOG(WARNING) << "Could not create OpenItem() AE event";
+ return;
+ }
+
+ // Create the list of files (only ever one) to open.
+ scoped_aedesc<AEDescList> fileList;
+ status = AECreateList(NULL, // factoringPtr
+ 0, // factoredSize
+ false, // isRecord
+ fileList.OutPointer()); // resultList
+ if (status != noErr) {
+ LOG(WARNING) << "Could not create OpenItem() AE file list";
+ return;
+ }
+
+ // Add the single path to the file list. C-style cast to avoid both a
+ // static_cast and a const_cast to get across the toll-free bridge.
+ CFURLRef pathURLRef = (CFURLRef)[NSURL fileURLWithPath:path_string];
+ FSRef pathRef;
+ if (CFURLGetFSRef(pathURLRef, &pathRef)) {
+ status = AEPutPtr(fileList.OutPointer(), // theAEDescList
+ 0, // index
+ typeFSRef, // typeCode
+ &pathRef, // dataPtr
+ sizeof(pathRef)); // dataSize
+ if (status != noErr) {
+ LOG(WARNING) << "Could not add file path to AE list in OpenItem()";
+ return;
+ }
+ } else {
+ LOG(WARNING) << "Could not get FSRef for path URL in OpenItem()";
+ return;
+ }
+
+ // Attach the file list to the AppleEvent.
+ status = AEPutParamDesc(theEvent.OutPointer(), // theAppleEvent
+ keyDirectObject, // theAEKeyword
+ fileList); // theAEDesc
+ if (status != noErr) {
+ LOG(WARNING) << "Could not put the AE file list the path in OpenItem()";
+ return;
+ }
+
+ // Send the actual event. Do not care about the reply.
+ scoped_aedesc<AppleEvent> reply;
+ status = AESend(theEvent, // theAppleEvent
+ reply.OutPointer(), // reply
+ kAENoReply + kAEAlwaysInteract, // sendMode
+ kAENormalPriority, // sendPriority
+ kAEDefaultTimeout, // timeOutInTicks
+ NULL, // idleProc
+ NULL); // filterProc
+ if (status != noErr) {
+ LOG(WARNING) << "Could not send AE to Finder in OpenItem()";
+ }
}
void OpenExternal(const GURL& url) {
« no previous file with comments | « base/scoped_aedesc.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698