| // Copyright 2016 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/arc/arc_bridge_host_impl.h" |
| |
| #include <algorithm> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "components/arc/arc_bridge_service.h" |
| |
| namespace arc { |
| |
| // Thin interface to wrap InterfacePtr<T> with type erasure. |
| class ArcBridgeHostImpl::MojoChannel { |
| public: |
| virtual ~MojoChannel() = default; |
| |
| protected: |
| MojoChannel() = default; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MojoChannel); |
| }; |
| |
| namespace { |
| |
| // The thin wrapper for InterfacePtr<T>, where T is one of ARC mojo Instance |
| // class. |
| template <typename InstanceType, typename HostType> |
| class MojoChannelImpl : public ArcBridgeHostImpl::MojoChannel { |
| public: |
| MojoChannelImpl(ConnectionHolder<InstanceType, HostType>* holder, |
| mojo::InterfacePtr<InstanceType> ptr) |
| : holder_(holder), ptr_(std::move(ptr)) { |
| // Delay registration to the ConnectionHolder until the version is ready. |
| } |
| |
| ~MojoChannelImpl() override { holder_->CloseInstance(ptr_.get()); } |
| |
| void set_connection_error_handler(base::OnceClosure error_handler) { |
| ptr_.set_connection_error_handler(std::move(error_handler)); |
| } |
| |
| void QueryVersion() { |
| // Note: the callback will not be called if |ptr_| is destroyed. |
| ptr_.QueryVersion( |
| base::Bind(&MojoChannelImpl::OnVersionReady, base::Unretained(this))); |
| } |
| |
| private: |
| void OnVersionReady(uint32_t unused_version) { |
| holder_->SetInstance(ptr_.get(), ptr_.version()); |
| } |
| |
| // Owned by ArcBridgeService. |
| ConnectionHolder<InstanceType, HostType>* const holder_; |
| |
| // Put as a last member to ensure that any callback tied to the |ptr_| |
| // is not invoked. |
| mojo::InterfacePtr<InstanceType> ptr_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MojoChannelImpl); |
| }; |
| |
| } // namespace |
| |
| ArcBridgeHostImpl::ArcBridgeHostImpl(ArcBridgeService* arc_bridge_service, |
| mojom::ArcBridgeInstancePtr instance) |
| : arc_bridge_service_(arc_bridge_service), |
| binding_(this), |
| instance_(std::move(instance)) { |
| DCHECK(arc_bridge_service_); |
| DCHECK(instance_.is_bound()); |
| instance_.set_connection_error_handler( |
| base::BindOnce(&ArcBridgeHostImpl::OnClosed, base::Unretained(this))); |
| mojom::ArcBridgeHostPtr host_proxy; |
| binding_.Bind(mojo::MakeRequest(&host_proxy)); |
| instance_->Init(std::move(host_proxy)); |
| } |
| |
| ArcBridgeHostImpl::~ArcBridgeHostImpl() { |
| OnClosed(); |
| } |
| |
| void ArcBridgeHostImpl::OnAccessibilityHelperInstanceReady( |
| mojom::AccessibilityHelperInstancePtr accessibility_helper_ptr) { |
| OnInstanceReady(arc_bridge_service_->accessibility_helper(), |
| std::move(accessibility_helper_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnAppInstanceReady(mojom::AppInstancePtr app_ptr) { |
| OnInstanceReady(arc_bridge_service_->app(), std::move(app_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnAudioInstanceReady( |
| mojom::AudioInstancePtr audio_ptr) { |
| OnInstanceReady(arc_bridge_service_->audio(), std::move(audio_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnAuthInstanceReady(mojom::AuthInstancePtr auth_ptr) { |
| OnInstanceReady(arc_bridge_service_->auth(), std::move(auth_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnBackupSettingsInstanceReady( |
| mojom::BackupSettingsInstancePtr backup_settings_ptr) { |
| OnInstanceReady(arc_bridge_service_->backup_settings(), |
| std::move(backup_settings_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnBluetoothInstanceReady( |
| mojom::BluetoothInstancePtr bluetooth_ptr) { |
| OnInstanceReady(arc_bridge_service_->bluetooth(), std::move(bluetooth_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnBootPhaseMonitorInstanceReady( |
| mojom::BootPhaseMonitorInstancePtr boot_phase_monitor_ptr) { |
| OnInstanceReady(arc_bridge_service_->boot_phase_monitor(), |
| std::move(boot_phase_monitor_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnCastReceiverInstanceReady( |
| mojom::CastReceiverInstancePtr cast_receiver_ptr) { |
| OnInstanceReady(arc_bridge_service_->cast_receiver(), |
| std::move(cast_receiver_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnCertStoreInstanceReady( |
| mojom::CertStoreInstancePtr instance_ptr) { |
| OnInstanceReady(arc_bridge_service_->cert_store(), std::move(instance_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnClipboardInstanceReady( |
| mojom::ClipboardInstancePtr clipboard_ptr) { |
| OnInstanceReady(arc_bridge_service_->clipboard(), std::move(clipboard_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnCrashCollectorInstanceReady( |
| mojom::CrashCollectorInstancePtr crash_collector_ptr) { |
| OnInstanceReady(arc_bridge_service_->crash_collector(), |
| std::move(crash_collector_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnEnterpriseReportingInstanceReady( |
| mojom::EnterpriseReportingInstancePtr enterprise_reporting_ptr) { |
| OnInstanceReady(arc_bridge_service_->enterprise_reporting(), |
| std::move(enterprise_reporting_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnFileSystemInstanceReady( |
| mojom::FileSystemInstancePtr file_system_ptr) { |
| OnInstanceReady(arc_bridge_service_->file_system(), |
| std::move(file_system_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnImeInstanceReady(mojom::ImeInstancePtr ime_ptr) { |
| OnInstanceReady(arc_bridge_service_->ime(), std::move(ime_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnIntentHelperInstanceReady( |
| mojom::IntentHelperInstancePtr intent_helper_ptr) { |
| OnInstanceReady(arc_bridge_service_->intent_helper(), |
| std::move(intent_helper_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnKioskInstanceReady( |
| mojom::KioskInstancePtr kiosk_ptr) { |
| OnInstanceReady(arc_bridge_service_->kiosk(), std::move(kiosk_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnLockScreenInstanceReady( |
| mojom::LockScreenInstancePtr lock_screen_ptr) { |
| OnInstanceReady(arc_bridge_service_->lock_screen(), |
| std::move(lock_screen_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnMetricsInstanceReady( |
| mojom::MetricsInstancePtr metrics_ptr) { |
| OnInstanceReady(arc_bridge_service_->metrics(), std::move(metrics_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnMidisInstanceReady( |
| mojom::MidisInstancePtr midis_ptr) { |
| OnInstanceReady(arc_bridge_service_->midis(), std::move(midis_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnNetInstanceReady(mojom::NetInstancePtr net_ptr) { |
| OnInstanceReady(arc_bridge_service_->net(), std::move(net_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnNotificationsInstanceReady( |
| mojom::NotificationsInstancePtr notifications_ptr) { |
| OnInstanceReady(arc_bridge_service_->notifications(), |
| std::move(notifications_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnObbMounterInstanceReady( |
| mojom::ObbMounterInstancePtr obb_mounter_ptr) { |
| OnInstanceReady(arc_bridge_service_->obb_mounter(), |
| std::move(obb_mounter_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnOemCryptoInstanceReady( |
| mojom::OemCryptoInstancePtr oemcrypto_ptr) { |
| OnInstanceReady(arc_bridge_service_->oemcrypto(), std::move(oemcrypto_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnPolicyInstanceReady( |
| mojom::PolicyInstancePtr policy_ptr) { |
| OnInstanceReady(arc_bridge_service_->policy(), std::move(policy_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnPowerInstanceReady( |
| mojom::PowerInstancePtr power_ptr) { |
| OnInstanceReady(arc_bridge_service_->power(), std::move(power_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnPrintInstanceReady( |
| mojom::PrintInstancePtr print_ptr) { |
| OnInstanceReady(arc_bridge_service_->print(), std::move(print_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnProcessInstanceReady( |
| mojom::ProcessInstancePtr process_ptr) { |
| OnInstanceReady(arc_bridge_service_->process(), std::move(process_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnRotationLockInstanceReady( |
| mojom::RotationLockInstancePtr rotation_lock_ptr) { |
| OnInstanceReady(arc_bridge_service_->rotation_lock(), |
| std::move(rotation_lock_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnStorageManagerInstanceReady( |
| mojom::StorageManagerInstancePtr storage_manager_ptr) { |
| OnInstanceReady(arc_bridge_service_->storage_manager(), |
| std::move(storage_manager_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnTracingInstanceReady( |
| mojom::TracingInstancePtr tracing_ptr) { |
| OnInstanceReady(arc_bridge_service_->tracing(), std::move(tracing_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnTtsInstanceReady(mojom::TtsInstancePtr tts_ptr) { |
| OnInstanceReady(arc_bridge_service_->tts(), std::move(tts_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnUsbHostInstanceReady( |
| mojom::UsbHostInstancePtr usb_host_ptr) { |
| OnInstanceReady(arc_bridge_service_->usb_host(), std::move(usb_host_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnVideoInstanceReady( |
| mojom::VideoInstancePtr video_ptr) { |
| OnInstanceReady(arc_bridge_service_->video(), std::move(video_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnVoiceInteractionArcHomeInstanceReady( |
| mojom::VoiceInteractionArcHomeInstancePtr home_ptr) { |
| OnInstanceReady(arc_bridge_service_->voice_interaction_arc_home(), |
| std::move(home_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnVoiceInteractionFrameworkInstanceReady( |
| mojom::VoiceInteractionFrameworkInstancePtr framework_ptr) { |
| OnInstanceReady(arc_bridge_service_->voice_interaction_framework(), |
| std::move(framework_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnVolumeMounterInstanceReady( |
| mojom::VolumeMounterInstancePtr volume_mounter_ptr) { |
| OnInstanceReady(arc_bridge_service_->volume_mounter(), |
| std::move(volume_mounter_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnWallpaperInstanceReady( |
| mojom::WallpaperInstancePtr wallpaper_ptr) { |
| OnInstanceReady(arc_bridge_service_->wallpaper(), std::move(wallpaper_ptr)); |
| } |
| |
| void ArcBridgeHostImpl::OnClosed() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| VLOG(1) << "Mojo connection lost"; |
| |
| // Close all mojo channels. |
| mojo_channels_.clear(); |
| instance_.reset(); |
| if (binding_.is_bound()) |
| binding_.Close(); |
| } |
| |
| template <typename InstanceType, typename HostType> |
| void ArcBridgeHostImpl::OnInstanceReady( |
| ConnectionHolder<InstanceType, HostType>* holder, |
| mojo::InterfacePtr<InstanceType> ptr) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| DCHECK(binding_.is_bound()); |
| DCHECK(ptr.is_bound()); |
| |
| // Track |channel|'s lifetime via |mojo_channels_| so that it will be |
| // closed on ArcBridgeHost/Instance closing or the ArcBridgeHostImpl's |
| // destruction. |
| auto* channel = |
| new MojoChannelImpl<InstanceType, HostType>(holder, std::move(ptr)); |
| mojo_channels_.emplace_back(channel); |
| |
| // Since |channel| is managed by |mojo_channels_|, its lifetime is shorter |
| // than |this|. Thus, the connection error handler will be invoked only |
| // when |this| is alive and base::Unretained is safe here. |
| channel->set_connection_error_handler(base::BindOnce( |
| &ArcBridgeHostImpl::OnChannelClosed, base::Unretained(this), channel)); |
| |
| // Call QueryVersion so that the version info is properly stored in the |
| // InterfacePtr<T>. |
| channel->QueryVersion(); |
| } |
| |
| void ArcBridgeHostImpl::OnChannelClosed(MojoChannel* channel) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| mojo_channels_.erase( |
| std::find_if(mojo_channels_.begin(), mojo_channels_.end(), |
| [channel](std::unique_ptr<MojoChannel>& ptr) { |
| return ptr.get() == channel; |
| })); |
| } |
| |
| } // namespace arc |