Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: components/proximity_auth/webui/proximity_auth_webui_handler.cc

Issue 1352063002: Change chrome://proximity-auth to use RemoteDeviceLifeCycle. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor_mocks
Patch Set: fix win compile Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/proximity_auth/webui/proximity_auth_webui_handler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/proximity_auth/webui/proximity_auth_webui_handler.h" 5 #include "components/proximity_auth/webui/proximity_auth_webui_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/i18n/time_formatting.h" 10 #include "base/i18n/time_formatting.h"
11 #include "base/prefs/pref_service.h" 11 #include "base/prefs/pref_service.h"
12 #include "base/thread_task_runner_handle.h" 12 #include "base/thread_task_runner_handle.h"
13 #include "base/time/default_clock.h" 13 #include "base/time/default_clock.h"
14 #include "base/time/default_tick_clock.h" 14 #include "base/time/default_tick_clock.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h "
17 #include "components/proximity_auth/ble/bluetooth_low_energy_device_whitelist.h"
18 #include "components/proximity_auth/ble/pref_names.h" 16 #include "components/proximity_auth/ble/pref_names.h"
19 #include "components/proximity_auth/bluetooth_connection_finder.h" 17 #include "components/proximity_auth/bluetooth_connection_finder.h"
20 #include "components/proximity_auth/bluetooth_throttler_impl.h"
21 #include "components/proximity_auth/cryptauth/base64url.h" 18 #include "components/proximity_auth/cryptauth/base64url.h"
22 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" 19 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h"
23 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" 20 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h"
24 #include "components/proximity_auth/cryptauth/secure_message_delegate.h" 21 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
25 #include "components/proximity_auth/device_to_device_authenticator.h"
26 #include "components/proximity_auth/logging/logging.h" 22 #include "components/proximity_auth/logging/logging.h"
27 #include "components/proximity_auth/messenger_impl.h" 23 #include "components/proximity_auth/messenger.h"
24 #include "components/proximity_auth/remote_device_life_cycle_impl.h"
28 #include "components/proximity_auth/remote_status_update.h" 25 #include "components/proximity_auth/remote_status_update.h"
29 #include "components/proximity_auth/secure_context.h" 26 #include "components/proximity_auth/secure_context.h"
30 #include "components/proximity_auth/webui/reachable_phone_flow.h" 27 #include "components/proximity_auth/webui/reachable_phone_flow.h"
31 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
32 #include "content/public/browser/web_ui.h" 29 #include "content/public/browser/web_ui.h"
33 #include "device/bluetooth/bluetooth_uuid.h" 30 #include "device/bluetooth/bluetooth_uuid.h"
34 31
35 namespace proximity_auth { 32 namespace proximity_auth {
36 33
37 namespace { 34 namespace {
38 35
39 // The UUID of the Smart Lock classic Bluetooth service.
40 const char kClassicBluetoothServiceUUID[] =
41 "704EE561-3782-405A-A14B-2D47A2DDCDDF";
42
43 // The UUID of the Bluetooth Low Energy service.
44 const char kBLESmartLockServiceUUID[] = "b3b7e28e-a000-3e17-bd86-6e97b9e28c11";
45
46 // Keys in the JSON representation of a log message. 36 // Keys in the JSON representation of a log message.
47 const char kLogMessageTextKey[] = "text"; 37 const char kLogMessageTextKey[] = "text";
48 const char kLogMessageTimeKey[] = "time"; 38 const char kLogMessageTimeKey[] = "time";
49 const char kLogMessageFileKey[] = "file"; 39 const char kLogMessageFileKey[] = "file";
50 const char kLogMessageLineKey[] = "line"; 40 const char kLogMessageLineKey[] = "line";
51 const char kLogMessageSeverityKey[] = "severity"; 41 const char kLogMessageSeverityKey[] = "severity";
52 42
53 // Keys in the JSON representation of a SyncState object for enrollment or 43 // Keys in the JSON representation of a SyncState object for enrollment or
54 // device sync. 44 // device sync.
55 const char kSyncStateLastSuccessTime[] = "lastSuccessTime"; 45 const char kSyncStateLastSuccessTime[] = "lastSuccessTime";
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 return; 323 return;
334 324
335 std::string b64_public_key; 325 std::string b64_public_key;
336 std::string public_key; 326 std::string public_key;
337 if (!enrollment_manager || !device_manager || !args->GetSize() || 327 if (!enrollment_manager || !device_manager || !args->GetSize() ||
338 !args->GetString(0, &b64_public_key) || 328 !args->GetString(0, &b64_public_key) ||
339 !Base64UrlDecode(b64_public_key, &public_key)) { 329 !Base64UrlDecode(b64_public_key, &public_key)) {
340 return; 330 return;
341 } 331 }
342 332
343 Connection* connection = GetConnection();
344 for (const auto& unlock_key : device_manager->unlock_keys()) { 333 for (const auto& unlock_key : device_manager->unlock_keys()) {
345 if (unlock_key.public_key() == public_key) { 334 if (unlock_key.public_key() == public_key) {
346 // Check if there is an existing connection to disconnect from first. 335 if (life_cycle_ && selected_remote_device_.public_key == public_key) {
347 if (connection && connection->IsConnected() && 336 CleanUpRemoteDeviceLifeCycle();
348 selected_remote_device_.public_key == public_key) {
349 PA_LOG(INFO) << "Disconnecting from "
350 << unlock_key.friendly_device_name() << "["
351 << unlock_key.bluetooth_address() << "]";
352 connection->Disconnect();
353 return; 337 return;
354 } 338 }
355 339
356 // Derive the PSK before connecting to the device. 340 // Derive the PSK before connecting to the device.
357 PA_LOG(INFO) << "Deriving PSK before connecting to " 341 PA_LOG(INFO) << "Deriving PSK before connecting to "
358 << unlock_key.friendly_device_name(); 342 << unlock_key.friendly_device_name();
359 secure_message_delegate_ = 343 secure_message_delegate_ =
360 proximity_auth_client_->CreateSecureMessageDelegate(); 344 proximity_auth_client_->CreateSecureMessageDelegate();
361 secure_message_delegate_->DeriveKey( 345 secure_message_delegate_->DeriveKey(
362 enrollment_manager->GetUserPrivateKey(), unlock_key.public_key(), 346 enrollment_manager->GetUserPrivateKey(), unlock_key.public_key(),
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 if (!device_manager) 448 if (!device_manager)
465 return unlock_keys; 449 return unlock_keys;
466 450
467 for (const auto& unlock_key : device_manager->unlock_keys()) { 451 for (const auto& unlock_key : device_manager->unlock_keys()) {
468 unlock_keys->Append(ExternalDeviceInfoToDictionary(unlock_key)); 452 unlock_keys->Append(ExternalDeviceInfoToDictionary(unlock_key));
469 } 453 }
470 454
471 return unlock_keys; 455 return unlock_keys;
472 } 456 }
473 457
474 Connection* ProximityAuthWebUIHandler::GetConnection() {
475 Connection* connection = connection_.get();
476 if (messenger_) {
477 DCHECK(!connection);
478 connection = messenger_->connection();
479 }
480 return connection;
481 }
482
483 void ProximityAuthWebUIHandler::OnPSKDerived( 458 void ProximityAuthWebUIHandler::OnPSKDerived(
484 const cryptauth::ExternalDeviceInfo& unlock_key, 459 const cryptauth::ExternalDeviceInfo& unlock_key,
485 const std::string& persistent_symmetric_key) { 460 const std::string& persistent_symmetric_key) {
486 if (persistent_symmetric_key.empty()) { 461 if (persistent_symmetric_key.empty()) {
487 PA_LOG(ERROR) << "Failed to derive PSK."; 462 PA_LOG(ERROR) << "Failed to derive PSK.";
488 return; 463 return;
489 } 464 }
490 465
491 selected_remote_device_ = 466 selected_remote_device_ =
492 RemoteDevice(unlock_key.friendly_device_name(), unlock_key.public_key(), 467 RemoteDevice(unlock_key.friendly_device_name(), unlock_key.public_key(),
493 unlock_key.bluetooth_address(), persistent_symmetric_key); 468 unlock_key.bluetooth_address(), persistent_symmetric_key);
494 469
495 // TODO(tengs): We distinguish whether the unlock key uses classic Bluetooth 470 life_cycle_.reset(new RemoteDeviceLifeCycleImpl(selected_remote_device_,
496 // or BLE based on the presence of the |bluetooth_address| field. However, we 471 proximity_auth_client_));
497 // should ideally have a separate field specifying the protocol. 472 life_cycle_->AddObserver(this);
498 if (selected_remote_device_.bluetooth_address.empty()) 473 life_cycle_->Start();
499 FindBluetoothLowEnergyConnection(selected_remote_device_);
500 else
501 FindBluetoothClassicConnection(selected_remote_device_);
502 }
503
504 void ProximityAuthWebUIHandler::FindBluetoothClassicConnection(
505 const RemoteDevice& remote_device) {
506 PA_LOG(INFO) << "Finding classic Bluetooth device " << remote_device.name
507 << " [" << remote_device.bluetooth_address << "].";
508
509 // TODO(tengs): Set a timeout to stop the connection finder eventually.
510 connection_finder_.reset(new BluetoothConnectionFinder(
511 remote_device, device::BluetoothUUID(kClassicBluetoothServiceUUID),
512 base::TimeDelta::FromSeconds(3)));
513 connection_finder_->Find(
514 base::Bind(&ProximityAuthWebUIHandler::OnConnectionFound,
515 weak_ptr_factory_.GetWeakPtr()));
516
517 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged",
518 *GetUnlockKeysList());
519 }
520
521 void ProximityAuthWebUIHandler::FindBluetoothLowEnergyConnection(
522 const RemoteDevice& remote_device) {
523 PrefService* pref_service = proximity_auth_client_->GetPrefService();
524 if (!pref_service->FindPreference(
525 prefs::kBluetoothLowEnergyDeviceWhitelist)) {
526 PA_LOG(ERROR) << "Please enable the BLE experiment in chrome://flags.";
527 return;
528 }
529
530 PA_LOG(INFO) << "Finding Bluetooth Low Energy device " << remote_device.name;
531 if (!bluetooth_throttler_) {
532 bluetooth_throttler_.reset(new BluetoothThrottlerImpl(
533 make_scoped_ptr(new base::DefaultTickClock())));
534 }
535
536 ble_device_whitelist_.reset(new BluetoothLowEnergyDeviceWhitelist(
537 proximity_auth_client_->GetPrefService()));
538
539 // TODO(tengs): Set a timeout to stop the connection finder eventually.
540 connection_finder_.reset(new BluetoothLowEnergyConnectionFinder(
541 remote_device, kBLESmartLockServiceUUID,
542 BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE,
543 ble_device_whitelist_.get(), bluetooth_throttler_.get(), 3));
544 connection_finder_->Find(
545 base::Bind(&ProximityAuthWebUIHandler::OnConnectionFound,
546 weak_ptr_factory_.GetWeakPtr()));
547
548 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged",
549 *GetUnlockKeysList());
550 }
551
552 void ProximityAuthWebUIHandler::OnAuthenticationResult(
553 Authenticator::Result result,
554 scoped_ptr<SecureContext> secure_context) {
555 secure_context_ = secure_context.Pass();
556
557 // Create the MessengerImpl asynchronously. |messenger_| registers itself as
558 // an observer of |connection_|, so creating it synchronously would trigger
559 // |OnSendComplete()| as an observer call for |messenger_|.
560 base::ThreadTaskRunnerHandle::Get()->PostTask(
561 FROM_HERE,
562 base::Bind(&ProximityAuthWebUIHandler::CreateStatusUpdateMessenger,
563 weak_ptr_factory_.GetWeakPtr()));
564 }
565
566 void ProximityAuthWebUIHandler::OnConnectionFound(
567 scoped_ptr<Connection> connection) {
568 DCHECK(connection->IsConnected());
569 connection_ = connection.Pass();
570 connection_->AddObserver(this);
571
572 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged",
573 *GetUnlockKeysList());
574
575 // TODO(tengs): Create an authenticator for BLE connections.
576 if (selected_remote_device_.bluetooth_address.empty())
577 return;
578
579 authenticator_.reset(new DeviceToDeviceAuthenticator(
580 connection_.get(), proximity_auth_client_->GetAccountId(),
581 proximity_auth_client_->CreateSecureMessageDelegate()));
582 authenticator_->Authenticate(
583 base::Bind(&ProximityAuthWebUIHandler::OnAuthenticationResult,
584 weak_ptr_factory_.GetWeakPtr()));
585 }
586
587 void ProximityAuthWebUIHandler::CreateStatusUpdateMessenger() {
588 messenger_.reset(
589 new MessengerImpl(connection_.Pass(), secure_context_.Pass()));
590 messenger_->AddObserver(this);
591 } 474 }
592 475
593 scoped_ptr<base::DictionaryValue> 476 scoped_ptr<base::DictionaryValue>
594 ProximityAuthWebUIHandler::ExternalDeviceInfoToDictionary( 477 ProximityAuthWebUIHandler::ExternalDeviceInfoToDictionary(
595 const cryptauth::ExternalDeviceInfo& device_info) { 478 const cryptauth::ExternalDeviceInfo& device_info) {
596 std::string base64_public_key; 479 std::string base64_public_key;
597 Base64UrlEncode(device_info.public_key(), &base64_public_key); 480 Base64UrlEncode(device_info.public_key(), &base64_public_key);
598 481
599 // Set the fields in the ExternalDeviceInfo proto. 482 // Set the fields in the ExternalDeviceInfo proto.
600 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue()); 483 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue());
(...skipping 21 matching lines...) Expand all
622 [&public_key](const cryptauth::ExternalDeviceInfo& unlock_key) { 505 [&public_key](const cryptauth::ExternalDeviceInfo& unlock_key) {
623 return unlock_key.public_key() == public_key; 506 return unlock_key.public_key() == public_key;
624 }); 507 });
625 508
626 if (iterator == device_manager->unlock_keys().end() || 509 if (iterator == device_manager->unlock_keys().end() ||
627 selected_remote_device_.public_key != device_info.public_key()) 510 selected_remote_device_.public_key != device_info.public_key())
628 return dictionary; 511 return dictionary;
629 512
630 // Fill in the current Bluetooth connection status. 513 // Fill in the current Bluetooth connection status.
631 std::string connection_status = kExternalDeviceDisconnected; 514 std::string connection_status = kExternalDeviceDisconnected;
632 Connection* connection = GetConnection(); 515 if (life_cycle_ &&
633 if (connection && connection->IsConnected()) { 516 life_cycle_->GetState() ==
517 RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED) {
634 connection_status = kExternalDeviceConnected; 518 connection_status = kExternalDeviceConnected;
635 } else if (connection_finder_) { 519 } else if (life_cycle_) {
636 connection_status = kExternalDeviceConnecting; 520 connection_status = kExternalDeviceConnecting;
637 } 521 }
638 dictionary->SetString(kExternalDeviceConnectionStatus, connection_status); 522 dictionary->SetString(kExternalDeviceConnectionStatus, connection_status);
639 523
640 // Fill the remote status dictionary. 524 // Fill the remote status dictionary.
641 if (last_remote_status_update_) { 525 if (last_remote_status_update_) {
642 scoped_ptr<base::DictionaryValue> status_dictionary( 526 scoped_ptr<base::DictionaryValue> status_dictionary(
643 new base::DictionaryValue()); 527 new base::DictionaryValue());
644 status_dictionary->SetInteger("userPresent", 528 status_dictionary->SetInteger("userPresent",
645 last_remote_status_update_->user_presence); 529 last_remote_status_update_->user_presence);
(...skipping 16 matching lines...) Expand all
662 ineligibility_reasons->AppendString(reason); 546 ineligibility_reasons->AppendString(reason);
663 } 547 }
664 548
665 scoped_ptr<base::DictionaryValue> device_dictionary = 549 scoped_ptr<base::DictionaryValue> device_dictionary =
666 ExternalDeviceInfoToDictionary(ineligible_device.device()); 550 ExternalDeviceInfoToDictionary(ineligible_device.device());
667 device_dictionary->Set(kIneligibleDeviceReasons, 551 device_dictionary->Set(kIneligibleDeviceReasons,
668 ineligibility_reasons.Pass()); 552 ineligibility_reasons.Pass());
669 return device_dictionary; 553 return device_dictionary;
670 } 554 }
671 555
672 void ProximityAuthWebUIHandler::OnConnectionStatusChanged( 556 void ProximityAuthWebUIHandler::CleanUpRemoteDeviceLifeCycle() {
673 Connection* connection, 557 PA_LOG(INFO) << "Cleaning up connection to " << selected_remote_device_.name
674 Connection::Status old_status, 558 << " [" << selected_remote_device_.bluetooth_address << "]";
675 Connection::Status new_status) { 559 life_cycle_.reset();
676 PA_LOG(INFO) << "Connection status changed from " << old_status << " to " 560 selected_remote_device_ = RemoteDevice();
677 << new_status; 561 last_remote_status_update_.reset();
562 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged",
563 *GetUnlockKeysList());
564 }
678 565
679 if (new_status == Connection::DISCONNECTED) { 566 void ProximityAuthWebUIHandler::OnLifeCycleStateChanged(
680 last_remote_status_update_.reset(); 567 RemoteDeviceLifeCycle::State old_state,
681 selected_remote_device_ = RemoteDevice(); 568 RemoteDeviceLifeCycle::State new_state) {
682 connection_finder_.reset(); 569 // Do not re-attempt to find a connection after the first one fails--just
570 // abort.
571 if ((old_state != RemoteDeviceLifeCycle::State::STOPPED &&
572 new_state == RemoteDeviceLifeCycle::State::FINDING_CONNECTION) ||
573 new_state == RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED) {
574 // Clean up the life cycle asynchronously, because we are currently in the
575 // call stack of |life_cycle_|.
576 base::ThreadTaskRunnerHandle::Get()->PostTask(
577 FROM_HERE,
578 base::Bind(&ProximityAuthWebUIHandler::CleanUpRemoteDeviceLifeCycle,
579 weak_ptr_factory_.GetWeakPtr()));
580 } else if (new_state ==
581 RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED) {
582 life_cycle_->GetMessenger()->AddObserver(this);
683 } 583 }
684 584
685 scoped_ptr<base::ListValue> unlock_keys = GetUnlockKeysList();
686 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged", 585 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged",
687 *unlock_keys); 586 *GetUnlockKeysList());
688 }
689
690 void ProximityAuthWebUIHandler::OnMessageReceived(const Connection& connection,
691 const WireMessage& message) {
692 std::string address = connection.remote_device().bluetooth_address;
693 PA_LOG(INFO) << "Message received from " << address;
694 } 587 }
695 588
696 void ProximityAuthWebUIHandler::OnRemoteStatusUpdate( 589 void ProximityAuthWebUIHandler::OnRemoteStatusUpdate(
697 const RemoteStatusUpdate& status_update) { 590 const RemoteStatusUpdate& status_update) {
698 PA_LOG(INFO) << "Remote status update:" 591 PA_LOG(INFO) << "Remote status update:"
699 << "\n user_presence: " 592 << "\n user_presence: "
700 << static_cast<int>(status_update.user_presence) 593 << static_cast<int>(status_update.user_presence)
701 << "\n secure_screen_lock_state: " 594 << "\n secure_screen_lock_state: "
702 << static_cast<int>(status_update.secure_screen_lock_state) 595 << static_cast<int>(status_update.secure_screen_lock_state)
703 << "\n trust_agent_state: " 596 << "\n trust_agent_state: "
704 << static_cast<int>(status_update.trust_agent_state); 597 << static_cast<int>(status_update.trust_agent_state);
705 598
706 last_remote_status_update_.reset(new RemoteStatusUpdate(status_update)); 599 last_remote_status_update_.reset(new RemoteStatusUpdate(status_update));
707 scoped_ptr<base::ListValue> unlock_keys = GetUnlockKeysList(); 600 scoped_ptr<base::ListValue> unlock_keys = GetUnlockKeysList();
708 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged", 601 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged",
709 *unlock_keys); 602 *unlock_keys);
710 } 603 }
711 604
712 } // namespace proximity_auth 605 } // namespace proximity_auth
OLDNEW
« no previous file with comments | « components/proximity_auth/webui/proximity_auth_webui_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698