| OLD | NEW |
| 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 "chrome/browser/extensions/api/messaging/native_message_process_host.h" | 5 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <utility> |
| 9 | 10 |
| 10 #include "base/bind.h" | 11 #include "base/bind.h" |
| 11 #include "base/files/file.h" | 12 #include "base/files/file.h" |
| 12 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
| 13 #include "base/files/file_util.h" | 14 #include "base/files/file_util.h" |
| 14 #include "base/files/scoped_file.h" | 15 #include "base/files/scoped_file.h" |
| 15 #include "base/files/scoped_temp_dir.h" | 16 #include "base/files/scoped_temp_dir.h" |
| 16 #include "base/json/json_reader.h" | 17 #include "base/json/json_reader.h" |
| 17 #include "base/memory/scoped_ptr.h" | 18 #include "base/memory/scoped_ptr.h" |
| 18 #include "base/message_loop/message_loop.h" | 19 #include "base/message_loop/message_loop.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 46 | 47 |
| 47 const char kTestMessage[] = "{\"text\": \"Hello.\"}"; | 48 const char kTestMessage[] = "{\"text\": \"Hello.\"}"; |
| 48 | 49 |
| 49 } // namespace | 50 } // namespace |
| 50 | 51 |
| 51 namespace extensions { | 52 namespace extensions { |
| 52 | 53 |
| 53 class FakeLauncher : public NativeProcessLauncher { | 54 class FakeLauncher : public NativeProcessLauncher { |
| 54 public: | 55 public: |
| 55 FakeLauncher(base::File read_file, base::File write_file) | 56 FakeLauncher(base::File read_file, base::File write_file) |
| 56 : read_file_(read_file.Pass()), | 57 : read_file_(std::move(read_file)), write_file_(std::move(write_file)) {} |
| 57 write_file_(write_file.Pass()) { | |
| 58 } | |
| 59 | 58 |
| 60 static scoped_ptr<NativeProcessLauncher> Create(base::FilePath read_file, | 59 static scoped_ptr<NativeProcessLauncher> Create(base::FilePath read_file, |
| 61 base::FilePath write_file) { | 60 base::FilePath write_file) { |
| 62 int read_flags = base::File::FLAG_OPEN | base::File::FLAG_READ; | 61 int read_flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
| 63 int write_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE; | 62 int write_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE; |
| 64 #if !defined(OS_POSIX) | 63 #if !defined(OS_POSIX) |
| 65 read_flags |= base::File::FLAG_ASYNC; | 64 read_flags |= base::File::FLAG_ASYNC; |
| 66 write_flags |= base::File::FLAG_ASYNC; | 65 write_flags |= base::File::FLAG_ASYNC; |
| 67 #endif | 66 #endif |
| 68 return scoped_ptr<NativeProcessLauncher>(new FakeLauncher( | 67 return scoped_ptr<NativeProcessLauncher>(new FakeLauncher( |
| 69 base::File(read_file, read_flags), | 68 base::File(read_file, read_flags), |
| 70 base::File(write_file, write_flags))); | 69 base::File(write_file, write_flags))); |
| 71 } | 70 } |
| 72 | 71 |
| 73 static scoped_ptr<NativeProcessLauncher> CreateWithPipeInput( | 72 static scoped_ptr<NativeProcessLauncher> CreateWithPipeInput( |
| 74 base::File read_pipe, | 73 base::File read_pipe, |
| 75 base::FilePath write_file) { | 74 base::FilePath write_file) { |
| 76 int write_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE; | 75 int write_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE; |
| 77 #if !defined(OS_POSIX) | 76 #if !defined(OS_POSIX) |
| 78 write_flags |= base::File::FLAG_ASYNC; | 77 write_flags |= base::File::FLAG_ASYNC; |
| 79 #endif | 78 #endif |
| 80 | 79 |
| 81 return scoped_ptr<NativeProcessLauncher>(new FakeLauncher( | 80 return scoped_ptr<NativeProcessLauncher>(new FakeLauncher( |
| 82 read_pipe.Pass(), | 81 std::move(read_pipe), base::File(write_file, write_flags))); |
| 83 base::File(write_file, write_flags))); | |
| 84 } | 82 } |
| 85 | 83 |
| 86 void Launch(const GURL& origin, | 84 void Launch(const GURL& origin, |
| 87 const std::string& native_host_name, | 85 const std::string& native_host_name, |
| 88 const LaunchedCallback& callback) const override { | 86 const LaunchedCallback& callback) const override { |
| 89 callback.Run(NativeProcessLauncher::RESULT_SUCCESS, | 87 callback.Run(NativeProcessLauncher::RESULT_SUCCESS, base::Process(), |
| 90 base::Process(), read_file_.Pass(), write_file_.Pass()); | 88 std::move(read_file_), std::move(write_file_)); |
| 91 } | 89 } |
| 92 | 90 |
| 93 private: | 91 private: |
| 94 mutable base::File read_file_; | 92 mutable base::File read_file_; |
| 95 mutable base::File write_file_; | 93 mutable base::File write_file_; |
| 96 }; | 94 }; |
| 97 | 95 |
| 98 class NativeMessagingTest : public ::testing::Test, | 96 class NativeMessagingTest : public ::testing::Test, |
| 99 public NativeMessageHost::Client, | 97 public NativeMessageHost::Client, |
| 100 public base::SupportsWeakPtr<NativeMessagingTest> { | 98 public base::SupportsWeakPtr<NativeMessagingTest> { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 114 base::RunLoop().RunUntilIdle(); | 112 base::RunLoop().RunUntilIdle(); |
| 115 } | 113 } |
| 116 | 114 |
| 117 void PostMessageFromNativeHost(const std::string& message) override { | 115 void PostMessageFromNativeHost(const std::string& message) override { |
| 118 last_message_ = message; | 116 last_message_ = message; |
| 119 | 117 |
| 120 // Parse the message. | 118 // Parse the message. |
| 121 scoped_ptr<base::DictionaryValue> dict_value = | 119 scoped_ptr<base::DictionaryValue> dict_value = |
| 122 base::DictionaryValue::From(base::JSONReader::Read(message)); | 120 base::DictionaryValue::From(base::JSONReader::Read(message)); |
| 123 if (dict_value) { | 121 if (dict_value) { |
| 124 last_message_parsed_ = dict_value.Pass(); | 122 last_message_parsed_ = std::move(dict_value); |
| 125 } else { | 123 } else { |
| 126 LOG(ERROR) << "Failed to parse " << message; | 124 LOG(ERROR) << "Failed to parse " << message; |
| 127 last_message_parsed_.reset(); | 125 last_message_parsed_.reset(); |
| 128 } | 126 } |
| 129 | 127 |
| 130 if (run_loop_) | 128 if (run_loop_) |
| 131 run_loop_->Quit(); | 129 run_loop_->Quit(); |
| 132 } | 130 } |
| 133 | 131 |
| 134 void CloseChannel(const std::string& error_message) override { | 132 void CloseChannel(const std::string& error_message) override { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 bool channel_closed_; | 167 bool channel_closed_; |
| 170 }; | 168 }; |
| 171 | 169 |
| 172 // Read a single message from a local file. | 170 // Read a single message from a local file. |
| 173 TEST_F(NativeMessagingTest, SingleSendMessageRead) { | 171 TEST_F(NativeMessagingTest, SingleSendMessageRead) { |
| 174 base::FilePath temp_output_file = temp_dir_.path().AppendASCII("output"); | 172 base::FilePath temp_output_file = temp_dir_.path().AppendASCII("output"); |
| 175 base::FilePath temp_input_file = CreateTempFileWithMessage(kTestMessage); | 173 base::FilePath temp_input_file = CreateTempFileWithMessage(kTestMessage); |
| 176 ASSERT_FALSE(temp_input_file.empty()); | 174 ASSERT_FALSE(temp_input_file.empty()); |
| 177 | 175 |
| 178 scoped_ptr<NativeProcessLauncher> launcher = | 176 scoped_ptr<NativeProcessLauncher> launcher = |
| 179 FakeLauncher::Create(temp_input_file, temp_output_file).Pass(); | 177 FakeLauncher::Create(temp_input_file, temp_output_file); |
| 180 native_message_host_ = NativeMessageProcessHost::CreateWithLauncher( | 178 native_message_host_ = NativeMessageProcessHost::CreateWithLauncher( |
| 181 ScopedTestNativeMessagingHost::kExtensionId, | 179 ScopedTestNativeMessagingHost::kExtensionId, "empty_app.py", |
| 182 "empty_app.py", | 180 std::move(launcher)); |
| 183 launcher.Pass()); | |
| 184 native_message_host_->Start(this); | 181 native_message_host_->Start(this); |
| 185 ASSERT_TRUE(native_message_host_.get()); | 182 ASSERT_TRUE(native_message_host_.get()); |
| 186 run_loop_.reset(new base::RunLoop()); | 183 run_loop_.reset(new base::RunLoop()); |
| 187 run_loop_->RunUntilIdle(); | 184 run_loop_->RunUntilIdle(); |
| 188 | 185 |
| 189 if (last_message_.empty()) { | 186 if (last_message_.empty()) { |
| 190 run_loop_.reset(new base::RunLoop()); | 187 run_loop_.reset(new base::RunLoop()); |
| 191 scoped_ptr<NativeMessageProcessHost> native_message_process_host_( | 188 scoped_ptr<NativeMessageProcessHost> native_message_process_host_( |
| 192 static_cast<NativeMessageProcessHost*>(native_message_host_.release())); | 189 static_cast<NativeMessageProcessHost*>(native_message_host_.release())); |
| 193 native_message_process_host_->ReadNowForTesting(); | 190 native_message_process_host_->ReadNowForTesting(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 218 | 215 |
| 219 read_file = read_handle.Pass(); | 216 read_file = read_handle.Pass(); |
| 220 #else // defined(OS_WIN) | 217 #else // defined(OS_WIN) |
| 221 base::PlatformFile pipe_handles[2]; | 218 base::PlatformFile pipe_handles[2]; |
| 222 ASSERT_EQ(0, pipe(pipe_handles)); | 219 ASSERT_EQ(0, pipe(pipe_handles)); |
| 223 read_file = base::File(pipe_handles[0]); | 220 read_file = base::File(pipe_handles[0]); |
| 224 base::File write_file(pipe_handles[1]); | 221 base::File write_file(pipe_handles[1]); |
| 225 #endif // !defined(OS_WIN) | 222 #endif // !defined(OS_WIN) |
| 226 | 223 |
| 227 scoped_ptr<NativeProcessLauncher> launcher = | 224 scoped_ptr<NativeProcessLauncher> launcher = |
| 228 FakeLauncher::CreateWithPipeInput(read_file.Pass(), | 225 FakeLauncher::CreateWithPipeInput(std::move(read_file), temp_output_file); |
| 229 temp_output_file).Pass(); | |
| 230 native_message_host_ = NativeMessageProcessHost::CreateWithLauncher( | 226 native_message_host_ = NativeMessageProcessHost::CreateWithLauncher( |
| 231 ScopedTestNativeMessagingHost::kExtensionId, | 227 ScopedTestNativeMessagingHost::kExtensionId, "empty_app.py", |
| 232 "empty_app.py", | 228 std::move(launcher)); |
| 233 launcher.Pass()); | |
| 234 native_message_host_->Start(this); | 229 native_message_host_->Start(this); |
| 235 ASSERT_TRUE(native_message_host_.get()); | 230 ASSERT_TRUE(native_message_host_.get()); |
| 236 base::RunLoop().RunUntilIdle(); | 231 base::RunLoop().RunUntilIdle(); |
| 237 | 232 |
| 238 native_message_host_->OnMessage(kTestMessage); | 233 native_message_host_->OnMessage(kTestMessage); |
| 239 base::RunLoop().RunUntilIdle(); | 234 base::RunLoop().RunUntilIdle(); |
| 240 | 235 |
| 241 std::string output; | 236 std::string output; |
| 242 base::TimeTicks start_time = base::TimeTicks::Now(); | 237 base::TimeTicks start_time = base::TimeTicks::Now(); |
| 243 while (base::TimeTicks::Now() - start_time < TestTimeouts::action_timeout()) { | 238 while (base::TimeTicks::Now() - start_time < TestTimeouts::action_timeout()) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 native_message_host_->Start(this); | 324 native_message_host_->Start(this); |
| 330 ASSERT_TRUE(native_message_host_.get()); | 325 ASSERT_TRUE(native_message_host_.get()); |
| 331 run_loop_.reset(new base::RunLoop()); | 326 run_loop_.reset(new base::RunLoop()); |
| 332 run_loop_->Run(); | 327 run_loop_->Run(); |
| 333 | 328 |
| 334 // The host should fail to start. | 329 // The host should fail to start. |
| 335 ASSERT_TRUE(channel_closed_); | 330 ASSERT_TRUE(channel_closed_); |
| 336 } | 331 } |
| 337 | 332 |
| 338 } // namespace extensions | 333 } // namespace extensions |
| OLD | NEW |