| // Copyright 2014 The Chromium OS 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 "privetd/privet_handler.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/bind.h> |
| #include <base/values.h> |
| #include <chromeos/http/http_request.h> |
| #include <chromeos/strings/string_utils.h> |
| |
| #include "privetd/cloud_delegate.h" |
| #include "privetd/device_delegate.h" |
| #include "privetd/security_delegate.h" |
| #include "privetd/wifi_delegate.h" |
| |
| namespace privetd { |
| |
| namespace { |
| |
| const char kInfoApiPath[] = "/privet/info"; |
| const char kPairingStartApiPath[] = "/privet/v3/pairing/start"; |
| const char kPairingConfirmApiPath[] = "/privet/v3/pairing/confirm"; |
| const char kPairingCancelApiPath[] = "/privet/v3/pairing/cancel"; |
| const char kAuthApiPath[] = "/privet/v3/auth"; |
| const char kSetupStartApiPath[] = "/privet/v3/setup/start"; |
| const char kSetupStatusApiPath[] = "/privet/v3/setup/status"; |
| |
| const char kInfoVersionKey[] = "version"; |
| const char kInfoVersionValue[] = "3.0"; |
| |
| const char kNameKey[] = "name"; |
| const char kDescrptionKey[] = "description"; |
| const char kLocationKey[] = "location"; |
| |
| const char kGcdKey[] = "gcd"; |
| const char kWifiKey[] = "wifi"; |
| const char kStatusKey[] = "status"; |
| const char kErrorKey[] = "error"; |
| const char kCryptoKey[] = "crypto"; |
| |
| const char kInfoIdKey[] = "id"; |
| const char kInfoServicesKey[] = "services"; |
| const char kInfoClassKey[] = "class"; |
| const char kInfoModelIdKey[] = "modelId"; |
| |
| const char kInfoEndpointsKey[] = "endpoints"; |
| const char kInfoEndpointsHttpPortKey[] = "httpPort"; |
| const char kInfoEndpointsHttpUpdatePortKey[] = "httpUpdatesPort"; |
| const char kInfoEndpointsHttpsPortKey[] = "httpsPort"; |
| const char kInfoEndpointsHttpsUpdatePortKey[] = "httpsUpdatesPort"; |
| |
| const char kInfoAuthenticationKey[] = "authentication"; |
| |
| const char kInfoWifiCapabilitiesKey[] = "capabilities"; |
| const char kInfoWifiSsidKey[] = "ssid"; |
| const char kInfoWifiHostedSsidKey[] = "hostedSsid"; |
| |
| const char kInfoUptimeKey[] = "uptime"; |
| const char kInfoApiKey[] = "api"; |
| |
| const char kPairingKey[] = "pairing"; |
| const char kPairingSessionIdKey[] = "sessionId"; |
| const char kPairingDeviceCommitmentKey[] = "deviceCommitment"; |
| const char kPairingClientCommitmentKey[] = "clientCommitment"; |
| const char kPairingFingerprintKey[] = "certFingerprint"; |
| const char kPairingSignatureKey[] = "certSignature"; |
| |
| const char kAuthTypeAnonymousValue[] = "anonymous"; |
| const char kAuthTypePairingValue[] = "pairing"; |
| const char kAuthTypeCloudValue[] = "cloud"; |
| |
| const char kAuthModeKey[] = "mode"; |
| const char kAuthCodeKey[] = "authCode"; |
| const char kAuthRequestedScopeKey[] = "requestedScope"; |
| const char kAuthScopeAutoValue[] = "auto"; |
| |
| const char kAuthAccessTokenKey[] = "accessToken"; |
| const char kAuthTokenTypeKey[] = "tokenType"; |
| const char kAuthExpiresInKey[] = "expiresIn"; |
| const char kAuthScopeKey[] = "scope"; |
| |
| const char kAuthorizationHeaderPrefix[] = "Privet"; |
| const char kErrorReasonKey[] = "reason"; |
| const char kErrorMessageKey[] = "message"; |
| |
| const char kSetupStartSsidKey[] = "ssid"; |
| const char kSetupStartPassKey[] = "passphrase"; |
| const char kSetupStartTicketIdKey[] = "ticketId"; |
| const char kSetupStartUserKey[] = "user"; |
| |
| const int kAccesssTokenExpirationSeconds = 3600; |
| |
| // Threshold to reduce probability of expiration because of clock difference |
| // between device and client. Value is just a guess. |
| const int kAccesssTokenExpirationThresholdSeconds = 300; |
| |
| std::unique_ptr<base::ListValue> ToValue(const std::vector<std::string> list) { |
| std::unique_ptr<base::ListValue> value_list(new base::ListValue()); |
| for (const std::string& val : list) |
| value_list->AppendString(val); |
| return std::move(value_list); |
| } |
| |
| template <typename T> |
| class EnumToStringMap { |
| public: |
| static std::string FindNameById(T id) { |
| for (const Map& m : kMap) { |
| if (m.id == id) { |
| CHECK(m.name); |
| return m.name; |
| } |
| } |
| NOTREACHED(); |
| return std::string(); |
| } |
| |
| static bool FindIdByName(const std::string& name, T* id) { |
| for (const Map& m : kMap) { |
| if (m.name && m.name == name) { |
| *id = m.id; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private: |
| struct Map { |
| const T id; |
| const char* const name; |
| }; |
| static const Map kMap[]; |
| }; |
| |
| template <> |
| const EnumToStringMap<ConnectionState::Status>::Map |
| EnumToStringMap<ConnectionState::Status>::kMap[] = { |
| {ConnectionState::kDisabled, "disabled"}, |
| {ConnectionState::kUnconfigured, "unconfigured"}, |
| {ConnectionState::kConnecting, "connecting"}, |
| {ConnectionState::kOnline, "online"}, |
| {ConnectionState::kOffline, "offline"}, |
| {ConnectionState::kError, "error"}, |
| }; |
| |
| template <> |
| const EnumToStringMap<SetupState::Status>::Map |
| EnumToStringMap<SetupState::Status>::kMap[] = { |
| {SetupState::kNone, nullptr}, |
| {SetupState::kInProgress, "inProgress"}, |
| {SetupState::kSuccess, "success"}, |
| {SetupState::kError, "error"}, |
| }; |
| |
| template <> |
| const EnumToStringMap<Error>::Map EnumToStringMap<Error>::kMap[] = { |
| {Error::kNone, nullptr}, |
| {Error::kInvalidFormat, "invalidFormat"}, |
| {Error::kMissingAuthorization, "missingAuthorization"}, |
| {Error::kInvalidAuthorization, "invalidAuthorization"}, |
| {Error::kInvalidAuthorizationScope, "invalidAuthorizationScope"}, |
| {Error::kCommitmentMismatch, "commitmentMismatch"}, |
| {Error::kUnknownSession, "unknownSession"}, |
| {Error::kInvalidAuthCode, "invalidAuthCode"}, |
| {Error::kInvalidAuthMode, "invalidAuthMode"}, |
| {Error::kInvalidRequestedScope, "invalidRequestedScope"}, |
| {Error::kAccessDenied, "accessDenied"}, |
| {Error::kInvalidParams, "invalidParams"}, |
| {Error::kSetupUnavailable, "setupUnavailable"}, |
| {Error::kDeviceBusy, "deviceBusy"}, |
| {Error::kInvalidTicket, "invalidTicket"}, |
| {Error::kServerError, "serverError"}, |
| {Error::kDeviceConfigError, "deviceConfigError"}, |
| {Error::kInvalidSsid, "invalidSsid"}, |
| {Error::kInvalidPassphrase, "invalidPassphrase"}, |
| }; |
| |
| template <> |
| const EnumToStringMap<WifiType>::Map EnumToStringMap<WifiType>::kMap[] = { |
| {WifiType::kWifi24, "2.4GHz"}, |
| {WifiType::kWifi50, "5.0GHz"}, |
| }; |
| |
| template <> |
| const EnumToStringMap<PairingType>::Map EnumToStringMap<PairingType>::kMap[] = { |
| {PairingType::kPinCode, "pinCode"}, |
| {PairingType::kEmbeddedCode, "embeddedCode"}, |
| {PairingType::kUltrasoundDsssBroadcaster, "ultrasoundDsssBroadcaster"}, |
| {PairingType::kAudibleDtmfBroadcaster, "audibleDtmfBroadcaster"}, |
| }; |
| |
| template <> |
| const EnumToStringMap<CryptoType>::Map EnumToStringMap<CryptoType>::kMap[] = { |
| {CryptoType::kNone, "none"}, |
| {CryptoType::kSpake_p224, "p224_spake2"}, |
| {CryptoType::kSpake_p256, "p256_spake2"}, |
| }; |
| |
| template <> |
| const EnumToStringMap<AuthScope>::Map EnumToStringMap<AuthScope>::kMap[] = { |
| {AuthScope::kNone, nullptr}, |
| {AuthScope::kGuest, "guest"}, |
| {AuthScope::kViewer, "viewer"}, |
| {AuthScope::kUser, "user"}, |
| {AuthScope::kOwner, "owner"}, |
| }; |
| |
| template <typename T> |
| std::string EnumToString(T id) { |
| return EnumToStringMap<T>::FindNameById(id); |
| } |
| |
| template <typename T> |
| bool StringToEnum(const std::string& name, T* id) { |
| return EnumToStringMap<T>::FindIdByName(name, id); |
| } |
| |
| AuthScope AuthScopeFromString(const std::string& scope, AuthScope auto_scope) { |
| if (scope == kAuthScopeAutoValue) |
| return auto_scope; |
| AuthScope scope_id = AuthScope::kNone; |
| StringToEnum(scope, &scope_id); |
| return scope_id; |
| } |
| |
| std::string GetAuthTokenFromAuthHeader(const std::string& auth_header) { |
| std::string name; |
| std::string value; |
| chromeos::string_utils::SplitAtFirst(auth_header, ' ', &name, &value); |
| return value; |
| } |
| |
| std::unique_ptr<base::DictionaryValue> CreateError(Error error, |
| const std::string& message) { |
| if (error == Error::kNone) |
| return nullptr; |
| std::unique_ptr<base::DictionaryValue> output(new base::DictionaryValue); |
| output->SetString(kErrorReasonKey, EnumToString(error)); |
| if (!message.empty()) |
| output->SetString(kErrorMessageKey, message); |
| return output; |
| } |
| |
| template <class T> |
| void SetState(const T& state, base::DictionaryValue* parent) { |
| parent->SetString(kStatusKey, EnumToString(state.status)); |
| if (state.error == Error::kNone) |
| return; |
| parent->Set(kErrorKey, |
| CreateError(state.error, state.error_message).release()); |
| } |
| |
| void ReturnErrorWithMessage(Error error, |
| const std::string& message, |
| const PrivetHandler::RequestCallback& callback) { |
| std::unique_ptr<base::DictionaryValue> output = CreateError(error, message); |
| callback.Run(chromeos::http::status_code::BadRequest, *output); |
| } |
| |
| void ReturnError(Error error, const PrivetHandler::RequestCallback& callback) { |
| ReturnErrorWithMessage(error, std::string(), callback); |
| } |
| |
| void ReturnNotFound(const PrivetHandler::RequestCallback& callback) { |
| callback.Run(chromeos::http::status_code::NotFound, base::DictionaryValue()); |
| } |
| |
| } // namespace |
| |
| PrivetHandler::PrivetHandler(CloudDelegate* cloud, |
| DeviceDelegate* device, |
| SecurityDelegate* security, |
| WifiDelegate* wifi) |
| : cloud_(cloud), device_(device), security_(security), wifi_(wifi) { |
| handlers_[kInfoApiPath] = std::make_pair( |
| AuthScope::kGuest, |
| base::Bind(&PrivetHandler::HandleInfo, base::Unretained(this))); |
| handlers_[kPairingStartApiPath] = std::make_pair( |
| AuthScope::kGuest, |
| base::Bind(&PrivetHandler::HandlePairingStart, base::Unretained(this))); |
| handlers_[kPairingConfirmApiPath] = std::make_pair( |
| AuthScope::kGuest, |
| base::Bind(&PrivetHandler::HandlePairingConfirm, base::Unretained(this))); |
| handlers_[kPairingCancelApiPath] = std::make_pair( |
| AuthScope::kGuest, |
| base::Bind(&PrivetHandler::HandlePairingCancel, base::Unretained(this))); |
| handlers_[kAuthApiPath] = std::make_pair( |
| AuthScope::kGuest, |
| base::Bind(&PrivetHandler::HandleAuth, base::Unretained(this))); |
| handlers_[kSetupStartApiPath] = std::make_pair( |
| AuthScope::kOwner, |
| base::Bind(&PrivetHandler::HandleSetupStart, base::Unretained(this))); |
| handlers_[kSetupStatusApiPath] = std::make_pair( |
| AuthScope::kOwner, |
| base::Bind(&PrivetHandler::HandleSetupStatus, base::Unretained(this))); |
| } |
| |
| PrivetHandler::~PrivetHandler() { |
| } |
| |
| void PrivetHandler::HandleRequest(const std::string& api, |
| const std::string& auth_header, |
| const base::DictionaryValue* input, |
| const RequestCallback& callback) { |
| if (!input) |
| return ReturnError(Error::kInvalidFormat, callback); |
| auto handler = handlers_.find(api); |
| if (handler == handlers_.end()) |
| return ReturnNotFound(callback); |
| if (auth_header.empty()) |
| return ReturnError(Error::kMissingAuthorization, callback); |
| std::string token = GetAuthTokenFromAuthHeader(auth_header); |
| if (token.empty()) |
| return ReturnError(Error::kInvalidAuthorization, callback); |
| AuthScope scope = AuthScope::kNone; |
| if (token == kAuthTypeAnonymousValue) { |
| scope = AuthScope::kGuest; |
| } else { |
| base::Time time; |
| scope = security_->ParseAccessToken(token, &time); |
| time += base::TimeDelta::FromSeconds(kAccesssTokenExpirationSeconds); |
| time += |
| base::TimeDelta::FromSeconds(kAccesssTokenExpirationThresholdSeconds); |
| if (time < base::Time::Now()) |
| scope = AuthScope::kNone; |
| } |
| if (scope == AuthScope::kNone) |
| return ReturnError(Error::kInvalidAuthorization, callback); |
| if (handler->second.first > scope) |
| return ReturnError(Error::kInvalidAuthorizationScope, callback); |
| handler->second.second.Run(*input, callback); |
| } |
| |
| void PrivetHandler::HandleInfo(const base::DictionaryValue&, |
| const RequestCallback& callback) { |
| base::DictionaryValue output; |
| output.SetString(kInfoVersionKey, kInfoVersionValue); |
| output.SetString(kInfoIdKey, device_->GetId()); |
| output.SetString(kNameKey, device_->GetName()); |
| |
| std::string description{device_->GetDescription()}; |
| if (!description.empty()) |
| output.SetString(kDescrptionKey, description); |
| |
| std::string location{device_->GetLocation()}; |
| if (!location.empty()) |
| output.SetString(kLocationKey, location); |
| |
| std::string dev_class{device_->GetClass()}; |
| CHECK_EQ(2u, dev_class.size()); |
| output.SetString(kInfoClassKey, dev_class); |
| std::string model_id{device_->GetModelId()}; |
| CHECK_EQ(3u, model_id.size()); |
| output.SetString(kInfoModelIdKey, model_id); |
| output.Set(kInfoServicesKey, ToValue(device_->GetServices()).release()); |
| |
| output.Set(kInfoAuthenticationKey, CreateInfoAuthSection().release()); |
| |
| output.Set(kInfoEndpointsKey, CreateEndpointsSection().release()); |
| |
| if (wifi_) |
| output.Set(kWifiKey, CreateWifiSection().release()); |
| |
| if (cloud_) |
| output.Set(kGcdKey, CreateGcdSection().release()); |
| |
| output.SetInteger(kInfoUptimeKey, device_->GetUptime().InSeconds()); |
| |
| std::unique_ptr<base::ListValue> apis(new base::ListValue()); |
| for (const auto& key_value : handlers_) |
| apis->AppendString(key_value.first); |
| output.Set(kInfoApiKey, apis.release()); |
| |
| callback.Run(chromeos::http::status_code::Ok, output); |
| } |
| |
| void PrivetHandler::HandlePairingStart(const base::DictionaryValue& input, |
| const RequestCallback& callback) { |
| std::string pairing_str; |
| input.GetString(kPairingKey, &pairing_str); |
| |
| std::string crypto_str; |
| input.GetString(kCryptoKey, &crypto_str); |
| |
| PairingType pairing; |
| std::vector<PairingType> modes = security_->GetPairingTypes(); |
| if (!StringToEnum(pairing_str, &pairing) || |
| std::find(modes.begin(), modes.end(), pairing) == modes.end()) { |
| return ReturnError(Error::kInvalidParams, callback); |
| } |
| |
| CryptoType crypto; |
| std::vector<CryptoType> cryptos = security_->GetCryptoTypes(); |
| if (!StringToEnum(crypto_str, &crypto) || |
| std::find(cryptos.begin(), cryptos.end(), crypto) == cryptos.end()) { |
| return ReturnError(Error::kInvalidParams, callback); |
| } |
| |
| std::string id; |
| std::string commitment; |
| Error error = security_->StartPairing(pairing, crypto, &id, &commitment); |
| if (error != Error::kNone) |
| return ReturnError(error, callback); |
| |
| base::DictionaryValue output; |
| output.SetString(kPairingSessionIdKey, id); |
| output.SetString(kPairingDeviceCommitmentKey, commitment); |
| callback.Run(chromeos::http::status_code::Ok, output); |
| } |
| |
| void PrivetHandler::HandlePairingConfirm(const base::DictionaryValue& input, |
| const RequestCallback& callback) { |
| std::string id; |
| input.GetString(kPairingSessionIdKey, &id); |
| |
| std::string commitment; |
| input.GetString(kPairingClientCommitmentKey, &commitment); |
| |
| std::string fingerprint; |
| std::string signature; |
| Error error = |
| security_->ConfirmPairing(id, commitment, &fingerprint, &signature); |
| if (error != Error::kNone) |
| return ReturnError(error, callback); |
| |
| base::DictionaryValue output; |
| output.SetString(kPairingFingerprintKey, fingerprint); |
| output.SetString(kPairingSignatureKey, signature); |
| callback.Run(chromeos::http::status_code::Ok, output); |
| } |
| |
| void PrivetHandler::HandlePairingCancel(const base::DictionaryValue& input, |
| const RequestCallback& callback) { |
| std::string id; |
| input.GetString(kPairingSessionIdKey, &id); |
| |
| Error error = security_->CancelPairing(id); |
| if (error != Error::kNone) |
| return ReturnError(error, callback); |
| |
| base::DictionaryValue output; |
| callback.Run(chromeos::http::status_code::Ok, output); |
| } |
| |
| void PrivetHandler::HandleAuth(const base::DictionaryValue& input, |
| const RequestCallback& callback) { |
| std::string auth_code_type; |
| input.GetString(kAuthModeKey, &auth_code_type); |
| |
| std::string auth_code; |
| input.GetString(kAuthCodeKey, &auth_code); |
| |
| AuthScope max_auth_scope = AuthScope::kNone; |
| if (auth_code_type == kAuthTypeAnonymousValue) { |
| max_auth_scope = AuthScope::kGuest; |
| } else if (auth_code_type == kAuthTypePairingValue) { |
| if (!security_->IsValidPairingCode(auth_code)) |
| return ReturnError(Error::kInvalidAuthCode, callback); |
| max_auth_scope = AuthScope::kOwner; |
| } else { |
| return ReturnError(Error::kInvalidAuthMode, callback); |
| } |
| |
| std::string requested_scope; |
| input.GetString(kAuthRequestedScopeKey, &requested_scope); |
| |
| AuthScope requested_auth_scope = |
| AuthScopeFromString(requested_scope, max_auth_scope); |
| if (requested_auth_scope == AuthScope::kNone) |
| return ReturnError(Error::kInvalidRequestedScope, callback); |
| |
| if (requested_auth_scope > max_auth_scope) |
| return ReturnError(Error::kAccessDenied, callback); |
| |
| base::DictionaryValue output; |
| output.SetString( |
| kAuthAccessTokenKey, |
| security_->CreateAccessToken(requested_auth_scope, base::Time::Now())); |
| output.SetString(kAuthTokenTypeKey, kAuthorizationHeaderPrefix); |
| output.SetInteger(kAuthExpiresInKey, kAccesssTokenExpirationSeconds); |
| output.SetString(kAuthScopeKey, EnumToString(requested_auth_scope)); |
| callback.Run(chromeos::http::status_code::Ok, output); |
| } |
| |
| void PrivetHandler::HandleSetupStart(const base::DictionaryValue& input, |
| const RequestCallback& callback) { |
| std::string param; |
| if (input.GetString(kNameKey, ¶m)) |
| device_->SetName(param); |
| if (input.GetString(kDescrptionKey, ¶m)) |
| device_->SetDescription(param); |
| if (input.GetString(kLocationKey, ¶m)) |
| device_->SetLocation(param); |
| |
| std::string ssid; |
| std::string passphrase; |
| std::string ticket; |
| std::string user; |
| |
| const base::DictionaryValue* wifi = nullptr; |
| if (input.GetDictionary(kWifiKey, &wifi)) { |
| if (!wifi_ || wifi_->GetTypes().empty()) |
| return ReturnError(Error::kSetupUnavailable, callback); |
| wifi->GetString(kSetupStartSsidKey, &ssid); |
| if (ssid.empty()) |
| return ReturnError(Error::kInvalidParams, callback); |
| wifi->GetString(kSetupStartPassKey, &passphrase); |
| } |
| |
| const base::DictionaryValue* registration = nullptr; |
| if (input.GetDictionary(kGcdKey, ®istration)) { |
| if (!cloud_) |
| return ReturnError(Error::kSetupUnavailable, callback); |
| registration->GetString(kSetupStartTicketIdKey, &ticket); |
| if (ticket.empty()) |
| return ReturnError(Error::kInvalidParams, callback); |
| registration->GetString(kSetupStartUserKey, &user); |
| } |
| |
| if (!ssid.empty() && !wifi_->ConfigureCredentials(ssid, passphrase)) |
| return ReturnError(Error::kDeviceBusy, callback); |
| |
| if (!ticket.empty() && !cloud_->Setup(ticket, user)) |
| return ReturnError(Error::kDeviceBusy, callback); |
| |
| return HandleSetupStatus(input, callback); |
| } |
| |
| void PrivetHandler::HandleSetupStatus(const base::DictionaryValue& input, |
| const RequestCallback& callback) { |
| base::DictionaryValue output; |
| |
| if (cloud_) { |
| SetupState state = cloud_->GetSetupState(); |
| if (state.status != SetupState::kNone) { |
| base::DictionaryValue* gcd = new base::DictionaryValue; |
| output.Set(kGcdKey, gcd); |
| SetState(state, gcd); |
| if (state.status == SetupState::kSuccess) |
| gcd->SetString(kInfoIdKey, cloud_->GetCloudId()); |
| } |
| } |
| |
| if (wifi_) { |
| SetupState state = wifi_->GetSetupState(); |
| if (state.status != SetupState::kNone) { |
| base::DictionaryValue* wifi = new base::DictionaryValue; |
| output.Set(kWifiKey, wifi); |
| SetState(state, wifi); |
| if (state.status == SetupState::kSuccess) |
| wifi->SetString(kInfoWifiSsidKey, wifi_->GetCurrentlyConnectedSsid()); |
| } |
| } |
| |
| callback.Run(chromeos::http::status_code::Ok, output); |
| } |
| |
| std::unique_ptr<base::DictionaryValue> PrivetHandler::CreateEndpointsSection() |
| const { |
| std::unique_ptr<base::DictionaryValue> endpoints(new base::DictionaryValue()); |
| auto http_endpoint = device_->GetHttpEnpoint(); |
| endpoints->SetInteger(kInfoEndpointsHttpPortKey, http_endpoint.first); |
| endpoints->SetInteger(kInfoEndpointsHttpUpdatePortKey, http_endpoint.second); |
| |
| auto https_endpoint = device_->GetHttpsEnpoint(); |
| endpoints->SetInteger(kInfoEndpointsHttpsPortKey, https_endpoint.first); |
| endpoints->SetInteger(kInfoEndpointsHttpsUpdatePortKey, |
| https_endpoint.second); |
| |
| return std::move(endpoints); |
| } |
| |
| std::unique_ptr<base::DictionaryValue> PrivetHandler::CreateInfoAuthSection() |
| const { |
| std::unique_ptr<base::DictionaryValue> auth(new base::DictionaryValue()); |
| |
| std::unique_ptr<base::ListValue> pairing_types(new base::ListValue()); |
| for (PairingType type : security_->GetPairingTypes()) |
| pairing_types->AppendString(EnumToString(type)); |
| auth->Set(kPairingKey, pairing_types.release()); |
| |
| std::unique_ptr<base::ListValue> auth_types(new base::ListValue()); |
| auth_types->AppendString(kAuthTypeAnonymousValue); |
| auth_types->AppendString(kAuthTypePairingValue); |
| if (cloud_ && cloud_->GetConnectionState().status == ConnectionState::kOnline) |
| auth_types->AppendString(kAuthTypeCloudValue); |
| auth->Set(kAuthModeKey, auth_types.release()); |
| |
| std::unique_ptr<base::ListValue> crypto_types(new base::ListValue()); |
| for (CryptoType type : security_->GetCryptoTypes()) |
| crypto_types->AppendString(EnumToString(type)); |
| auth->Set(kCryptoKey, crypto_types.release()); |
| |
| return std::move(auth); |
| } |
| |
| std::unique_ptr<base::DictionaryValue> PrivetHandler::CreateWifiSection() |
| const { |
| std::unique_ptr<base::DictionaryValue> wifi(new base::DictionaryValue()); |
| |
| std::unique_ptr<base::ListValue> capabilities(new base::ListValue()); |
| for (WifiType type : wifi_->GetTypes()) |
| capabilities->AppendString(EnumToString(type)); |
| wifi->Set(kInfoWifiCapabilitiesKey, capabilities.release()); |
| |
| wifi->SetString(kInfoWifiSsidKey, wifi_->GetCurrentlyConnectedSsid()); |
| |
| std::string hosted_ssid = wifi_->GetHostedSsid(); |
| ConnectionState state = wifi_->GetConnectionState(); |
| if (!hosted_ssid.empty()) { |
| DCHECK(state.status != ConnectionState::kDisabled); |
| DCHECK(state.status != ConnectionState::kOnline); |
| wifi->SetString(kInfoWifiHostedSsidKey, hosted_ssid); |
| } |
| SetState(state, wifi.get()); |
| return std::move(wifi); |
| } |
| |
| std::unique_ptr<base::DictionaryValue> PrivetHandler::CreateGcdSection() const { |
| std::unique_ptr<base::DictionaryValue> gcd(new base::DictionaryValue()); |
| gcd->SetString(kInfoIdKey, cloud_->GetCloudId()); |
| SetState(cloud_->GetConnectionState(), gcd.get()); |
| return std::move(gcd); |
| } |
| |
| } // namespace privetd |