Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / apps / app_shim / app_shim_host_manager_browsertest_mac.mm
blob2018c986de070656000c7d9fa7bd23ff3164d2ad
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h"
7 #include <unistd.h>
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/path_service.h"
12 #include "chrome/browser/apps/app_shim/app_shim_handler_mac.h"
13 #include "chrome/browser/apps/app_shim/test/app_shim_host_manager_test_api_mac.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "chrome/common/mac/app_mode_common.h"
19 #include "chrome/common/mac/app_shim_messages.h"
20 #include "chrome/test/base/in_process_browser_test.h"
21 #include "components/version_info/version_info.h"
22 #include "content/public/test/test_utils.h"
23 #include "ipc/ipc_channel_proxy.h"
24 #include "ipc/ipc_listener.h"
25 #include "ipc/ipc_message.h"
27 namespace {
29 const char kTestAppMode[] = "test_app";
31 // A test version of the AppShimController IPC client in chrome_main_app_mode.
32 class TestShimClient : public IPC::Listener {
33  public:
34   TestShimClient();
35   ~TestShimClient() override;
37   template <class T>
38   void Send(const T& message) {
39     channel_->Send(message);
40   }
42  private:
43   // IPC::Listener overrides:
44   bool OnMessageReceived(const IPC::Message& message) override;
45   void OnChannelError() override;
47   base::Thread io_thread_;
48   scoped_ptr<IPC::ChannelProxy> channel_;
50   DISALLOW_COPY_AND_ASSIGN(TestShimClient);
53 TestShimClient::TestShimClient() : io_thread_("TestShimClientIO") {
54   base::Thread::Options io_thread_options;
55   io_thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
56   io_thread_.StartWithOptions(io_thread_options);
58   base::FilePath user_data_dir;
59   CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
60   base::FilePath symlink_path =
61       user_data_dir.Append(app_mode::kAppShimSocketSymlinkName);
63   base::FilePath socket_path;
64   CHECK(base::ReadSymbolicLink(symlink_path, &socket_path));
65   app_mode::VerifySocketPermissions(socket_path);
67   IPC::ChannelHandle handle(socket_path.value());
68   channel_ = IPC::ChannelProxy::Create(handle, IPC::Channel::MODE_NAMED_CLIENT,
69                                        this, io_thread_.task_runner().get());
72 TestShimClient::~TestShimClient() {}
74 bool TestShimClient::OnMessageReceived(const IPC::Message& message) {
75   return true;
78 void TestShimClient::OnChannelError() {
79   // Client should not get any channel errors for the current set of tests.
80   PLOG(FATAL) << "ChannelError";
83 // Browser Test for AppShimHostManager to test IPC interactions across the
84 // UNIX domain socket.
85 class AppShimHostManagerBrowserTest : public InProcessBrowserTest,
86                                       public apps::AppShimHandler {
87  public:
88   AppShimHostManagerBrowserTest();
89   ~AppShimHostManagerBrowserTest() override;
91  protected:
92   // Wait for OnShimLaunch, then send a quit, and wait for the response. Used to
93   // test launch behavior.
94   void RunAndExitGracefully();
96   // InProcessBrowserTest overrides:
97   void SetUpOnMainThread() override;
98   void TearDownOnMainThread() override;
100   // AppShimHandler overrides:
101   void OnShimLaunch(apps::AppShimHandler::Host* host,
102                     apps::AppShimLaunchType launch_type,
103                     const std::vector<base::FilePath>& files) override;
104   void OnShimClose(apps::AppShimHandler::Host* host) override {}
105   void OnShimFocus(apps::AppShimHandler::Host* host,
106                    apps::AppShimFocusType focus_type,
107                    const std::vector<base::FilePath>& files) override {}
108   void OnShimSetHidden(apps::AppShimHandler::Host* host, bool hidden) override {
109   }
110   void OnShimQuit(apps::AppShimHandler::Host* host) override;
112   scoped_ptr<TestShimClient> test_client_;
113   std::vector<base::FilePath> last_launch_files_;
114   apps::AppShimLaunchType last_launch_type_;
116 private:
117   scoped_refptr<content::MessageLoopRunner> runner_;
119   int launch_count_;
120   int quit_count_;
122   DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTest);
125 AppShimHostManagerBrowserTest::AppShimHostManagerBrowserTest()
126     : last_launch_type_(apps::APP_SHIM_LAUNCH_NUM_TYPES),
127       launch_count_(0),
128       quit_count_(0) {
131 AppShimHostManagerBrowserTest::~AppShimHostManagerBrowserTest() {
134 void AppShimHostManagerBrowserTest::RunAndExitGracefully() {
135   runner_ = new content::MessageLoopRunner();
136   EXPECT_EQ(0, launch_count_);
137   runner_->Run();  // Will stop in OnShimLaunch().
138   EXPECT_EQ(1, launch_count_);
140   runner_ = new content::MessageLoopRunner();
141   test_client_->Send(new AppShimHostMsg_QuitApp);
142   EXPECT_EQ(0, quit_count_);
143   runner_->Run();  // Will stop in OnShimQuit().
144   EXPECT_EQ(1, quit_count_);
146   test_client_.reset();
149 void AppShimHostManagerBrowserTest::SetUpOnMainThread() {
150   // Can't do this in the constructor, it needs a BrowserProcess.
151   apps::AppShimHandler::RegisterHandler(kTestAppMode, this);
154 void AppShimHostManagerBrowserTest::TearDownOnMainThread() {
155   apps::AppShimHandler::RemoveHandler(kTestAppMode);
158 void AppShimHostManagerBrowserTest::OnShimLaunch(
159     apps::AppShimHandler::Host* host,
160     apps::AppShimLaunchType launch_type,
161     const std::vector<base::FilePath>& files) {
162   host->OnAppLaunchComplete(apps::APP_SHIM_LAUNCH_SUCCESS);
163   ++launch_count_;
164   last_launch_type_ = launch_type;
165   last_launch_files_ = files;
166   runner_->Quit();
169 void AppShimHostManagerBrowserTest::OnShimQuit(
170     apps::AppShimHandler::Host* host) {
171   ++quit_count_;
172   runner_->Quit();
175 // Test regular launch, which would ask Chrome to launch the app.
176 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, LaunchNormal) {
177   test_client_.reset(new TestShimClient());
178   test_client_->Send(new AppShimHostMsg_LaunchApp(
179       browser()->profile()->GetPath(),
180       kTestAppMode,
181       apps::APP_SHIM_LAUNCH_NORMAL,
182       std::vector<base::FilePath>()));
184   RunAndExitGracefully();
185   EXPECT_EQ(apps::APP_SHIM_LAUNCH_NORMAL, last_launch_type_);
186   EXPECT_TRUE(last_launch_files_.empty());
189 // Test register-only launch, used when Chrome has already launched the app.
190 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, LaunchRegisterOnly) {
191   test_client_.reset(new TestShimClient());
192   test_client_->Send(new AppShimHostMsg_LaunchApp(
193       browser()->profile()->GetPath(),
194       kTestAppMode,
195       apps::APP_SHIM_LAUNCH_REGISTER_ONLY,
196       std::vector<base::FilePath>()));
198   RunAndExitGracefully();
199   EXPECT_EQ(apps::APP_SHIM_LAUNCH_REGISTER_ONLY, last_launch_type_);
200   EXPECT_TRUE(last_launch_files_.empty());
203 // Ensure the domain socket can be created in a fresh user data dir.
204 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest,
205                        PRE_ReCreate) {
206   test::AppShimHostManagerTestApi test_api(
207       g_browser_process->platform_part()->app_shim_host_manager());
208   EXPECT_TRUE(test_api.acceptor());
211 // Ensure the domain socket can be re-created after a prior browser process has
212 // quit.
213 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest,
214                        ReCreate) {
215   test::AppShimHostManagerTestApi test_api(
216       g_browser_process->platform_part()->app_shim_host_manager());
217   EXPECT_TRUE(test_api.acceptor());
220 // Tests for the files created by AppShimHostManager.
221 class AppShimHostManagerBrowserTestSocketFiles
222     : public AppShimHostManagerBrowserTest {
223  public:
224   AppShimHostManagerBrowserTestSocketFiles() {}
226  protected:
227   base::FilePath directory_in_tmp_;
228   base::FilePath symlink_path_;
229   base::FilePath version_path_;
231  private:
232   bool SetUpUserDataDirectory() override;
233   void TearDownInProcessBrowserTestFixture() override;
235   DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTestSocketFiles);
238 bool AppShimHostManagerBrowserTestSocketFiles::SetUpUserDataDirectory() {
239   // Create an existing symlink. It should be replaced by AppShimHostManager.
240   base::FilePath user_data_dir;
241   EXPECT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
242   symlink_path_ = user_data_dir.Append(app_mode::kAppShimSocketSymlinkName);
243   base::FilePath temp_dir;
244   PathService::Get(base::DIR_TEMP, &temp_dir);
245   EXPECT_TRUE(base::CreateSymbolicLink(temp_dir.Append("chrome-XXXXXX"),
246                                        symlink_path_));
248   // Create an invalid RunningChromeVersion file.
249   version_path_ =
250       user_data_dir.Append(app_mode::kRunningChromeVersionSymlinkName);
251   EXPECT_TRUE(base::CreateSymbolicLink(base::FilePath("invalid_version"),
252                                        version_path_));
253   return AppShimHostManagerBrowserTest::SetUpUserDataDirectory();
256 void AppShimHostManagerBrowserTestSocketFiles::
257     TearDownInProcessBrowserTestFixture() {
258   // Check that created files have been deleted.
259   EXPECT_FALSE(base::PathExists(directory_in_tmp_));
260   EXPECT_FALSE(base::PathExists(symlink_path_));
261   EXPECT_FALSE(base::PathExists(version_path_));
264 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTestSocketFiles,
265                        ReplacesSymlinkAndCleansUpFiles) {
266   // Get the directory created by AppShimHostManager.
267   test::AppShimHostManagerTestApi test_api(
268       g_browser_process->platform_part()->app_shim_host_manager());
269   directory_in_tmp_ = test_api.directory_in_tmp();
271   // Check that socket files have been created.
272   EXPECT_TRUE(base::PathExists(directory_in_tmp_));
273   EXPECT_TRUE(base::PathExists(symlink_path_));
275   // Check that the symlink has been replaced.
276   base::FilePath socket_path;
277   ASSERT_TRUE(base::ReadSymbolicLink(symlink_path_, &socket_path));
278   EXPECT_EQ(app_mode::kAppShimSocketShortName, socket_path.BaseName().value());
280   // Check that the RunningChromeVersion file is correctly written.
281   base::FilePath version;
282   EXPECT_TRUE(base::ReadSymbolicLink(version_path_, &version));
283   EXPECT_EQ(version_info::GetVersionNumber(), version.value());
286 }  // namespace