Don't preload rarely seen large images
[chromium-blink-merge.git] / components / proximity_auth / webui / proximity_auth_webui_handler.cc
blob3e73c515b167d21eca448624cc87d68cbc14468b
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"
7 #include "base/bind.h"
8 #include "base/i18n/time_formatting.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/time/default_clock.h"
11 #include "base/values.h"
12 #include "components/proximity_auth/cryptauth/base64url.h"
13 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h"
14 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h"
15 #include "components/proximity_auth/logging/logging.h"
16 #include "components/proximity_auth/webui/cryptauth_enroller_factory_impl.h"
17 #include "components/proximity_auth/webui/proximity_auth_ui_delegate.h"
18 #include "content/public/browser/web_ui.h"
20 namespace proximity_auth {
22 namespace {
24 // Keys in the JSON representation of a log message.
25 const char kLogMessageTextKey[] = "text";
26 const char kLogMessageTimeKey[] = "time";
27 const char kLogMessageFileKey[] = "file";
28 const char kLogMessageLineKey[] = "line";
29 const char kLogMessageSeverityKey[] = "severity";
31 // Keys in the JSON representation of a SyncState object for enrollment or
32 // device sync.
33 const char kSyncStateLastSuccessTime[] = "lastSuccessTime";
34 const char kSyncStateNextRefreshTime[] = "nextRefreshTime";
35 const char kSyncStateRecoveringFromFailure[] = "recoveringFromFailure";
36 const char kSyncStateOperationInProgress[] = "operationInProgress";
38 // Converts |log_message| to a raw dictionary value used as a JSON argument to
39 // JavaScript functions.
40 scoped_ptr<base::DictionaryValue> LogMessageToDictionary(
41 const LogBuffer::LogMessage& log_message) {
42 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue());
43 dictionary->SetString(kLogMessageTextKey, log_message.text);
44 dictionary->SetString(
45 kLogMessageTimeKey,
46 base::TimeFormatTimeOfDayWithMilliseconds(log_message.time));
47 dictionary->SetString(kLogMessageFileKey, log_message.file);
48 dictionary->SetInteger(kLogMessageLineKey, log_message.line);
49 dictionary->SetInteger(kLogMessageSeverityKey,
50 static_cast<int>(log_message.severity));
51 return dictionary.Pass();
54 // Keys in the JSON representation of an ExternalDeviceInfo proto.
55 const char kExternalDevicePublicKey[] = "publicKey";
56 const char kExternalDeviceFriendlyName[] = "friendlyDeviceName";
57 const char kExternalDeviceUnlockKey[] = "unlockKey";
58 const char kExternalDeviceConnectionStatus[] = "connectionStatus";
60 // The possible values of the |kExternalDeviceConnectionStatus| field.
61 const char kExternalDeviceDisconnected[] = "disconnected";
63 // Converts an ExternalDeviceInfo proto to a JSON dictionary used in JavaScript.
64 scoped_ptr<base::DictionaryValue> ExternalDeviceInfoToDictionary(
65 const cryptauth::ExternalDeviceInfo& device_info) {
66 std::string base64_public_key;
67 Base64UrlEncode(device_info.public_key(), &base64_public_key);
69 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue());
70 dictionary->SetString(kExternalDevicePublicKey, base64_public_key);
71 dictionary->SetString(kExternalDeviceFriendlyName,
72 device_info.friendly_device_name());
73 dictionary->SetBoolean(kExternalDeviceUnlockKey, device_info.unlock_key());
74 dictionary->SetString(kExternalDeviceConnectionStatus,
75 kExternalDeviceDisconnected);
76 return dictionary.Pass();
79 // Keys in the JSON representation of an IneligibleDevice proto.
80 const char kIneligibleDeviceReasons[] = "ineligibilityReasons";
82 // Converts an IneligibleDevice proto to a JSON dictionary used in JavaScript.
83 scoped_ptr<base::DictionaryValue> IneligibleDeviceToDictionary(
84 const cryptauth::IneligibleDevice& ineligible_device) {
85 scoped_ptr<base::ListValue> ineligibility_reasons(new base::ListValue());
86 for (const std::string& reason : ineligible_device.reasons()) {
87 ineligibility_reasons->AppendString(reason);
90 scoped_ptr<base::DictionaryValue> device_dictionary =
91 ExternalDeviceInfoToDictionary(ineligible_device.device());
92 device_dictionary->Set(kIneligibleDeviceReasons,
93 ineligibility_reasons.Pass());
94 return device_dictionary;
97 } // namespace
99 ProximityAuthWebUIHandler::ProximityAuthWebUIHandler(
100 ProximityAuthUIDelegate* delegate)
101 : delegate_(delegate), weak_ptr_factory_(this) {
102 cryptauth_client_factory_ = delegate_->CreateCryptAuthClientFactory();
105 ProximityAuthWebUIHandler::~ProximityAuthWebUIHandler() {
106 LogBuffer::GetInstance()->RemoveObserver(this);
107 if (enrollment_manager_)
108 enrollment_manager_->RemoveObserver(this);
111 void ProximityAuthWebUIHandler::RegisterMessages() {
112 web_ui()->RegisterMessageCallback(
113 "clearLogBuffer", base::Bind(&ProximityAuthWebUIHandler::ClearLogBuffer,
114 base::Unretained(this)));
116 web_ui()->RegisterMessageCallback(
117 "getLogMessages", base::Bind(&ProximityAuthWebUIHandler::GetLogMessages,
118 base::Unretained(this)));
120 web_ui()->RegisterMessageCallback(
121 "findEligibleUnlockDevices",
122 base::Bind(&ProximityAuthWebUIHandler::FindEligibleUnlockDevices,
123 base::Unretained(this)));
125 web_ui()->RegisterMessageCallback(
126 "getEnrollmentState",
127 base::Bind(&ProximityAuthWebUIHandler::GetEnrollmentState,
128 base::Unretained(this)));
130 web_ui()->RegisterMessageCallback(
131 "forceEnrollment", base::Bind(&ProximityAuthWebUIHandler::ForceEnrollment,
132 base::Unretained(this)));
134 LogBuffer::GetInstance()->AddObserver(this);
135 InitEnrollmentManager();
138 void ProximityAuthWebUIHandler::OnLogMessageAdded(
139 const LogBuffer::LogMessage& log_message) {
140 scoped_ptr<base::DictionaryValue> dictionary =
141 LogMessageToDictionary(log_message);
142 web_ui()->CallJavascriptFunction("LogBufferInterface.onLogMessageAdded",
143 *dictionary);
146 void ProximityAuthWebUIHandler::OnLogBufferCleared() {
147 web_ui()->CallJavascriptFunction("LogBufferInterface.onLogBufferCleared");
150 void ProximityAuthWebUIHandler::OnEnrollmentStarted() {
151 web_ui()->CallJavascriptFunction(
152 "SyncStateInterface.onEnrollmentStateChanged",
153 *GetEnrollmentStateDictionary());
156 void ProximityAuthWebUIHandler::OnEnrollmentFinished(bool success) {
157 scoped_ptr<base::DictionaryValue> enrollment_state =
158 GetEnrollmentStateDictionary();
159 PA_LOG(INFO) << "Enrollment attempt completed with success=" << success
160 << ":\n" << *enrollment_state;
161 web_ui()->CallJavascriptFunction(
162 "SyncStateInterface.onEnrollmentStateChanged", *enrollment_state);
165 void ProximityAuthWebUIHandler::GetLogMessages(const base::ListValue* args) {
166 base::ListValue json_logs;
167 for (const auto& log : *LogBuffer::GetInstance()->logs()) {
168 json_logs.Append(LogMessageToDictionary(log).release());
170 web_ui()->CallJavascriptFunction("LogBufferInterface.onGotLogMessages",
171 json_logs);
174 void ProximityAuthWebUIHandler::ClearLogBuffer(const base::ListValue* args) {
175 // The OnLogBufferCleared() observer function will be called after the buffer
176 // is cleared.
177 LogBuffer::GetInstance()->Clear();
180 void ProximityAuthWebUIHandler::FindEligibleUnlockDevices(
181 const base::ListValue* args) {
182 cryptauth_client_ = cryptauth_client_factory_->CreateInstance();
184 cryptauth::FindEligibleUnlockDevicesRequest request;
185 *(request.mutable_device_classifier()) = delegate_->GetDeviceClassifier();
186 cryptauth_client_->FindEligibleUnlockDevices(
187 request,
188 base::Bind(&ProximityAuthWebUIHandler::OnFoundEligibleUnlockDevices,
189 weak_ptr_factory_.GetWeakPtr()),
190 base::Bind(&ProximityAuthWebUIHandler::OnCryptAuthClientError,
191 weak_ptr_factory_.GetWeakPtr()));
194 void ProximityAuthWebUIHandler::ForceEnrollment(const base::ListValue* args) {
195 if (enrollment_manager_) {
196 enrollment_manager_->ForceEnrollmentNow(
197 cryptauth::INVOCATION_REASON_MANUAL);
201 void ProximityAuthWebUIHandler::InitEnrollmentManager() {
202 #if defined(OS_CHROMEOS)
203 // TODO(tengs): We initialize a CryptAuthEnrollmentManager here for
204 // development and testing purposes until it is ready to be moved into Chrome.
205 // The public/private key pair has been generated and serialized in a previous
206 // session.
207 std::string user_public_key;
208 Base64UrlDecode(
209 "CAESRgohAD1lP_wgQ8XqVVwz4aK_89SqdvAQG5L_NZH5zXxwg5UbEiEAZFMlgCZ9h8OlyE4"
210 "QYKY5oiOBu0FmLSKeTAXEq2jnVJI=",
211 &user_public_key);
213 std::string user_private_key;
214 Base64UrlDecode(
215 "MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP____8AAAABAAAAAAA"
216 "AAAAAAAAA________________MFsEIP____8AAAABAAAAAAAAAAAAAAAA______________"
217 "_8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw-J9JgSwMVAMSdNgiG5wSTamZ44ROdJ"
218 "reBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li_hp_m47n60p8"
219 "D54WK84zV2sxXs7LtkBoN79R9QIhAP____8AAAAA__________-85vqtpxeehPO5ysL8YyV"
220 "RAgEBBG0wawIBAQQgKZ4Dsm5xe4p5U2XPGxjrG376ZWWIa9E6r0y1BdjIntyhRANCAAQ9ZT"
221 "_8IEPF6lVcM-Giv_PUqnbwEBuS_zWR-c18cIOVG2RTJYAmfYfDpchOEGCmOaIjgbtBZi0in"
222 "kwFxKto51SS",
223 &user_private_key);
225 // This serialized DeviceInfo proto was previously captured from a real
226 // CryptAuth enrollment, and is replayed here for testing purposes.
227 std::string serialized_device_info;
228 Base64UrlDecode(
229 "IkoIARJGCiEAX_ZjLSq73EVcrarX-7l7No7nSP86GEC322ocSZKqUKwSIQDbEDu9KN7AgLM"
230 "v_lzZZNui9zSOgXCeDpLhS2tgrYVXijoEbGlua0IFZW4tVVNKSggBEkYKIQBf9mMtKrvcRV"
231 "ytqtf7uXs2judI_zoYQLfbahxJkqpQrBIhANsQO70o3sCAsy_-XNlk26L3NI6BcJ4OkuFLa"
232 "2CthVeKam9Nb3ppbGxhLzUuMCAoWDExOyBDck9TIHg4Nl82NCA3MTM0LjAuMCkgQXBwbGVX"
233 "ZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzQ1LjAuMjQyMi4wIFN"
234 "hZmFyaS81MzcuMzZwLYoBAzEuMJABAZoBIG1rYWVtaWdob2xlYmNnY2hsa2JhbmttaWhrbm"
235 "9qZWFrsAHDPuoBHEJLZEluZWxFZk05VG1adGV3eTRGb19RV1Vicz2AAgKyBqIBQVBBOTFiS"
236 "FZDdlJJNGJFSXppMmFXOTBlZ044eHFBYkhWYnJwSVFuMTk3bWltd3RWWTZYN0JEcEI4Szg3"
237 "RjRubkJnejdLX1BQV2xkcUtDRVhiZkFiMGwyN1VaQXgtVjBWbEE4WlFwdkhETmpHVlh4RlV"
238 "WRDFNY1AzNTgtYTZ3eHRpVG5LQnpMTEVIT1F6Ujdpb0lUMzRtWWY1VmNhbmhPZDh3ugYgs9"
239 "7-c7qNUzzLeEqVCDXb_EaJ8wC3iie_Lpid44iuAh3CPo0CCugBCiMIARACGgi5wHHa82avM"
240 "ioQ7y8xhiUBs7Um73ZC1vQlzzIBABLAAeCqGnWF7RwtnmdfIQJoEqXoXrH1qLw4yqUAA1TW"
241 "M1qxTepJOdDHrh54eiejobW0SKpHqTlZIyiK3ObHAPdfzFum1l640RFdFGZTTTksZFqfD9O"
242 "dftoi0pMrApob4gXj8Pv2g22ArX55BiH56TkTIcDcEE3KKnA_2G0INT1y_clZvZfDw1n0WP"
243 "0Xdg1PLLCOb46WfDWUhHvUk3GzUce8xyxsjOkiZUNh8yvhFXaP2wJgVKVWInf0inuofo9Za"
244 "7p44hIgHgKJIr_4fuVs9Ojf0KcMzxoJTbFUGg58jglUAKFfJBLKPpMBeWEyOS5pQUdTNFZ1"
245 "bF9JVWY4YTJDSmJNbXFqaWpYUFYzaVV5dmJXSVRrR3d1bFRaVUs3RGVZczJtT0h5ZkQ1NWR"
246 "HRXEtdnJTdVc4VEZ2Z1haa2xhVEZTN0dqM2xCVUktSHd5Z0h6bHZHX2NGLWtzQmw0dXdveG"
247 "VPWE1hRlJ3WGJHVUU1Tm9sLS1mdkRIcGVZVnJR",
248 &serialized_device_info);
249 cryptauth::GcmDeviceInfo device_info;
250 device_info.ParseFromString(serialized_device_info);
252 enrollment_manager_.reset(new CryptAuthEnrollmentManager(
253 make_scoped_ptr(new base::DefaultClock()),
254 make_scoped_ptr(new CryptAuthEnrollerFactoryImpl(delegate_)),
255 user_public_key, user_private_key, device_info,
256 delegate_->GetPrefService()));
257 enrollment_manager_->AddObserver(this);
258 enrollment_manager_->Start();
259 #endif
262 void ProximityAuthWebUIHandler::OnCryptAuthClientError(
263 const std::string& error_message) {
264 PA_LOG(WARNING) << "CryptAuth request failed: " << error_message;
265 base::StringValue error_string(error_message);
266 web_ui()->CallJavascriptFunction("CryptAuthInterface.onError", error_string);
269 void ProximityAuthWebUIHandler::OnFoundEligibleUnlockDevices(
270 const cryptauth::FindEligibleUnlockDevicesResponse& response) {
271 base::ListValue eligible_devices;
272 for (const auto& external_device : response.eligible_devices()) {
273 eligible_devices.Append(ExternalDeviceInfoToDictionary(external_device));
276 base::ListValue ineligible_devices;
277 for (const auto& ineligible_device : response.ineligible_devices()) {
278 ineligible_devices.Append(IneligibleDeviceToDictionary(ineligible_device));
281 PA_LOG(INFO) << "Found " << eligible_devices.GetSize()
282 << " eligible devices and " << ineligible_devices.GetSize()
283 << " ineligible devices.";
284 web_ui()->CallJavascriptFunction("CryptAuthInterface.onGotEligibleDevices",
285 eligible_devices, ineligible_devices);
288 void ProximityAuthWebUIHandler::GetEnrollmentState(
289 const base::ListValue* args) {
290 scoped_ptr<base::DictionaryValue> enrollment_state =
291 GetEnrollmentStateDictionary();
292 PA_LOG(INFO) << "Got Enrollment State: \n" << *enrollment_state;
293 web_ui()->CallJavascriptFunction("SyncStateInterface.onGotEnrollmentState",
294 *enrollment_state);
297 scoped_ptr<base::DictionaryValue>
298 ProximityAuthWebUIHandler::GetEnrollmentStateDictionary() {
299 scoped_ptr<base::DictionaryValue> enrollment_state(
300 new base::DictionaryValue());
302 if (!enrollment_manager_)
303 return enrollment_state;
305 enrollment_state->SetDouble(
306 kSyncStateLastSuccessTime,
307 enrollment_manager_->GetLastEnrollmentTime().ToJsTime());
308 enrollment_state->SetDouble(
309 kSyncStateNextRefreshTime,
310 enrollment_manager_->GetTimeToNextAttempt().InMillisecondsF());
311 enrollment_state->SetBoolean(kSyncStateRecoveringFromFailure,
312 enrollment_manager_->IsRecoveringFromFailure());
313 enrollment_state->SetBoolean(kSyncStateOperationInProgress,
314 enrollment_manager_->IsEnrollmentInProgress());
315 return enrollment_state;
318 } // namespace proximity_auth