diff options
Diffstat (limited to 'chrome/browser')
9 files changed, 530 insertions, 17 deletions
diff --git a/chrome/browser/local_discovery/privet_constants.cc b/chrome/browser/local_discovery/privet_constants.cc index 525e79f..a2a4871 100644 --- a/chrome/browser/local_discovery/privet_constants.cc +++ b/chrome/browser/local_discovery/privet_constants.cc @@ -32,6 +32,10 @@ const char kPrivetErrorInvalidXPrivetToken[] = "invalid_x_privet_token"; const char kPrivetErrorTimeout[] = "confirmation_timeout"; const char kPrivetErrorCancel[] = "user_cancel"; +const char kPrivetV3ErrorDeviceBusy[] = "deviceBusy"; +const char kPrivetV3ErrorInvalidParams[] = "invalidParams"; +const char kPrivetV3ErrorSetupUnavailable[] = "setupUnavailable"; + const char kPrivetActionStart[] = "start"; const char kPrivetActionGetClaimToken[] = "getClaimToken"; const char kPrivetActionComplete[] = "complete"; diff --git a/chrome/browser/local_discovery/privet_constants.h b/chrome/browser/local_discovery/privet_constants.h index 99547b1..f0b65414 100644 --- a/chrome/browser/local_discovery/privet_constants.h +++ b/chrome/browser/local_discovery/privet_constants.h @@ -33,6 +33,10 @@ extern const char kPrivetErrorInvalidXPrivetToken[]; extern const char kPrivetErrorTimeout[]; extern const char kPrivetErrorCancel[]; +extern const char kPrivetV3ErrorDeviceBusy[]; +extern const char kPrivetV3ErrorInvalidParams[]; +extern const char kPrivetV3ErrorSetupUnavailable[]; + extern const char kPrivetActionStart[]; extern const char kPrivetActionGetClaimToken[]; extern const char kPrivetActionComplete[]; diff --git a/chrome/browser/local_discovery/privet_url_fetcher.cc b/chrome/browser/local_discovery/privet_url_fetcher.cc index 9b9e9c3..bb64b88 100644 --- a/chrome/browser/local_discovery/privet_url_fetcher.cc +++ b/chrome/browser/local_discovery/privet_url_fetcher.cc @@ -345,6 +345,7 @@ void PrivetURLFetcher::RefreshToken(const std::string& token) { bool PrivetURLFetcher::PrivetErrorTransient(const std::string& error) { return (error == kPrivetErrorDeviceBusy) || + (error == kPrivetV3ErrorDeviceBusy) || (error == kPrivetErrorPendingUserAction) || (error == kPrivetErrorPrinterBusy); } diff --git a/chrome/browser/local_discovery/privetv3_session.cc b/chrome/browser/local_discovery/privetv3_session.cc index 64c8d1f..296bb07 100644 --- a/chrome/browser/local_discovery/privetv3_session.cc +++ b/chrome/browser/local_discovery/privetv3_session.cc @@ -4,25 +4,124 @@ #include "chrome/browser/local_discovery/privetv3_session.h" +#include "base/json/json_writer.h" #include "base/logging.h" #include "chrome/browser/local_discovery/privet_http.h" +#include "chrome/common/cloud_print/cloud_print_constants.h" namespace local_discovery { +namespace { + +const char kUrlPlaceHolder[] = "http://host/"; + +GURL CreatePrivetURL(const std::string& path) { + GURL url(kUrlPlaceHolder); + GURL::Replacements replacements; + replacements.SetPathStr(path); + return url.ReplaceComponents(replacements); +} + +} // namespace + +class PrivetV3Session::FetcherDelegate : public PrivetURLFetcher::Delegate { + public: + FetcherDelegate(const base::WeakPtr<PrivetV3Session>& session, + Request* request); + virtual ~FetcherDelegate(); + + // PrivetURLFetcher::Delegate methods. + virtual void OnNeedPrivetToken( + PrivetURLFetcher* fetcher, + const PrivetURLFetcher::TokenCallback& callback) OVERRIDE; + virtual void OnError(PrivetURLFetcher* fetcher, + PrivetURLFetcher::ErrorType error) OVERRIDE; + virtual void OnParsedJson(PrivetURLFetcher* fetcher, + const base::DictionaryValue& value, + bool has_error) OVERRIDE; + + private: + friend class PrivetV3Session; + scoped_ptr<PrivetURLFetcher> url_fetcher_; + base::WeakPtr<PrivetV3Session> session_; + Request* request_; +}; + +PrivetV3Session::FetcherDelegate::FetcherDelegate( + const base::WeakPtr<PrivetV3Session>& session, + Request* request) + : session_(session), request_(request) { +} + +PrivetV3Session::FetcherDelegate::~FetcherDelegate() { +} + +void PrivetV3Session::FetcherDelegate::OnNeedPrivetToken( + PrivetURLFetcher* fetcher, + const PrivetURLFetcher::TokenCallback& callback) { + if (session_) + session_->client_->RefreshPrivetToken(callback); +} + +void PrivetV3Session::FetcherDelegate::OnError( + PrivetURLFetcher* fetcher, + PrivetURLFetcher::ErrorType error) { + request_->OnError(error); +} + +void PrivetV3Session::FetcherDelegate::OnParsedJson( + PrivetURLFetcher* fetcher, + const base::DictionaryValue& value, + bool has_error) { + request_->OnParsedJson(value, has_error); +} + PrivetV3Session::Delegate::~Delegate() { } +PrivetV3Session::Request::Request() { +} + PrivetV3Session::Request::~Request() { } PrivetV3Session::PrivetV3Session(scoped_ptr<PrivetHTTPClient> client, - Delegate* delegate) { + Delegate* delegate) + : delegate_(delegate), + client_(client.Pass()), + code_confirmed_(false), + weak_ptr_factory_(this) { } PrivetV3Session::~PrivetV3Session() { } void PrivetV3Session::Start() { + delegate_->OnSetupConfirmationNeeded("01234"); +} + +void PrivetV3Session::ConfirmCode() { + code_confirmed_ = true; + delegate_->OnSessionEstablished(); +} + +void PrivetV3Session::StartRequest(Request* request) { + CHECK(code_confirmed_); + + request->fetcher_delegate_.reset( + new FetcherDelegate(weak_ptr_factory_.GetWeakPtr(), request)); + + scoped_ptr<PrivetURLFetcher> url_fetcher = + client_->CreateURLFetcher(CreatePrivetURL(request->GetName()), + net::URLFetcher::POST, + request->fetcher_delegate_.get()); + std::string json; + base::JSONWriter::WriteWithOptions( + &request->GetInput(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &json); + url_fetcher->SetUploadData(cloud_print::kContentTypeJSON, json); + + request->fetcher_delegate_->url_fetcher_ = url_fetcher.Pass(); + request->fetcher_delegate_->url_fetcher_->Start(); } } // namespace local_discovery diff --git a/chrome/browser/local_discovery/privetv3_session.h b/chrome/browser/local_discovery/privetv3_session.h index 1d943f2..9a96c50 100644 --- a/chrome/browser/local_discovery/privetv3_session.h +++ b/chrome/browser/local_discovery/privetv3_session.h @@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" +#include "chrome/browser/local_discovery/privet_url_fetcher.h" namespace base { class DictionaryValue; @@ -20,22 +21,18 @@ class PrivetHTTPClient; // Manages secure communication between browser and local Privet device. class PrivetV3Session { - public: - typedef base::Callback< - void(bool success, const base::DictionaryValue& response)> - RequestCallback; + private: + class FetcherDelegate; + public: // Delegate to be implemented by client code. class Delegate { public: - typedef base::Callback<void(bool confirm)> ConfirmationCallback; - virtual ~Delegate(); // Called when client code should prompt user to check |confirmation_code|. virtual void OnSetupConfirmationNeeded( - const std::string& confirmation_code, - const ConfirmationCallback& callback) = 0; + const std::string& confirmation_code) = 0; // Called when session successfully establish and client code my call // |CreateRequest| method. @@ -48,8 +45,18 @@ class PrivetV3Session { // Represents request in progress using secure session. class Request { public: + Request(); virtual ~Request(); - virtual void Start() = 0; + + virtual std::string GetName() = 0; + virtual const base::DictionaryValue& GetInput() = 0; + virtual void OnError(PrivetURLFetcher::ErrorType error) = 0; + virtual void OnParsedJson(const base::DictionaryValue& value, + bool has_error) = 0; + + private: + friend class PrivetV3Session; + scoped_ptr<FetcherDelegate> fetcher_delegate_; }; PrivetV3Session(scoped_ptr<PrivetHTTPClient> client, Delegate* delegate); @@ -59,13 +66,16 @@ class PrivetV3Session { // |OnSessionEstablished|. void Start(); + void ConfirmCode(); + // Create a single /privet/v3/session/call request. - // Must be called only after receiving |OnSessionEstablished|. - scoped_ptr<Request> CreateRequest(const std::string& api_name, - const base::DictionaryValue& request, - const RequestCallback& callback); + void StartRequest(Request* request); private: + Delegate* delegate_; + scoped_ptr<PrivetHTTPClient> client_; + bool code_confirmed_; + base::WeakPtrFactory<PrivetV3Session> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(PrivetV3Session); }; diff --git a/chrome/browser/local_discovery/privetv3_session_unittest.cc b/chrome/browser/local_discovery/privetv3_session_unittest.cc new file mode 100644 index 0000000..31291c3 --- /dev/null +++ b/chrome/browser/local_discovery/privetv3_session_unittest.cc @@ -0,0 +1,59 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/local_discovery/privetv3_session.h" + +#include "chrome/browser/local_discovery/privet_http.h" +#include "net/url_request/test_url_fetcher_factory.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace local_discovery { + +namespace { + +using testing::InvokeWithoutArgs; +using testing::StrictMock; +using testing::_; + +class MockDelegate : public PrivetV3Session::Delegate { + public: + MOCK_METHOD1(OnSetupConfirmationNeeded, void(const std::string&)); + MOCK_METHOD0(OnSessionEstablished, void()); + MOCK_METHOD0(OnCannotEstablishSession, void()); +}; + +class PrivetV3SessionTest : public testing::Test { + public: + PrivetV3SessionTest() + : session_(scoped_ptr<PrivetHTTPClient>(), &delegate_) {} + + virtual ~PrivetV3SessionTest() {} + + protected: + virtual void SetUp() OVERRIDE { + EXPECT_CALL(delegate_, OnSetupConfirmationNeeded(_)).Times(0); + EXPECT_CALL(delegate_, OnSessionEstablished()).Times(0); + EXPECT_CALL(delegate_, OnCannotEstablishSession()).Times(0); + } + + StrictMock<MockDelegate> delegate_; + PrivetV3Session session_; +}; + +TEST_F(PrivetV3SessionTest, NotConfirmed) { + EXPECT_CALL(delegate_, OnSetupConfirmationNeeded(_)).Times(1); + session_.Start(); +} + +TEST_F(PrivetV3SessionTest, Confirmed) { + EXPECT_CALL(delegate_, OnSessionEstablished()).Times(1); + EXPECT_CALL(delegate_, OnSetupConfirmationNeeded(_)).Times(1).WillOnce( + InvokeWithoutArgs(&session_, &PrivetV3Session::ConfirmCode)); + session_.Start(); +} + +} // namespace + +} // namespace local_discovery diff --git a/chrome/browser/local_discovery/privetv3_setup_flow.cc b/chrome/browser/local_discovery/privetv3_setup_flow.cc index 5cafa93..fd87149 100644 --- a/chrome/browser/local_discovery/privetv3_setup_flow.cc +++ b/chrome/browser/local_discovery/privetv3_setup_flow.cc @@ -5,9 +5,79 @@ #include "chrome/browser/local_discovery/privetv3_setup_flow.h" #include "base/logging.h" +#include "chrome/browser/local_discovery/gcd_registration_ticket_request.h" namespace local_discovery { +namespace { + +const char kSsidJsonKeyName[] = "wifi.ssid"; +const char kPasswordJsonKeyName[] = "wifi.passphrase"; +const char kTicketJsonKeyName[] = "registration.ticketID"; +const char kUserJsonKeyName[] = "registration.user"; + +class SetupRequest : public PrivetV3Session::Request { + public: + explicit SetupRequest(PrivetV3SetupFlow* setup_flow); + virtual ~SetupRequest(); + + virtual std::string GetName() OVERRIDE { return "/privet/v3/setup/start"; } + virtual const base::DictionaryValue& GetInput() OVERRIDE; + + virtual void OnError(PrivetURLFetcher::ErrorType error) OVERRIDE; + virtual void OnParsedJson(const base::DictionaryValue& value, + bool has_error) OVERRIDE; + + void SetWiFiCridentials(const std::string& ssid, const std::string& password); + + void SetRegistrationTicket(const std::string& ticket_id, + const std::string& owner_email); + + private: + base::DictionaryValue input_; + PrivetV3SetupFlow* setup_flow_; +}; + +SetupRequest::SetupRequest(PrivetV3SetupFlow* setup_flow) + : setup_flow_(setup_flow) { +} + +SetupRequest::~SetupRequest() { +} + +const base::DictionaryValue& SetupRequest::GetInput() { + return input_; +} + +void SetupRequest::OnError(PrivetURLFetcher::ErrorType error) { + setup_flow_->OnSetupError(); +} + +void SetupRequest::OnParsedJson(const base::DictionaryValue& value, + bool has_error) { + if (has_error) + return setup_flow_->OnSetupError(); + setup_flow_->OnDeviceRegistered(); +} + +void SetupRequest::SetWiFiCridentials(const std::string& ssid, + const std::string& password) { + DCHECK(!ssid.empty()); + DCHECK(!password.empty()); + input_.SetString(kSsidJsonKeyName, ssid); + input_.SetString(kPasswordJsonKeyName, password); +} + +void SetupRequest::SetRegistrationTicket(const std::string& ticket_id, + const std::string& owner_email) { + DCHECK(!ticket_id.empty()); + DCHECK(!owner_email.empty()); + input_.SetString(kTicketJsonKeyName, ticket_id); + input_.SetString(kUserJsonKeyName, owner_email); +} + +} // namespace + PrivetV3SetupFlow::Delegate::~Delegate() { } @@ -19,7 +89,17 @@ PrivetV3SetupFlow::~PrivetV3SetupFlow() { } void PrivetV3SetupFlow::Register(const std::string& service_name) { - NOTIMPLEMENTED(); + service_name_ = service_name; + ticket_request_ = delegate_->CreateApiFlow(); + if (!ticket_request_) { + OnSetupError(); + return; + } + scoped_ptr<GCDApiFlow::Request> ticket_request( + new GCDRegistrationTicketRequest( + base::Bind(&PrivetV3SetupFlow::OnTicketCreated, + weak_ptr_factory_.GetWeakPtr()))); + ticket_request_->Start(ticket_request.Pass()); } #if defined(ENABLE_WIFI_BOOTSTRAPPING) @@ -28,4 +108,58 @@ void PrivetV3SetupFlow::SetupWifiAndRegister(const std::string& device_ssid) { } #endif // ENABLE_WIFI_BOOTSTRAPPING +void PrivetV3SetupFlow::OnSetupConfirmationNeeded( + const std::string& confirmation_code) { + delegate_->ConfirmSecurityCode(confirmation_code, + base::Bind(&PrivetV3SetupFlow::OnCodeConfirmed, + weak_ptr_factory_.GetWeakPtr())); +} + +void PrivetV3SetupFlow::OnSessionEstablished() { + DCHECK(setup_request_); + session_->StartRequest(setup_request_.get()); +} + +void PrivetV3SetupFlow::OnCannotEstablishSession() { + OnSetupError(); +} + +void PrivetV3SetupFlow::OnSetupError() { + delegate_->OnSetupError(); +} + +void PrivetV3SetupFlow::OnDeviceRegistered() { + delegate_->OnSetupDone(); +} + +void PrivetV3SetupFlow::OnTicketCreated(const std::string& ticket_id) { + if (ticket_id.empty()) { + OnSetupError(); + return; + } + SetupRequest* setup_request = new SetupRequest(this); + setup_request_.reset(setup_request); + setup_request->SetRegistrationTicket(ticket_id, "me"); + delegate_->CreatePrivetV3Client( + service_name_, + base::Bind(&PrivetV3SetupFlow::OnPrivetClientCreated, + weak_ptr_factory_.GetWeakPtr())); +} + +void PrivetV3SetupFlow::OnPrivetClientCreated( + scoped_ptr<PrivetHTTPClient> privet_http_client) { + if (!privet_http_client) { + OnSetupError(); + return; + } + session_.reset(new PrivetV3Session(privet_http_client.Pass(), this)); + session_->Start(); +} + +void PrivetV3SetupFlow::OnCodeConfirmed(bool success) { + if (!success) + return OnSetupError(); + session_->ConfirmCode(); +} + } // namespace local_discovery diff --git a/chrome/browser/local_discovery/privetv3_setup_flow.h b/chrome/browser/local_discovery/privetv3_setup_flow.h index 614a221..e039fa4 100644 --- a/chrome/browser/local_discovery/privetv3_setup_flow.h +++ b/chrome/browser/local_discovery/privetv3_setup_flow.h @@ -11,11 +11,12 @@ #include "base/memory/scoped_ptr.h" #include "chrome/browser/local_discovery/gcd_api_flow.h" #include "chrome/browser/local_discovery/privet_http.h" +#include "chrome/browser/local_discovery/privetv3_session.h" namespace local_discovery { // Provides complete flow for Privet v3 device setup. -class PrivetV3SetupFlow { +class PrivetV3SetupFlow : public PrivetV3Session::Delegate { public: // Delegate to be implemented by client code. class Delegate { @@ -61,7 +62,7 @@ class PrivetV3SetupFlow { }; explicit PrivetV3SetupFlow(Delegate* delegate); - ~PrivetV3SetupFlow(); + virtual ~PrivetV3SetupFlow(); // Starts registration. void Register(const std::string& service_name); @@ -70,9 +71,25 @@ class PrivetV3SetupFlow { void SetupWifiAndRegister(const std::string& device_ssid); #endif // ENABLE_WIFI_BOOTSTRAPPING + // PrivetV3Session::Delegate implementation. + virtual void OnSetupConfirmationNeeded( + const std::string& confirmation_code) OVERRIDE; + virtual void OnSessionEstablished() OVERRIDE; + virtual void OnCannotEstablishSession() OVERRIDE; + + void OnSetupError(); + void OnDeviceRegistered(); + private: + void OnTicketCreated(const std::string& ticket_id); + void OnPrivetClientCreated(scoped_ptr<PrivetHTTPClient> privet_http_client); + void OnCodeConfirmed(bool success); + Delegate* delegate_; std::string service_name_; + scoped_ptr<GCDApiFlow> ticket_request_; + scoped_ptr<PrivetV3Session> session_; + scoped_ptr<PrivetV3Session::Request> setup_request_; base::WeakPtrFactory<PrivetV3SetupFlow> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(PrivetV3SetupFlow); diff --git a/chrome/browser/local_discovery/privetv3_setup_flow_unittest.cc b/chrome/browser/local_discovery/privetv3_setup_flow_unittest.cc new file mode 100644 index 0000000..2b6a636 --- /dev/null +++ b/chrome/browser/local_discovery/privetv3_setup_flow_unittest.cc @@ -0,0 +1,185 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/local_discovery/privetv3_setup_flow.h" + +#include "base/json/json_reader.h" +#include "chrome/browser/local_discovery/gcd_api_flow.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/test_url_fetcher_factory.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace local_discovery { + +namespace { + +using testing::HasSubstr; +using testing::Invoke; +using testing::Return; +using testing::SaveArg; +using testing::StrictMock; +using testing::WithArgs; +using testing::_; + +const char kServiceName[] = "test_service"; + +const char kRegistrationTicketResponse[] = + "{" + "\"kind\": \"clouddevices#registrationTicket\"," + "\"id\": \"test_ticket\"" + "}"; + +class MockPrivetHTTPClient : public PrivetHTTPClient { + public: + MockPrivetHTTPClient() { + request_context_ = + new net::TestURLRequestContextGetter(base::MessageLoopProxy::current()); + } + + MOCK_METHOD0(GetName, const std::string&()); + MOCK_METHOD1( + CreateInfoOperationPtr, + PrivetJSONOperation*(const PrivetJSONOperation::ResultCallback&)); + + virtual void RefreshPrivetToken( + const PrivetURLFetcher::TokenCallback& callback) OVERRIDE { + callback.Run("x-privet-token"); + } + + virtual scoped_ptr<PrivetJSONOperation> CreateInfoOperation( + const PrivetJSONOperation::ResultCallback& callback) OVERRIDE { + return make_scoped_ptr(CreateInfoOperationPtr(callback)); + } + + virtual scoped_ptr<PrivetURLFetcher> CreateURLFetcher( + const GURL& url, + net::URLFetcher::RequestType request_type, + PrivetURLFetcher::Delegate* delegate) OVERRIDE { + return make_scoped_ptr( + new PrivetURLFetcher(url, request_type, request_context_, delegate)); + } + + scoped_refptr<net::TestURLRequestContextGetter> request_context_; +}; + +class MockDelegate : public PrivetV3SetupFlow::Delegate { + public: + MockDelegate() : privet_client_ptr_(NULL) {} + + class MockGCDApiFlow : public GCDApiFlow { + public: + explicit MockGCDApiFlow(MockDelegate* delegate) : delegate_(delegate) {} + + virtual void Start(scoped_ptr<Request> request) OVERRIDE { + ASSERT_FALSE(delegate_->gcd_request_); + delegate_->gcd_request_ = request.Pass(); + delegate_->ReplyWithToken(); + } + + private: + MockDelegate* delegate_; + }; + + MOCK_METHOD1(GetWiFiCredentials, void(const CredentialsCallback&)); + MOCK_METHOD1(SwitchToSetupWiFi, void(const ResultCallback&)); + virtual void CreatePrivetV3Client( + const std::string& service_name, + const PrivetClientCallback& callback) OVERRIDE { + scoped_ptr<MockPrivetHTTPClient> privet_client(new MockPrivetHTTPClient()); + privet_client_ptr_ = privet_client.get(); + callback.Run(privet_client.PassAs<PrivetHTTPClient>()); + } + MOCK_METHOD2(ConfirmSecurityCode, + void(const std::string&, const ResultCallback&)); + MOCK_METHOD1(RestoreWifi, void(const ResultCallback&)); + MOCK_METHOD0(OnSetupDone, void()); + MOCK_METHOD0(OnSetupError, void()); + + virtual scoped_ptr<GCDApiFlow> CreateApiFlow() OVERRIDE { + scoped_ptr<MockGCDApiFlow> mock_gcd(new MockGCDApiFlow(this)); + return mock_gcd.PassAs<GCDApiFlow>(); + } + + void ReplyWithToken() { + scoped_ptr<base::Value> value(base::JSONReader::Read(gcd_server_response_)); + const base::DictionaryValue* dictionary = NULL; + value->GetAsDictionary(&dictionary); + gcd_request_->OnGCDAPIFlowComplete(*dictionary); + } + + void ConfirmCode(const ResultCallback& confirm_callback) { + confirm_callback.Run(true); + } + + std::string gcd_server_response_; + scoped_ptr<GCDApiFlow::Request> gcd_request_; + MockPrivetHTTPClient* privet_client_ptr_; +}; + +class PrivetV3SetupFlowTest : public testing::Test { + public: + PrivetV3SetupFlowTest() : setup_(&delegate_) {} + + virtual ~PrivetV3SetupFlowTest() {} + + protected: + virtual void SetUp() OVERRIDE { + EXPECT_CALL(delegate_, GetWiFiCredentials(_)).Times(0); + EXPECT_CALL(delegate_, SwitchToSetupWiFi(_)).Times(0); + EXPECT_CALL(delegate_, ConfirmSecurityCode(_, _)).Times(0); + EXPECT_CALL(delegate_, RestoreWifi(_)).Times(0); + EXPECT_CALL(delegate_, OnSetupDone()).Times(0); + EXPECT_CALL(delegate_, OnSetupError()).Times(0); + } + + void SimulateFetch(int response_code, const std::string& response) { + net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); + ASSERT_TRUE(fetcher); + EXPECT_THAT(fetcher->GetOriginalURL().spec(), + testing::HasSubstr("/privet/v3/setup/start")); + fetcher->set_response_code(response_code); + scoped_refptr<net::HttpResponseHeaders> response_headers( + new net::HttpResponseHeaders("")); + response_headers->AddHeader("Content-Type: application/json"); + fetcher->set_response_headers(response_headers); + fetcher->SetResponseString(response); + fetcher->delegate()->OnURLFetchComplete(fetcher); + } + + base::MessageLoop loop_; + net::TestURLFetcherFactory url_fetcher_factory_; + + StrictMock<MockDelegate> delegate_; + PrivetV3SetupFlow setup_; +}; + +TEST_F(PrivetV3SetupFlowTest, InvalidTicket) { + EXPECT_CALL(delegate_, OnSetupError()).Times(1); + delegate_.gcd_server_response_ = "{}"; + setup_.Register(kServiceName); +} + +TEST_F(PrivetV3SetupFlowTest, InvalidDeviceResponce) { + EXPECT_CALL(delegate_, OnSetupError()).Times(1); + EXPECT_CALL(delegate_, ConfirmSecurityCode(_, _)).Times(1).WillOnce( + WithArgs<1>(Invoke(&delegate_, &MockDelegate::ConfirmCode))); + delegate_.gcd_server_response_ = kRegistrationTicketResponse; + setup_.Register(kServiceName); + SimulateFetch(0, "{}"); +} + +TEST_F(PrivetV3SetupFlowTest, Success) { + EXPECT_CALL(delegate_, OnSetupDone()).Times(1); + EXPECT_CALL(delegate_, ConfirmSecurityCode(_, _)).Times(1).WillOnce( + WithArgs<1>(Invoke(&delegate_, &MockDelegate::ConfirmCode))); + delegate_.gcd_server_response_ = kRegistrationTicketResponse; + setup_.Register(kServiceName); + SimulateFetch(200, "{}"); +} + +} // namespace + +} // namespace local_discovery |