Browse Source

platform_util code should not involve V8 code

Cheng Zhao 8 years ago
parent
commit
090a5d9a61
3 changed files with 90 additions and 64 deletions
  1. 14 2
      atom/common/api/atom_api_shell.cc
  2. 5 3
      atom/common/platform_util.h
  3. 71 59
      atom/common/platform_util_mac.mm

+ 14 - 2
atom/common/api/atom_api_shell.cc

@@ -42,6 +42,16 @@ struct Converter<base::win::ShortcutOperation> {
 
 namespace {
 
+void OnOpenExternalFinished(
+    v8::Isolate* isolate,
+    const base::Callback<void(v8::Local<v8::Value>)>& callback,
+    const std::string& error) {
+  if (error.empty())
+    callback.Run(v8::Null(isolate));
+  else
+    callback.Run(v8::String::NewFromUtf8(isolate, error.c_str()));
+}
+
 bool OpenExternal(
 #if defined(OS_WIN)
     const base::string16& url,
@@ -58,9 +68,11 @@ bool OpenExternal(
   }
 
   if (args->Length() >= 3) {
-    platform_util::OpenExternalCallback callback;
+    base::Callback<void(v8::Local<v8::Value>)> callback;
     if (args->GetNext(&callback)) {
-      platform_util::OpenExternal(url, activate, callback);
+      platform_util::OpenExternal(
+          url, activate,
+          base::Bind(&OnOpenExternalFinished, args->isolate(), callback));
       return true;
     }
   }

+ 5 - 3
atom/common/platform_util.h

@@ -5,9 +5,10 @@
 #ifndef ATOM_COMMON_PLATFORM_UTIL_H_
 #define ATOM_COMMON_PLATFORM_UTIL_H_
 
+#include <string>
+
 #include "base/callback_forward.h"
 #include "build/build_config.h"
-#include "v8/include/v8.h"
 
 #if defined(OS_WIN)
 #include "base/strings/string16.h"
@@ -21,6 +22,8 @@ class FilePath;
 
 namespace platform_util {
 
+typedef base::Callback<void(const std::string&)> OpenExternalCallback;
+
 // Show the given file in a file manager. If possible, select the file.
 // Must be called from the UI thread.
 bool ShowItemInFolder(const base::FilePath& full_path);
@@ -29,8 +32,6 @@ bool ShowItemInFolder(const base::FilePath& full_path);
 // Must be called from the UI thread.
 bool OpenItem(const base::FilePath& full_path);
 
-typedef base::Callback<void(v8::Local<v8::Value> error)> OpenExternalCallback;
-
 // Open the given external protocol URL in the desktop's default manner.
 // (For example, mailto: URLs in the default mail user agent.)
 bool OpenExternal(
@@ -41,6 +42,7 @@ bool OpenExternal(
 #endif
     bool activate);
 
+// The asynchronous version of OpenExternal.
 void OpenExternal(
 #if defined(OS_WIN)
     const base::string16& url,

+ 71 - 59
atom/common/platform_util_mac.mm

@@ -4,82 +4,97 @@
 
 #include "atom/common/platform_util.h"
 
-#include <Carbon/Carbon.h>
+#import <Carbon/Carbon.h>
 #import <Cocoa/Cocoa.h>
 
-#include "base/cancelable_callback.h"
+#include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/mac/mac_logging.h"
 #include "base/mac/scoped_aedesc.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 #include "net/base/mac/url_conversions.h"
 #include "url/gurl.h"
 
 namespace {
 
-NSError *PlatformError(NSString* message) {
-  return [NSError errorWithDomain:@"Electron"
-                  code:0
-                  userInfo:@{NSLocalizedDescriptionKey: message}];
-}
-
-NSString *MessageForOSStatus(OSStatus status, NSString* defaultMessage) {
+std::string MessageForOSStatus(OSStatus status, const char* default_message) {
   switch (status) {
-    case kLSAppInTrashErr: return @"The application cannot be run because it is inside a Trash folder.";
-    case kLSUnknownErr: return @"An unknown error has occurred.";
-    case kLSNotAnApplicationErr: return @"The item to be registered is not an application.";
-    case kLSNotInitializedErr: return @"Formerly returned by LSInit on initialization failure; no longer used.";
-    case kLSDataUnavailableErr: return @"Data of the desired type is not available (for example, there is no kind string).";
-    case kLSApplicationNotFoundErr: return @"No application in the Launch Services database matches the input criteria.";
-    case kLSDataErr: return @"Data is structured improperly (for example, an item’s information property list is malformed). Not used in macOS 10.4.";
-    case kLSLaunchInProgressErr: return @"A launch of the application is already in progress.";
-    case kLSServerCommunicationErr: return @"There is a problem communicating with the server process that maintains the Launch Services database.";
-    case kLSCannotSetInfoErr: return @"The filename extension to be hidden cannot be hidden.";
-    case kLSIncompatibleSystemVersionErr: return @"The application to be launched cannot run on the current Mac OS version.";
-    case kLSNoLaunchPermissionErr: return @"The user does not have permission to launch the application (on a managed network).";
-    case kLSNoExecutableErr: return @"The executable file is missing or has an unusable format.";
-    case kLSNoClassicEnvironmentErr: return @"The Classic emulation environment was required but is not available.";
-    case kLSMultipleSessionsNotSupportedErr: return @"The application to be launched cannot run simultaneously in two different user sessions.";
-    default: return [NSString stringWithFormat:@"%@ (%@)", defaultMessage, @(status)];
+    case kLSAppInTrashErr:
+      return "The application cannot be run because it is inside a Trash "
+             "folder.";
+    case kLSUnknownErr:
+      return "An unknown error has occurred.";
+    case kLSNotAnApplicationErr:
+      return "The item to be registered is not an application.";
+    case kLSNotInitializedErr:
+      return "Formerly returned by LSInit on initialization failure; "
+             "no longer used.";
+    case kLSDataUnavailableErr:
+      return "Data of the desired type is not available (for example, there is "
+             "no kind string).";
+    case kLSApplicationNotFoundErr:
+      return "No application in the Launch Services database matches the input "
+             "criteria.";
+    case kLSDataErr:
+      return "Data is structured improperly (for example, an item’s "
+             "information property list is malformed). Not used in macOS 10.4.";
+    case kLSLaunchInProgressErr:
+      return "A launch of the application is already in progress.";
+    case kLSServerCommunicationErr:
+      return "There is a problem communicating with the server process that "
+             "maintains the Launch Services database.";
+    case kLSCannotSetInfoErr:
+      return "The filename extension to be hidden cannot be hidden.";
+    case kLSIncompatibleSystemVersionErr:
+      return "The application to be launched cannot run on the current Mac OS "
+             "version.";
+    case kLSNoLaunchPermissionErr:
+      return "The user does not have permission to launch the application (on a"
+             "managed network).";
+    case kLSNoExecutableErr:
+      return "The executable file is missing or has an unusable format.";
+    case kLSNoClassicEnvironmentErr:
+      return "The Classic emulation environment was required but is not "
+             "available.";
+    case kLSMultipleSessionsNotSupportedErr:
+      return "The application to be launched cannot run simultaneously in two "
+             "different user sessions.";
+    default:
+      return base::StringPrintf("%s (%d)", default_message, status);
   }
 }
 
-// This may be called from a global dispatch queue, the methods used here are thread safe,
-// including LSGetApplicationForURL (> 10.2) and NSWorkspace#openURLs.
-NSError* OpenURL(NSURL* ns_url, bool activate) {
+// This may be called from a global dispatch queue, the methods used here are
+// thread safe, including LSGetApplicationForURL (> 10.2) and
+// NSWorkspace#openURLs.
+std::string OpenURL(NSURL* ns_url, bool activate) {
   CFURLRef openingApp = NULL;
   OSStatus status = LSGetApplicationForURL((CFURLRef)ns_url,
                                            kLSRolesAll,
                                            NULL,
                                            &openingApp);
-  if (status != noErr) {
-    return PlatformError(MessageForOSStatus(status, @"Failed to open"));
-  }
+  if (status != noErr)
+    return MessageForOSStatus(status, "Failed to open");
+
   CFRelease(openingApp);  // NOT A BUG; LSGetApplicationForURL retains for us
 
   NSUInteger launchOptions = NSWorkspaceLaunchDefault;
   if (!activate)
     launchOptions |= NSWorkspaceLaunchWithoutActivation;
 
-  bool opened = [[NSWorkspace sharedWorkspace] openURLs: @[ns_url]
-                                               withAppBundleIdentifier: nil
-                                               options: launchOptions
-                                               additionalEventParamDescriptor: nil
-                                               launchIdentifiers: nil];
-  if (!opened) return PlatformError(@"Failed to open URL");
-  return nil;
-}
+  bool opened = [[NSWorkspace sharedWorkspace]
+                            openURLs:@[ns_url]
+             withAppBundleIdentifier:nil
+                             options:launchOptions
+      additionalEventParamDescriptor:nil
+                   launchIdentifiers:nil];
+  if (!opened)
+    return "Failed to open URL";
 
-v8::Local<v8::Value> ConvertNSError(v8::Isolate* isolate, NSError* platformError) {
-  if (!platformError) {
-    return v8::Null(isolate);
-  } else {
-    v8::Local<v8::String> error_message =
-      v8::String::NewFromUtf8(isolate, platformError.localizedDescription.UTF8String);
-    return v8::Exception::Error(error_message);
-  }
+  return "";
 }
 
 }  // namespace
@@ -199,27 +214,24 @@ bool OpenItem(const base::FilePath& full_path) {
 bool OpenExternal(const GURL& url, bool activate) {
   DCHECK([NSThread isMainThread]);
   NSURL* ns_url = net::NSURLWithGURL(url);
-  if (!ns_url) {
-    return false;
-  }
-  NSError *error = OpenURL(ns_url, activate);
-  return !error;
+  if (ns_url)
+    return OpenURL(ns_url, activate).empty();
+  return false;
 }
 
-void OpenExternal(const GURL& url, bool activate, const OpenExternalCallback& c) {
+void OpenExternal(const GURL& url, bool activate,
+                  const OpenExternalCallback& callback) {
   NSURL* ns_url = net::NSURLWithGURL(url);
   if (!ns_url) {
-    v8::Isolate* isolate = v8::Isolate::GetCurrent();
-    c.Run(ConvertNSError(isolate, PlatformError(@"Invalid URL")));
+    callback.Run("Invalid URL");
     return;
   }
 
-  __block OpenExternalCallback callback = c;
+  __block OpenExternalCallback c = callback;
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-    NSError *openError = OpenURL(ns_url, activate);
+    __block std::string error = OpenURL(ns_url, activate);
     dispatch_async(dispatch_get_main_queue(), ^{
-      v8::Isolate* isolate = v8::Isolate::GetCurrent();
-      callback.Run(ConvertNSError(isolate, openError));
+      c.Run(error);
     });
   });
 }