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 |