Commit 3ddc5f07 authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

Always use Mojo ChannelMac in app shims

ChannelMac is now the default Mojo channel implementation, and the
feature condition between it and ChannelPosix can be removed. This
removes the now-dead code for manipulating the UNIX domain socket app
shims used to connect with over ChannelPosix.

Bug: 973882
Change-Id: I67ffa068c814c459002e63c587225394d072271f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1677286
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#673723}
parent 25cb54f6
...@@ -71,13 +71,17 @@ class AppShimController : public chrome::mojom::AppShim { ...@@ -71,13 +71,17 @@ class AppShimController : public chrome::mojom::AppShim {
// Terminates the app shim process. // Terminates the app shim process.
void Close(); void Close();
// Returns the connection to the AppShimHostManager in the browser. Returns
// an invalid endpoint if it is not available yet.
mojo::PlatformChannelEndpoint GetBrowserEndpoint();
// Sets up a connection to the AppShimHostManager at the given Mach // Sets up a connection to the AppShimHostManager at the given Mach
// endpoint name. // endpoint name.
static mojo::PlatformChannelEndpoint ConnectToBrowser( static mojo::PlatformChannelEndpoint ConnectToBrowser(
const mojo::NamedPlatformChannel::ServerName& server_name); const mojo::NamedPlatformChannel::ServerName& server_name);
// Connects to Chrome and sends a LaunchApp message. // Connects to Chrome and sends a LaunchApp message.
void InitBootstrapPipe(); void InitBootstrapPipe(mojo::PlatformChannelEndpoint endpoint);
// Find a running instance of Chrome and set |chrome_running_app_| to it. If // Find a running instance of Chrome and set |chrome_running_app_| to it. If
// none exists, launch Chrome, and set |chrome_running_app_|. // none exists, launch Chrome, and set |chrome_running_app_|.
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include "components/remote_cocoa/common/application.mojom.h" #include "components/remote_cocoa/common/application.mojom.h"
#include "content/public/browser/remote_cocoa.h" #include "content/public/browser/remote_cocoa.h"
#include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/platform/features.h"
#include "mojo/public/cpp/platform/named_platform_channel.h" #include "mojo/public/cpp/platform/named_platform_channel.h"
#include "mojo/public/cpp/platform/platform_channel.h" #include "mojo/public/cpp/platform/platform_channel.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
...@@ -129,21 +128,9 @@ void AppShimController::PollForChromeReady( ...@@ -129,21 +128,9 @@ void AppShimController::PollForChromeReady(
if ([chrome_running_app_ isTerminated]) if ([chrome_running_app_ isTerminated])
LOG(FATAL) << "Running chrome instance terminated before connecting."; LOG(FATAL) << "Running chrome instance terminated before connecting.";
// Check to see if the app shim socket symlink path exists. If it does, then mojo::PlatformChannelEndpoint endpoint = GetBrowserEndpoint();
// we know that the AppShimHostManager is listening in the browser process, if (endpoint.is_valid()) {
// and we can connect. InitBootstrapPipe(std::move(endpoint));
CHECK(!params_.user_data_dir.empty());
base::FilePath symlink_path =
params_.user_data_dir.Append(app_mode::kAppShimSocketSymlinkName);
// If the MojoChannelMac signal file is present, the browser is running
// with Mach IPC instead of socket-based IPC, and the shim can connect
// via that.
base::FilePath mojo_channel_mac_signal_file =
params_.user_data_dir.Append(app_mode::kMojoChannelMacSignalFile);
if (base::PathExists(symlink_path) ||
base::PathExists(mojo_channel_mac_signal_file)) {
InitBootstrapPipe();
return; return;
} }
...@@ -158,6 +145,19 @@ void AppShimController::PollForChromeReady( ...@@ -158,6 +145,19 @@ void AppShimController::PollForChromeReady(
kPollPeriodMsec); kPollPeriodMsec);
} }
mojo::PlatformChannelEndpoint AppShimController::GetBrowserEndpoint() {
NSString* browser_bundle_id =
base::mac::ObjCCast<NSString>([[NSBundle mainBundle]
objectForInfoDictionaryKey:app_mode::kBrowserBundleIDKey]);
CHECK(browser_bundle_id);
std::string name_fragment = base::StringPrintf(
"%s.%s.%s", base::SysNSStringToUTF8(browser_bundle_id).c_str(),
app_mode::kAppShimBootstrapNameFragment,
base::MD5String(params_.user_data_dir.value()).c_str());
return ConnectToBrowser(name_fragment);
}
// static // static
mojo::PlatformChannelEndpoint AppShimController::ConnectToBrowser( mojo::PlatformChannelEndpoint AppShimController::ConnectToBrowser(
const mojo::NamedPlatformChannel::ServerName& server_name) { const mojo::NamedPlatformChannel::ServerName& server_name) {
...@@ -170,6 +170,11 @@ mojo::PlatformChannelEndpoint AppShimController::ConnectToBrowser( ...@@ -170,6 +170,11 @@ mojo::PlatformChannelEndpoint AppShimController::ConnectToBrowser(
// remote (receive) end. // remote (receive) end.
mojo::PlatformChannelEndpoint server_endpoint = mojo::PlatformChannelEndpoint server_endpoint =
mojo::NamedPlatformChannel::ConnectToServer(server_name); mojo::NamedPlatformChannel::ConnectToServer(server_name);
// The browser may still be in the process of launching, so the endpoint
// may not yet be available.
if (!server_endpoint.is_valid())
return mojo::PlatformChannelEndpoint();
mojo::PlatformChannel channel; mojo::PlatformChannel channel;
mach_msg_base_t message{}; mach_msg_base_t message{};
message.header.msgh_id = app_mode::kBootstrapMsgId; message.header.msgh_id = app_mode::kBootstrapMsgId;
...@@ -188,50 +193,14 @@ mojo::PlatformChannelEndpoint AppShimController::ConnectToBrowser( ...@@ -188,50 +193,14 @@ mojo::PlatformChannelEndpoint AppShimController::ConnectToBrowser(
return channel.TakeRemoteEndpoint(); return channel.TakeRemoteEndpoint();
} }
void AppShimController::InitBootstrapPipe() { void AppShimController::InitBootstrapPipe(
mojo::PlatformChannelEndpoint endpoint) {
SetUpMenu(); SetUpMenu();
// Chrome will relaunch shims when relaunching apps. // Chrome will relaunch shims when relaunching apps.
[NSApp disableRelaunchOnLogin]; [NSApp disableRelaunchOnLogin];
CHECK(!params_.user_data_dir.empty()); CHECK(!params_.user_data_dir.empty());
mojo::PlatformChannelEndpoint endpoint;
// Check for the signal file. If this file is present, then Chrome is running
// with features::kMojoChannelMac and the app shim needs to connect over
// Mach IPC. The FeatureList also needs to be initialized with that on, so
// Mojo internals use the right transport mechanism.
base::FilePath mojo_channel_mac_signal_file =
params_.user_data_dir.Append(app_mode::kMojoChannelMacSignalFile);
if (base::PathExists(mojo_channel_mac_signal_file)) {
base::FeatureList::InitializeInstance(mojo::features::kMojoChannelMac.name,
std::string());
NSString* browser_bundle_id =
base::mac::ObjCCast<NSString>([[NSBundle mainBundle]
objectForInfoDictionaryKey:app_mode::kBrowserBundleIDKey]);
CHECK(browser_bundle_id);
std::string name_fragment = base::StringPrintf(
"%s.%s.%s", base::SysNSStringToUTF8(browser_bundle_id).c_str(),
app_mode::kAppShimBootstrapNameFragment,
base::MD5String(params_.user_data_dir.value()).c_str());
endpoint = ConnectToBrowser(name_fragment);
} else {
base::FilePath symlink_path =
params_.user_data_dir.Append(app_mode::kAppShimSocketSymlinkName);
base::FilePath socket_path;
if (base::ReadSymbolicLink(symlink_path, &socket_path)) {
app_mode::VerifySocketPermissions(socket_path);
} else {
// The path in the user data dir is not a symlink, try connecting
// directly.
socket_path = symlink_path;
}
endpoint = mojo::NamedPlatformChannel::ConnectToServer(socket_path.value());
}
CreateChannelAndSendLaunchApp(std::move(endpoint)); CreateChannelAndSendLaunchApp(std::move(endpoint));
} }
......
...@@ -20,8 +20,6 @@ source_set("app_shim") { ...@@ -20,8 +20,6 @@ source_set("app_shim") {
"extension_app_shim_handler_mac.h", "extension_app_shim_handler_mac.h",
"mach_bootstrap_acceptor.cc", "mach_bootstrap_acceptor.cc",
"mach_bootstrap_acceptor.h", "mach_bootstrap_acceptor.h",
"unix_domain_socket_acceptor.cc",
"unix_domain_socket_acceptor.h",
] ]
deps = [ deps = [
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include "components/version_info/version_info.h" #include "components/version_info/version_info.h"
#include "content/public/test/test_utils.h" #include "content/public/test/test_utils.h"
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/platform/features.h"
#include "mojo/public/cpp/platform/named_platform_channel.h" #include "mojo/public/cpp/platform/named_platform_channel.h"
#include "mojo/public/cpp/platform/platform_channel.h" #include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/isolated_connection.h" #include "mojo/public/cpp/system/isolated_connection.h"
...@@ -92,32 +91,19 @@ TestShimClient::TestShimClient() ...@@ -92,32 +91,19 @@ TestShimClient::TestShimClient()
base::FilePath user_data_dir; base::FilePath user_data_dir;
CHECK(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); CHECK(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
mojo::PlatformChannelEndpoint endpoint; std::string name_fragment =
base::StringPrintf("%s.%s.%s", base::mac::BaseBundleID(),
if (base::FeatureList::IsEnabled(mojo::features::kMojoChannelMac)) { app_mode::kAppShimBootstrapNameFragment,
std::string name_fragment = base::MD5String(user_data_dir.value()).c_str());
base::StringPrintf("%s.%s.%s", base::mac::BaseBundleID(), mojo::PlatformChannelEndpoint endpoint = ConnectToBrowser(name_fragment);
app_mode::kAppShimBootstrapNameFragment,
base::MD5String(user_data_dir.value()).c_str());
endpoint = ConnectToBrowser(name_fragment);
} else {
base::FilePath symlink_path =
user_data_dir.Append(app_mode::kAppShimSocketSymlinkName);
base::FilePath socket_path;
base::ScopedAllowBlockingForTesting allow_blocking;
CHECK(base::ReadSymbolicLink(symlink_path, &socket_path));
app_mode::VerifySocketPermissions(socket_path);
endpoint = mojo::NamedPlatformChannel::ConnectToServer(socket_path.value());
}
mojo::ScopedMessagePipeHandle message_pipe = mojo::ScopedMessagePipeHandle message_pipe =
mojo_connection_.Connect(std::move(endpoint)); mojo_connection_.Connect(std::move(endpoint));
host_bootstrap_ = chrome::mojom::AppShimHostBootstrapPtr( host_bootstrap_ = chrome::mojom::AppShimHostBootstrapPtr(
chrome::mojom::AppShimHostBootstrapPtrInfo(std::move(message_pipe), 0)); chrome::mojom::AppShimHostBootstrapPtrInfo(std::move(message_pipe), 0));
} }
// Browser Test for AppShimHostManager to test IPC interactions across the // Browser Test for AppShimHostManager to test IPC interactions.
// UNIX domain socket.
class AppShimHostManagerBrowserTest : public InProcessBrowserTest, class AppShimHostManagerBrowserTest : public InProcessBrowserTest,
public apps::AppShimHandler, public apps::AppShimHandler,
public chrome::mojom::AppShimHost { public chrome::mojom::AppShimHost {
...@@ -233,58 +219,43 @@ IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, LaunchRegisterOnly) { ...@@ -233,58 +219,43 @@ IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, LaunchRegisterOnly) {
EXPECT_TRUE(last_launch_files_.empty()); EXPECT_TRUE(last_launch_files_.empty());
} }
// Ensure the domain socket can be created in a fresh user data dir. // Ensure bootstrap name registers.
IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest,
PRE_ReCreate) { PRE_ReCreate) {
test::AppShimHostManagerTestApi test_api( test::AppShimHostManagerTestApi test_api(
g_browser_process->platform_part()->app_shim_host_manager()); g_browser_process->platform_part()->app_shim_host_manager());
if (base::FeatureList::IsEnabled(mojo::features::kMojoChannelMac)) { EXPECT_TRUE(test_api.mach_acceptor());
EXPECT_TRUE(test_api.mach_acceptor());
} else {
EXPECT_TRUE(test_api.acceptor());
}
} }
// Ensure the domain socket can be re-created after a prior browser process has // Ensure the bootstrap name can be re-created after a prior browser process has
// quit. // quit.
IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest,
ReCreate) { ReCreate) {
test::AppShimHostManagerTestApi test_api( test::AppShimHostManagerTestApi test_api(
g_browser_process->platform_part()->app_shim_host_manager()); g_browser_process->platform_part()->app_shim_host_manager());
if (base::FeatureList::IsEnabled(mojo::features::kMojoChannelMac)) { EXPECT_TRUE(test_api.mach_acceptor());
EXPECT_TRUE(test_api.mach_acceptor());
} else {
EXPECT_TRUE(test_api.acceptor());
}
} }
// Tests for the files created by AppShimHostManager. // Tests for the files created by AppShimHostManager.
class AppShimHostManagerBrowserTestSocketFiles class AppShimHostManagerBrowserTestSymlink
: public AppShimHostManagerBrowserTest { : public AppShimHostManagerBrowserTest {
public: public:
AppShimHostManagerBrowserTestSocketFiles() {} AppShimHostManagerBrowserTestSymlink() {}
protected: protected:
base::FilePath directory_in_tmp_;
base::FilePath symlink_path_;
base::FilePath version_path_; base::FilePath version_path_;
private: private:
bool SetUpUserDataDirectory() override; bool SetUpUserDataDirectory() override;
void TearDownInProcessBrowserTestFixture() override; void TearDownInProcessBrowserTestFixture() override;
DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTestSocketFiles); DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTestSymlink);
}; };
bool AppShimHostManagerBrowserTestSocketFiles::SetUpUserDataDirectory() { bool AppShimHostManagerBrowserTestSymlink::SetUpUserDataDirectory() {
// Create an existing symlink. It should be replaced by AppShimHostManager. // Create an existing symlink. It should be replaced by AppShimHostManager.
base::FilePath user_data_dir; base::FilePath user_data_dir;
EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
symlink_path_ = user_data_dir.Append(app_mode::kAppShimSocketSymlinkName);
base::FilePath temp_dir;
base::PathService::Get(base::DIR_TEMP, &temp_dir);
EXPECT_TRUE(base::CreateSymbolicLink(temp_dir.Append("chrome-XXXXXX"),
symlink_path_));
// Create an invalid RunningChromeVersion file. // Create an invalid RunningChromeVersion file.
version_path_ = version_path_ =
...@@ -294,34 +265,14 @@ bool AppShimHostManagerBrowserTestSocketFiles::SetUpUserDataDirectory() { ...@@ -294,34 +265,14 @@ bool AppShimHostManagerBrowserTestSocketFiles::SetUpUserDataDirectory() {
return AppShimHostManagerBrowserTest::SetUpUserDataDirectory(); return AppShimHostManagerBrowserTest::SetUpUserDataDirectory();
} }
void AppShimHostManagerBrowserTestSocketFiles:: void AppShimHostManagerBrowserTestSymlink::
TearDownInProcessBrowserTestFixture() { TearDownInProcessBrowserTestFixture() {
// Check that created files have been deleted. // Check that created files have been deleted.
EXPECT_FALSE(base::PathExists(directory_in_tmp_));
EXPECT_FALSE(base::PathExists(symlink_path_));
EXPECT_FALSE(base::PathExists(version_path_)); EXPECT_FALSE(base::PathExists(version_path_));
} }
IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTestSocketFiles, IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTestSymlink,
ReplacesSymlinkAndCleansUpFiles) { RunningChromeVersionCorrectlyWritten) {
if (base::FeatureList::IsEnabled(mojo::features::kMojoChannelMac))
return;
// Get the directory created by AppShimHostManager.
test::AppShimHostManagerTestApi test_api(
g_browser_process->platform_part()->app_shim_host_manager());
directory_in_tmp_ = test_api.directory_in_tmp();
// Check that socket files have been created.
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(base::PathExists(directory_in_tmp_));
EXPECT_TRUE(base::PathExists(symlink_path_));
// Check that the symlink has been replaced.
base::FilePath socket_path;
ASSERT_TRUE(base::ReadSymbolicLink(symlink_path_, &socket_path));
EXPECT_EQ(app_mode::kAppShimSocketShortName, socket_path.BaseName().value());
// Check that the RunningChromeVersion file is correctly written. // Check that the RunningChromeVersion file is correctly written.
base::FilePath version; base::FilePath version;
EXPECT_TRUE(base::ReadSymbolicLink(version_path_, &version)); EXPECT_TRUE(base::ReadSymbolicLink(version_path_, &version));
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "chrome/browser/apps/app_shim/mach_bootstrap_acceptor.h" #include "chrome/browser/apps/app_shim/mach_bootstrap_acceptor.h"
#include "chrome/browser/apps/app_shim/unix_domain_socket_acceptor.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/platform/platform_channel_endpoint.h" #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
...@@ -26,10 +25,10 @@ namespace test { ...@@ -26,10 +25,10 @@ namespace test {
class AppShimHostManagerTestApi; class AppShimHostManagerTestApi;
} }
// The AppShimHostManager receives connections from app shims on a UNIX // The AppShimHostManager receives connections from app shims on a Mach
// socket (|acceptor_|) and creates a helper object to manage the connection. // bootstrap namespace entry (mach_acceptor_) and creates a helper object
class AppShimHostManager : public apps::UnixDomainSocketAcceptor::Delegate, // to manage the connection.
public apps::MachBootstrapAcceptor::Delegate, class AppShimHostManager : public apps::MachBootstrapAcceptor::Delegate,
public base::RefCountedThreadSafe< public base::RefCountedThreadSafe<
AppShimHostManager, AppShimHostManager,
content::BrowserThread::DeleteOnUIThread> { content::BrowserThread::DeleteOnUIThread> {
...@@ -53,10 +52,6 @@ class AppShimHostManager : public apps::UnixDomainSocketAcceptor::Delegate, ...@@ -53,10 +52,6 @@ class AppShimHostManager : public apps::UnixDomainSocketAcceptor::Delegate,
friend class test::AppShimHostManagerTestApi; friend class test::AppShimHostManagerTestApi;
virtual ~AppShimHostManager(); virtual ~AppShimHostManager();
// UnixDomainSocketAcceptor::Delegate implementation.
void OnClientConnected(mojo::PlatformChannelEndpoint endpoint) override;
void OnListenError() override;
// MachBootstrapAcceptor::Delegate: // MachBootstrapAcceptor::Delegate:
void OnClientConnected(mojo::PlatformChannelEndpoint endpoint, void OnClientConnected(mojo::PlatformChannelEndpoint endpoint,
base::ProcessId peer_pid) override; base::ProcessId peer_pid) override;
...@@ -64,12 +59,8 @@ class AppShimHostManager : public apps::UnixDomainSocketAcceptor::Delegate, ...@@ -64,12 +59,8 @@ class AppShimHostManager : public apps::UnixDomainSocketAcceptor::Delegate,
// The |acceptor_| must be created on a thread which allows blocking I/O. // The |acceptor_| must be created on a thread which allows blocking I/O.
void InitOnBackgroundThread(); void InitOnBackgroundThread();
// Called on the IO thread to begin listening for connections from app shims.
void ListenOnIOThread();
base::FilePath directory_in_tmp_; base::FilePath directory_in_tmp_;
std::unique_ptr<apps::UnixDomainSocketAcceptor> acceptor_;
std::unique_ptr<apps::MachBootstrapAcceptor> mach_acceptor_; std::unique_ptr<apps::MachBootstrapAcceptor> mach_acceptor_;
std::unique_ptr<apps::ExtensionAppShimHandler> extension_app_shim_handler_; std::unique_ptr<apps::ExtensionAppShimHandler> extension_app_shim_handler_;
......
...@@ -22,38 +22,6 @@ ...@@ -22,38 +22,6 @@
#include "chrome/common/mac/app_mode_common.h" #include "chrome/common/mac/app_mode_common.h"
#include "components/version_info/version_info.h" #include "components/version_info/version_info.h"
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "mojo/public/cpp/platform/features.h"
namespace {
base::FilePath GetDirectoryInTmpTemplate(const base::FilePath& user_data_dir) {
base::FilePath temp_dir;
CHECK(base::PathService::Get(base::DIR_TEMP, &temp_dir));
// Check that it's shorter than the IPC socket length (104) minus the
// intermediate folder ("/chrome-XXXXXX/") and kAppShimSocketShortName.
DCHECK_GT(83u, temp_dir.value().length());
return temp_dir.Append("chrome-XXXXXX");
}
void DeleteSocketFiles(const base::FilePath& directory_in_tmp,
const base::FilePath& symlink_path,
const base::FilePath& version_path,
const base::FilePath& mojo_channel_mac_signal_file) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
// Delete in reverse order of creation.
if (!version_path.empty())
base::DeleteFile(version_path, false);
if (!symlink_path.empty())
base::DeleteFile(symlink_path, false);
if (!directory_in_tmp.empty())
base::DeleteFile(directory_in_tmp, true);
if (!mojo_channel_mac_signal_file.empty())
base::DeleteFile(mojo_channel_mac_signal_file, false);
}
} // namespace
AppShimHostManager::AppShimHostManager() {} AppShimHostManager::AppShimHostManager() {}
...@@ -72,8 +40,6 @@ void AppShimHostManager::Init() { ...@@ -72,8 +40,6 @@ void AppShimHostManager::Init() {
} }
AppShimHostManager::~AppShimHostManager() { AppShimHostManager::~AppShimHostManager() {
base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
->DeleteSoon(FROM_HERE, std::move(acceptor_));
base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO}) base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
->DeleteSoon(FROM_HERE, std::move(mach_acceptor_)); ->DeleteSoon(FROM_HERE, std::move(mach_acceptor_));
...@@ -84,23 +50,19 @@ AppShimHostManager::~AppShimHostManager() { ...@@ -84,23 +50,19 @@ AppShimHostManager::~AppShimHostManager() {
return; return;
apps::AppShimHandler::SetDefaultHandler(NULL); apps::AppShimHandler::SetDefaultHandler(NULL);
base::FilePath user_data_dir; base::FilePath user_data_dir;
base::FilePath symlink_path;
base::FilePath version_path;
base::FilePath mojo_channel_mac_signal_file;
if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
symlink_path = user_data_dir.Append(app_mode::kAppShimSocketSymlinkName); base::FilePath version_path =
version_path =
user_data_dir.Append(app_mode::kRunningChromeVersionSymlinkName); user_data_dir.Append(app_mode::kRunningChromeVersionSymlinkName);
mojo_channel_mac_signal_file =
user_data_dir.Append(app_mode::kMojoChannelMacSignalFile); base::PostTaskWithTraits(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(base::IgnoreResult(&base::DeleteFile), version_path,
false));
} }
base::PostTaskWithTraits(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(&DeleteSocketFiles, directory_in_tmp_, symlink_path,
version_path, mojo_channel_mac_signal_file));
} }
void AppShimHostManager::InitOnBackgroundThread() { void AppShimHostManager::InitOnBackgroundThread() {
...@@ -110,62 +72,18 @@ void AppShimHostManager::InitOnBackgroundThread() { ...@@ -110,62 +72,18 @@ void AppShimHostManager::InitOnBackgroundThread() {
if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
return; return;
std::string name_fragment =
std::string(app_mode::kAppShimBootstrapNameFragment) + "." +
base::MD5String(user_data_dir.value());
mach_acceptor_ =
std::make_unique<apps::MachBootstrapAcceptor>(name_fragment, this);
mach_acceptor_->Start();
// TODO(rsesek): Delete this after a little while, to ensure everything
// is cleaned up.
base::FilePath mojo_channel_mac_signal_file = base::FilePath mojo_channel_mac_signal_file =
user_data_dir.Append(app_mode::kMojoChannelMacSignalFile); user_data_dir.Append(app_mode::kMojoChannelMacSignalFile);
if (base::FeatureList::IsEnabled(mojo::features::kMojoChannelMac)) { base::DeleteFile(mojo_channel_mac_signal_file, false);
std::string name_fragment =
std::string(app_mode::kAppShimBootstrapNameFragment) + "." +
base::MD5String(user_data_dir.value());
mach_acceptor_ =
std::make_unique<apps::MachBootstrapAcceptor>(name_fragment, this);
mach_acceptor_->Start();
// App shims do not have Finch initialized and so cannot test for the
// kMojoChannelMac feature. Instead, put a file in the profile directory.
// The presence of this file will indicate that app shims should connect
// over a Mach channel instead.
char data = 1;
if (base::WriteFile(mojo_channel_mac_signal_file, &data, 1) != 1) {
LOG(ERROR) << "Failed to write MojoChannelMac signal file.";
}
return;
} else {
base::DeleteFile(mojo_channel_mac_signal_file, false);
}
// The socket path must be shorter than 104 chars (IPC::kMaxSocketNameLength).
// To accommodate this, we use a short path in /tmp/ that is generated from a
// hash of the user data dir.
std::string directory_string =
GetDirectoryInTmpTemplate(user_data_dir).value();
// mkdtemp() replaces trailing X's randomly and creates the directory.
if (!mkdtemp(&directory_string[0])) {
PLOG(ERROR) << directory_string;
return;
}
directory_in_tmp_ = base::FilePath(directory_string);
// Check that the directory was created with the correct permissions.
int dir_mode = 0;
if (!base::GetPosixFilePermissions(directory_in_tmp_, &dir_mode) ||
dir_mode != base::FILE_PERMISSION_USER_MASK) {
NOTREACHED();
return;
}
// UnixDomainSocketAcceptor creates the socket immediately.
base::FilePath socket_path =
directory_in_tmp_.Append(app_mode::kAppShimSocketShortName);
acceptor_.reset(new apps::UnixDomainSocketAcceptor(socket_path, this));
// Create a symlink to the socket in the user data dir. This lets the shim
// process started from Finder find the actual socket path by following the
// symlink with ::readlink().
base::FilePath symlink_path =
user_data_dir.Append(app_mode::kAppShimSocketSymlinkName);
base::DeleteFile(symlink_path, false);
base::CreateSymbolicLink(socket_path, symlink_path);
// Create a symlink containing the current version string. This allows the // Create a symlink containing the current version string. This allows the
// shim to load the same framework version as the currently running Chrome // shim to load the same framework version as the currently running Chrome
...@@ -175,28 +93,6 @@ void AppShimHostManager::InitOnBackgroundThread() { ...@@ -175,28 +93,6 @@ void AppShimHostManager::InitOnBackgroundThread() {
base::DeleteFile(version_path, false); base::DeleteFile(version_path, false);
base::CreateSymbolicLink(base::FilePath(version_info::GetVersionNumber()), base::CreateSymbolicLink(base::FilePath(version_info::GetVersionNumber()),
version_path); version_path);
base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
->PostTask(FROM_HERE,
base::BindOnce(&AppShimHostManager::ListenOnIOThread, this));
}
void AppShimHostManager::ListenOnIOThread() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (!acceptor_->Listen()) {
base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI})
->PostTask(FROM_HERE,
base::BindOnce(&AppShimHostManager::OnListenError, this));
}
}
void AppShimHostManager::OnClientConnected(
mojo::PlatformChannelEndpoint endpoint) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI})
->PostTask(FROM_HERE,
base::BindOnce(&AppShimHostBootstrap::CreateForChannel,
std::move(endpoint)));
} }
void AppShimHostManager::OnClientConnected( void AppShimHostManager::OnClientConnected(
...@@ -208,10 +104,3 @@ void AppShimHostManager::OnClientConnected( ...@@ -208,10 +104,3 @@ void AppShimHostManager::OnClientConnected(
base::BindOnce(&AppShimHostBootstrap::CreateForChannelAndPeerID, base::BindOnce(&AppShimHostBootstrap::CreateForChannelAndPeerID,
std::move(endpoint), peer_pid)); std::move(endpoint), peer_pid));
} }
void AppShimHostManager::OnListenError() {
// TODO(tapted): Set a timeout and attempt to reconstruct the channel. Until
// cases where the error could occur are better known, just reset the acceptor
// to allow failure to be communicated via the test API.
acceptor_.reset();
}
...@@ -19,10 +19,6 @@ AppShimHostManagerTestApi::AppShimHostManagerTestApi( ...@@ -19,10 +19,6 @@ AppShimHostManagerTestApi::AppShimHostManagerTestApi(
DCHECK(host_manager_); DCHECK(host_manager_);
} }
apps::UnixDomainSocketAcceptor* AppShimHostManagerTestApi::acceptor() {
return host_manager_->acceptor_.get();
}
apps::MachBootstrapAcceptor* AppShimHostManagerTestApi::mach_acceptor() { apps::MachBootstrapAcceptor* AppShimHostManagerTestApi::mach_acceptor() {
return host_manager_->mach_acceptor_.get(); return host_manager_->mach_acceptor_.get();
} }
......
...@@ -18,7 +18,6 @@ class FilePath; ...@@ -18,7 +18,6 @@ class FilePath;
namespace apps { namespace apps {
class ExtensionAppShimHandler; class ExtensionAppShimHandler;
class MachBootstrapAcceptor; class MachBootstrapAcceptor;
class UnixDomainSocketAcceptor;
} }
namespace test { namespace test {
...@@ -27,8 +26,6 @@ class AppShimHostManagerTestApi { ...@@ -27,8 +26,6 @@ class AppShimHostManagerTestApi {
public: public:
explicit AppShimHostManagerTestApi(AppShimHostManager* host_manager); explicit AppShimHostManagerTestApi(AppShimHostManager* host_manager);
apps::UnixDomainSocketAcceptor* acceptor();
apps::MachBootstrapAcceptor* mach_acceptor(); apps::MachBootstrapAcceptor* mach_acceptor();
const base::FilePath& directory_in_tmp(); const base::FilePath& directory_in_tmp();
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/apps/app_shim/unix_domain_socket_acceptor.h"
#include <utility>
#include "base/logging.h"
#include "base/message_loop/message_loop_current.h"
#include "mojo/public/cpp/platform/socket_utils_posix.h"
namespace apps {
UnixDomainSocketAcceptor::UnixDomainSocketAcceptor(const base::FilePath& path,
Delegate* delegate)
: server_listen_connection_watcher_(FROM_HERE),
named_pipe_(path.value()),
delegate_(delegate) {
mojo::NamedPlatformChannel::Options options;
options.server_name = named_pipe_;
mojo::NamedPlatformChannel channel(options);
listen_handle_ = channel.TakeServerEndpoint();
DCHECK(delegate_);
}
UnixDomainSocketAcceptor::~UnixDomainSocketAcceptor() {
Close();
}
bool UnixDomainSocketAcceptor::Listen() {
if (!listen_handle_.is_valid())
return false;
// Watch the fd for connections, and turn any connections into
// active sockets.
base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
listen_handle_.platform_handle().GetFD().get(), true,
base::MessagePumpForIO::WATCH_READ, &server_listen_connection_watcher_,
this);
return true;
}
// Called by libevent when we can read from the fd without blocking.
void UnixDomainSocketAcceptor::OnFileCanReadWithoutBlocking(int fd) {
DCHECK_EQ(fd, listen_handle_.platform_handle().GetFD().get());
base::ScopedFD connection_fd;
if (!mojo::AcceptSocketConnection(fd, &connection_fd)) {
Close();
delegate_->OnListenError();
return;
}
if (!connection_fd.is_valid()) {
// The accept() failed, but not in such a way that the factory needs to be
// shut down.
return;
}
delegate_->OnClientConnected(mojo::PlatformChannelEndpoint(
mojo::PlatformHandle(std::move(connection_fd))));
}
void UnixDomainSocketAcceptor::OnFileCanWriteWithoutBlocking(int fd) {
NOTREACHED() << "Listen fd should never be writable.";
}
void UnixDomainSocketAcceptor::Close() {
if (!listen_handle_.is_valid())
return;
listen_handle_.reset();
if (unlink(named_pipe_.c_str()) < 0)
PLOG(ERROR) << "unlink";
// Unregister libevent for the listening socket and close it.
server_listen_connection_watcher_.StopWatchingFileDescriptor();
}
} // namespace apps
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_APPS_APP_SHIM_UNIX_DOMAIN_SOCKET_ACCEPTOR_H_
#define CHROME_BROWSER_APPS_APP_SHIM_UNIX_DOMAIN_SOCKET_ACCEPTOR_H_
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/message_loop/message_pump_for_io.h"
#include "mojo/public/cpp/platform/named_platform_channel.h"
#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
#include "mojo/public/cpp/platform/platform_channel_server_endpoint.h"
namespace apps {
// A UnixDomainSocketAcceptor listens on a UNIX domain socket. When a
// client connects to the socket, it accept()s the connection and
// passes the new FD to the delegate. The delegate is then responsible
// for creating a new IPC::Channel for the FD.
class UnixDomainSocketAcceptor : public base::MessagePumpForIO::FdWatcher {
public:
class Delegate {
public:
// Called when a client connects to the factory. It is the delegate's
// responsibility to create an IPC::Channel for the handle, or else close
// the file descriptor contained therein.
virtual void OnClientConnected(mojo::PlatformChannelEndpoint endpoint) = 0;
// Called when an error occurs and the channel is closed.
virtual void OnListenError() = 0;
};
UnixDomainSocketAcceptor(const base::FilePath& path, Delegate* delegate);
~UnixDomainSocketAcceptor() override;
// Call this to start listening on the socket.
bool Listen();
// Close and unlink the socket, and stop accepting connections.
void Close();
private:
void OnFileCanReadWithoutBlocking(int fd) override;
void OnFileCanWriteWithoutBlocking(int fd) override;
base::MessagePumpForIO::FdWatchController server_listen_connection_watcher_;
mojo::NamedPlatformChannel::ServerName named_pipe_;
Delegate* delegate_;
mojo::PlatformChannelServerEndpoint listen_handle_;
DISALLOW_COPY_AND_ASSIGN(UnixDomainSocketAcceptor);
};
} // namespace apps
#endif // CHROME_BROWSER_APPS_APP_SHIM_UNIX_DOMAIN_SOCKET_ACCEPTOR_H_
...@@ -34,13 +34,6 @@ class NSString; ...@@ -34,13 +34,6 @@ class NSString;
namespace app_mode { namespace app_mode {
// The IPC socket used to communicate between app shims and Chrome will be
// created under a temporary directory with this name.
extern const char kAppShimSocketShortName[];
// A symlink to allow the app shim to find the socket will be created under the
// user data dir with this name.
extern const char kAppShimSocketSymlinkName[];
// Mach message ID used by the shim to connect to Chrome. // Mach message ID used by the shim to connect to Chrome.
constexpr mach_msg_id_t kBootstrapMsgId = 'apps'; constexpr mach_msg_id_t kBootstrapMsgId = 'apps';
...@@ -50,6 +43,7 @@ constexpr mach_msg_id_t kBootstrapMsgId = 'apps'; ...@@ -50,6 +43,7 @@ constexpr mach_msg_id_t kBootstrapMsgId = 'apps';
// of the full profile directory path. // of the full profile directory path.
extern const char kAppShimBootstrapNameFragment[]; extern const char kAppShimBootstrapNameFragment[];
// TODO(rsesek): Delete this after ensuring the file has been cleaned up.
// The name of a file placed in the profile directory to indicate that app // The name of a file placed in the profile directory to indicate that app
// shims should connect over Mach IPC rather than a UNIX domain socket. If // shims should connect over Mach IPC rather than a UNIX domain socket. If
// a file named this does not exist, app shims will fall back to the UNIX // a file named this does not exist, app shims will fall back to the UNIX
...@@ -198,10 +192,6 @@ struct ChromeAppModeInfo { ...@@ -198,10 +192,6 @@ struct ChromeAppModeInfo {
const char* profile_dir; const char* profile_dir;
}; };
// Check that the socket and its parent directory have the correct permissions
// and are owned by the user.
void VerifySocketPermissions(const base::FilePath& socket_path);
} // namespace app_mode } // namespace app_mode
#endif // CHROME_COMMON_MAC_APP_MODE_COMMON_H_ #endif // CHROME_COMMON_MAC_APP_MODE_COMMON_H_
...@@ -7,13 +7,8 @@ ...@@ -7,13 +7,8 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#include <type_traits> #include <type_traits>
#include "base/files/file_util.h"
namespace app_mode { namespace app_mode {
const char kAppShimSocketShortName[] = "Socket";
const char kAppShimSocketSymlinkName[] = "App Shim Socket";
const char kAppShimBootstrapNameFragment[] = "apps"; const char kAppShimBootstrapNameFragment[] = "apps";
const char kMojoChannelMacSignalFile[] = "apps_use_mojo_channel_mac"; const char kMojoChannelMacSignalFile[] = "apps_use_mojo_channel_mac";
...@@ -78,12 +73,4 @@ static_assert( ...@@ -78,12 +73,4 @@ static_assert(
"ChromeAppModeInfo layout has changed; bump the APP_SHIM_VERSION_NUMBER " "ChromeAppModeInfo layout has changed; bump the APP_SHIM_VERSION_NUMBER "
"in chrome/common/mac/app_mode_common.h. (And fix this static_assert.)"); "in chrome/common/mac/app_mode_common.h. (And fix this static_assert.)");
void VerifySocketPermissions(const base::FilePath& socket_path) {
CHECK(base::PathIsWritable(socket_path));
base::FilePath socket_dir = socket_path.DirName();
int socket_dir_mode = 0;
CHECK(base::GetPosixFilePermissions(socket_dir, &socket_dir_mode));
CHECK_EQ(0700, socket_dir_mode);
}
} // namespace app_mode } // namespace app_mode
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