Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / apps / app_shim / app_shim_host_manager_browsertest_mac.mm
blobc48de0db85ac8127416a1a22dc297794a4056947
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/test/app_shim_host_manager_test_api_mac.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/common/chrome_version_info.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 "content/public/test/test_utils.h"
22 #include "ipc/ipc_channel_proxy.h"
23 #include "ipc/ipc_listener.h"
24 #include "ipc/ipc_message.h"
26 namespace {
28 const char kTestAppMode[] = "test_app";
30 // A test version of the AppShimController IPC client in chrome_main_app_mode.
31 class TestShimClient : public IPC::Listener {
32  public:
33   TestShimClient();
34   ~TestShimClient() override;
36   template <class T>
37   void Send(const T& message) {
38     channel_->Send(message);
39   }
41  private:
42   // IPC::Listener overrides:
43   bool OnMessageReceived(const IPC::Message& message) override;
44   void OnChannelError() override;
46   base::Thread io_thread_;
47   scoped_ptr<IPC::ChannelProxy> channel_;
49   DISALLOW_COPY_AND_ASSIGN(TestShimClient);
52 TestShimClient::TestShimClient() : io_thread_("TestShimClientIO") {
53   base::Thread::Options io_thread_options;
54   io_thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
55   io_thread_.StartWithOptions(io_thread_options);
57   base::FilePath user_data_dir;
58   CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
59   base::FilePath symlink_path =
60       user_data_dir.Append(app_mode::kAppShimSocketSymlinkName);
62   base::FilePath socket_path;
63   CHECK(base::ReadSymbolicLink(symlink_path, &socket_path));
64   app_mode::VerifySocketPermissions(socket_path);
66   IPC::ChannelHandle handle(socket_path.value());
67   channel_ = IPC::ChannelProxy::Create(handle,
68                                        IPC::Channel::MODE_NAMED_CLIENT,
69                                        this,
70                                        io_thread_.message_loop_proxy().get());
73 TestShimClient::~TestShimClient() {}
75 bool TestShimClient::OnMessageReceived(const IPC::Message& message) {
76   return true;
79 void TestShimClient::OnChannelError() {
80   // Client should not get any channel errors for the current set of tests.
81   PLOG(FATAL) << "ChannelError";
84 // Browser Test for AppShimHostManager to test IPC interactions across the
85 // UNIX domain socket.
86 class AppShimHostManagerBrowserTest : public InProcessBrowserTest,
87                                       public apps::AppShimHandler {
88  public:
89   AppShimHostManagerBrowserTest();
90   ~AppShimHostManagerBrowserTest() override;
92  protected:
93   // Wait for OnShimLaunch, then send a quit, and wait for the response. Used to
94   // test launch behavior.
95   void RunAndExitGracefully();
97   // InProcessBrowserTest overrides:
98   void SetUpOnMainThread() override;
99   void TearDownOnMainThread() override;
101   // AppShimHandler overrides:
102   void OnShimLaunch(apps::AppShimHandler::Host* host,
103                     apps::AppShimLaunchType launch_type,
104                     const std::vector<base::FilePath>& files) override;
105   void OnShimClose(apps::AppShimHandler::Host* host) override {}
106   void OnShimFocus(apps::AppShimHandler::Host* host,
107                    apps::AppShimFocusType focus_type,
108                    const std::vector<base::FilePath>& files) override {}
109   void OnShimSetHidden(apps::AppShimHandler::Host* host, bool hidden) override {
110   }
111   void OnShimQuit(apps::AppShimHandler::Host* host) override;
113   scoped_ptr<TestShimClient> test_client_;
114   std::vector<base::FilePath> last_launch_files_;
115   apps::AppShimLaunchType last_launch_type_;
117 private:
118   scoped_refptr<content::MessageLoopRunner> runner_;
120   int launch_count_;
121   int quit_count_;
123   DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTest);
126 AppShimHostManagerBrowserTest::AppShimHostManagerBrowserTest()
127     : last_launch_type_(apps::APP_SHIM_LAUNCH_NUM_TYPES),
128       launch_count_(0),
129       quit_count_(0) {
132 AppShimHostManagerBrowserTest::~AppShimHostManagerBrowserTest() {
135 void AppShimHostManagerBrowserTest::RunAndExitGracefully() {
136   runner_ = new content::MessageLoopRunner();
137   EXPECT_EQ(0, launch_count_);
138   runner_->Run();  // Will stop in OnShimLaunch().
139   EXPECT_EQ(1, launch_count_);
141   runner_ = new content::MessageLoopRunner();
142   test_client_->Send(new AppShimHostMsg_QuitApp);
143   EXPECT_EQ(0, quit_count_);
144   runner_->Run();  // Will stop in OnShimQuit().
145   EXPECT_EQ(1, quit_count_);
147   test_client_.reset();
150 void AppShimHostManagerBrowserTest::SetUpOnMainThread() {
151   // Can't do this in the constructor, it needs a BrowserProcess.
152   apps::AppShimHandler::RegisterHandler(kTestAppMode, this);
155 void AppShimHostManagerBrowserTest::TearDownOnMainThread() {
156   apps::AppShimHandler::RemoveHandler(kTestAppMode);
159 void AppShimHostManagerBrowserTest::OnShimLaunch(
160     apps::AppShimHandler::Host* host,
161     apps::AppShimLaunchType launch_type,
162     const std::vector<base::FilePath>& files) {
163   host->OnAppLaunchComplete(apps::APP_SHIM_LAUNCH_SUCCESS);
164   ++launch_count_;
165   last_launch_type_ = launch_type;
166   last_launch_files_ = files;
167   runner_->Quit();
170 void AppShimHostManagerBrowserTest::OnShimQuit(
171     apps::AppShimHandler::Host* host) {
172   ++quit_count_;
173   runner_->Quit();
176 // Test regular launch, which would ask Chrome to launch the app.
177 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, LaunchNormal) {
178   test_client_.reset(new TestShimClient());
179   test_client_->Send(new AppShimHostMsg_LaunchApp(
180       browser()->profile()->GetPath(),
181       kTestAppMode,
182       apps::APP_SHIM_LAUNCH_NORMAL,
183       std::vector<base::FilePath>()));
185   RunAndExitGracefully();
186   EXPECT_EQ(apps::APP_SHIM_LAUNCH_NORMAL, last_launch_type_);
187   EXPECT_TRUE(last_launch_files_.empty());
190 // Test register-only launch, used when Chrome has already launched the app.
191 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, LaunchRegisterOnly) {
192   test_client_.reset(new TestShimClient());
193   test_client_->Send(new AppShimHostMsg_LaunchApp(
194       browser()->profile()->GetPath(),
195       kTestAppMode,
196       apps::APP_SHIM_LAUNCH_REGISTER_ONLY,
197       std::vector<base::FilePath>()));
199   RunAndExitGracefully();
200   EXPECT_EQ(apps::APP_SHIM_LAUNCH_REGISTER_ONLY, last_launch_type_);
201   EXPECT_TRUE(last_launch_files_.empty());
204 // Ensure the domain socket can be created in a fresh user data dir.
205 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest,
206                        PRE_ReCreate) {
207   test::AppShimHostManagerTestApi test_api(
208       g_browser_process->platform_part()->app_shim_host_manager());
209   EXPECT_TRUE(test_api.acceptor());
212 // Ensure the domain socket can be re-created after a prior browser process has
213 // quit.
214 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest,
215                        ReCreate) {
216   test::AppShimHostManagerTestApi test_api(
217       g_browser_process->platform_part()->app_shim_host_manager());
218   EXPECT_TRUE(test_api.acceptor());
221 // Tests for the files created by AppShimHostManager.
222 class AppShimHostManagerBrowserTestSocketFiles
223     : public AppShimHostManagerBrowserTest {
224  public:
225   AppShimHostManagerBrowserTestSocketFiles() {}
227  protected:
228   base::FilePath directory_in_tmp_;
229   base::FilePath symlink_path_;
230   base::FilePath version_path_;
232  private:
233   bool SetUpUserDataDirectory() override;
234   void TearDownInProcessBrowserTestFixture() override;
236   DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTestSocketFiles);
239 bool AppShimHostManagerBrowserTestSocketFiles::SetUpUserDataDirectory() {
240   // Create an existing symlink. It should be replaced by AppShimHostManager.
241   base::FilePath user_data_dir;
242   EXPECT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
243   symlink_path_ = user_data_dir.Append(app_mode::kAppShimSocketSymlinkName);
244   base::FilePath temp_dir;
245   PathService::Get(base::DIR_TEMP, &temp_dir);
246   EXPECT_TRUE(base::CreateSymbolicLink(temp_dir.Append("chrome-XXXXXX"),
247                                        symlink_path_));
249   // Create an invalid RunningChromeVersion file.
250   version_path_ =
251       user_data_dir.Append(app_mode::kRunningChromeVersionSymlinkName);
252   EXPECT_TRUE(base::CreateSymbolicLink(base::FilePath("invalid_version"),
253                                        version_path_));
254   return AppShimHostManagerBrowserTest::SetUpUserDataDirectory();
257 void AppShimHostManagerBrowserTestSocketFiles::
258     TearDownInProcessBrowserTestFixture() {
259   // Check that created files have been deleted.
260   EXPECT_FALSE(base::PathExists(directory_in_tmp_));
261   EXPECT_FALSE(base::PathExists(symlink_path_));
262   EXPECT_FALSE(base::PathExists(version_path_));
265 IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTestSocketFiles,
266                        ReplacesSymlinkAndCleansUpFiles) {
267   // Get the directory created by AppShimHostManager.
268   test::AppShimHostManagerTestApi test_api(
269       g_browser_process->platform_part()->app_shim_host_manager());
270   directory_in_tmp_ = test_api.directory_in_tmp();
272   // Check that socket files have been created.
273   EXPECT_TRUE(base::PathExists(directory_in_tmp_));
274   EXPECT_TRUE(base::PathExists(symlink_path_));
276   // Check that the symlink has been replaced.
277   base::FilePath socket_path;
278   ASSERT_TRUE(base::ReadSymbolicLink(symlink_path_, &socket_path));
279   EXPECT_EQ(app_mode::kAppShimSocketShortName, socket_path.BaseName().value());
281   // Check that the RunningChromeVersion file is correctly written.
282   base::FilePath version;
283   EXPECT_TRUE(base::ReadSymbolicLink(version_path_, &version));
284   EXPECT_EQ(chrome::VersionInfo().Version(), version.value());
287 }  // namespace