summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/local_discovery/privet_constants.cc4
-rw-r--r--chrome/browser/local_discovery/privet_constants.h4
-rw-r--r--chrome/browser/local_discovery/privet_url_fetcher.cc1
-rw-r--r--chrome/browser/local_discovery/privetv3_session.cc101
-rw-r--r--chrome/browser/local_discovery/privetv3_session.h36
-rw-r--r--chrome/browser/local_discovery/privetv3_session_unittest.cc59
-rw-r--r--chrome/browser/local_discovery/privetv3_setup_flow.cc136
-rw-r--r--chrome/browser/local_discovery/privetv3_setup_flow.h21
-rw-r--r--chrome/browser/local_discovery/privetv3_setup_flow_unittest.cc185
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