Commit 04f5f76a authored by Lambros Lambrou's avatar Lambros Lambrou Committed by Commit Bot

Launch PermissionWizard in native-messaging host

The Me2Me native-messaging host has a command-line option:
--check-permission
to check for host permissions. This CL updates this to run the
permission-wizard.

Bug: 1015201
Change-Id: Ie936de8fae413567b5260cde5fb62b0a5803712e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1913473
Commit-Queue: Lambros Lambrou <lambroslambrou@chromium.org>
Reviewed-by: default avatarGary Kacmarcik <garykac@chromium.org>
Cr-Commit-Position: refs/heads/master@{#714772}
parent 3466ef9c
...@@ -167,6 +167,8 @@ foreach(locale, remoting_locales_with_underscores) { ...@@ -167,6 +167,8 @@ foreach(locale, remoting_locales_with_underscores) {
bundle_data("remoting_native_messaging_host_resources") { bundle_data("remoting_native_messaging_host_resources") {
sources = [ sources = [
"//remoting/host/mac/remoting_me2me_host.icns",
# This image is used to badge the lock icon in the authentication dialogs, # This image is used to badge the lock icon in the authentication dialogs,
# used for elevating privileges to set up the host. The exact filename is # used for elevating privileges to set up the host. The exact filename is
# required by base::mac::GetAuthorizationRightsWithPrompt(). # required by base::mac::GetAuthorizationRightsWithPrompt().
......
...@@ -50,6 +50,10 @@ source_set("common") { ...@@ -50,6 +50,10 @@ source_set("common") {
"//services/network/public/mojom", "//services/network/public/mojom",
] ]
if (is_mac) {
deps += [ "//remoting/host/mac:permission_checking" ]
}
if (is_mac || is_ios) { if (is_mac || is_ios) {
deps += [ "//remoting/host/mac:constants" ] deps += [ "//remoting/host/mac:constants" ]
} }
......
...@@ -51,9 +51,9 @@ void DaemonController::GetConfig(const GetConfigCallback& done) { ...@@ -51,9 +51,9 @@ void DaemonController::GetConfig(const GetConfigCallback& done) {
ServiceOrQueueRequest(request); ServiceOrQueueRequest(request);
} }
bool DaemonController::CheckPermission() { void DaemonController::CheckPermission(BoolCallback callback) {
DCHECK(caller_task_runner_->BelongsToCurrentThread()); DCHECK(caller_task_runner_->BelongsToCurrentThread());
return delegate_->CheckPermission(); return delegate_->CheckPermission(std::move(callback));
} }
void DaemonController::SetConfigAndStart( void DaemonController::SetConfigAndStart(
......
...@@ -73,6 +73,9 @@ class DaemonController : public base::RefCountedThreadSafe<DaemonController> { ...@@ -73,6 +73,9 @@ class DaemonController : public base::RefCountedThreadSafe<DaemonController> {
// starting/stopping the service. // starting/stopping the service.
typedef base::Callback<void (AsyncResult result)> CompletionCallback; typedef base::Callback<void (AsyncResult result)> CompletionCallback;
// Callback used to notify a Boolean result.
typedef base::OnceCallback<void(bool)> BoolCallback;
struct UsageStatsConsent { struct UsageStatsConsent {
// Indicates whether crash dump reporting is supported by the host. // Indicates whether crash dump reporting is supported by the host.
bool supported; bool supported;
...@@ -110,9 +113,10 @@ class DaemonController : public base::RefCountedThreadSafe<DaemonController> { ...@@ -110,9 +113,10 @@ class DaemonController : public base::RefCountedThreadSafe<DaemonController> {
virtual std::unique_ptr<base::DictionaryValue> GetConfig() = 0; virtual std::unique_ptr<base::DictionaryValue> GetConfig() = 0;
// Checks to verify that the required OS permissions have been granted to // Checks to verify that the required OS permissions have been granted to
// the host process, querying the user if necessary. Returns true iff all // the host process, querying the user if necessary. Notifies the callback
// required permissions have been granted. // when permission status is established, passing true iff all required
virtual bool CheckPermission() = 0; // permissions have been granted.
virtual void CheckPermission(BoolCallback callback) = 0;
// Starts the daemon process. This may require that the daemon be // Starts the daemon process. This may require that the daemon be
// downloaded and installed. |done| is invoked on the calling thread when // downloaded and installed. |done| is invoked on the calling thread when
...@@ -157,8 +161,9 @@ class DaemonController : public base::RefCountedThreadSafe<DaemonController> { ...@@ -157,8 +161,9 @@ class DaemonController : public base::RefCountedThreadSafe<DaemonController> {
// Checks to see if the required OS permissions have been granted. This may // Checks to see if the required OS permissions have been granted. This may
// show a dialog to the user requesting the permissions. // show a dialog to the user requesting the permissions.
// Returns true iff all required permissions have been granted. // Notifies the callback when permission status is established, passing true
bool CheckPermission(); // iff all required permissions have been granted.
void CheckPermission(BoolCallback callback);
// Start the daemon process. This may require that the daemon be // Start the daemon process. This may require that the daemon be
// downloaded and installed. |done| is called when the // downloaded and installed. |done| is called when the
......
...@@ -165,8 +165,9 @@ DaemonControllerDelegateLinux::GetConfig() { ...@@ -165,8 +165,9 @@ DaemonControllerDelegateLinux::GetConfig() {
return result; return result;
} }
bool DaemonControllerDelegateLinux::CheckPermission() { void DaemonControllerDelegateLinux::CheckPermission(
return true; DaemonController::BoolCallback callback) {
std::move(callback).Run(true);
} }
void DaemonControllerDelegateLinux::SetConfigAndStart( void DaemonControllerDelegateLinux::SetConfigAndStart(
......
...@@ -20,7 +20,7 @@ class DaemonControllerDelegateLinux : public DaemonController::Delegate { ...@@ -20,7 +20,7 @@ class DaemonControllerDelegateLinux : public DaemonController::Delegate {
// DaemonController::Delegate interface. // DaemonController::Delegate interface.
DaemonController::State GetState() override; DaemonController::State GetState() override;
std::unique_ptr<base::DictionaryValue> GetConfig() override; std::unique_ptr<base::DictionaryValue> GetConfig() override;
bool CheckPermission() override; void CheckPermission(DaemonController::BoolCallback) override;
void SetConfigAndStart( void SetConfigAndStart(
std::unique_ptr<base::DictionaryValue> config, std::unique_ptr<base::DictionaryValue> config,
bool consent, bool consent,
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
namespace remoting { namespace remoting {
namespace mac {
class PermissionWizard;
}
class DaemonControllerDelegateMac : public DaemonController::Delegate { class DaemonControllerDelegateMac : public DaemonController::Delegate {
public: public:
DaemonControllerDelegateMac(); DaemonControllerDelegateMac();
...@@ -22,7 +26,7 @@ class DaemonControllerDelegateMac : public DaemonController::Delegate { ...@@ -22,7 +26,7 @@ class DaemonControllerDelegateMac : public DaemonController::Delegate {
// DaemonController::Delegate interface. // DaemonController::Delegate interface.
DaemonController::State GetState() override; DaemonController::State GetState() override;
std::unique_ptr<base::DictionaryValue> GetConfig() override; std::unique_ptr<base::DictionaryValue> GetConfig() override;
bool CheckPermission() override; void CheckPermission(DaemonController::BoolCallback) override;
void SetConfigAndStart( void SetConfigAndStart(
std::unique_ptr<base::DictionaryValue> config, std::unique_ptr<base::DictionaryValue> config,
bool consent, bool consent,
...@@ -33,6 +37,8 @@ class DaemonControllerDelegateMac : public DaemonController::Delegate { ...@@ -33,6 +37,8 @@ class DaemonControllerDelegateMac : public DaemonController::Delegate {
DaemonController::UsageStatsConsent GetUsageStatsConsent() override; DaemonController::UsageStatsConsent GetUsageStatsConsent() override;
private: private:
std::unique_ptr<mac::PermissionWizard> permission_wizard_;
DISALLOW_COPY_AND_ASSIGN(DaemonControllerDelegateMac); DISALLOW_COPY_AND_ASSIGN(DaemonControllerDelegateMac);
}; };
......
...@@ -19,14 +19,14 @@ ...@@ -19,14 +19,14 @@
#include "base/mac/scoped_authorizationref.h" #include "base/mac/scoped_authorizationref.h"
#include "base/mac/scoped_launch_data.h" #include "base/mac/scoped_launch_data.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "base/posix/eintr_wrapper.h" #include "base/posix/eintr_wrapper.h"
#include "base/process/launch.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/process/process.h"
#include "base/values.h" #include "base/values.h"
#include "remoting/base/string_resources.h" #include "remoting/base/string_resources.h"
#include "remoting/host/host_config.h" #include "remoting/host/host_config.h"
#include "remoting/host/mac/constants_mac.h" #include "remoting/host/mac/constants_mac.h"
#include "remoting/host/mac/permission_checker.h"
#include "remoting/host/mac/permission_wizard.h"
#include "remoting/host/resources.h" #include "remoting/host/resources.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/l10n_util_mac.h" #include "ui/base/l10n/l10n_util_mac.h"
...@@ -243,57 +243,14 @@ DaemonControllerDelegateMac::GetConfig() { ...@@ -243,57 +243,14 @@ DaemonControllerDelegateMac::GetConfig() {
return config; return config;
} }
base::FilePath GetHostExePath() { void DaemonControllerDelegateMac::CheckPermission(
// Get path to directory that contains the NMH Application bundle. DaemonController::BoolCallback callback) {
base::FilePath nmh_dir; auto checker = std::make_unique<mac::PermissionChecker>(
base::PathService::Get(base::DIR_EXE, &nmh_dir); mac::HostMode::ME2ME, base::ThreadTaskRunnerHandle::Get());
// The NMH path ends with <nmh>.app/Contents/MacOS/, so we need to strip permission_wizard_ =
// off the last 3 parent dirs to get to the app's directory. std::make_unique<mac::PermissionWizard>(std::move(checker));
auto host_path = nmh_dir.DirName().DirName().DirName(); permission_wizard_->SetCompletionCallback(std::move(callback));
permission_wizard_->Start(base::ThreadTaskRunnerHandle::Get());
// For installed builds, the host exe should be in this directory.
// TODO(garykac) This assumes that the location of the host exe is relative
// to the location of the NMH exe, which may not be true in the future. The
// relative path is needed for dev builds (where the binaries are written to
// the Chromium 'out' directory), but the release version should get this
// path from the build script to ensure that it matches where we install the
// host.
base::FilePath host_path_exe = host_path.Append("remoting_me2me_host");
if (!base::PathExists(host_path_exe)) {
// For local dev builds, the host exe is in an app container, so we have to
// navigate down to it.
host_path_exe = host_path.Append(
"remoting_me2me_host.app/Contents/MacOS/remoting_me2me_host");
if (!base::PathExists(host_path_exe))
LOG(ERROR) << "Path doesn't exist: " << host_path_exe;
}
return host_path_exe;
}
bool CheckHostPermission(std::string perm) {
base::CommandLine cmdLine(GetHostExePath());
cmdLine.AppendSwitch(perm);
base::LaunchOptions options;
options.disclaim_responsibility = true;
base::Process process = base::LaunchProcess(cmdLine, options);
if (!process.IsValid()) {
LOG(ERROR) << "Unable to launch host process";
return false;
}
int exit_code;
process.WaitForExit(&exit_code);
LOG(INFO) << "Permission '" << perm << "' is "
<< ((exit_code == 0) ? "granted" : "denied");
return exit_code == 0;
}
bool DaemonControllerDelegateMac::CheckPermission() {
if (CheckHostPermission("check-accessibility-permission")) {
return CheckHostPermission("check-screen-recording-permission");
}
return false;
} }
void DaemonControllerDelegateMac::SetConfigAndStart( void DaemonControllerDelegateMac::SetConfigAndStart(
......
...@@ -439,8 +439,9 @@ DaemonControllerDelegateWin::GetUsageStatsConsent() { ...@@ -439,8 +439,9 @@ DaemonControllerDelegateWin::GetUsageStatsConsent() {
return consent; return consent;
} }
bool DaemonControllerDelegateWin::CheckPermission() { void DaemonControllerDelegateWin::CheckPermission(
return true; DaemonController::BoolCallback callback) {
std::move(callback).Run(true);
} }
void DaemonControllerDelegateWin::SetConfigAndStart( void DaemonControllerDelegateWin::SetConfigAndStart(
......
...@@ -18,7 +18,7 @@ class DaemonControllerDelegateWin : public DaemonController::Delegate { ...@@ -18,7 +18,7 @@ class DaemonControllerDelegateWin : public DaemonController::Delegate {
// DaemonController::Delegate interface. // DaemonController::Delegate interface.
DaemonController::State GetState() override; DaemonController::State GetState() override;
std::unique_ptr<base::DictionaryValue> GetConfig() override; std::unique_ptr<base::DictionaryValue> GetConfig() override;
bool CheckPermission() override; void CheckPermission(DaemonController::BoolCallback) override;
void SetConfigAndStart( void SetConfigAndStart(
std::unique_ptr<base::DictionaryValue> config, std::unique_ptr<base::DictionaryValue> config,
bool consent, bool consent,
......
...@@ -110,8 +110,19 @@ int Me2MeNativeMessagingHostMain(int argc, char** argv) { ...@@ -110,8 +110,19 @@ int Me2MeNativeMessagingHostMain(int argc, char** argv) {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
if (command_line->HasSwitch(kCheckPermissionSwitchName)) { if (command_line->HasSwitch(kCheckPermissionSwitchName)) {
bool perm = daemon_controller->CheckPermission(); int exit_code;
return perm ? kSuccessExitCode : kNoPermissionExitCode; daemon_controller->CheckPermission(
// base::BindOnce cannot bind a capturing lambda, so the "captured"
// parameters are bound manually. This is safe because the run-loop is
// run to completion within this scope.
base::BindOnce(
[](int* exit_code, base::RunLoop* run_loop, bool perm) {
*exit_code = (perm ? kSuccessExitCode : kNoPermissionExitCode);
run_loop->Quit();
},
&exit_code, &run_loop));
run_loop.Run();
return exit_code;
} }
#endif // defined(OS_MACOSX) #endif // defined(OS_MACOSX)
......
...@@ -175,7 +175,7 @@ class MockDaemonControllerDelegate : public DaemonController::Delegate { ...@@ -175,7 +175,7 @@ class MockDaemonControllerDelegate : public DaemonController::Delegate {
// DaemonController::Delegate interface. // DaemonController::Delegate interface.
DaemonController::State GetState() override; DaemonController::State GetState() override;
std::unique_ptr<base::DictionaryValue> GetConfig() override; std::unique_ptr<base::DictionaryValue> GetConfig() override;
bool CheckPermission() override; void CheckPermission(DaemonController::BoolCallback callback) override;
void SetConfigAndStart( void SetConfigAndStart(
std::unique_ptr<base::DictionaryValue> config, std::unique_ptr<base::DictionaryValue> config,
bool consent, bool consent,
...@@ -202,8 +202,9 @@ MockDaemonControllerDelegate::GetConfig() { ...@@ -202,8 +202,9 @@ MockDaemonControllerDelegate::GetConfig() {
return std::make_unique<base::DictionaryValue>(); return std::make_unique<base::DictionaryValue>();
} }
bool MockDaemonControllerDelegate::CheckPermission() { void MockDaemonControllerDelegate::CheckPermission(
return true; DaemonController::BoolCallback callback) {
std::move(callback).Run(true);
} }
void MockDaemonControllerDelegate::SetConfigAndStart( void MockDaemonControllerDelegate::SetConfigAndStart(
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>native_messaging_host</string> <string>remoting_me2me_host</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>${BUNDLE_ID}</string> <string>${BUNDLE_ID}</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment