Implement privet properties for changing cloud print endpoints

BUG:23907593
BUG:26525138
Change-Id: I377a3f6bf114a9ca04c56e19f90f970f5bcdd3f8
Reviewed-on: https://weave-review.googlesource.com/2591
Reviewed-by: Alex Vakulenko <avakulenko@google.com>
diff --git a/src/privet/cloud_delegate.cc b/src/privet/cloud_delegate.cc
index 3266ef9..0b4400f 100644
--- a/src/privet/cloud_delegate.cc
+++ b/src/privet/cloud_delegate.cc
@@ -139,6 +139,18 @@
                : "";
   }
 
+  std::string GetOAuthUrl() const override {
+    return device_->GetSettings().oauth_url;
+  }
+
+  std::string GetServiceUrl() const override {
+    return device_->GetSettings().service_url;
+  }
+
+  std::string GetXmppEndpoint() const override {
+    return device_->GetSettings().xmpp_endpoint;
+  }
+
   const base::DictionaryValue& GetLegacyCommandDef() const override {
     return component_manager_->GetLegacyCommandDefinitions();
   }
diff --git a/src/privet/cloud_delegate.h b/src/privet/cloud_delegate.h
index 01d2c30..37ed723 100644
--- a/src/privet/cloud_delegate.h
+++ b/src/privet/cloud_delegate.h
@@ -95,6 +95,11 @@
   // Returns cloud id if the registered device or empty string if unregistered.
   virtual std::string GetCloudId() const = 0;
 
+  // Returns currently active cloud endponts.
+  virtual std::string GetOAuthUrl() const = 0;
+  virtual std::string GetServiceUrl() const = 0;
+  virtual std::string GetXmppEndpoint() const = 0;
+
   // Returns dictionary with device state (for legacy APIs).
   virtual const base::DictionaryValue& GetLegacyState() const = 0;
 
diff --git a/src/privet/mock_delegates.h b/src/privet/mock_delegates.h
index 5b5bd2f..108e450 100644
--- a/src/privet/mock_delegates.h
+++ b/src/privet/mock_delegates.h
@@ -185,6 +185,9 @@
   MOCK_CONST_METHOD0(GetSetupState, const SetupState&());
   MOCK_METHOD2(Setup, bool(const RegistrationData&, ErrorPtr*));
   MOCK_CONST_METHOD0(GetCloudId, std::string());
+  MOCK_CONST_METHOD0(GetOAuthUrl, std::string());
+  MOCK_CONST_METHOD0(GetServiceUrl, std::string());
+  MOCK_CONST_METHOD0(GetXmppEndpoint, std::string());
   MOCK_CONST_METHOD0(GetLegacyState, const base::DictionaryValue&());
   MOCK_CONST_METHOD0(GetLegacyCommandDef, const base::DictionaryValue&());
   MOCK_CONST_METHOD0(GetComponents, const base::DictionaryValue&());
@@ -208,6 +211,10 @@
 
   MockCloudDelegate() {
     EXPECT_CALL(*this, GetDeviceId()).WillRepeatedly(Return("TestId"));
+    EXPECT_CALL(*this, GetOAuthUrl()).WillRepeatedly(Return("https://oauths/"));
+    EXPECT_CALL(*this, GetServiceUrl())
+        .WillRepeatedly(Return("https://service/"));
+    EXPECT_CALL(*this, GetXmppEndpoint()).WillRepeatedly(Return("xmpp:678"));
     EXPECT_CALL(*this, GetModelId()).WillRepeatedly(Return("ABMID"));
     EXPECT_CALL(*this, GetName()).WillRepeatedly(Return("TestDevice"));
     EXPECT_CALL(*this, GetDescription()).WillRepeatedly(Return(""));
diff --git a/src/privet/privet_handler.cc b/src/privet/privet_handler.cc
index 517c60f..05b6e0a 100644
--- a/src/privet/privet_handler.cc
+++ b/src/privet/privet_handler.cc
@@ -99,6 +99,19 @@
 const char kSetupStartPassKey[] = "passphrase";
 const char kSetupStartTicketIdKey[] = "ticketId";
 const char kSetupStartUserKey[] = "user";
+const char kSetupStartClientIdKey[] = "client_id";
+const char kSetupStartClientSecretKey[] = "client_secret";
+const char kSetupStartApiKeyKey[] = "api_key";
+const char kSetupStartOAuthUrlKey[] = "oauth_url";
+const char kSetupStartServiceUrlKey[] = "service_url";
+const char kSetupStartXmppEndpointKey[] = "xmpp_endpoint";
+
+std::string oauth_url;
+std::string client_id;
+std::string client_secret;
+std::string api_key;
+std::string service_url;
+std::string xmpp_endpoint;
 
 const char kFingerprintKey[] = "fingerprint";
 const char kStateKey[] = "state";
@@ -286,10 +299,17 @@
   return result;
 }
 
