| // Copyright 2015 The Chromium 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 "components/cryptauth/cryptauth_gcm_manager_impl.h" |
| |
| #include "base/bind.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/strings/string_util.h" |
| #include "chromeos/components/proximity_auth/logging/logging.h" |
| #include "components/cryptauth/pref_names.h" |
| #include "components/gcm_driver/gcm_driver.h" |
| #include "components/prefs/pref_service.h" |
| |
| namespace cryptauth { |
| |
| namespace { |
| |
| // The GCM app id identifies the client. |
| const char kCryptAuthGCMAppId[] = "com.google.chrome.cryptauth"; |
| |
| // The GCM sender id identifies the CryptAuth server. |
| const char kCryptAuthGCMSenderId[] = "381449029288"; |
| |
| // The 'registrationTickleType' key-value pair is present in GCM push |
| // messages. The values correspond to a server-side enum. |
| const char kRegistrationTickleTypeKey[] = "registrationTickleType"; |
| const char kRegistrationTickleTypeForceEnrollment[] = "1"; |
| const char kRegistrationTickleTypeUpdateEnrollment[] = "2"; |
| const char kRegistrationTickleTypeDevicesSync[] = "3"; |
| |
| } // namespace |
| |
| // static |
| CryptAuthGCMManagerImpl::Factory* |
| CryptAuthGCMManagerImpl::Factory::factory_instance_ = nullptr; |
| |
| // static |
| std::unique_ptr<CryptAuthGCMManager> |
| CryptAuthGCMManagerImpl::Factory::NewInstance(gcm::GCMDriver* gcm_driver, |
| PrefService* pref_service) { |
| if (!factory_instance_) |
| factory_instance_ = new Factory(); |
| |
| return factory_instance_->BuildInstance(gcm_driver, pref_service); |
| } |
| |
| // static |
| void CryptAuthGCMManagerImpl::Factory::SetInstanceForTesting(Factory* factory) { |
| factory_instance_ = factory; |
| } |
| |
| CryptAuthGCMManagerImpl::Factory::~Factory() = default; |
| |
| std::unique_ptr<CryptAuthGCMManager> |
| CryptAuthGCMManagerImpl::Factory::BuildInstance(gcm::GCMDriver* gcm_driver, |
| PrefService* pref_service) { |
| return base::WrapUnique( |
| new CryptAuthGCMManagerImpl(gcm_driver, pref_service)); |
| } |
| |
| CryptAuthGCMManagerImpl::CryptAuthGCMManagerImpl(gcm::GCMDriver* gcm_driver, |
| PrefService* pref_service) |
| : gcm_driver_(gcm_driver), |
| pref_service_(pref_service), |
| registration_in_progress_(false), |
| weak_ptr_factory_(this) { |
| } |
| |
| CryptAuthGCMManagerImpl::~CryptAuthGCMManagerImpl() { |
| if (gcm_driver_->GetAppHandler(kCryptAuthGCMAppId) == this) |
| gcm_driver_->RemoveAppHandler(kCryptAuthGCMAppId); |
| } |
| |
| void CryptAuthGCMManagerImpl::StartListening() { |
| if (gcm_driver_->GetAppHandler(kCryptAuthGCMAppId) == this) { |
| PA_LOG(VERBOSE) << "GCM app handler already added"; |
| return; |
| } |
| |
| gcm_driver_->AddAppHandler(kCryptAuthGCMAppId, this); |
| } |
| |
| void CryptAuthGCMManagerImpl::RegisterWithGCM() { |
| if (registration_in_progress_) { |
| PA_LOG(VERBOSE) << "GCM Registration is already in progress"; |
| return; |
| } |
| |
| PA_LOG(VERBOSE) << "Beginning GCM registration..."; |
| registration_in_progress_ = true; |
| |
| std::vector<std::string> sender_ids(1, kCryptAuthGCMSenderId); |
| gcm_driver_->Register( |
| kCryptAuthGCMAppId, sender_ids, |
| base::Bind(&CryptAuthGCMManagerImpl::OnRegistrationCompleted, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| std::string CryptAuthGCMManagerImpl::GetRegistrationId() { |
| return pref_service_->GetString(prefs::kCryptAuthGCMRegistrationId); |
| } |
| |
| void CryptAuthGCMManagerImpl::AddObserver(Observer* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void CryptAuthGCMManagerImpl::RemoveObserver(Observer* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| void CryptAuthGCMManagerImpl::ShutdownHandler() { |
| } |
| |
| void CryptAuthGCMManagerImpl::OnStoreReset() { |
| // We will automatically re-register to GCM and re-enroll the new registration |
| // ID to Cryptauth during the next scheduled sync. |
| pref_service_->ClearPref(prefs::kCryptAuthGCMRegistrationId); |
| } |
| |
| void CryptAuthGCMManagerImpl::OnMessage(const std::string& app_id, |
| const gcm::IncomingMessage& message) { |
| std::vector<std::string> fields; |
| for (const auto& kv : message.data) { |
| fields.push_back(std::string(kv.first) + ": " + std::string(kv.second)); |
| } |
| |
| PA_LOG(VERBOSE) << "GCM message received:\n" |
| << " sender_id: " << message.sender_id << "\n" |
| << " collapse_key: " << message.collapse_key << "\n" |
| << " data:\n " << base::JoinString(fields, "\n "); |
| |
| if (message.data.find(kRegistrationTickleTypeKey) == message.data.end()) { |
| PA_LOG(WARNING) << "GCM message does not contain 'registrationTickleType'."; |
| } else { |
| std::string tickle_type = message.data.at(kRegistrationTickleTypeKey); |
| if (tickle_type == kRegistrationTickleTypeForceEnrollment || |
| tickle_type == kRegistrationTickleTypeUpdateEnrollment) { |
| // These tickle types correspond to re-enrollment messages. |
| for (auto& observer : observers_) |
| observer.OnReenrollMessage(); |
| } else if (tickle_type == kRegistrationTickleTypeDevicesSync) { |
| for (auto& observer : observers_) |
| observer.OnResyncMessage(); |
| } else { |
| PA_LOG(WARNING) << "Unknown tickle type in GCM message."; |
| } |
| } |
| } |
| |
| void CryptAuthGCMManagerImpl::OnMessagesDeleted(const std::string& app_id) { |
| } |
| |
| void CryptAuthGCMManagerImpl::OnSendError( |
| const std::string& app_id, |
| const gcm::GCMClient::SendErrorDetails& details) { |
| NOTREACHED(); |
| } |
| |
| void CryptAuthGCMManagerImpl::OnSendAcknowledged( |
| const std::string& app_id, |
| const std::string& message_id) { |
| NOTREACHED(); |
| } |
| |
| void CryptAuthGCMManagerImpl::OnRegistrationCompleted( |
| const std::string& registration_id, |
| gcm::GCMClient::Result result) { |
| registration_in_progress_ = false; |
| if (result != gcm::GCMClient::SUCCESS) { |
| PA_LOG(WARNING) << "GCM registration failed with result=" |
| << static_cast<int>(result); |
| for (auto& observer : observers_) |
| observer.OnGCMRegistrationResult(false); |
| return; |
| } |
| |
| PA_LOG(VERBOSE) << "GCM registration success, registration_id=" |
| << registration_id; |
| pref_service_->SetString(prefs::kCryptAuthGCMRegistrationId, registration_id); |
| for (auto& observer : observers_) |
| observer.OnGCMRegistrationResult(true); |
| } |
| |
| } // namespace cryptauth |