| 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 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 } | 138 } |
| 139 | 139 |
| 140 protected: | 140 protected: |
| 141 std::string FormatMessage(const std::string& message) { | 141 std::string FormatMessage(const std::string& message) { |
| 142 uint32_t length = message.length(); | 142 uint32_t length = message.length(); |
| 143 return std::string(reinterpret_cast<char*>(&length), 4).append(message); | 143 return std::string(reinterpret_cast<char*>(&length), 4).append(message); |
| 144 } | 144 } |
| 145 | 145 |
| 146 base::FilePath CreateTempFileWithMessage(const std::string& message) { | 146 base::FilePath CreateTempFileWithMessage(const std::string& message) { |
| 147 base::FilePath filename; | 147 base::FilePath filename; |
| 148 if (!base::CreateTemporaryFileInDir(temp_dir_.path(), &filename)) | 148 if (!base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &filename)) |
| 149 return base::FilePath(); | 149 return base::FilePath(); |
| 150 | 150 |
| 151 std::string message_with_header = FormatMessage(message); | 151 std::string message_with_header = FormatMessage(message); |
| 152 int bytes_written = base::WriteFile( | 152 int bytes_written = base::WriteFile( |
| 153 filename, message_with_header.data(), message_with_header.size()); | 153 filename, message_with_header.data(), message_with_header.size()); |
| 154 if (bytes_written < 0 || | 154 if (bytes_written < 0 || |
| 155 (message_with_header.size() != static_cast<size_t>(bytes_written))) { | 155 (message_with_header.size() != static_cast<size_t>(bytes_written))) { |
| 156 return base::FilePath(); | 156 return base::FilePath(); |
| 157 } | 157 } |
| 158 return filename; | 158 return filename; |
| 159 } | 159 } |
| 160 | 160 |
| 161 base::ScopedTempDir temp_dir_; | 161 base::ScopedTempDir temp_dir_; |
| 162 // Force the channel to be dev. | 162 // Force the channel to be dev. |
| 163 ScopedCurrentChannel current_channel_; | 163 ScopedCurrentChannel current_channel_; |
| 164 std::unique_ptr<NativeMessageHost> native_message_host_; | 164 std::unique_ptr<NativeMessageHost> native_message_host_; |
| 165 std::unique_ptr<base::RunLoop> run_loop_; | 165 std::unique_ptr<base::RunLoop> run_loop_; |
| 166 content::TestBrowserThreadBundle thread_bundle_; | 166 content::TestBrowserThreadBundle thread_bundle_; |
| 167 std::string last_message_; | 167 std::string last_message_; |
| 168 std::unique_ptr<base::DictionaryValue> last_message_parsed_; | 168 std::unique_ptr<base::DictionaryValue> last_message_parsed_; |
| 169 bool channel_closed_; | 169 bool channel_closed_; |
| 170 }; | 170 }; |
| 171 | 171 |
| 172 // Read a single message from a local file. | 172 // Read a single message from a local file. |
| 173 TEST_F(NativeMessagingTest, SingleSendMessageRead) { | 173 TEST_F(NativeMessagingTest, SingleSendMessageRead) { |
| 174 base::FilePath temp_output_file = temp_dir_.path().AppendASCII("output"); | 174 base::FilePath temp_output_file = temp_dir_.GetPath().AppendASCII("output"); |
| 175 base::FilePath temp_input_file = CreateTempFileWithMessage(kTestMessage); | 175 base::FilePath temp_input_file = CreateTempFileWithMessage(kTestMessage); |
| 176 ASSERT_FALSE(temp_input_file.empty()); | 176 ASSERT_FALSE(temp_input_file.empty()); |
| 177 | 177 |
| 178 std::unique_ptr<NativeProcessLauncher> launcher = | 178 std::unique_ptr<NativeProcessLauncher> launcher = |
| 179 FakeLauncher::Create(temp_input_file, temp_output_file); | 179 FakeLauncher::Create(temp_input_file, temp_output_file); |
| 180 native_message_host_ = NativeMessageProcessHost::CreateWithLauncher( | 180 native_message_host_ = NativeMessageProcessHost::CreateWithLauncher( |
| 181 ScopedTestNativeMessagingHost::kExtensionId, "empty_app.py", | 181 ScopedTestNativeMessagingHost::kExtensionId, "empty_app.py", |
| 182 std::move(launcher)); | 182 std::move(launcher)); |
| 183 native_message_host_->Start(this); | 183 native_message_host_->Start(this); |
| 184 ASSERT_TRUE(native_message_host_.get()); | 184 ASSERT_TRUE(native_message_host_.get()); |
| 185 run_loop_.reset(new base::RunLoop()); | 185 run_loop_.reset(new base::RunLoop()); |
| 186 run_loop_->RunUntilIdle(); | 186 run_loop_->RunUntilIdle(); |
| 187 | 187 |
| 188 if (last_message_.empty()) { | 188 if (last_message_.empty()) { |
| 189 run_loop_.reset(new base::RunLoop()); | 189 run_loop_.reset(new base::RunLoop()); |
| 190 std::unique_ptr<NativeMessageProcessHost> native_message_process_host_( | 190 std::unique_ptr<NativeMessageProcessHost> native_message_process_host_( |
| 191 static_cast<NativeMessageProcessHost*>(native_message_host_.release())); | 191 static_cast<NativeMessageProcessHost*>(native_message_host_.release())); |
| 192 native_message_process_host_->ReadNowForTesting(); | 192 native_message_process_host_->ReadNowForTesting(); |
| 193 run_loop_->Run(); | 193 run_loop_->Run(); |
| 194 } | 194 } |
| 195 EXPECT_EQ(kTestMessage, last_message_); | 195 EXPECT_EQ(kTestMessage, last_message_); |
| 196 } | 196 } |
| 197 | 197 |
| 198 // Tests sending a single message. The message should get written to | 198 // Tests sending a single message. The message should get written to |
| 199 // |temp_file| and should match the contents of single_message_request.msg. | 199 // |temp_file| and should match the contents of single_message_request.msg. |
| 200 TEST_F(NativeMessagingTest, SingleSendMessageWrite) { | 200 TEST_F(NativeMessagingTest, SingleSendMessageWrite) { |
| 201 base::FilePath temp_output_file = temp_dir_.path().AppendASCII("output"); | 201 base::FilePath temp_output_file = temp_dir_.GetPath().AppendASCII("output"); |
| 202 | 202 |
| 203 base::File read_file; | 203 base::File read_file; |
| 204 #if defined(OS_WIN) | 204 #if defined(OS_WIN) |
| 205 base::string16 pipe_name = base::StringPrintf( | 205 base::string16 pipe_name = base::StringPrintf( |
| 206 L"\\\\.\\pipe\\chrome.nativeMessaging.out.%llx", base::RandUint64()); | 206 L"\\\\.\\pipe\\chrome.nativeMessaging.out.%llx", base::RandUint64()); |
| 207 base::File write_handle = base::File::CreateForAsyncHandle( | 207 base::File write_handle = base::File::CreateForAsyncHandle( |
| 208 CreateNamedPipeW(pipe_name.c_str(), | 208 CreateNamedPipeW(pipe_name.c_str(), |
| 209 PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED | | 209 PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED | |
| 210 FILE_FLAG_FIRST_PIPE_INSTANCE, | 210 FILE_FLAG_FIRST_PIPE_INSTANCE, |
| 211 PIPE_TYPE_BYTE, 1, 0, 0, 5000, NULL)); | 211 PIPE_TYPE_BYTE, 1, 0, 0, 5000, NULL)); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 native_message_host_->Start(this); | 326 native_message_host_->Start(this); |
| 327 ASSERT_TRUE(native_message_host_.get()); | 327 ASSERT_TRUE(native_message_host_.get()); |
| 328 run_loop_.reset(new base::RunLoop()); | 328 run_loop_.reset(new base::RunLoop()); |
| 329 run_loop_->Run(); | 329 run_loop_->Run(); |
| 330 | 330 |
| 331 // The host should fail to start. | 331 // The host should fail to start. |
| 332 ASSERT_TRUE(channel_closed_); | 332 ASSERT_TRUE(channel_closed_); |
| 333 } | 333 } |
| 334 | 334 |
| 335 } // namespace extensions | 335 } // namespace extensions |
| OLD | NEW |