+void SetGcdProperties(const CloudDelegate& cloud, base::DictionaryValue* dict) {
+  dict->SetString(kInfoIdKey, cloud.GetCloudId());
+  dict->SetString(kSetupStartOAuthUrlKey, cloud.GetOAuthUrl());
+  dict->SetString(kSetupStartServiceUrlKey, cloud.GetServiceUrl());
+  dict->SetString(kSetupStartXmppEndpointKey, cloud.GetXmppEndpoint());
+}
+
 std::unique_ptr<base::DictionaryValue> CreateGcdSection(
     const CloudDelegate& cloud) {
   std::unique_ptr<base::DictionaryValue> gcd(new base::DictionaryValue());
-  gcd->SetString(kInfoIdKey, cloud.GetCloudId());
+  SetGcdProperties(cloud, gcd.get());
   SetStateProperties(cloud.GetConnectionState(), gcd.get());
   return gcd;
 }
@@ -757,7 +777,7 @@
 
   std::string ssid;
   std::string passphrase;
-  std::string ticket;
+  RegistrationData registration_data;
   std::string user;
 
   const base::DictionaryValue* wifi = nullptr;
@@ -786,14 +806,26 @@
                    "Only owner can register device");
       return ReturnError(*error, callback);
     }
-    registration->GetString(kSetupStartTicketIdKey, &ticket);
-    if (ticket.empty()) {
+    registration->GetString(kSetupStartTicketIdKey,
+                            &registration_data.ticket_id);
+    if (registration_data.ticket_id.empty()) {
       ErrorPtr error;
       Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidParams,
                          kInvalidParamValueFormat, kSetupStartTicketIdKey, "");
       return ReturnError(*error, callback);
     }
     registration->GetString(kSetupStartUserKey, &user);
+    registration->GetString(kSetupStartClientIdKey,
+                            &registration_data.client_id);
+    registration->GetString(kSetupStartClientSecretKey,
+                            &registration_data.client_secret);
+    registration->GetString(kSetupStartApiKeyKey, &registration_data.api_key);
+    registration->GetString(kSetupStartOAuthUrlKey,
+                            &registration_data.oauth_url);
+    registration->GetString(kSetupStartServiceUrlKey,
+                            &registration_data.service_url);
+    registration->GetString(kSetupStartXmppEndpointKey,
+                            &registration_data.xmpp_endpoint);
   }
 
   cloud_->UpdateDeviceInfo(name, description, location);
@@ -802,7 +834,8 @@
   if (!ssid.empty() && !wifi_->ConfigureCredentials(ssid, passphrase, &error))
     return ReturnError(*error, callback);
 
-  if (!ticket.empty() && !cloud_->Setup(RegistrationData{ticket}, &error))
+  if (!registration_data.ticket_id.empty() &&
+      !cloud_->Setup(registration_data, &error))
     return ReturnError(*error, callback);
 
   ReplyWithSetupStatus(callback);
