167 lines
5.7 KiB
Plaintext
167 lines
5.7 KiB
Plaintext
// Copyright 2013 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#import "base/mac/launch_application.h"
|
|
|
|
#include "base/command_line.h"
|
|
#include "base/functional/callback.h"
|
|
#include "base/logging.h"
|
|
#include "base/mac/foundation_util.h"
|
|
#include "base/strings/sys_string_conversions.h"
|
|
#include "base/types/expected.h"
|
|
|
|
namespace base::mac {
|
|
|
|
namespace {
|
|
|
|
NSArray* CommandLineArgsToArgsArray(const CommandLineArgs& command_line_args) {
|
|
if (const CommandLine* command_line =
|
|
absl::get_if<CommandLine>(&command_line_args)) {
|
|
const auto& argv = command_line->argv();
|
|
size_t argc = argv.size();
|
|
DCHECK_GT(argc, 0lu);
|
|
|
|
NSMutableArray* args_array = [NSMutableArray arrayWithCapacity:argc - 1];
|
|
// NSWorkspace automatically adds the binary path as the first argument and
|
|
// thus it should not be included in the list.
|
|
for (size_t i = 1; i < argc; ++i) {
|
|
[args_array addObject:base::SysUTF8ToNSString(argv[i])];
|
|
}
|
|
|
|
return args_array;
|
|
}
|
|
|
|
if (const std::vector<std::string>* string_vector =
|
|
absl::get_if<std::vector<std::string>>(&command_line_args)) {
|
|
NSMutableArray* args_array =
|
|
[NSMutableArray arrayWithCapacity:string_vector->size()];
|
|
for (const auto& arg : *string_vector) {
|
|
[args_array addObject:base::SysUTF8ToNSString(arg)];
|
|
}
|
|
}
|
|
|
|
return @[];
|
|
}
|
|
|
|
NSWorkspaceOpenConfiguration* GetOpenConfiguration(
|
|
LaunchApplicationOptions options,
|
|
const CommandLineArgs& command_line_args) API_AVAILABLE(macos(10.15)) {
|
|
NSWorkspaceOpenConfiguration* config =
|
|
[NSWorkspaceOpenConfiguration configuration];
|
|
|
|
config.activates = options.activate;
|
|
config.createsNewApplicationInstance = options.create_new_instance;
|
|
config.promptsUserIfNeeded = options.prompt_user_if_needed;
|
|
config.arguments = CommandLineArgsToArgsArray(command_line_args);
|
|
|
|
return config;
|
|
}
|
|
|
|
NSWorkspaceLaunchOptions GetLaunchOptions(LaunchApplicationOptions options) {
|
|
NSWorkspaceLaunchOptions launch_options = NSWorkspaceLaunchDefault;
|
|
|
|
if (!options.activate) {
|
|
launch_options |= NSWorkspaceLaunchWithoutActivation;
|
|
}
|
|
if (options.create_new_instance) {
|
|
launch_options |= NSWorkspaceLaunchNewInstance;
|
|
}
|
|
if (options.prompt_user_if_needed) {
|
|
launch_options |= NSWorkspaceLaunchWithErrorPresentation;
|
|
}
|
|
|
|
return launch_options;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void LaunchApplication(const base::FilePath& app_bundle_path,
|
|
const CommandLineArgs& command_line_args,
|
|
const std::vector<std::string>& url_specs,
|
|
LaunchApplicationOptions options,
|
|
LaunchApplicationCallback callback) {
|
|
__block LaunchApplicationCallback callback_block_access = std::move(callback);
|
|
|
|
NSURL* bundle_url = FilePathToNSURL(app_bundle_path);
|
|
if (!bundle_url) {
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
std::move(callback_block_access)
|
|
.Run(base::unexpected([NSError errorWithDomain:NSCocoaErrorDomain
|
|
code:NSFileNoSuchFileError
|
|
userInfo:nil]));
|
|
});
|
|
return;
|
|
}
|
|
|
|
NSMutableArray* ns_urls = nil;
|
|
if (!url_specs.empty()) {
|
|
ns_urls = [NSMutableArray arrayWithCapacity:url_specs.size()];
|
|
for (const auto& url_spec : url_specs) {
|
|
[ns_urls
|
|
addObject:[NSURL URLWithString:base::SysUTF8ToNSString(url_spec)]];
|
|
}
|
|
}
|
|
|
|
if (@available(macOS 10.15, *)) {
|
|
void (^action_block)(NSRunningApplication*, NSError*) =
|
|
^void(NSRunningApplication* app, NSError* error) {
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
if (error) {
|
|
LOG(ERROR) << base::SysNSStringToUTF8(error.localizedDescription);
|
|
std::move(callback_block_access).Run(base::unexpected(error));
|
|
} else {
|
|
std::move(callback_block_access).Run(app);
|
|
}
|
|
});
|
|
};
|
|
|
|
NSWorkspaceOpenConfiguration* configuration =
|
|
GetOpenConfiguration(options, command_line_args);
|
|
|
|
if (ns_urls) {
|
|
[NSWorkspace.sharedWorkspace openURLs:ns_urls
|
|
withApplicationAtURL:bundle_url
|
|
configuration:configuration
|
|
completionHandler:action_block];
|
|
} else {
|
|
[NSWorkspace.sharedWorkspace openApplicationAtURL:bundle_url
|
|
configuration:configuration
|
|
completionHandler:action_block];
|
|
}
|
|
} else {
|
|
NSDictionary* configuration = @{
|
|
NSWorkspaceLaunchConfigurationArguments :
|
|
CommandLineArgsToArgsArray(command_line_args),
|
|
};
|
|
|
|
NSWorkspaceLaunchOptions launch_options = GetLaunchOptions(options);
|
|
|
|
NSError* error = nil;
|
|
NSRunningApplication* app;
|
|
if (ns_urls) {
|
|
app = [NSWorkspace.sharedWorkspace openURLs:ns_urls
|
|
withApplicationAtURL:bundle_url
|
|
options:launch_options
|
|
configuration:configuration
|
|
error:&error];
|
|
} else {
|
|
app = [NSWorkspace.sharedWorkspace launchApplicationAtURL:bundle_url
|
|
options:launch_options
|
|
configuration:configuration
|
|
error:&error];
|
|
}
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
if (error) {
|
|
LOG(ERROR) << base::SysNSStringToUTF8(error.localizedDescription);
|
|
std::move(callback_block_access).Run(base::unexpected(error));
|
|
} else {
|
|
std::move(callback_block_access).Run(app);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
} // namespace base::mac
|