| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/gcd_private/privet_v3_session.h" | 5 #include "chrome/browser/extensions/api/gcd_private/privet_v3_session.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/command_line.h" |
| 8 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 9 #include "base/thread_task_runner_handle.h" | 10 #include "base/thread_task_runner_handle.h" |
| 10 #include "chrome/browser/local_discovery/privet_http.h" | 11 #include "chrome/browser/local_discovery/privet_http.h" |
| 12 #include "chrome/common/chrome_switches.h" |
| 11 #include "content/public/test/test_utils.h" | 13 #include "content/public/test/test_utils.h" |
| 12 #include "crypto/hmac.h" | 14 #include "crypto/hmac.h" |
| 13 #include "crypto/p224_spake.h" | 15 #include "crypto/p224_spake.h" |
| 14 #include "net/url_request/test_url_fetcher_factory.h" | 16 #include "net/url_request/test_url_fetcher_factory.h" |
| 15 #include "net/url_request/url_request_test_util.h" | 17 #include "net/url_request/url_request_test_util.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 20 |
| 19 using local_discovery::PrivetHTTPClient; | 21 using local_discovery::PrivetHTTPClient; |
| 20 using local_discovery::PrivetJSONOperation; | 22 using local_discovery::PrivetJSONOperation; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 url, request_type, request_context_.get(), delegate)); | 81 url, request_type, request_context_.get(), delegate)); |
| 80 } | 82 } |
| 81 | 83 |
| 82 scoped_refptr<net::TestURLRequestContextGetter> request_context_; | 84 scoped_refptr<net::TestURLRequestContextGetter> request_context_; |
| 83 }; | 85 }; |
| 84 | 86 |
| 85 } // namespace | 87 } // namespace |
| 86 | 88 |
| 87 class PrivetV3SessionTest : public testing::Test { | 89 class PrivetV3SessionTest : public testing::Test { |
| 88 public: | 90 public: |
| 89 PrivetV3SessionTest() | 91 PrivetV3SessionTest() : fetcher_factory_(nullptr) {} |
| 90 : fetcher_factory_(nullptr), | |
| 91 http_client_(new StrictMock<MockPrivetHTTPClient>()), | |
| 92 session_(make_scoped_ptr(http_client_)) {} | |
| 93 | 92 |
| 94 void OnInitialized(Result result, const base::DictionaryValue& info) { | 93 void OnInitialized(Result result, const base::DictionaryValue& info) { |
| 95 info_.MergeDictionary(&info); | 94 info_.MergeDictionary(&info); |
| 96 OnInitializedMock(result, info); | 95 OnInitializedMock(result, info); |
| 97 } | 96 } |
| 98 | 97 |
| 99 MOCK_METHOD2(OnInitializedMock, void(Result, const base::DictionaryValue&)); | 98 MOCK_METHOD2(OnInitializedMock, void(Result, const base::DictionaryValue&)); |
| 100 MOCK_METHOD1(OnPairingStarted, void(Result)); | 99 MOCK_METHOD1(OnPairingStarted, void(Result)); |
| 101 MOCK_METHOD1(OnCodeConfirmed, void(Result)); | 100 MOCK_METHOD1(OnCodeConfirmed, void(Result)); |
| 102 MOCK_METHOD2(OnMessageSend, void(Result, const base::DictionaryValue&)); | 101 MOCK_METHOD2(OnMessageSend, void(Result, const base::DictionaryValue&)); |
| 103 MOCK_METHOD1(OnPostData, void(const base::DictionaryValue&)); | 102 MOCK_METHOD1(OnPostData, void(const base::DictionaryValue&)); |
| 104 | 103 |
| 105 protected: | 104 protected: |
| 106 void SetUp() override { | 105 void SetUp() override { |
| 107 session_.on_post_data_ = | 106 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 107 switches::kEnablePrivetV3); |
| 108 |
| 109 http_client_ = new StrictMock<MockPrivetHTTPClient>(); |
| 110 session_.reset(new PrivetV3Session(make_scoped_ptr(http_client_))); |
| 111 |
| 112 session_->on_post_data_ = |
| 108 base::Bind(&PrivetV3SessionTest::OnPostData, base::Unretained(this)); | 113 base::Bind(&PrivetV3SessionTest::OnPostData, base::Unretained(this)); |
| 109 | 114 |
| 110 EXPECT_CALL(*http_client_, IsInHttpsMode()).WillRepeatedly(Return(false)); | 115 EXPECT_CALL(*http_client_, IsInHttpsMode()).WillRepeatedly(Return(false)); |
| 116 EXPECT_CALL(*http_client_, GetHost()).WillRepeatedly(Return("1.1.1.1")); |
| 111 } | 117 } |
| 112 | 118 |
| 113 base::MessageLoop loop_; | 119 base::MessageLoop loop_; |
| 114 net::FakeURLFetcherFactory fetcher_factory_; | 120 net::FakeURLFetcherFactory fetcher_factory_; |
| 115 StrictMock<MockPrivetHTTPClient>* http_client_; | 121 StrictMock<MockPrivetHTTPClient>* http_client_ = nullptr; |
| 116 base::DictionaryValue info_; | 122 base::DictionaryValue info_; |
| 117 base::Closure quit_closure_; | 123 base::Closure quit_closure_; |
| 118 PrivetV3Session session_; | 124 scoped_ptr<PrivetV3Session> session_; |
| 119 }; | 125 }; |
| 120 | 126 |
| 121 TEST_F(PrivetV3SessionTest, InitError) { | 127 TEST_F(PrivetV3SessionTest, InitError) { |
| 122 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_CONNECTIONERROR, _)) | 128 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_CONNECTIONERROR, _)) |
| 123 .Times(1); | 129 .Times(1); |
| 124 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), "", | 130 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), "", |
| 125 net::HTTP_OK, net::URLRequestStatus::FAILED); | 131 net::HTTP_OK, net::URLRequestStatus::FAILED); |
| 126 session_.Init( | 132 session_->Init( |
| 127 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); | 133 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); |
| 128 base::RunLoop().RunUntilIdle(); | 134 base::RunLoop().RunUntilIdle(); |
| 129 } | 135 } |
| 130 | 136 |
| 131 TEST_F(PrivetV3SessionTest, VersionError) { | 137 TEST_F(PrivetV3SessionTest, VersionError) { |
| 132 std::string response(kInfoResponse); | 138 std::string response(kInfoResponse); |
| 133 base::ReplaceFirstSubstringAfterOffset(&response, 0, "3.0", "4.1"); | 139 base::ReplaceFirstSubstringAfterOffset(&response, 0, "3.0", "4.1"); |
| 134 | 140 |
| 135 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SESSIONERROR, _)) | 141 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SESSIONERROR, _)) |
| 136 .Times(1); | 142 .Times(1); |
| 137 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), response, | 143 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), response, |
| 138 net::HTTP_OK, | 144 net::HTTP_OK, |
| 139 net::URLRequestStatus::SUCCESS); | 145 net::URLRequestStatus::SUCCESS); |
| 140 session_.Init( | 146 session_->Init( |
| 141 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); | 147 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); |
| 142 base::RunLoop().RunUntilIdle(); | 148 base::RunLoop().RunUntilIdle(); |
| 143 } | 149 } |
| 144 | 150 |
| 145 TEST_F(PrivetV3SessionTest, ModeError) { | 151 TEST_F(PrivetV3SessionTest, ModeError) { |
| 146 std::string response(kInfoResponse); | 152 std::string response(kInfoResponse); |
| 147 base::ReplaceFirstSubstringAfterOffset(&response, 0, "mode", "mode_"); | 153 base::ReplaceFirstSubstringAfterOffset(&response, 0, "mode", "mode_"); |
| 148 | 154 |
| 149 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SESSIONERROR, _)) | 155 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SESSIONERROR, _)) |
| 150 .Times(1); | 156 .Times(1); |
| 151 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), response, | 157 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), response, |
| 152 net::HTTP_OK, | 158 net::HTTP_OK, |
| 153 net::URLRequestStatus::SUCCESS); | 159 net::URLRequestStatus::SUCCESS); |
| 154 session_.Init( | 160 session_->Init( |
| 155 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); | 161 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); |
| 156 base::RunLoop().RunUntilIdle(); | 162 base::RunLoop().RunUntilIdle(); |
| 157 } | 163 } |
| 158 | 164 |
| 159 TEST_F(PrivetV3SessionTest, NoHttpsError) { | 165 TEST_F(PrivetV3SessionTest, NoHttpsError) { |
| 160 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SUCCESS, _)).Times(1); | 166 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SUCCESS, _)).Times(1); |
| 161 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), | 167 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), |
| 162 kInfoResponse, net::HTTP_OK, | 168 kInfoResponse, net::HTTP_OK, |
| 163 net::URLRequestStatus::SUCCESS); | 169 net::URLRequestStatus::SUCCESS); |
| 164 | 170 |
| 165 session_.Init( | 171 session_->Init( |
| 166 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); | 172 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); |
| 167 base::RunLoop().RunUntilIdle(); | 173 base::RunLoop().RunUntilIdle(); |
| 168 | 174 |
| 169 EXPECT_CALL(*this, OnMessageSend(Result::STATUS_SESSIONERROR, _)).Times(1); | 175 EXPECT_CALL(*this, OnMessageSend(Result::STATUS_SESSIONERROR, _)).Times(1); |
| 170 session_.SendMessage( | 176 session_->SendMessage( |
| 171 "/privet/v3/state", base::DictionaryValue(), | 177 "/privet/v3/state", base::DictionaryValue(), |
| 172 base::Bind(&PrivetV3SessionTest::OnMessageSend, base::Unretained(this))); | 178 base::Bind(&PrivetV3SessionTest::OnMessageSend, base::Unretained(this))); |
| 173 base::RunLoop().RunUntilIdle(); | 179 base::RunLoop().RunUntilIdle(); |
| 174 } | 180 } |
| 175 | 181 |
| 176 TEST_F(PrivetV3SessionTest, Pairing) { | 182 TEST_F(PrivetV3SessionTest, Pairing) { |
| 177 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SUCCESS, _)).Times(1); | 183 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SUCCESS, _)).Times(1); |
| 178 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), | 184 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), |
| 179 kInfoResponse, net::HTTP_OK, | 185 kInfoResponse, net::HTTP_OK, |
| 180 net::URLRequestStatus::SUCCESS); | 186 net::URLRequestStatus::SUCCESS); |
| 181 | 187 |
| 182 session_.Init( | 188 session_->Init( |
| 183 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); | 189 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); |
| 184 base::RunLoop().RunUntilIdle(); | 190 base::RunLoop().RunUntilIdle(); |
| 185 | 191 |
| 186 const base::ListValue* pairing = nullptr; | 192 const base::ListValue* pairing = nullptr; |
| 187 ASSERT_TRUE(info_.GetList("authentication.pairing", &pairing)); | 193 ASSERT_TRUE(info_.GetList("authentication.pairing", &pairing)); |
| 188 | 194 |
| 189 std::string pairing_string; | 195 std::string pairing_string; |
| 190 ASSERT_TRUE(pairing->GetString(0, &pairing_string)); | 196 ASSERT_TRUE(pairing->GetString(0, &pairing_string)); |
| 191 EXPECT_EQ("pinCode", pairing_string); | 197 EXPECT_EQ("pinCode", pairing_string); |
| 192 | 198 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 209 | 215 |
| 210 std::string device_commitment; | 216 std::string device_commitment; |
| 211 base::Base64Encode(spake.GetNextMessage(), &device_commitment); | 217 base::Base64Encode(spake.GetNextMessage(), &device_commitment); |
| 212 fetcher_factory_.SetFakeResponse( | 218 fetcher_factory_.SetFakeResponse( |
| 213 GURL("http://host/privet/v3/pairing/start"), | 219 GURL("http://host/privet/v3/pairing/start"), |
| 214 base::StringPrintf( | 220 base::StringPrintf( |
| 215 "{\"deviceCommitment\":\"%s\",\"sessionId\":\"testId\"}", | 221 "{\"deviceCommitment\":\"%s\",\"sessionId\":\"testId\"}", |
| 216 device_commitment.c_str()), | 222 device_commitment.c_str()), |
| 217 net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 223 net::HTTP_OK, net::URLRequestStatus::SUCCESS); |
| 218 })); | 224 })); |
| 219 session_.StartPairing(PairingType::PAIRING_TYPE_EMBEDDEDCODE, | 225 session_->StartPairing(PairingType::PAIRING_TYPE_EMBEDDEDCODE, |
| 220 base::Bind(&PrivetV3SessionTest::OnPairingStarted, | 226 base::Bind(&PrivetV3SessionTest::OnPairingStarted, |
| 221 base::Unretained(this))); | 227 base::Unretained(this))); |
| 222 base::RunLoop().RunUntilIdle(); | 228 base::RunLoop().RunUntilIdle(); |
| 223 | 229 |
| 224 EXPECT_EQ("Privet anonymous", session_.privet_auth_token_); | 230 EXPECT_EQ("Privet anonymous", session_->privet_auth_token_); |
| 225 | 231 |
| 226 std::string fingerprint("testFingerprint testFingerprint"); | 232 std::string fingerprint("testFingerprint testFingerprint"); |
| 227 net::SHA256HashValue sha_fingerprint; | 233 net::SHA256HashValue sha_fingerprint; |
| 228 ASSERT_EQ(sizeof(sha_fingerprint.data), fingerprint.size()); | 234 ASSERT_EQ(sizeof(sha_fingerprint.data), fingerprint.size()); |
| 229 memcpy(sha_fingerprint.data, fingerprint.data(), fingerprint.size()); | 235 memcpy(sha_fingerprint.data, fingerprint.data(), fingerprint.size()); |
| 230 | 236 |
| 231 EXPECT_CALL(*http_client_, | 237 EXPECT_CALL(*http_client_, |
| 232 SwitchToHttps(443, Field(&net::SHA256HashValue::data, | 238 SwitchToHttps(443, Field(&net::SHA256HashValue::data, |
| 233 ElementsAreArray(sha_fingerprint.data)))) | 239 ElementsAreArray(sha_fingerprint.data)))) |
| 234 .WillOnce(InvokeWithoutArgs([this]() { | 240 .WillOnce(InvokeWithoutArgs([this]() { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 const std::string& key = spake.GetUnverifiedKey(); | 289 const std::string& key = spake.GetUnverifiedKey(); |
| 284 EXPECT_TRUE(hmac.Init(key)); | 290 EXPECT_TRUE(hmac.Init(key)); |
| 285 EXPECT_TRUE(hmac.Verify("testId", access_token)); | 291 EXPECT_TRUE(hmac.Verify("testId", access_token)); |
| 286 | 292 |
| 287 fetcher_factory_.SetFakeResponse( | 293 fetcher_factory_.SetFakeResponse( |
| 288 GURL("http://host/privet/v3/auth"), | 294 GURL("http://host/privet/v3/auth"), |
| 289 "{\"accessToken\":\"567\",\"tokenType\":\"testType\"," | 295 "{\"accessToken\":\"567\",\"tokenType\":\"testType\"," |
| 290 "\"scope\":\"owner\"}", | 296 "\"scope\":\"owner\"}", |
| 291 net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 297 net::HTTP_OK, net::URLRequestStatus::SUCCESS); |
| 292 })); | 298 })); |
| 293 session_.ConfirmCode("testPin", | 299 session_->ConfirmCode("testPin", |
| 294 base::Bind(&PrivetV3SessionTest::OnCodeConfirmed, | 300 base::Bind(&PrivetV3SessionTest::OnCodeConfirmed, |
| 295 base::Unretained(this))); | 301 base::Unretained(this))); |
| 296 base::RunLoop().RunUntilIdle(); | 302 base::RunLoop().RunUntilIdle(); |
| 297 | 303 |
| 298 EXPECT_TRUE(session_.client_->IsInHttpsMode()); | 304 EXPECT_TRUE(session_->client_->IsInHttpsMode()); |
| 299 EXPECT_EQ("testType 567", session_.privet_auth_token_); | 305 EXPECT_EQ("testType 567", session_->privet_auth_token_); |
| 300 } | 306 } |
| 301 | 307 |
| 302 TEST_F(PrivetV3SessionTest, Cancel) { | 308 TEST_F(PrivetV3SessionTest, Cancel) { |
| 303 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SUCCESS, _)).Times(1); | 309 EXPECT_CALL(*this, OnInitializedMock(Result::STATUS_SUCCESS, _)).Times(1); |
| 304 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), | 310 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), |
| 305 kInfoResponse, net::HTTP_OK, | 311 kInfoResponse, net::HTTP_OK, |
| 306 net::URLRequestStatus::SUCCESS); | 312 net::URLRequestStatus::SUCCESS); |
| 307 | 313 |
| 308 session_.Init( | 314 session_->Init( |
| 309 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); | 315 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this))); |
| 310 base::RunLoop().RunUntilIdle(); | 316 base::RunLoop().RunUntilIdle(); |
| 311 | 317 |
| 312 EXPECT_CALL(*http_client_, IsInHttpsMode()).WillRepeatedly(Return(false)); | 318 EXPECT_CALL(*http_client_, IsInHttpsMode()).WillRepeatedly(Return(false)); |
| 313 | 319 |
| 314 EXPECT_CALL(*this, OnPairingStarted(Result::STATUS_SUCCESS)).Times(1); | 320 EXPECT_CALL(*this, OnPairingStarted(Result::STATUS_SUCCESS)).Times(1); |
| 315 EXPECT_CALL(*this, OnPostData(_)) | 321 EXPECT_CALL(*this, OnPostData(_)) |
| 316 .WillOnce(Invoke([this](const base::DictionaryValue& data) { | 322 .WillOnce(Invoke([this](const base::DictionaryValue& data) { |
| 317 std::string device_commitment; | 323 std::string device_commitment; |
| 318 base::Base64Encode("1234", &device_commitment); | 324 base::Base64Encode("1234", &device_commitment); |
| 319 fetcher_factory_.SetFakeResponse( | 325 fetcher_factory_.SetFakeResponse( |
| 320 GURL("http://host/privet/v3/pairing/start"), | 326 GURL("http://host/privet/v3/pairing/start"), |
| 321 base::StringPrintf( | 327 base::StringPrintf( |
| 322 "{\"deviceCommitment\":\"%s\",\"sessionId\":\"testId\"}", | 328 "{\"deviceCommitment\":\"%s\",\"sessionId\":\"testId\"}", |
| 323 device_commitment.c_str()), | 329 device_commitment.c_str()), |
| 324 net::HTTP_OK, net::URLRequestStatus::SUCCESS); | 330 net::HTTP_OK, net::URLRequestStatus::SUCCESS); |
| 325 })); | 331 })); |
| 326 session_.StartPairing(PairingType::PAIRING_TYPE_EMBEDDEDCODE, | 332 session_->StartPairing(PairingType::PAIRING_TYPE_EMBEDDEDCODE, |
| 327 base::Bind(&PrivetV3SessionTest::OnPairingStarted, | 333 base::Bind(&PrivetV3SessionTest::OnPairingStarted, |
| 328 base::Unretained(this))); | 334 base::Unretained(this))); |
| 329 base::RunLoop().RunUntilIdle(); | 335 base::RunLoop().RunUntilIdle(); |
| 330 | 336 |
| 331 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/v3/pairing/cancel"), | 337 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/v3/pairing/cancel"), |
| 332 kInfoResponse, net::HTTP_OK, | 338 kInfoResponse, net::HTTP_OK, |
| 333 net::URLRequestStatus::SUCCESS); | 339 net::URLRequestStatus::SUCCESS); |
| 334 EXPECT_CALL(*this, OnPostData(_)) | 340 EXPECT_CALL(*this, OnPostData(_)) |
| 335 .WillOnce(Invoke([this](const base::DictionaryValue& data) { | 341 .WillOnce(Invoke([this](const base::DictionaryValue& data) { |
| 336 std::string session_id; | 342 std::string session_id; |
| 337 EXPECT_TRUE(data.GetString("sessionId", &session_id)); | 343 EXPECT_TRUE(data.GetString("sessionId", &session_id)); |
| 338 })); | 344 })); |
| 339 } | 345 } |
| 340 | 346 |
| 341 // TODO(vitalybuka): replace PrivetHTTPClient with regular URL fetcher and | 347 // TODO(vitalybuka): replace PrivetHTTPClient with regular URL fetcher and |
| 342 // implement SendMessage test. | 348 // implement SendMessage test. |
| 343 | 349 |
| 344 } // namespace extensions | 350 } // namespace extensions |
| OLD | NEW |