| // Copyright 2018 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 "chrome/browser/chromeos/android_sms/connection_manager.h" |
| |
| #include <utility> |
| |
| #include "chrome/browser/chromeos/android_sms/android_sms_urls.h" |
| #include "chrome/browser/chromeos/android_sms/connection_establisher.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chromeos/components/multidevice/logging/logging.h" |
| #include "components/session_manager/core/session_manager.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/service_worker_context.h" |
| #include "content/public/browser/storage_partition.h" |
| |
| namespace chromeos { |
| |
| namespace android_sms { |
| |
| ConnectionManager::ServiceWorkerProvider::ServiceWorkerProvider() = default; |
| |
| ConnectionManager::ServiceWorkerProvider::~ServiceWorkerProvider() = default; |
| |
| content::ServiceWorkerContext* ConnectionManager::ServiceWorkerProvider::Get( |
| const GURL& url, |
| Profile* profile) { |
| return content::BrowserContext::GetStoragePartitionForSite(profile, url) |
| ->GetServiceWorkerContext(); |
| } |
| |
| ConnectionManager::ConnectionManager( |
| std::unique_ptr<ConnectionEstablisher> connection_establisher, |
| Profile* profile, |
| AndroidSmsAppManager* android_sms_app_manager, |
| multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client) |
| : ConnectionManager(std::move(connection_establisher), |
| profile, |
| android_sms_app_manager, |
| multidevice_setup_client, |
| std::make_unique<ServiceWorkerProvider>()) {} |
| |
| ConnectionManager::ConnectionManager( |
| std::unique_ptr<ConnectionEstablisher> connection_establisher, |
| Profile* profile, |
| AndroidSmsAppManager* android_sms_app_manager, |
| multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client, |
| std::unique_ptr<ServiceWorkerProvider> service_worker_provider) |
| : connection_establisher_(std::move(connection_establisher)), |
| profile_(profile), |
| android_sms_app_manager_(android_sms_app_manager), |
| multidevice_setup_client_(multidevice_setup_client), |
| service_worker_provider_(std::move(service_worker_provider)) { |
| android_sms_app_manager_->AddObserver(this); |
| multidevice_setup_client_->AddObserver(this); |
| |
| UpdateConnectionStatus(); |
| } |
| |
| ConnectionManager::~ConnectionManager() { |
| android_sms_app_manager_->RemoveObserver(this); |
| multidevice_setup_client_->RemoveObserver(this); |
| |
| if (GetCurrentServiceWorkerContext()) |
| GetCurrentServiceWorkerContext()->RemoveObserver(this); |
| } |
| |
| void ConnectionManager::OnVersionActivated(int64_t version_id, |
| const GURL& scope) { |
| if (!enabled_pwa_url_ || !scope.EqualsIgnoringRef(*enabled_pwa_url_)) |
| return; |
| |
| prev_active_version_id_ = active_version_id_; |
| active_version_id_ = version_id; |
| |
| connection_establisher_->EstablishConnection( |
| *enabled_pwa_url_, |
| ConnectionEstablisher::ConnectionMode::kResumeExistingConnection, |
| GetCurrentServiceWorkerContext()); |
| } |
| |
| void ConnectionManager::OnVersionRedundant(int64_t version_id, |
| const GURL& scope) { |
| if (!enabled_pwa_url_ || !scope.EqualsIgnoringRef(*enabled_pwa_url_)) |
| return; |
| |
| if (active_version_id_ != version_id) |
| return; |
| |
| // If the active version is marked redundant then it cannot handle messages |
| // anymore, so stop tracking it. |
| prev_active_version_id_ = active_version_id_; |
| active_version_id_.reset(); |
| } |
| |
| void ConnectionManager::OnNoControllees(int64_t version_id, const GURL& scope) { |
| if (!enabled_pwa_url_ || !scope.EqualsIgnoringRef(*enabled_pwa_url_)) |
| return; |
| |
| // Set active_version_id_ in case we missed version activated. |
| // This is unlikely but protects against a case where a Android Messages for |
| // Web page may have opened before the ConnectionManager is created. |
| if (!active_version_id_ && prev_active_version_id_ != version_id) |
| active_version_id_ = version_id; |
| |
| if (active_version_id_ != version_id) |
| return; |
| |
| connection_establisher_->EstablishConnection( |
| *enabled_pwa_url_, |
| ConnectionEstablisher::ConnectionMode::kResumeExistingConnection, |
| GetCurrentServiceWorkerContext()); |
| } |
| |
| void ConnectionManager::OnInstalledAppUrlChanged() { |
| UpdateConnectionStatus(); |
| } |
| |
| void ConnectionManager::OnFeatureStatesChanged( |
| const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& |
| feature_states_map) { |
| UpdateConnectionStatus(); |
| } |
| |
| void ConnectionManager::UpdateConnectionStatus() { |
| base::Optional<GURL> updated_pwa_url = |
| ConnectionManager::GenerateEnabledPwaUrl(); |
| if (enabled_pwa_url_ == updated_pwa_url) |
| return; |
| |
| // If the URL was previously enabled, stop the ServiceWorker. This occurs when |
| // the feature was disabled and when migrating from the old URL to the new |
| // one. |
| if (enabled_pwa_url_) { |
| PA_LOG(INFO) << "ConnectionManager::UpdateConnectionStatus(): Stopping " |
| << "connection to PWA at " << *enabled_pwa_url_ << "."; |
| connection_establisher_->TearDownConnection( |
| *enabled_pwa_url_, GetCurrentServiceWorkerContext()); |
| GetCurrentServiceWorkerContext()->RemoveObserver(this); |
| active_version_id_.reset(); |
| prev_active_version_id_.reset(); |
| } |
| |
| enabled_pwa_url_ = updated_pwa_url; |
| if (!enabled_pwa_url_) |
| return; |
| |
| PA_LOG(INFO) << "ConnectionManager::UpdateConnectionStatus(): Establishing " |
| << "connection to PWA at " << *enabled_pwa_url_ << "."; |
| GetCurrentServiceWorkerContext()->AddObserver(this); |
| connection_establisher_->EstablishConnection( |
| *enabled_pwa_url_, |
| ConnectionEstablisher::ConnectionMode::kStartConnection, |
| GetCurrentServiceWorkerContext()); |
| } |
| |
| base::Optional<GURL> ConnectionManager::GenerateEnabledPwaUrl() { |
| const auto it = multidevice_setup_client_->GetFeatureStates().find( |
| multidevice_setup::mojom::Feature::kMessages); |
| |
| // If the feature is not enabled, there is no enabled URL. |
| if (it->second != multidevice_setup::mojom::FeatureState::kEnabledByUser) |
| return base::nullopt; |
| |
| // Return the installed app URL if the PWA is installed. |
| base::Optional<GURL> installed_url = |
| android_sms_app_manager_->GetCurrentAppUrl(); |
| if (installed_url) |
| return installed_url; |
| |
| // Otherwise, return the default URL. |
| return GetAndroidMessagesURL(); |
| } |
| |
| content::ServiceWorkerContext* |
| ConnectionManager::GetCurrentServiceWorkerContext() { |
| if (!enabled_pwa_url_) |
| return nullptr; |
| |
| return service_worker_provider_->Get(*enabled_pwa_url_, profile_); |
| } |
| |
| void ConnectionManager::SetServiceWorkerProviderForTesting( |
| std::unique_ptr<ServiceWorkerProvider> service_worker_provider) { |
| service_worker_provider_ = std::move(service_worker_provider); |
| } |
| |
| } // namespace android_sms |
| |
| } // namespace chromeos |