OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "apps/app_shim/app_shim_host_manager_mac.h" | |
6 | |
7 #include <unistd.h> | |
8 | |
9 #include "apps/app_shim/app_shim_messages.h" | |
10 #include "apps/app_shim/test/app_shim_host_manager_test_api_mac.h" | |
11 #include "base/files/file_path.h" | |
12 #include "base/logging.h" | |
13 #include "base/path_service.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/chrome_version_info.h" | |
19 #include "chrome/common/mac/app_mode_common.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" | |
25 | |
26 namespace { | |
27 | |
28 const char kTestAppMode[] = "test_app"; | |
29 | |
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 virtual ~TestShimClient(); | |
35 | |
36 template <class T> | |
37 void Send(const T& message) { | |
38 channel_->Send(message); | |
39 } | |
40 | |
41 private: | |
42 // IPC::Listener overrides: | |
43 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; | |
44 virtual void OnChannelError() OVERRIDE; | |
45 | |
46 base::Thread io_thread_; | |
47 scoped_ptr<IPC::ChannelProxy> channel_; | |
48 | |
49 DISALLOW_COPY_AND_ASSIGN(TestShimClient); | |
50 }; | |
51 | |
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); | |
56 | |
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); | |
61 | |
62 base::FilePath socket_path; | |
63 CHECK(base::ReadSymbolicLink(symlink_path, &socket_path)); | |
64 app_mode::VerifySocketPermissions(socket_path); | |
65 | |
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()); | |
71 } | |
72 | |
73 TestShimClient::~TestShimClient() {} | |
74 | |
75 bool TestShimClient::OnMessageReceived(const IPC::Message& message) { | |
76 return true; | |
77 } | |
78 | |
79 void TestShimClient::OnChannelError() { | |
80 // Client should not get any channel errors for the current set of tests. | |
81 PLOG(FATAL) << "ChannelError"; | |
82 } | |
83 | |
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 virtual ~AppShimHostManagerBrowserTest(); | |
91 | |
92 protected: | |
93 // Wait for OnShimLaunch, then send a quit, and wait for the response. Used to | |
94 // test launch behavior. | |
95 void RunAndExitGracefully(); | |
96 | |
97 // InProcessBrowserTest overrides: | |
98 virtual void SetUpOnMainThread() OVERRIDE; | |
99 virtual void TearDownOnMainThread() OVERRIDE; | |
100 | |
101 // AppShimHandler overrides: | |
102 virtual void OnShimLaunch(apps::AppShimHandler::Host* host, | |
103 apps::AppShimLaunchType launch_type, | |
104 const std::vector<base::FilePath>& files) OVERRIDE; | |
105 virtual void OnShimClose(apps::AppShimHandler::Host* host) OVERRIDE {} | |
106 virtual void OnShimFocus(apps::AppShimHandler::Host* host, | |
107 apps::AppShimFocusType focus_type, | |
108 const std::vector<base::FilePath>& files) OVERRIDE {} | |
109 virtual void OnShimSetHidden(apps::AppShimHandler::Host* host, | |
110 bool hidden) OVERRIDE {} | |
111 virtual void OnShimQuit(apps::AppShimHandler::Host* host) OVERRIDE; | |
112 | |
113 scoped_ptr<TestShimClient> test_client_; | |
114 std::vector<base::FilePath> last_launch_files_; | |
115 apps::AppShimLaunchType last_launch_type_; | |
116 | |
117 private: | |
118 scoped_refptr<content::MessageLoopRunner> runner_; | |
119 | |
120 int launch_count_; | |
121 int quit_count_; | |
122 | |
123 DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTest); | |
124 }; | |
125 | |
126 AppShimHostManagerBrowserTest::AppShimHostManagerBrowserTest() | |
127 : last_launch_type_(apps::APP_SHIM_LAUNCH_NUM_TYPES), | |
128 launch_count_(0), | |
129 quit_count_(0) { | |
130 } | |
131 | |
132 AppShimHostManagerBrowserTest::~AppShimHostManagerBrowserTest() { | |
133 } | |
134 | |
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_); | |
140 | |
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_); | |
146 | |
147 test_client_.reset(); | |
148 } | |
149 | |
150 void AppShimHostManagerBrowserTest::SetUpOnMainThread() { | |
151 // Can't do this in the constructor, it needs a BrowserProcess. | |
152 apps::AppShimHandler::RegisterHandler(kTestAppMode, this); | |
153 } | |
154 | |
155 void AppShimHostManagerBrowserTest::TearDownOnMainThread() { | |
156 apps::AppShimHandler::RemoveHandler(kTestAppMode); | |
157 } | |
158 | |
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(); | |
168 } | |
169 | |
170 void AppShimHostManagerBrowserTest::OnShimQuit( | |
171 apps::AppShimHandler::Host* host) { | |
172 ++quit_count_; | |
173 runner_->Quit(); | |
174 } | |
175 | |
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>())); | |
184 | |
185 RunAndExitGracefully(); | |
186 EXPECT_EQ(apps::APP_SHIM_LAUNCH_NORMAL, last_launch_type_); | |
187 EXPECT_TRUE(last_launch_files_.empty()); | |
188 } | |
189 | |
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>())); | |
198 | |
199 RunAndExitGracefully(); | |
200 EXPECT_EQ(apps::APP_SHIM_LAUNCH_REGISTER_ONLY, last_launch_type_); | |
201 EXPECT_TRUE(last_launch_files_.empty()); | |
202 } | |
203 | |
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()); | |
210 } | |
211 | |
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()); | |
219 } | |
220 | |
221 // Tests for the files created by AppShimHostManager. | |
222 class AppShimHostManagerBrowserTestSocketFiles | |
223 : public AppShimHostManagerBrowserTest { | |
224 public: | |
225 AppShimHostManagerBrowserTestSocketFiles() {} | |
226 | |
227 protected: | |
228 base::FilePath directory_in_tmp_; | |
229 base::FilePath symlink_path_; | |
230 base::FilePath version_path_; | |
231 | |
232 private: | |
233 virtual bool SetUpUserDataDirectory() OVERRIDE; | |
234 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE; | |
235 | |
236 DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTestSocketFiles); | |
237 }; | |
238 | |
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_)); | |
248 | |
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(); | |
255 } | |
256 | |
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_)); | |
263 } | |
264 | |
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(); | |
271 | |
272 // Check that socket files have been created. | |
273 EXPECT_TRUE(base::PathExists(directory_in_tmp_)); | |
274 EXPECT_TRUE(base::PathExists(symlink_path_)); | |
275 | |
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()); | |
280 | |
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()); | |
285 } | |
286 | |
287 } // namespace | |
OLD | NEW |