me2me_native_messaging_host_unittest.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  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. #include "remoting/host/setup/me2me_native_messaging_host.h"
  5. #include <stddef.h>
  6. #include <cstdint>
  7. #include <memory>
  8. #include <string>
  9. #include <utility>
  10. #include "base/bind.h"
  11. #include "base/compiler_specific.h"
  12. #include "base/json/json_reader.h"
  13. #include "base/json/json_writer.h"
  14. #include "base/memory/ptr_util.h"
  15. #include "base/memory/raw_ptr.h"
  16. #include "base/run_loop.h"
  17. #include "base/strings/stringize_macros.h"
  18. #include "base/test/task_environment.h"
  19. #include "base/values.h"
  20. #include "google_apis/gaia/gaia_oauth_client.h"
  21. #include "net/base/file_stream.h"
  22. #include "net/base/network_interfaces.h"
  23. #include "remoting/base/auto_thread_task_runner.h"
  24. #include "remoting/base/mock_oauth_client.h"
  25. #include "remoting/host/chromoting_host_context.h"
  26. #include "remoting/host/native_messaging/log_message_handler.h"
  27. #include "remoting/host/native_messaging/native_messaging_pipe.h"
  28. #include "remoting/host/native_messaging/pipe_messaging_channel.h"
  29. #include "remoting/host/pin_hash.h"
  30. #include "remoting/host/setup/test_util.h"
  31. #include "remoting/protocol/pairing_registry.h"
  32. #include "remoting/protocol/protocol_mock_objects.h"
  33. #include "testing/gtest/include/gtest/gtest.h"
  34. #include "third_party/abseil-cpp/absl/types/optional.h"
  35. namespace {
  36. using remoting::protocol::MockPairingRegistryDelegate;
  37. using remoting::protocol::PairingRegistry;
  38. using remoting::protocol::SynchronousPairingRegistry;
  39. using ::testing::Optional;
  40. void VerifyHelloResponse(const base::Value::Dict& response) {
  41. const std::string* value = response.FindString("type");
  42. ASSERT_TRUE(value);
  43. EXPECT_EQ("helloResponse", *value);
  44. value = response.FindString("version");
  45. ASSERT_TRUE(value);
  46. // The check below will compile but fail if VERSION isn't defined (STRINGIZE
  47. // silently converts undefined values).
  48. #ifndef VERSION
  49. #error VERSION must be defined
  50. #endif
  51. EXPECT_EQ(STRINGIZE(VERSION), *value);
  52. }
  53. void VerifyGetHostNameResponse(const base::Value::Dict& response) {
  54. const std::string* value = response.FindString("type");
  55. ASSERT_TRUE(value);
  56. EXPECT_EQ("getHostNameResponse", *value);
  57. value = response.FindString("hostname");
  58. ASSERT_TRUE(value);
  59. EXPECT_EQ(net::GetHostName(), *value);
  60. }
  61. void VerifyGetPinHashResponse(const base::Value::Dict& response) {
  62. const std::string* value = response.FindString("type");
  63. ASSERT_TRUE(value);
  64. EXPECT_EQ("getPinHashResponse", *value);
  65. value = response.FindString("hash");
  66. ASSERT_TRUE(value);
  67. EXPECT_EQ(remoting::MakeHostPinHash("my_host", "1234"), *value);
  68. }
  69. void VerifyGenerateKeyPairResponse(const base::Value::Dict& response) {
  70. const std::string* value = response.FindString("type");
  71. ASSERT_TRUE(value);
  72. EXPECT_EQ("generateKeyPairResponse", *value);
  73. EXPECT_TRUE(response.FindString("privateKey"));
  74. EXPECT_TRUE(response.FindString("publicKey"));
  75. }
  76. void VerifyGetDaemonConfigResponse(const base::Value::Dict& response) {
  77. const std::string* value = response.FindString("type");
  78. ASSERT_TRUE(value);
  79. EXPECT_EQ("getDaemonConfigResponse", *value);
  80. const base::Value::Dict* config = response.FindDict("config");
  81. ASSERT_TRUE(config);
  82. EXPECT_EQ(base::Value::Dict(), *config);
  83. }
  84. void VerifyGetUsageStatsConsentResponse(const base::Value::Dict& response) {
  85. const std::string* value = response.FindString("type");
  86. ASSERT_TRUE(value);
  87. EXPECT_EQ("getUsageStatsConsentResponse", *value);
  88. EXPECT_THAT(response.FindBool("supported"), Optional(true));
  89. EXPECT_THAT(response.FindBool("allowed"), Optional(true));
  90. EXPECT_THAT(response.FindBool("setByPolicy"), Optional(true));
  91. }
  92. void VerifyStopDaemonResponse(const base::Value::Dict& response) {
  93. const std::string* value = response.FindString("type");
  94. ASSERT_TRUE(value);
  95. EXPECT_EQ("stopDaemonResponse", *value);
  96. value = response.FindString("result");
  97. ASSERT_TRUE(value);
  98. EXPECT_EQ("OK", *value);
  99. }
  100. void VerifyGetDaemonStateResponse(const base::Value::Dict& response) {
  101. const std::string* value = response.FindString("type");
  102. ASSERT_TRUE(value);
  103. EXPECT_EQ("getDaemonStateResponse", *value);
  104. value = response.FindString("state");
  105. ASSERT_TRUE(value);
  106. EXPECT_EQ("STARTED", *value);
  107. }
  108. void VerifyUpdateDaemonConfigResponse(const base::Value::Dict& response) {
  109. const std::string* value = response.FindString("type");
  110. ASSERT_TRUE(value);
  111. EXPECT_EQ("updateDaemonConfigResponse", *value);
  112. value = response.FindString("result");
  113. ASSERT_TRUE(value);
  114. EXPECT_EQ("OK", *value);
  115. }
  116. void VerifyStartDaemonResponse(const base::Value::Dict& response) {
  117. const std::string* value = response.FindString("type");
  118. ASSERT_TRUE(value);
  119. EXPECT_EQ("startDaemonResponse", *value);
  120. value = response.FindString("result");
  121. ASSERT_TRUE(value);
  122. EXPECT_EQ("OK", *value);
  123. }
  124. void VerifyGetCredentialsFromAuthCodeResponse(
  125. const base::Value::Dict& response) {
  126. const std::string* value = response.FindString("type");
  127. ASSERT_TRUE(value);
  128. EXPECT_EQ("getCredentialsFromAuthCodeResponse", *value);
  129. value = response.FindString("userEmail");
  130. ASSERT_TRUE(value);
  131. EXPECT_EQ("fake_user_email", *value);
  132. value = response.FindString("refreshToken");
  133. ASSERT_TRUE(value);
  134. EXPECT_EQ("fake_refresh_token", *value);
  135. }
  136. } // namespace
  137. namespace remoting {
  138. class MockDaemonControllerDelegate : public DaemonController::Delegate {
  139. public:
  140. MockDaemonControllerDelegate();
  141. MockDaemonControllerDelegate(const MockDaemonControllerDelegate&) = delete;
  142. MockDaemonControllerDelegate& operator=(const MockDaemonControllerDelegate&) =
  143. delete;
  144. ~MockDaemonControllerDelegate() override;
  145. // DaemonController::Delegate interface.
  146. DaemonController::State GetState() override;
  147. absl::optional<base::Value::Dict> GetConfig() override;
  148. void CheckPermission(bool it2me,
  149. DaemonController::BoolCallback callback) override;
  150. void SetConfigAndStart(base::Value::Dict config,
  151. bool consent,
  152. DaemonController::CompletionCallback done) override;
  153. void UpdateConfig(base::Value::Dict config,
  154. DaemonController::CompletionCallback done) override;
  155. void Stop(DaemonController::CompletionCallback done) override;
  156. DaemonController::UsageStatsConsent GetUsageStatsConsent() override;
  157. };
  158. MockDaemonControllerDelegate::MockDaemonControllerDelegate() = default;
  159. MockDaemonControllerDelegate::~MockDaemonControllerDelegate() = default;
  160. DaemonController::State MockDaemonControllerDelegate::GetState() {
  161. return DaemonController::STATE_STARTED;
  162. }
  163. absl::optional<base::Value::Dict> MockDaemonControllerDelegate::GetConfig() {
  164. return base::Value::Dict();
  165. }
  166. void MockDaemonControllerDelegate::CheckPermission(
  167. bool it2me,
  168. DaemonController::BoolCallback callback) {
  169. std::move(callback).Run(true);
  170. }
  171. void MockDaemonControllerDelegate::SetConfigAndStart(
  172. base::Value::Dict config,
  173. bool consent,
  174. DaemonController::CompletionCallback done) {
  175. // Verify parameters passed in.
  176. if (consent && config.Find("start")) {
  177. std::move(done).Run(DaemonController::RESULT_OK);
  178. } else {
  179. std::move(done).Run(DaemonController::RESULT_FAILED);
  180. }
  181. }
  182. void MockDaemonControllerDelegate::UpdateConfig(
  183. base::Value::Dict config,
  184. DaemonController::CompletionCallback done) {
  185. if (config.Find("update")) {
  186. std::move(done).Run(DaemonController::RESULT_OK);
  187. } else {
  188. std::move(done).Run(DaemonController::RESULT_FAILED);
  189. }
  190. }
  191. void MockDaemonControllerDelegate::Stop(
  192. DaemonController::CompletionCallback done) {
  193. std::move(done).Run(DaemonController::RESULT_OK);
  194. }
  195. DaemonController::UsageStatsConsent
  196. MockDaemonControllerDelegate::GetUsageStatsConsent() {
  197. DaemonController::UsageStatsConsent consent;
  198. consent.supported = true;
  199. consent.allowed = true;
  200. consent.set_by_policy = true;
  201. return consent;
  202. }
  203. class Me2MeNativeMessagingHostTest : public testing::Test {
  204. public:
  205. Me2MeNativeMessagingHostTest();
  206. Me2MeNativeMessagingHostTest(const Me2MeNativeMessagingHostTest&) = delete;
  207. Me2MeNativeMessagingHostTest& operator=(const Me2MeNativeMessagingHostTest&) =
  208. delete;
  209. ~Me2MeNativeMessagingHostTest() override;
  210. void SetUp() override;
  211. void TearDown() override;
  212. absl::optional<base::Value::Dict> ReadMessageFromOutputPipe();
  213. void WriteMessageToInputPipe(const base::ValueView& message);
  214. // The Host process should shut down when it receives a malformed request.
  215. // This is tested by sending a known-good request, followed by |message|,
  216. // followed by the known-good request again. The response file should only
  217. // contain a single response from the first good request.
  218. void TestBadRequest(const base::Value& message);
  219. protected:
  220. // Reference to the MockDaemonControllerDelegate, which is owned by
  221. // |channel_|.
  222. raw_ptr<MockDaemonControllerDelegate> daemon_controller_delegate_;
  223. private:
  224. void StartHost();
  225. void StopHost();
  226. void ExitTest();
  227. // Each test creates two unidirectional pipes: "input" and "output".
  228. // Me2MeNativeMessagingHost reads from input_read_handle and writes to
  229. // output_write_file. The unittest supplies data to input_write_handle, and
  230. // verifies output from output_read_handle.
  231. //
  232. // unittest -> [input] -> Me2MeNativeMessagingHost -> [output] -> unittest
  233. base::File input_write_file_;
  234. base::File output_read_file_;
  235. std::unique_ptr<base::test::SingleThreadTaskEnvironment> task_environment_;
  236. std::unique_ptr<base::RunLoop> test_run_loop_;
  237. std::unique_ptr<base::Thread> host_thread_;
  238. std::unique_ptr<base::RunLoop> host_run_loop_;
  239. // Task runner of the host thread.
  240. scoped_refptr<AutoThreadTaskRunner> host_task_runner_;
  241. std::unique_ptr<NativeMessagingPipe> native_messaging_pipe_;
  242. };
  243. Me2MeNativeMessagingHostTest::Me2MeNativeMessagingHostTest() = default;
  244. Me2MeNativeMessagingHostTest::~Me2MeNativeMessagingHostTest() = default;
  245. void Me2MeNativeMessagingHostTest::SetUp() {
  246. base::File input_read_file;
  247. base::File output_write_file;
  248. ASSERT_TRUE(MakePipe(&input_read_file, &input_write_file_));
  249. ASSERT_TRUE(MakePipe(&output_read_file_, &output_write_file));
  250. task_environment_ =
  251. std::make_unique<base::test::SingleThreadTaskEnvironment>();
  252. test_run_loop_ = std::make_unique<base::RunLoop>();
  253. // Run the host on a dedicated thread.
  254. host_thread_ = std::make_unique<base::Thread>("host_thread");
  255. host_thread_->Start();
  256. // Arrange to run |task_environment_| until no components depend on it.
  257. host_task_runner_ = new AutoThreadTaskRunner(
  258. host_thread_->task_runner(),
  259. base::BindOnce(&Me2MeNativeMessagingHostTest::ExitTest,
  260. base::Unretained(this)));
  261. host_task_runner_->PostTask(
  262. FROM_HERE, base::BindOnce(&Me2MeNativeMessagingHostTest::StartHost,
  263. base::Unretained(this)));
  264. // Wait until the host finishes starting.
  265. test_run_loop_->Run();
  266. }
  267. void Me2MeNativeMessagingHostTest::StartHost() {
  268. DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
  269. base::File input_read_file;
  270. base::File output_write_file;
  271. ASSERT_TRUE(MakePipe(&input_read_file, &input_write_file_));
  272. ASSERT_TRUE(MakePipe(&output_read_file_, &output_write_file));
  273. daemon_controller_delegate_ = new MockDaemonControllerDelegate();
  274. scoped_refptr<DaemonController> daemon_controller(new DaemonController(
  275. base::WrapUnique(daemon_controller_delegate_.get())));
  276. scoped_refptr<PairingRegistry> pairing_registry =
  277. new SynchronousPairingRegistry(
  278. base::WrapUnique(new MockPairingRegistryDelegate()));
  279. native_messaging_pipe_ = std::make_unique<NativeMessagingPipe>();
  280. std::unique_ptr<extensions::NativeMessagingChannel> channel(
  281. new PipeMessagingChannel(std::move(input_read_file),
  282. std::move(output_write_file)));
  283. std::unique_ptr<OAuthClient> oauth_client(
  284. new MockOAuthClient("fake_user_email", "fake_refresh_token"));
  285. std::unique_ptr<ChromotingHostContext> context =
  286. ChromotingHostContext::Create(new remoting::AutoThreadTaskRunner(
  287. host_task_runner_,
  288. base::BindOnce(&Me2MeNativeMessagingHostTest::StopHost,
  289. base::Unretained(this))));
  290. std::unique_ptr<remoting::Me2MeNativeMessagingHost> host(
  291. new Me2MeNativeMessagingHost(false, 0, std::move(context),
  292. daemon_controller, pairing_registry,
  293. std::move(oauth_client)));
  294. host->Start(native_messaging_pipe_.get());
  295. native_messaging_pipe_->Start(std::move(host), std::move(channel));
  296. // Notify the test that the host has finished starting up.
  297. test_run_loop_->Quit();
  298. }
  299. void Me2MeNativeMessagingHostTest::StopHost() {
  300. DCHECK(host_task_runner_->RunsTasksInCurrentSequence());
  301. native_messaging_pipe_.reset();
  302. // Wait till all shutdown tasks have completed.
  303. base::RunLoop().RunUntilIdle();
  304. // Trigger a test shutdown via ExitTest().
  305. host_task_runner_ = nullptr;
  306. }
  307. void Me2MeNativeMessagingHostTest::ExitTest() {
  308. if (!task_environment_->GetMainThreadTaskRunner()
  309. ->RunsTasksInCurrentSequence()) {
  310. task_environment_->GetMainThreadTaskRunner()->PostTask(
  311. FROM_HERE, base::BindOnce(&Me2MeNativeMessagingHostTest::ExitTest,
  312. base::Unretained(this)));
  313. return;
  314. }
  315. test_run_loop_->Quit();
  316. }
  317. void Me2MeNativeMessagingHostTest::TearDown() {
  318. // Closing the write-end of the input will send an EOF to the native
  319. // messaging reader. This will trigger a host shutdown.
  320. input_write_file_.Close();
  321. // Start a new RunLoop and Wait until the host finishes shutting down.
  322. test_run_loop_ = std::make_unique<base::RunLoop>();
  323. test_run_loop_->Run();
  324. // Verify there are no more message in the output pipe.
  325. absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
  326. EXPECT_FALSE(response);
  327. // The It2MeMe2MeNativeMessagingHost dtor closes the handles that are passed
  328. // to it. So the only handle left to close is |output_read_file_|.
  329. output_read_file_.Close();
  330. }
  331. absl::optional<base::Value::Dict>
  332. Me2MeNativeMessagingHostTest::ReadMessageFromOutputPipe() {
  333. while (true) {
  334. uint32_t length;
  335. int read_result = output_read_file_.ReadAtCurrentPos(
  336. reinterpret_cast<char*>(&length), sizeof(length));
  337. if (read_result != sizeof(length)) {
  338. return absl::nullopt;
  339. }
  340. std::string message_json(length, '\0');
  341. read_result =
  342. output_read_file_.ReadAtCurrentPos(std::data(message_json), length);
  343. if (read_result != static_cast<int>(length)) {
  344. return absl::nullopt;
  345. }
  346. absl::optional<base::Value> message = base::JSONReader::Read(message_json);
  347. if (!message || !message->is_dict()) {
  348. return absl::nullopt;
  349. }
  350. base::Value::Dict& result = message->GetDict();
  351. const std::string* type = result.FindString("type");
  352. // If this is a debug message log, ignore it, otherwise return it.
  353. if (!type || *type != LogMessageHandler::kDebugMessageTypeName) {
  354. return std::move(result);
  355. }
  356. }
  357. }
  358. void Me2MeNativeMessagingHostTest::WriteMessageToInputPipe(
  359. const base::ValueView& message) {
  360. std::string message_json;
  361. base::JSONWriter::Write(message, &message_json);
  362. uint32_t length = message_json.length();
  363. input_write_file_.WriteAtCurrentPos(reinterpret_cast<char*>(&length),
  364. sizeof(length));
  365. input_write_file_.WriteAtCurrentPos(message_json.data(), length);
  366. }
  367. void Me2MeNativeMessagingHostTest::TestBadRequest(const base::Value& message) {
  368. base::Value::Dict good_message;
  369. good_message.Set("type", "hello");
  370. // This test currently relies on synchronous processing of hello messages and
  371. // message parameters verification.
  372. WriteMessageToInputPipe(good_message);
  373. WriteMessageToInputPipe(message);
  374. WriteMessageToInputPipe(good_message);
  375. // Read from output pipe, and verify responses.
  376. absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
  377. ASSERT_TRUE(response);
  378. VerifyHelloResponse(std::move(*response));
  379. response = ReadMessageFromOutputPipe();
  380. EXPECT_FALSE(response);
  381. }
  382. // TODO (weitaosu): crbug.com/323306. Re-enable these tests.
  383. // Test all valid request-types.
  384. TEST_F(Me2MeNativeMessagingHostTest, All) {
  385. int next_id = 0;
  386. base::Value::Dict message;
  387. message.Set("id", next_id++);
  388. message.Set("type", "hello");
  389. WriteMessageToInputPipe(message);
  390. message.Set("id", next_id++);
  391. message.Set("type", "getHostName");
  392. WriteMessageToInputPipe(message);
  393. message.Set("id", next_id++);
  394. message.Set("type", "getPinHash");
  395. message.Set("hostId", "my_host");
  396. message.Set("pin", "1234");
  397. WriteMessageToInputPipe(message);
  398. message.clear();
  399. message.Set("id", next_id++);
  400. message.Set("type", "generateKeyPair");
  401. WriteMessageToInputPipe(message);
  402. message.Set("id", next_id++);
  403. message.Set("type", "getDaemonConfig");
  404. WriteMessageToInputPipe(message);
  405. message.Set("id", next_id++);
  406. message.Set("type", "getUsageStatsConsent");
  407. WriteMessageToInputPipe(message);
  408. message.Set("id", next_id++);
  409. message.Set("type", "stopDaemon");
  410. WriteMessageToInputPipe(message);
  411. message.Set("id", next_id++);
  412. message.Set("type", "getDaemonState");
  413. WriteMessageToInputPipe(message);
  414. // Following messages require a "config" dictionary.
  415. base::Value::Dict config;
  416. config.Set("update", true);
  417. message.Set("config", config.Clone());
  418. message.Set("id", next_id++);
  419. message.Set("type", "updateDaemonConfig");
  420. WriteMessageToInputPipe(message);
  421. config.clear();
  422. config.Set("start", true);
  423. message.Set("config", config.Clone());
  424. message.Set("consent", true);
  425. message.Set("id", next_id++);
  426. message.Set("type", "startDaemon");
  427. WriteMessageToInputPipe(message);
  428. message.Set("id", next_id++);
  429. message.Set("type", "getCredentialsFromAuthCode");
  430. message.Set("authorizationCode", "fake_auth_code");
  431. WriteMessageToInputPipe(message);
  432. void (*verify_routines[])(const base::Value::Dict&) = {
  433. &VerifyHelloResponse,
  434. &VerifyGetHostNameResponse,
  435. &VerifyGetPinHashResponse,
  436. &VerifyGenerateKeyPairResponse,
  437. &VerifyGetDaemonConfigResponse,
  438. &VerifyGetUsageStatsConsentResponse,
  439. &VerifyStopDaemonResponse,
  440. &VerifyGetDaemonStateResponse,
  441. &VerifyUpdateDaemonConfigResponse,
  442. &VerifyStartDaemonResponse,
  443. &VerifyGetCredentialsFromAuthCodeResponse,
  444. };
  445. ASSERT_EQ(std::size(verify_routines), static_cast<size_t>(next_id));
  446. // Read all responses from output pipe, and verify them.
  447. for (int i = 0; i < next_id; ++i) {
  448. absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
  449. ASSERT_TRUE(response);
  450. // Make sure that id is available and is in the range.
  451. absl::optional<int> id = response->FindInt("id");
  452. ASSERT_TRUE(id);
  453. ASSERT_TRUE(0 <= *id && *id < next_id);
  454. // Call the verification routine corresponding to the message id.
  455. ASSERT_TRUE(verify_routines[*id]);
  456. verify_routines[*id](std::move(*response));
  457. // Clear the pointer so that the routine cannot be called the second time.
  458. verify_routines[*id] = nullptr;
  459. }
  460. }
  461. // Verify that response ID matches request ID.
  462. TEST_F(Me2MeNativeMessagingHostTest, Id) {
  463. base::Value::Dict message;
  464. message.Set("type", "hello");
  465. WriteMessageToInputPipe(message);
  466. message.Set("id", "42");
  467. WriteMessageToInputPipe(message);
  468. absl::optional<base::Value::Dict> response = ReadMessageFromOutputPipe();
  469. EXPECT_TRUE(response);
  470. std::string* value = response->FindString("id");
  471. EXPECT_FALSE(value);
  472. response = ReadMessageFromOutputPipe();
  473. EXPECT_TRUE(response);
  474. value = response->FindString("id");
  475. EXPECT_TRUE(value);
  476. EXPECT_EQ("42", *value);
  477. }
  478. // Verify non-Dictionary requests are rejected.
  479. TEST_F(Me2MeNativeMessagingHostTest, WrongFormat) {
  480. TestBadRequest(base::Value(base::Value::Type::LIST));
  481. }
  482. // Verify requests with no type are rejected.
  483. TEST_F(Me2MeNativeMessagingHostTest, MissingType) {
  484. TestBadRequest(base::Value(base::Value::Type::DICT));
  485. }
  486. // Verify rejection if type is unrecognized.
  487. TEST_F(Me2MeNativeMessagingHostTest, InvalidType) {
  488. base::Value::Dict message;
  489. message.Set("type", "xxx");
  490. TestBadRequest(base::Value(std::move(message)));
  491. }
  492. // Verify rejection if getPinHash request has no hostId.
  493. TEST_F(Me2MeNativeMessagingHostTest, GetPinHashNoHostId) {
  494. base::Value::Dict message;
  495. message.Set("type", "getPinHash");
  496. message.Set("pin", "1234");
  497. TestBadRequest(base::Value(std::move(message)));
  498. }
  499. // Verify rejection if getPinHash request has no pin.
  500. TEST_F(Me2MeNativeMessagingHostTest, GetPinHashNoPin) {
  501. base::Value::Dict message;
  502. message.Set("type", "getPinHash");
  503. message.Set("hostId", "my_host");
  504. TestBadRequest(base::Value(std::move(message)));
  505. }
  506. // Verify rejection if updateDaemonConfig request has invalid config.
  507. TEST_F(Me2MeNativeMessagingHostTest, UpdateDaemonConfigInvalidConfig) {
  508. base::Value::Dict message;
  509. message.Set("type", "updateDaemonConfig");
  510. message.Set("config", "xxx");
  511. TestBadRequest(base::Value(std::move(message)));
  512. }
  513. // Verify rejection if startDaemon request has invalid config.
  514. TEST_F(Me2MeNativeMessagingHostTest, StartDaemonInvalidConfig) {
  515. base::Value::Dict message;
  516. message.Set("type", "startDaemon");
  517. message.Set("config", "xxx");
  518. message.Set("consent", true);
  519. TestBadRequest(base::Value(std::move(message)));
  520. }
  521. // Verify rejection if startDaemon request has no "consent" parameter.
  522. TEST_F(Me2MeNativeMessagingHostTest, StartDaemonNoConsent) {
  523. base::Value::Dict message;
  524. message.Set("type", "startDaemon");
  525. message.Set("config", base::Value::Dict());
  526. TestBadRequest(base::Value(std::move(message)));
  527. }
  528. // Verify rejection if getCredentialsFromAuthCode has no auth code.
  529. TEST_F(Me2MeNativeMessagingHostTest, GetCredentialsFromAuthCodeNoAuthCode) {
  530. base::Value::Dict message;
  531. message.Set("type", "getCredentialsFromAuthCode");
  532. TestBadRequest(base::Value(std::move(message)));
  533. }
  534. } // namespace remoting