1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/proximity_auth/webui/proximity_auth_webui_handler.h"
8 #include "base/i18n/time_formatting.h"
9 #include "base/values.h"
10 #include "components/proximity_auth/cryptauth/base64url.h"
11 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h"
12 #include "components/proximity_auth/logging/logging.h"
13 #include "components/proximity_auth/webui/proximity_auth_ui_delegate.h"
14 #include "content/public/browser/web_ui.h"
16 namespace proximity_auth
{
20 // Keys in the JSON representation of a log message.
21 const char kLogMessageTextKey
[] = "text";
22 const char kLogMessageTimeKey
[] = "time";
23 const char kLogMessageFileKey
[] = "file";
24 const char kLogMessageLineKey
[] = "line";
25 const char kLogMessageSeverityKey
[] = "severity";
27 // Converts |log_message| to a raw dictionary value used as a JSON argument to
28 // JavaScript functions.
29 scoped_ptr
<base::DictionaryValue
> LogMessageToDictionary(
30 const LogBuffer::LogMessage
& log_message
) {
31 scoped_ptr
<base::DictionaryValue
> dictionary(new base::DictionaryValue());
32 dictionary
->SetString(kLogMessageTextKey
, log_message
.text
);
33 dictionary
->SetString(kLogMessageTimeKey
,
34 base::TimeFormatTimeOfDay(log_message
.time
));
35 dictionary
->SetString(kLogMessageFileKey
, log_message
.file
);
36 dictionary
->SetInteger(kLogMessageLineKey
, log_message
.line
);
37 dictionary
->SetInteger(kLogMessageSeverityKey
,
38 static_cast<int>(log_message
.severity
));
39 return dictionary
.Pass();
42 // Keys in the JSON representation of an ExternalDeviceInfo proto.
43 const char kExternalDevicePublicKey
[] = "publicKey";
44 const char kExternalDeviceFriendlyName
[] = "friendlyDeviceName";
45 const char kExternalDeviceUnlockKey
[] = "unlockKey";
46 const char kExternalDeviceConnectionStatus
[] = "connectionStatus";
48 // The possible values of the |kExternalDeviceConnectionStatus| field.
49 const char kExternalDeviceDisconnected
[] = "disconnected";
51 // Converts an ExternalDeviceInfo proto to a JSON dictionary used in JavaScript.
52 scoped_ptr
<base::DictionaryValue
> ExternalDeviceInfoToDictionary(
53 const cryptauth::ExternalDeviceInfo
& device_info
) {
54 std::string base64_public_key
;
55 Base64UrlEncode(device_info
.public_key(), &base64_public_key
);
57 scoped_ptr
<base::DictionaryValue
> dictionary(new base::DictionaryValue());
58 dictionary
->SetString(kExternalDevicePublicKey
, base64_public_key
);
59 dictionary
->SetString(kExternalDeviceFriendlyName
,
60 device_info
.friendly_device_name());
61 dictionary
->SetBoolean(kExternalDeviceUnlockKey
, device_info
.unlock_key());
62 dictionary
->SetString(kExternalDeviceConnectionStatus
,
63 kExternalDeviceDisconnected
);
64 return dictionary
.Pass();
67 // Keys in the JSON representation of an IneligibleDevice proto.
68 const char kIneligibleDeviceReasons
[] = "ineligibilityReasons";
70 // Converts an IneligibleDevice proto to a JSON dictionary used in JavaScript.
71 scoped_ptr
<base::DictionaryValue
> IneligibleDeviceToDictionary(
72 const cryptauth::IneligibleDevice
& ineligible_device
) {
73 scoped_ptr
<base::ListValue
> ineligibility_reasons(new base::ListValue());
74 for (const std::string
& reason
: ineligible_device
.reasons()) {
75 ineligibility_reasons
->AppendString(reason
);
78 scoped_ptr
<base::DictionaryValue
> device_dictionary
=
79 ExternalDeviceInfoToDictionary(ineligible_device
.device());
80 device_dictionary
->Set(kIneligibleDeviceReasons
,
81 ineligibility_reasons
.Pass());
82 return device_dictionary
;
87 ProximityAuthWebUIHandler::ProximityAuthWebUIHandler(
88 ProximityAuthUIDelegate
* delegate
)
89 : delegate_(delegate
), weak_ptr_factory_(this) {
90 LogBuffer::GetInstance()->AddObserver(this);
91 cryptauth_client_factory_
= delegate_
->CreateCryptAuthClientFactory();
94 ProximityAuthWebUIHandler::~ProximityAuthWebUIHandler() {
95 LogBuffer::GetInstance()->RemoveObserver(this);
98 void ProximityAuthWebUIHandler::RegisterMessages() {
99 web_ui()->RegisterMessageCallback(
100 "clearLogBuffer", base::Bind(&ProximityAuthWebUIHandler::ClearLogBuffer
,
101 base::Unretained(this)));
103 web_ui()->RegisterMessageCallback(
104 "getLogMessages", base::Bind(&ProximityAuthWebUIHandler::GetLogMessages
,
105 base::Unretained(this)));
107 web_ui()->RegisterMessageCallback(
108 "findEligibleUnlockDevices",
109 base::Bind(&ProximityAuthWebUIHandler::FindEligibleUnlockDevices
,
110 base::Unretained(this)));
113 void ProximityAuthWebUIHandler::OnLogMessageAdded(
114 const LogBuffer::LogMessage
& log_message
) {
115 scoped_ptr
<base::DictionaryValue
> dictionary
=
116 LogMessageToDictionary(log_message
);
117 web_ui()->CallJavascriptFunction("LogBufferInterface.onLogMessageAdded",
121 void ProximityAuthWebUIHandler::OnLogBufferCleared() {
122 web_ui()->CallJavascriptFunction("LogBufferInterface.onLogBufferCleared");
125 void ProximityAuthWebUIHandler::GetLogMessages(const base::ListValue
* args
) {
126 base::ListValue json_logs
;
127 auto logs
= LogBuffer::GetInstance()->logs();
128 std::transform(logs
->begin(), logs
->end(), json_logs
.begin(),
129 [](const LogBuffer::LogMessage
& log
) {
130 return LogMessageToDictionary(log
).release();
133 web_ui()->CallJavascriptFunction("LogBufferInterface.onGotLogMessages",
137 void ProximityAuthWebUIHandler::ClearLogBuffer(const base::ListValue
* args
) {
138 // The OnLogBufferCleared() observer function will be called after the buffer
140 LogBuffer::GetInstance()->Clear();
143 void ProximityAuthWebUIHandler::FindEligibleUnlockDevices(
144 const base::ListValue
* args
) {
145 PA_LOG(INFO
) << "Finding eligible unlock devices...";
146 cryptauth_client_
= cryptauth_client_factory_
->CreateInstance();
148 cryptauth::FindEligibleUnlockDevicesRequest request
;
149 *(request
.mutable_device_classifier()) = delegate_
->GetDeviceClassifier();
150 cryptauth_client_
->FindEligibleUnlockDevices(
152 base::Bind(&ProximityAuthWebUIHandler::OnFoundEligibleUnlockDevices
,
153 weak_ptr_factory_
.GetWeakPtr()),
154 base::Bind(&ProximityAuthWebUIHandler::OnCryptAuthClientError
,
155 weak_ptr_factory_
.GetWeakPtr()));
158 void ProximityAuthWebUIHandler::OnCryptAuthClientError(
159 const std::string
& error_message
) {
160 PA_LOG(WARNING
) << "CryptAuth request failed: " << error_message
;
161 base::StringValue
error_string(error_message
);
162 web_ui()->CallJavascriptFunction("CryptAuthInterface.onError", error_string
);
165 void ProximityAuthWebUIHandler::OnFoundEligibleUnlockDevices(
166 const cryptauth::FindEligibleUnlockDevicesResponse
& response
) {
167 base::ListValue eligible_devices
;
168 for (const auto& external_device
: response
.eligible_devices()) {
169 eligible_devices
.Append(ExternalDeviceInfoToDictionary(external_device
));
172 base::ListValue ineligible_devices
;
173 for (const auto& ineligible_device
: response
.ineligible_devices()) {
174 ineligible_devices
.Append(IneligibleDeviceToDictionary(ineligible_device
));
177 PA_LOG(INFO
) << "Found " << eligible_devices
.GetSize()
178 << " eligible devices and " << ineligible_devices
.GetSize()
179 << " ineligible devices.";
180 web_ui()->CallJavascriptFunction("CryptAuthInterface.onGotEligibleDevices",
181 eligible_devices
, ineligible_devices
);
184 } // namespace proximity_auth