#include <string>
+#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#endif
mate::Arguments* args) {
bool activate = true;
- if (args->Length() == 2) {
+ if (args->Length() >= 2) {
mate::Dictionary options;
if (args->GetNext(&options)) {
options.Get("activate", &activate);
}
}
+
+ if (args->Length() >= 3) {
+ v8::Local<v8::Value> peek = args->PeekNext();
+ platform_util::OpenExternalCallback callback;
+ if (mate::Converter<platform_util::OpenExternalCallback>::FromV8(args->isolate(), peek, &callback)) {
+ return platform_util::OpenExternal(url, activate, callback);
+ }
+ return false;
+ }
+
return platform_util::OpenExternal(url, activate);
}
#define ATOM_COMMON_PLATFORM_UTIL_H_
#include "build/build_config.h"
+#include "base/callback_forward.h"
#if defined(OS_WIN)
#include "base/strings/string16.h"
// Must be called from the UI thread.
bool OpenItem(const base::FilePath& full_path);
+typedef base::Callback<void(bool opened)> 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(
#endif
bool activate);
+bool OpenExternal(
+#if defined(OS_WIN)
+ const base::string16& url,
+#else
+ const GURL& url,
+#endif
+ bool activate,
+ const OpenExternalCallback& callback);
+
// Move a file to trash.
bool MoveItemToTrash(const base::FilePath& full_path);
return XDGOpen(full_path.value(), true);
}
-bool OpenExternal(const GURL& url, bool activate) {
+bool openExternal(const GURL& url, bool activate) {
// Don't wait for exit, since we don't want to wait for the browser/email
// client window to close before returning
if (url.SchemeIs("mailto"))
return XDGOpen(url.spec(), false);
}
+bool OpenExternal(const GURL& url, bool activate) {
+ return openExternal(url, activate);
+}
+
+bool OpenExternal(const GURL& url, bool activate, const OpenExternalCallback& callback) {
+ // TODO: Implement async open if callback is specified
+ bool opened = openExternal(url, activate);
+ callback(opened);
+ return opened;
+}
+
bool MoveItemToTrash(const base::FilePath& full_path) {
std::string trash;
if (getenv(ELECTRON_TRASH) != NULL) {
#include <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
+#include "base/cancelable_callback.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
return status == noErr;
}
-bool OpenExternal(const GURL& url, bool activate) {
+bool openURLInWorkspace(NSURL* ns_url, NSUInteger launchOptions) {
+ return [[NSWorkspace sharedWorkspace] openURLs: @[ns_url]
+ withAppBundleIdentifier: nil
+ options: launchOptions
+ additionalEventParamDescriptor: NULL
+ launchIdentifiers: NULL];
+}
+
+typedef bool(^OpenExternalBlock)(NSURL* ns_url, NSUInteger launchOptions);
+
+bool openExternal(const GURL& url, bool activate, OpenExternalBlock open) {
DCHECK([NSThread isMainThread]);
NSURL* ns_url = net::NSURLWithGURL(url);
if (!ns_url) {
if (!activate)
launchOptions |= NSWorkspaceLaunchWithoutActivation;
- return [[NSWorkspace sharedWorkspace] openURLs: @[ns_url]
- withAppBundleIdentifier: nil
- options: launchOptions
- additionalEventParamDescriptor: NULL
- launchIdentifiers: NULL];
+ return open(ns_url, launchOptions);
+}
+
+bool OpenExternal(const GURL& url, bool activate) {
+ return openExternal(url, activate, ^bool(NSURL* ns_url, NSUInteger launchOptions) {
+ return openURLInWorkspace(ns_url, launchOptions);
+ });
+}
+
+bool OpenExternal(const GURL& url, bool activate, const OpenExternalCallback& c) {
+ __block OpenExternalCallback callback = c;
+ return openExternal(url, activate, ^bool(NSURL* ns_url, NSUInteger launchOptions) {
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ bool opened = openURLInWorkspace(ns_url, launchOptions);
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback.Run(opened);
+ });
+ });
+ return YES;
+ });
}
bool MoveItemToTrash(const base::FilePath& full_path) {
return ui::win::OpenFileViaShell(full_path);
}
-bool OpenExternal(const base::string16& url, bool activate) {
+bool openExternal(const base::string16& url, bool activate) {
// Quote the input scheme to be sure that the command does not have
// parameters unexpected by the external program. This url should already
// have been escaped.
return true;
}
+bool OpenExternal(const base::string16& url, bool activate) {
+ return openExternal(url, activate);
+}
+
+bool OpenExternal(const base::string16& url, bool activate, const OpenExternalCallback& callback) {
+ // TODO: Implement async open if callback is specified
+ bool opened = openExternal(url, activate)
+ callback(opened);
+ return opened;
+}
+
bool MoveItemToTrash(const base::FilePath& path) {
base::win::ScopedCOMInitializer com_initializer;
if (!com_initializer.succeeded())
Open the given file in the desktop's default manner.
-### `shell.openExternal(url[, options])`
+### `shell.openExternal(url[, options, callback])`
* `url` String
* `options` Object (optional) _macOS_
* `activate` Boolean - `true` to bring the opened application to the
foreground. The default is `true`.
+* `callback` Function (optional) _macOS_
Returns `Boolean` - Whether an application was available to open the URL.
Open the given external protocol URL in the desktop's default manner. (For
example, mailto: URLs in the user's default mail agent).
+If a `callback` is passed, the API call will be asynchronous and the result
+will be passed via `callback(opened)`.
+
### `shell.moveItemToTrash(fullPath)`
* `fullPath` String