@@ -823,8 +856,9 @@
     base::DictionaryValue* gcd = new base::DictionaryValue;
     output.Set(kGcdKey, gcd);
     SetStateProperties(state, gcd);
-    if (state.IsStatusEqual(SetupState::kSuccess))
-      gcd->SetString(kInfoIdKey, cloud_->GetCloudId());
+    if (state.IsStatusEqual(SetupState::kSuccess)) {
+      SetGcdProperties(*cloud_, gcd);
+    }
   }
 
   if (wifi_) {
diff --git a/src/privet/privet_handler_unittest.cc b/src/privet/privet_handler_unittest.cc
index 9e900df..22a8b8a 100644
--- a/src/privet/privet_handler_unittest.cc
+++ b/src/privet/privet_handler_unittest.cc
@@ -219,37 +219,40 @@
       .WillRepeatedly(Return(std::set<AuthType>{}));
 
   const char kExpected[] = R"({
-    'version': '3.0',
-    'id': 'TestId',
-    'name': 'TestDevice',
-    'services': [ "developmentBoard" ],
-    'modelManifestId': "ABMID",
-    'basicModelManifest': {
-      'uiDeviceKind': 'developmentBoard',
-      'oemName': 'Chromium',
-      'modelName': 'Brillo'
+    "version": "3.0",
+    "id": "TestId",
+    "name": "TestDevice",
+    "services": [ "developmentBoard" ],
+    "modelManifestId": "ABMID",
+    "basicModelManifest": {
+      "uiDeviceKind": "developmentBoard",
+      "oemName": "Chromium",
+      "modelName": "Brillo"
     },
-    'endpoints': {
-      'httpPort': 0,
-      'httpUpdatesPort': 0,
-      'httpsPort': 0,
-      'httpsUpdatesPort': 0
+    "endpoints": {
+      "httpPort": 0,
+      "httpUpdatesPort": 0,
+      "httpsPort": 0,
+      "httpsUpdatesPort": 0
     },
-    'authentication': {
-      'anonymousMaxScope': 'user',
-      'mode': [
+    "authentication": {
+      "anonymousMaxScope": "user",
+      "mode": [
       ],
-      'pairing': [
+      "pairing": [
       ],
-      'crypto': [
+      "crypto": [
       ]
     },
-    'gcd': {
-      'id': '',
-      'status': 'disabled'
+    "gcd": {
+      "id": "",
+      "oauth_url": "https://oauths/",
+      "service_url": "https://service/",
+      "status": "disabled",
+      "xmpp_endpoint": "xmpp:678"
     },
-    'time': 1410000001000.0,
-    'sessionId': 'SessionId'
+    "time": 1410000001000.0,
+    "sessionId": "SessionId"
   })";
   EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/info", "{}"));
 }
@@ -266,53 +269,56 @@
       .WillRepeatedly(Return("Test_device.BBABCLAprv"));
 
   const char kExpected[] = R"({
-    'version': '3.0',
-    'id': 'TestId',
-    'name': 'TestDevice',
-    'description': 'TestDescription',
-    'location': 'TestLocation',
-    'services': [ "developmentBoard" ],
-    'modelManifestId': "ABMID",
-    'basicModelManifest': {
-      'uiDeviceKind': 'developmentBoard',
-      'oemName': 'Chromium',
-      'modelName': 'Brillo'
+    "version": "3.0",
+    "id": "TestId",
+    "name": "TestDevice",
+    "description": "TestDescription",
+    "location": "TestLocation",
+    "services": [ "developmentBoard" ],
+    "modelManifestId": "ABMID",
+    "basicModelManifest": {
+      "uiDeviceKind": "developmentBoard",
+      "oemName": "Chromium",
+      "modelName": "Brillo"
     },
-    'endpoints': {
-      'httpPort': 80,
-      'httpUpdatesPort': 10080,
-      'httpsPort': 443,
-      'httpsUpdatesPort': 10443
+    "endpoints": {
+      "httpPort": 80,
+      "httpUpdatesPort": 10080,
+      "httpsPort": 443,
+      "httpsUpdatesPort": 10443
     },
-    'authentication': {
-      'anonymousMaxScope': 'none',
-      'mode': [
-        'anonymous',
-        'pairing',
-        'local'
+    "authentication": {
+      "anonymousMaxScope": "none",
+      "mode": [
+        "anonymous",
+        "pairing",
+        "local"
       ],
-      'pairing': [
-        'pinCode',
-        'embeddedCode'
+      "pairing": [
+        "pinCode",
+        "embeddedCode"
       ],
-      'crypto': [
-        'p224_spake2'
+      "crypto": [
+        "p224_spake2"
       ]
     },
-    'wifi': {
-      'capabilities': [
-        '2.4GHz'
+    "wifi": {
+      "capabilities": [
+        "2.4GHz"
       ],
-      'ssid': 'TestSsid',
-      'hostedSsid': 'Test_device.BBABCLAprv',
-      'status': 'offline'
+      "ssid": "TestSsid",
+      "hostedSsid": "Test_device.BBABCLAprv",
+      "status": "offline"
     },
-    'gcd': {
-      'id': 'TestCloudId',
-      'status': 'online'
+    "gcd": {
+      "id": "TestCloudId",
+      "oauth_url": "https://oauths/",
+      "service_url": "https://service/",
+      "status": "online",
+      "xmpp_endpoint": "xmpp:678"
     },
-    'time': 1410000001000.0,
-    'sessionId': 'SessionId'
+    "time": 1410000001000.0,
+    "sessionId": "SessionId"
   })";
   EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/info", "{}"));
 }
@@ -530,9 +536,12 @@
   cloud_.setup_state_ = SetupState{SetupState::kSuccess};
 
   const char kExpected[] = R"({
-    'gcd': {
-        'id': 'TestCloudId',
-        'status': 'success'
+    "gcd": {
+        "id": "TestCloudId",
+        "oauth_url": "https://oauths/",
+        "service_url": "https://service/",
+        "status": "success",
+        "xmpp_endpoint": "xmpp:678"
      }
   })";
   EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/setup/status", "{}"));
@@ -656,6 +665,41 @@
   EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/setup/start", kInput));
 }
 
+TEST_F(PrivetHandlerSetupTest, GcdSetupWithEndpoints) {
+  const char kInput[] = R"({
+    'gcd': {
+      "api_key": "test_api_key",
+      "client_id": "test_client_id",
+      "client_secret": "test_client_secret",
+      "oauth_url": "https://oauths/",
+      "service_url": "https://service/",
+      "status": "success",
+      "xmpp_endpoint": "xmpp:678",
+      "ticketId": "testTicket",
+      "user": "testUser"
+    }
+  })";
+
+  const char kExpected[] = R"({
+    'gcd': {
+      'status': 'inProgress'
+    }
+  })";
+  cloud_.setup_state_ = SetupState{SetupState::kInProgress};
+
+  RegistrationData expected_reg_data;
+  expected_reg_data.ticket_id = "testTicket";
+  expected_reg_data.oauth_url = "https://oauths/";
+  expected_reg_data.client_id = "test_client_id";
+  expected_reg_data.client_secret = "test_client_secret";
+  expected_reg_data.api_key = "test_api_key";
+  expected_reg_data.service_url = "https://service/";
+  expected_reg_data.xmpp_endpoint = "xmpp:678";
+
+  EXPECT_CALL(cloud_, Setup(expected_reg_data, _)).WillOnce(Return(true));
+  EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/setup/start", kInput));
+}
+
 TEST_F(PrivetHandlerSetupTest, GcdSetupAsMaster) {
   EXPECT_CALL(security_, ParseAccessToken(_, _, _))
       .WillRepeatedly(DoAll(