Commit 18d64ecb authored by noamsml's avatar noamsml Committed by Commit bot

API change to allow sticker authentication for devices

Change API to match protocol that may allow sticker authentication
for devices. The PIN will not necessarily be available at provision
time, and the client will need to send a user-typed PIN at
code verification time.

BUG=

Review URL: https://codereview.chromium.org/468613003

Cr-Commit-Position: refs/heads/master@{#291988}
parent 6b6cd502
......@@ -124,7 +124,9 @@ class GcdPrivateAPIImpl : public EventRouter::Observer,
int port,
ConfirmationCodeCallback callback);
void ConfirmCode(int session_id, SessionEstablishedCallback callback);
void ConfirmCode(int session_id,
const std::string& code,
SessionEstablishedCallback callback);
void SendMessage(int session_id,
const std::string& api,
......@@ -229,6 +231,7 @@ class GcdPrivateSessionHolder
void Start(const ConfirmationCodeCallback& callback);
void ConfirmCode(
const std::string& code,
const GcdPrivateAPIImpl::SessionEstablishedCallback& callback);
void SendMessage(const std::string& api,
......@@ -240,9 +243,9 @@ class GcdPrivateSessionHolder
private:
// local_discovery::PrivetV3Session::Delegate implementation.
virtual void OnSetupConfirmationNeeded(
const std::string& confirmation_code) OVERRIDE;
virtual void OnSessionEstablished() OVERRIDE;
virtual void OnCannotEstablishSession() OVERRIDE;
const std::string& confirmation_code,
api::gcd_private::ConfirmationType confirmation_type) OVERRIDE;
virtual void OnSessionStatus(api::gcd_private::Status status) OVERRIDE;
scoped_ptr<local_discovery::PrivetHTTPClient> http_client_;
scoped_ptr<local_discovery::PrivetV3Session> privet_session_;
......@@ -371,6 +374,7 @@ void GcdPrivateAPIImpl::EstablishSession(const std::string& ip_address,
}
void GcdPrivateAPIImpl::ConfirmCode(int session_id,
const std::string& code,
SessionEstablishedCallback callback) {
GCDSessionMap::iterator found = sessions_.find(session_id);
......@@ -379,7 +383,7 @@ void GcdPrivateAPIImpl::ConfirmCode(int session_id,
return;
}
found->second->ConfirmCode(callback);
found->second->ConfirmCode(code, callback);
}
void GcdPrivateAPIImpl::SendMessage(int session_id,
......@@ -551,9 +555,10 @@ void GcdPrivateSessionHolder::Start(const ConfirmationCodeCallback& callback) {
}
void GcdPrivateSessionHolder::ConfirmCode(
const std::string& code,
const GcdPrivateAPIImpl::SessionEstablishedCallback& callback) {
session_established_callback_ = callback;
privet_session_->ConfirmCode();
privet_session_->ConfirmCode(code);
}
void GcdPrivateSessionHolder::SendMessage(
......@@ -578,22 +583,16 @@ void GcdPrivateSessionHolder::DeleteRequest(GcdPrivateRequest* request) {
}
void GcdPrivateSessionHolder::OnSetupConfirmationNeeded(
const std::string& confirmation_code) {
confirm_callback_.Run(gcd_private::STATUS_SUCCESS,
confirmation_code,
gcd_private::CONFIRMATION_TYPE_DISPLAYCODE);
const std::string& confirmation_code,
gcd_private::ConfirmationType confirmation_type) {
confirm_callback_.Run(
gcd_private::STATUS_SUCCESS, confirmation_code, confirmation_type);
confirm_callback_.Reset();
}
void GcdPrivateSessionHolder::OnSessionEstablished() {
session_established_callback_.Run(gcd_private::STATUS_SUCCESS);
session_established_callback_.Reset();
}
void GcdPrivateSessionHolder::OnCannotEstablishSession() {
session_established_callback_.Run(gcd_private::STATUS_SESSIONERROR);
void GcdPrivateSessionHolder::OnSessionStatus(gcd_private::Status status) {
session_established_callback_.Run(status);
session_established_callback_.Reset();
}
......@@ -774,8 +773,15 @@ void GcdPrivateEstablishSessionFunction::OnConfirmCodeCallback(
gcd_private::Status status,
const std::string& confirm_code,
gcd_private::ConfirmationType confirmation_type) {
results_ = gcd_private::EstablishSession::Results::Create(
session_id, status, confirm_code, confirmation_type);
gcd_private::ConfirmationInfo info;
info.type = confirmation_type;
if (!confirm_code.empty()) {
info.code.reset(new std::string(confirm_code));
}
results_ =
gcd_private::EstablishSession::Results::Create(session_id, status, info);
SendResponse(true);
}
......@@ -796,6 +802,7 @@ bool GcdPrivateConfirmCodeFunction::RunAsync() {
gcd_api->ConfirmCode(
params->session_id,
params->code,
base::Bind(&GcdPrivateConfirmCodeFunction::OnSessionEstablishedCallback,
this));
......
......@@ -16,6 +16,8 @@ namespace {
const char kUrlPlaceHolder[] = "http://host/";
const char kStubPrivetCode[] = "01234";
GURL CreatePrivetURL(const std::string& path) {
GURL url(kUrlPlaceHolder);
GURL::Replacements replacements;
......@@ -105,9 +107,14 @@ void PrivetV3Session::Start() {
base::TimeDelta::FromSeconds(1));
}
void PrivetV3Session::ConfirmCode() {
code_confirmed_ = true;
delegate_->OnSessionEstablished();
void PrivetV3Session::ConfirmCode(const std::string& code) {
if (code == kStubPrivetCode) {
code_confirmed_ = true;
delegate_->OnSessionStatus(extensions::api::gcd_private::STATUS_SUCCESS);
} else {
delegate_->OnSessionStatus(
extensions::api::gcd_private::STATUS_BADCONFIRMATIONCODEERROR);
}
}
void PrivetV3Session::StartRequest(Request* request) {
......@@ -130,7 +137,9 @@ void PrivetV3Session::StartRequest(Request* request) {
}
void PrivetV3Session::ConfirmFakeCode() {
delegate_->OnSetupConfirmationNeeded("01234");
delegate_->OnSetupConfirmationNeeded(
kStubPrivetCode,
extensions::api::gcd_private::CONFIRMATION_TYPE_DISPLAYCODE);
}
} // namespace local_discovery
......@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/local_discovery/privet_url_fetcher.h"
#include "chrome/common/extensions/api/gcd_private.h"
namespace base {
class DictionaryValue;
......@@ -32,14 +33,11 @@ class PrivetV3Session {
// Called when client code should prompt user to check |confirmation_code|.
virtual void OnSetupConfirmationNeeded(
const std::string& confirmation_code) = 0;
const std::string& confirmation_code,
extensions::api::gcd_private::ConfirmationType confirmation_type) = 0;
// Called when session successfully establish and client code my call
// |CreateRequest| method.
virtual void OnSessionEstablished() = 0;
// Called when session setup fails.
virtual void OnCannotEstablishSession() = 0;
virtual void OnSessionStatus(
extensions::api::gcd_private::Status status) = 0;
};
// Represents request in progress using secure session.
......@@ -66,7 +64,7 @@ class PrivetV3Session {
// |OnSessionEstablished|.
void Start();
void ConfirmCode();
void ConfirmCode(const std::string& code);
// Create a single /privet/v3/session/call request.
void StartRequest(Request* request);
......
......@@ -21,9 +21,10 @@ using testing::_;
class MockDelegate : public PrivetV3Session::Delegate {
public:
MOCK_METHOD1(OnSetupConfirmationNeeded, void(const std::string&));
MOCK_METHOD0(OnSessionEstablished, void());
MOCK_METHOD0(OnCannotEstablishSession, void());
MOCK_METHOD2(OnSetupConfirmationNeeded,
void(const std::string&,
extensions::api::gcd_private::ConfirmationType));
MOCK_METHOD1(OnSessionStatus, void(extensions::api::gcd_private::Status));
};
class PrivetV3SessionTest : public testing::Test {
......@@ -37,12 +38,16 @@ class PrivetV3SessionTest : public testing::Test {
base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure_);
}
void ConfirmCode(const std::string& code,
extensions::api::gcd_private::ConfirmationType type) {
session_.ConfirmCode(code);
}
protected:
virtual void SetUp() OVERRIDE {
quit_closure_ = run_loop_.QuitClosure();
EXPECT_CALL(delegate_, OnSetupConfirmationNeeded(_)).Times(0);
EXPECT_CALL(delegate_, OnSessionEstablished()).Times(0);
EXPECT_CALL(delegate_, OnCannotEstablishSession()).Times(0);
EXPECT_CALL(delegate_, OnSetupConfirmationNeeded(_, _)).Times(0);
EXPECT_CALL(delegate_, OnSessionStatus(_)).Times(0);
}
StrictMock<MockDelegate> delegate_;
......@@ -53,17 +58,19 @@ class PrivetV3SessionTest : public testing::Test {
};
TEST_F(PrivetV3SessionTest, NotConfirmed) {
EXPECT_CALL(delegate_, OnSetupConfirmationNeeded(_)).Times(1).WillOnce(
EXPECT_CALL(delegate_, OnSetupConfirmationNeeded(_, _)).Times(1).WillOnce(
InvokeWithoutArgs(this, &PrivetV3SessionTest::QuitLoop));
session_.Start();
run_loop_.Run();
}
TEST_F(PrivetV3SessionTest, Confirmed) {
EXPECT_CALL(delegate_, OnSessionEstablished()).Times(1).WillOnce(
InvokeWithoutArgs(this, &PrivetV3SessionTest::QuitLoop));
EXPECT_CALL(delegate_, OnSetupConfirmationNeeded(_)).Times(1).WillOnce(
InvokeWithoutArgs(&session_, &PrivetV3Session::ConfirmCode));
EXPECT_CALL(delegate_,
OnSessionStatus(extensions::api::gcd_private::STATUS_SUCCESS))
.Times(1)
.WillOnce(InvokeWithoutArgs(this, &PrivetV3SessionTest::QuitLoop));
EXPECT_CALL(delegate_, OnSetupConfirmationNeeded(_, _)).Times(1).WillOnce(
Invoke(this, &PrivetV3SessionTest::ConfirmCode));
session_.Start();
run_loop_.Run();
}
......
......@@ -109,19 +109,22 @@ void PrivetV3SetupFlow::SetupWifiAndRegister(const std::string& device_ssid) {
#endif // ENABLE_WIFI_BOOTSTRAPPING
void PrivetV3SetupFlow::OnSetupConfirmationNeeded(
const std::string& confirmation_code) {
const std::string& confirmation_code,
extensions::api::gcd_private::ConfirmationType confirmation_type) {
delegate_->ConfirmSecurityCode(confirmation_code,
base::Bind(&PrivetV3SetupFlow::OnCodeConfirmed,
weak_ptr_factory_.GetWeakPtr()));
weak_ptr_factory_.GetWeakPtr(),
confirmation_code));
}
void PrivetV3SetupFlow::OnSessionEstablished() {
DCHECK(setup_request_);
session_->StartRequest(setup_request_.get());
}
void PrivetV3SetupFlow::OnCannotEstablishSession() {
OnSetupError();
void PrivetV3SetupFlow::OnSessionStatus(
extensions::api::gcd_private::Status status) {
if (status == extensions::api::gcd_private::STATUS_SUCCESS) {
DCHECK(setup_request_);
session_->StartRequest(setup_request_.get());
} else {
OnSetupError();
}
}
void PrivetV3SetupFlow::OnSetupError() {
......@@ -159,10 +162,10 @@ void PrivetV3SetupFlow::OnPrivetClientCreated(
session_->Start();
}
void PrivetV3SetupFlow::OnCodeConfirmed(bool success) {
void PrivetV3SetupFlow::OnCodeConfirmed(const std::string& code, bool success) {
if (!success)
return OnSetupError();
session_->ConfirmCode();
session_->ConfirmCode(code);
}
} // namespace local_discovery
......@@ -73,9 +73,11 @@ class PrivetV3SetupFlow : public PrivetV3Session::Delegate {
// PrivetV3Session::Delegate implementation.
virtual void OnSetupConfirmationNeeded(
const std::string& confirmation_code) OVERRIDE;
virtual void OnSessionEstablished() OVERRIDE;
virtual void OnCannotEstablishSession() OVERRIDE;
const std::string& confirmation_code,
extensions::api::gcd_private::ConfirmationType confirmation_type)
OVERRIDE;
virtual void OnSessionStatus(
extensions::api::gcd_private::Status status) OVERRIDE;
void OnSetupError();
void OnDeviceRegistered();
......@@ -86,7 +88,7 @@ class PrivetV3SetupFlow : public PrivetV3Session::Delegate {
void OnTicketCreated(const std::string& ticket_id,
const std::string& device_id);
void OnPrivetClientCreated(scoped_ptr<PrivetHTTPClient> privet_http_client);
void OnCodeConfirmed(bool success);
void OnCodeConfirmed(const std::string& code, bool success);
Delegate* delegate_;
std::string service_name_;
......
......@@ -46,13 +46,25 @@ namespace gcdPrivate {
// Unknown session.
unknownSessionError,
// Bad confirmation code. Ask user to retype.
badConfirmationCodeError,
// Success.
success
};
enum ConfirmationType {
displayCode,
audio
stickerCode
};
// Information regarding the confirmation of a device.
dictionary ConfirmationInfo {
// Type of confirmation.
ConfirmationType type;
// Code if available.
DOMString? code;
};
callback CloudDeviceListCallback = void(GCDDevice[] devices);
......@@ -75,12 +87,10 @@ namespace gcdPrivate {
// Called when the confirmation code is available or on error.
// |sessionId| is the session ID (identifies the session for future calls)
// |status| is the status (success or type of error)
// |code| is the confirmation code or empty on error
// |confirmationType| is the type of confirmation required
// |confirmation| is the information about the confirmation.
callback ConfirmationCodeCallback = void(long sessionId,
Status status,
DOMString code,
ConfirmationType type);
ConfirmationInfo confirmation);
// Called to indicated the session is established.
// |status| is the status (success or type of error)
......@@ -124,8 +134,11 @@ namespace gcdPrivate {
long port,
ConfirmationCodeCallback callback);
// Confirm that the code is correct. Device will still need to confirm.
// Send confirmation code. Device will still need to confirm. |code| must be
// present and must match the code from the device, even when the code is
// supplied in the |ConfirmationInfo| object.
static void confirmCode(long sessionId,
DOMString code,
SessionEstablishedCallback callback);
// Send an encrypted message to the device. |api| is the API path and
......
......@@ -5,10 +5,13 @@
onload = function() {
chrome.test.runTests([
function session() {
function onConfirmCode(sessionId, status, code, method) {
function onConfirmCode(sessionId, status, confirmationInfo) {
chrome.test.assertEq("success", status);
chrome.test.assertEq("01234", code);
chrome.test.assertEq("01234", confirmationInfo.code);
chrome.test.assertEq("displayCode", confirmationInfo.type);
chrome.gcdPrivate.confirmCode(sessionId,
"01234",
onSessionEstablished.bind(null,
sessionId));
}
......
......@@ -6,10 +6,11 @@ onload = function() {
chrome.test.runTests([
function wifiMessage() {
var messages_needed = 3;
function onConfirmCode(sessionId, status, code, method) {
function onConfirmCode(sessionId, status, confirmation) {
chrome.test.assertEq("success", status);
chrome.test.assertEq("01234", code);
chrome.test.assertEq("01234", confirmation.code);
chrome.gcdPrivate.confirmCode(sessionId,
confirmation.code,
onSessionEstablished.bind(null,
sessionId));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment