Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Side by Side Diff: chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc

Issue 24409004: Disconnect native messaging port on read pipe EOF. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/bind.h" 5 #include "base/bind.h"
6 #include "base/command_line.h" 6 #include "base/command_line.h"
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/files/scoped_temp_dir.h" 9 #include "base/files/scoped_temp_dir.h"
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/weak_ptr.h" 12 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
14 #include "base/path_service.h" 14 #include "base/path_service.h"
15 #include "base/platform_file.h" 15 #include "base/platform_file.h"
16 #include "base/rand_util.h"
16 #include "base/run_loop.h" 17 #include "base/run_loop.h"
17 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
18 #include "base/test/test_timeouts.h" 19 #include "base/test/test_timeouts.h"
19 #include "base/threading/platform_thread.h" 20 #include "base/threading/platform_thread.h"
20 #include "base/threading/sequenced_worker_pool.h" 21 #include "base/threading/sequenced_worker_pool.h"
21 #include "base/time/time.h" 22 #include "base/time/time.h"
22 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h" 23 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
23 #include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h" 24 #include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
24 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" 25 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
25 #include "chrome/common/chrome_paths.h" 26 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/chrome_version_info.h" 28 #include "chrome/common/chrome_version_info.h"
28 #include "chrome/common/extensions/extension.h" 29 #include "chrome/common/extensions/extension.h"
29 #include "chrome/common/extensions/features/feature_channel.h" 30 #include "chrome/common/extensions/features/feature_channel.h"
30 #include "content/public/browser/browser_thread.h" 31 #include "content/public/browser/browser_thread.h"
31 #include "content/public/test/test_browser_thread_bundle.h" 32 #include "content/public/test/test_browser_thread_bundle.h"
32 #include "testing/gtest/include/gtest/gtest.h" 33 #include "testing/gtest/include/gtest/gtest.h"
33 34
35 #if defined(OS_WIN)
36 #include <windows.h>
37 #include "base/win/scoped_handle.h"
38 #else
39 #include <unistd.h>
40 #endif
41
34 using content::BrowserThread; 42 using content::BrowserThread;
35 43
36 namespace { 44 namespace {
37 45
38 const char kTestMessage[] = "{\"text\": \"Hello.\"}"; 46 const char kTestMessage[] = "{\"text\": \"Hello.\"}";
39 47
40 base::FilePath GetTestDir() { 48 base::FilePath GetTestDir() {
41 base::FilePath test_dir; 49 base::FilePath test_dir;
42 PathService::Get(chrome::DIR_TEST_DATA, &test_dir); 50 PathService::Get(chrome::DIR_TEST_DATA, &test_dir);
43 test_dir = test_dir.AppendASCII("native_messaging"); 51 test_dir = test_dir.AppendASCII("native_messaging");
44 return test_dir; 52 return test_dir;
45 } 53 }
46 54
47 } // namespace 55 } // namespace
48 56
49 namespace extensions { 57 namespace extensions {
50 58
51 class FakeLauncher : public NativeProcessLauncher { 59 class FakeLauncher : public NativeProcessLauncher {
52 public: 60 public:
53 FakeLauncher(base::FilePath read_file, base::FilePath write_file) { 61 FakeLauncher(base::PlatformFile read_file, base::PlatformFile write_file)
54 read_file_ = base::CreatePlatformFile( 62 : read_file_(read_file),
55 read_file, 63 write_file_(write_file) {
56 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ | 64 }
57 base::PLATFORM_FILE_ASYNC, 65
58 NULL, NULL); 66 static scoped_ptr<NativeProcessLauncher> Create(base::FilePath read_file,
59 write_file_ = base::CreatePlatformFile( 67 base::FilePath write_file) {
60 write_file, 68 int read_flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ |
61 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE | 69 base::PLATFORM_FILE_ASYNC;
62 base::PLATFORM_FILE_ASYNC, 70 int write_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE |
63 NULL, NULL); 71 base::PLATFORM_FILE_ASYNC;
72 return scoped_ptr<NativeProcessLauncher>(new FakeLauncher(
73 base::CreatePlatformFile(read_file, read_flags, NULL, NULL),
74 base::CreatePlatformFile(write_file, write_flags, NULL, NULL)));
75 }
76
77 static scoped_ptr<NativeProcessLauncher> CreateWithPipeInput(
78 base::PlatformFile read_pipe,
79 base::FilePath write_file) {
80 int write_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE |
81 base::PLATFORM_FILE_ASYNC;
82 return scoped_ptr<NativeProcessLauncher>(new FakeLauncher(
83 read_pipe,
84 base::CreatePlatformFile(write_file, write_flags, NULL, NULL)));
64 } 85 }
65 86
66 virtual void Launch(const GURL& origin, 87 virtual void Launch(const GURL& origin,
67 const std::string& native_host_name, 88 const std::string& native_host_name,
68 LaunchedCallback callback) const OVERRIDE { 89 LaunchedCallback callback) const OVERRIDE {
69 callback.Run(NativeProcessLauncher::RESULT_SUCCESS, 90 callback.Run(NativeProcessLauncher::RESULT_SUCCESS,
70 read_file_, write_file_); 91 read_file_, write_file_);
71 } 92 }
72 93
73 private: 94 private:
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 content::TestBrowserThreadBundle thread_bundle_; 172 content::TestBrowserThreadBundle thread_bundle_;
152 std::string last_message_; 173 std::string last_message_;
153 scoped_ptr<base::DictionaryValue> last_message_parsed_; 174 scoped_ptr<base::DictionaryValue> last_message_parsed_;
154 }; 175 };
155 176
156 // Read a single message from a local file. 177 // Read a single message from a local file.
157 TEST_F(NativeMessagingTest, SingleSendMessageRead) { 178 TEST_F(NativeMessagingTest, SingleSendMessageRead) {
158 base::FilePath temp_output_file = temp_dir_.path().AppendASCII("output"); 179 base::FilePath temp_output_file = temp_dir_.path().AppendASCII("output");
159 base::FilePath temp_input_file = CreateTempFileWithMessage(kTestMessage); 180 base::FilePath temp_input_file = CreateTempFileWithMessage(kTestMessage);
160 181
161 scoped_ptr<NativeProcessLauncher> launcher( 182 scoped_ptr<NativeProcessLauncher> launcher =
162 new FakeLauncher(temp_input_file, temp_output_file)); 183 FakeLauncher::Create(temp_input_file, temp_output_file).Pass();
163 native_message_process_host_ = NativeMessageProcessHost::CreateWithLauncher( 184 native_message_process_host_ = NativeMessageProcessHost::CreateWithLauncher(
164 AsWeakPtr(), kTestNativeMessagingExtensionId, "empty_app.py", 185 AsWeakPtr(), kTestNativeMessagingExtensionId, "empty_app.py",
165 0, launcher.Pass()); 186 0, launcher.Pass());
166 ASSERT_TRUE(native_message_process_host_.get()); 187 ASSERT_TRUE(native_message_process_host_.get());
167 read_message_run_loop_.reset(new base::RunLoop()); 188 read_message_run_loop_.reset(new base::RunLoop());
168 read_message_run_loop_->RunUntilIdle(); 189 read_message_run_loop_->RunUntilIdle();
169 190
170 if (last_message_.empty()) { 191 if (last_message_.empty()) {
171 read_message_run_loop_.reset(new base::RunLoop()); 192 read_message_run_loop_.reset(new base::RunLoop());
172 native_message_process_host_->ReadNowForTesting(); 193 native_message_process_host_->ReadNowForTesting();
173 read_message_run_loop_->Run(); 194 read_message_run_loop_->Run();
174 } 195 }
175 EXPECT_EQ(kTestMessage, last_message_); 196 EXPECT_EQ(kTestMessage, last_message_);
176 } 197 }
177 198
178 // Tests sending a single message. The message should get written to 199 // Tests sending a single message. The message should get written to
179 // |temp_file| and should match the contents of single_message_request.msg. 200 // |temp_file| and should match the contents of single_message_request.msg.
180 TEST_F(NativeMessagingTest, SingleSendMessageWrite) { 201 TEST_F(NativeMessagingTest, SingleSendMessageWrite) {
181 base::FilePath temp_output_file = temp_dir_.path().AppendASCII("output"); 202 base::FilePath temp_output_file = temp_dir_.path().AppendASCII("output");
182 base::FilePath temp_input_file = CreateTempFileWithMessage(std::string());
183 203
184 scoped_ptr<NativeProcessLauncher> launcher( 204 base::PlatformFile read_file;
185 new FakeLauncher(temp_input_file, temp_output_file)); 205 #if defined(OS_WIN)
206 string16 pipe_name = base::StringPrintf(
207 L"\\\\.\\pipe\\chrome.nativeMessaging.out.%llx", base::RandUint64());
208 base::win::ScopedHandle write_handle(
209 CreateNamedPipeW(pipe_name.c_str(),
210 PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED |
211 FILE_FLAG_FIRST_PIPE_INSTANCE,
212 PIPE_TYPE_BYTE, 1, 0, 0, 5000, NULL));
213 ASSERT_TRUE(write_handle);
214 base::win::ScopedHandle read_handle(
215 CreateFileW(pipe_name.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
216 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL));
217 ASSERT_TRUE(read_handle);
218
219 read_file = read_handle.Get();
220 #else // defined(OS_WIN)
221 base::PlatformFile pipe_handles[2];
222 ASSERT_EQ(0, pipe(pipe_handles));
223 file_util::ScopedFD read_fd(pipe_handles);
224 file_util::ScopedFD write_fd(pipe_handles + 1);
225
226 read_file = pipe_handles[0];
227 #endif // !defined(OS_WIN)
228
229 scoped_ptr<NativeProcessLauncher> launcher =
230 FakeLauncher::CreateWithPipeInput(read_file, temp_output_file).Pass();
186 native_message_process_host_ = NativeMessageProcessHost::CreateWithLauncher( 231 native_message_process_host_ = NativeMessageProcessHost::CreateWithLauncher(
187 AsWeakPtr(), kTestNativeMessagingExtensionId, "empty_app.py", 232 AsWeakPtr(), kTestNativeMessagingExtensionId, "empty_app.py",
188 0, launcher.Pass()); 233 0, launcher.Pass());
189 ASSERT_TRUE(native_message_process_host_.get()); 234 ASSERT_TRUE(native_message_process_host_.get());
190 base::RunLoop().RunUntilIdle(); 235 base::RunLoop().RunUntilIdle();
191 236
192 native_message_process_host_->Send(kTestMessage); 237 native_message_process_host_->Send(kTestMessage);
193 base::RunLoop().RunUntilIdle(); 238 base::RunLoop().RunUntilIdle();
194 239
195 std::string output; 240 std::string output;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 read_message_run_loop_->Run(); 291 read_message_run_loop_->Run();
247 EXPECT_TRUE(last_message_parsed_->GetInteger("id", &id)); 292 EXPECT_TRUE(last_message_parsed_->GetInteger("id", &id));
248 EXPECT_EQ(2, id); 293 EXPECT_EQ(2, id);
249 EXPECT_TRUE(last_message_parsed_->GetString("echo.foo", &text)); 294 EXPECT_TRUE(last_message_parsed_->GetString("echo.foo", &text));
250 EXPECT_EQ("bar", text); 295 EXPECT_EQ("bar", text);
251 EXPECT_TRUE(last_message_parsed_->GetString("caller_url", &url)); 296 EXPECT_TRUE(last_message_parsed_->GetString("caller_url", &url));
252 EXPECT_EQ(expected_url, url); 297 EXPECT_EQ(expected_url, url);
253 } 298 }
254 299
255 } // namespace extensions 300 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698