refactor: make shell.OpenExternal async (#17135)
This commit is contained in:
parent
0755857a0c
commit
6d96f30ed3
16 changed files with 70 additions and 140 deletions
|
@ -52,33 +52,9 @@ void OnOpenExternalFinished(atom::util::Promise promise,
|
|||
promise.RejectWithErrorMessage(error.c_str());
|
||||
}
|
||||
|
||||
bool OpenExternalSync(
|
||||
#if defined(OS_WIN)
|
||||
const base::string16& url,
|
||||
#else
|
||||
const GURL& url,
|
||||
#endif
|
||||
mate::Arguments* args) {
|
||||
platform_util::OpenExternalOptions options;
|
||||
if (args->Length() >= 2) {
|
||||
mate::Dictionary obj;
|
||||
if (args->GetNext(&obj)) {
|
||||
obj.Get("activate", &options.activate);
|
||||
obj.Get("workingDirectory", &options.working_dir);
|
||||
}
|
||||
}
|
||||
|
||||
return platform_util::OpenExternal(url, options);
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> OpenExternal(
|
||||
#if defined(OS_WIN)
|
||||
const base::string16& url,
|
||||
#else
|
||||
const GURL& url,
|
||||
#endif
|
||||
mate::Arguments* args) {
|
||||
v8::Local<v8::Promise> OpenExternal(const GURL& url, mate::Arguments* args) {
|
||||
atom::util::Promise promise(args->isolate());
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
|
||||
platform_util::OpenExternalOptions options;
|
||||
if (args->Length() >= 2) {
|
||||
|
@ -89,7 +65,6 @@ v8::Local<v8::Promise> OpenExternal(
|
|||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
platform_util::OpenExternal(
|
||||
url, options,
|
||||
base::BindOnce(&OnOpenExternalFinished, std::move(promise)));
|
||||
|
@ -158,7 +133,6 @@ void Initialize(v8::Local<v8::Object> exports,
|
|||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("showItemInFolder", &platform_util::ShowItemInFolder);
|
||||
dict.SetMethod("openItem", &platform_util::OpenItem);
|
||||
dict.SetMethod("openExternalSync", &OpenExternalSync);
|
||||
dict.SetMethod("openExternal", &OpenExternal);
|
||||
dict.SetMethod("moveItemToTrash", &platform_util::MoveItemToTrash);
|
||||
dict.SetMethod("beep", &platform_util::Beep);
|
||||
|
|
|
@ -36,23 +36,9 @@ struct OpenExternalOptions {
|
|||
|
||||
// Open the given external protocol URL in the desktop's default manner.
|
||||
// (For example, mailto: URLs in the default mail user agent.)
|
||||
bool OpenExternal(
|
||||
#if defined(OS_WIN)
|
||||
const base::string16& url,
|
||||
#else
|
||||
const GURL& url,
|
||||
#endif
|
||||
const OpenExternalOptions& options);
|
||||
|
||||
// The asynchronous version of OpenExternal.
|
||||
void OpenExternal(
|
||||
#if defined(OS_WIN)
|
||||
const base::string16& url,
|
||||
#else
|
||||
const GURL& url,
|
||||
#endif
|
||||
const OpenExternalOptions& options,
|
||||
OpenExternalCallback callback);
|
||||
void OpenExternal(const GURL& url,
|
||||
const OpenExternalOptions& options,
|
||||
OpenExternalCallback callback);
|
||||
|
||||
// Move a file to trash.
|
||||
bool MoveItemToTrash(const base::FilePath& full_path);
|
||||
|
|
|
@ -81,20 +81,16 @@ bool OpenItem(const base::FilePath& full_path) {
|
|||
return XDGOpen(full_path.value(), false);
|
||||
}
|
||||
|
||||
bool OpenExternal(const GURL& url, const OpenExternalOptions& options) {
|
||||
// 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 XDGEmail(url.spec(), false);
|
||||
else
|
||||
return XDGOpen(url.spec(), false);
|
||||
}
|
||||
|
||||
void OpenExternal(const GURL& url,
|
||||
const OpenExternalOptions& options,
|
||||
OpenExternalCallback callback) {
|
||||
// TODO(gabriel): Implement async open if callback is specified
|
||||
std::move(callback).Run(OpenExternal(url, options) ? "" : "Failed to open");
|
||||
// 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"))
|
||||
std::move(callback).Run(XDGEmail(url.spec(), false) ? ""
|
||||
: "Failed to open");
|
||||
else
|
||||
std::move(callback).Run(XDGOpen(url.spec(), false) ? "" : "Failed to open");
|
||||
}
|
||||
|
||||
bool MoveItemToTrash(const base::FilePath& full_path) {
|
||||
|
|
|
@ -94,17 +94,10 @@ bool OpenItem(const base::FilePath& full_path) {
|
|||
launchIdentifiers:NULL];
|
||||
}
|
||||
|
||||
bool OpenExternal(const GURL& url, const OpenExternalOptions& options) {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
NSURL* ns_url = net::NSURLWithGURL(url);
|
||||
if (ns_url)
|
||||
return OpenURL(ns_url, options.activate).empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
void OpenExternal(const GURL& url,
|
||||
const OpenExternalOptions& options,
|
||||
OpenExternalCallback callback) {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
NSURL* ns_url = net::NSURLWithGURL(url);
|
||||
if (!ns_url) {
|
||||
std::move(callback).Run("Invalid URL");
|
||||
|
|
|
@ -230,6 +230,29 @@ HRESULT DeleteFileProgressSink::ResumeTimer() {
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
std::string OpenExternalOnWorkerThread(
|
||||
const GURL& url,
|
||||
const platform_util::OpenExternalOptions& options) {
|
||||
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
|
||||
base::BlockingType::MAY_BLOCK);
|
||||
// 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.
|
||||
std::string escaped_url = url.spec();
|
||||
escaped_url.insert(0, "\"");
|
||||
escaped_url += "\"";
|
||||
|
||||
std::string working_dir = options.working_dir.AsUTF8Unsafe();
|
||||
|
||||
if (reinterpret_cast<ULONG_PTR>(
|
||||
ShellExecuteA(nullptr, "open", escaped_url.c_str(), nullptr,
|
||||
working_dir.empty() ? nullptr : working_dir.c_str(),
|
||||
SW_SHOWNORMAL)) <= 32) {
|
||||
return "Failed to open";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void ShowItemInFolderOnWorkerThread(const base::FilePath& full_path) {
|
||||
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
|
||||
base::BlockingType::MAY_BLOCK);
|
||||
|
@ -301,31 +324,15 @@ bool OpenItem(const base::FilePath& full_path) {
|
|||
return ui::win::OpenFileViaShell(full_path);
|
||||
}
|
||||
|
||||
bool OpenExternal(const base::string16& url,
|
||||
const OpenExternalOptions& options) {
|
||||
// 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.
|
||||
base::string16 escaped_url = L"\"" + url + L"\"";
|
||||
auto working_dir = options.working_dir.value();
|
||||
|
||||
if (reinterpret_cast<ULONG_PTR>(
|
||||
ShellExecuteW(nullptr, L"open", escaped_url.c_str(), nullptr,
|
||||
working_dir.empty() ? nullptr : working_dir.c_str(),
|
||||
SW_SHOWNORMAL)) <= 32) {
|
||||
// We fail to execute the call. We could display a message to the user.
|
||||
// TODO(nsylvain): we should also add a dialog to warn on errors. See
|
||||
// bug 1136923.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenExternal(const base::string16& url,
|
||||
void OpenExternal(const GURL& url,
|
||||
const OpenExternalOptions& options,
|
||||
OpenExternalCallback callback) {
|
||||
// TODO(gabriel): Implement async open if callback is specified
|
||||
std::move(callback).Run(OpenExternal(url, options) ? "" : "Failed to open");
|
||||
base::PostTaskAndReplyWithResult(
|
||||
base::CreateCOMSTATaskRunnerWithTraits(
|
||||
{base::MayBlock(), base::TaskPriority::USER_BLOCKING})
|
||||
.get(),
|
||||
FROM_HERE, base::BindOnce(&OpenExternalOnWorkerThread, url, options),
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
bool MoveItemToTrash(const base::FilePath& path) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue