// 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/arc/arc_bridge_service.h" #include #include "base/command_line.h" #include "base/sequenced_task_runner.h" #include "base/thread_task_runner_handle.h" #include "chromeos/chromeos_switches.h" #include "components/arc/arc_bridge_service_impl.h" namespace arc { namespace { // Weak pointer. This class is owned by ArcServiceManager. ArcBridgeService* g_arc_bridge_service = nullptr; } // namespace ArcBridgeService::ArcBridgeService() : available_(false), state_(State::STOPPED), weak_factory_(this) { DCHECK(!g_arc_bridge_service); g_arc_bridge_service = this; } ArcBridgeService::~ArcBridgeService() { DCHECK(CalledOnValidThread()); DCHECK(state() == State::STOPPING || state() == State::STOPPED); DCHECK(g_arc_bridge_service == this); g_arc_bridge_service = nullptr; } // static ArcBridgeService* ArcBridgeService::Get() { if (!g_arc_bridge_service) { // ArcBridgeService may be indirectly referenced in unit tests where // ArcBridgeService is optional. LOG(ERROR) << "ArcBridgeService is not ready."; return nullptr; } DCHECK(g_arc_bridge_service->CalledOnValidThread()); return g_arc_bridge_service; } // static bool ArcBridgeService::GetEnabled(const base::CommandLine* command_line) { return command_line->HasSwitch(chromeos::switches::kEnableArc); } void ArcBridgeService::AddObserver(Observer* observer) { DCHECK(CalledOnValidThread()); observer_list_.AddObserver(observer); // If any of the instances were ready before the call to AddObserver(), the // |observer| won't get any readiness events. For such cases, we have to call // them explicitly now to avoid a race. if (app_instance()) observer->OnAppInstanceReady(); if (audio_instance()) observer->OnAudioInstanceReady(); if (auth_instance()) observer->OnAuthInstanceReady(); if (bluetooth_instance()) observer->OnBluetoothInstanceReady(); if (clipboard_instance()) observer->OnClipboardInstanceReady(); if (crash_collector_instance()) observer->OnCrashCollectorInstanceReady(); if (ime_instance()) observer->OnImeInstanceReady(); if (input_instance()) observer->OnInputInstanceReady(); if (net_instance()) observer->OnNetInstanceReady(); if (notifications_instance()) observer->OnNotificationsInstanceReady(); if (policy_instance()) observer->OnPolicyInstanceReady(); if (power_instance()) observer->OnPowerInstanceReady(); if (process_instance()) observer->OnProcessInstanceReady(); if (video_instance()) observer->OnVideoInstanceReady(); } void ArcBridgeService::RemoveObserver(Observer* observer) { DCHECK(CalledOnValidThread()); observer_list_.RemoveObserver(observer); } void ArcBridgeService::OnAppInstanceReady(AppInstancePtr app_ptr) { DCHECK(CalledOnValidThread()); temporary_app_ptr_ = std::move(app_ptr); temporary_app_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnAppVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnAppVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); app_ptr_ = std::move(temporary_app_ptr_); app_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseAppChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnAppInstanceReady()); } void ArcBridgeService::CloseAppChannel() { DCHECK(CalledOnValidThread()); if (!app_ptr_) return; app_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnAppInstanceClosed()); } void ArcBridgeService::OnAudioInstanceReady(AudioInstancePtr audio_ptr) { DCHECK(CalledOnValidThread()); temporary_audio_ptr_ = std::move(audio_ptr); temporary_audio_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnAudioVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnAudioVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); audio_ptr_ = std::move(temporary_audio_ptr_); audio_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseAudioChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnAudioInstanceReady()); } void ArcBridgeService::CloseAudioChannel() { if (!audio_ptr_) return; audio_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnAudioInstanceClosed()); } void ArcBridgeService::OnAuthInstanceReady(AuthInstancePtr auth_ptr) { DCHECK(CalledOnValidThread()); temporary_auth_ptr_ = std::move(auth_ptr); temporary_auth_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnAuthVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnAuthVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); auth_ptr_ = std::move(temporary_auth_ptr_); auth_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseAuthChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnAuthInstanceReady()); } void ArcBridgeService::CloseAuthChannel() { DCHECK(CalledOnValidThread()); if (!auth_ptr_) return; auth_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnAuthInstanceClosed()); } void ArcBridgeService::OnBluetoothInstanceReady( BluetoothInstancePtr bluetooth_ptr) { DCHECK(CalledOnValidThread()); temporary_bluetooth_ptr_ = std::move(bluetooth_ptr); temporary_bluetooth_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnBluetoothVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnBluetoothVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); bluetooth_ptr_ = std::move(temporary_bluetooth_ptr_); bluetooth_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseBluetoothChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnBluetoothInstanceReady()); } void ArcBridgeService::CloseBluetoothChannel() { DCHECK(CalledOnValidThread()); if (!bluetooth_ptr_) return; bluetooth_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnBluetoothInstanceClosed()); } void ArcBridgeService::OnClipboardInstanceReady( ClipboardInstancePtr clipboard_ptr) { DCHECK(CalledOnValidThread()); temporary_clipboard_ptr_ = std::move(clipboard_ptr); temporary_clipboard_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnClipboardVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnClipboardVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); clipboard_ptr_ = std::move(temporary_clipboard_ptr_); clipboard_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseClipboardChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnClipboardInstanceReady()); } void ArcBridgeService::CloseClipboardChannel() { DCHECK(CalledOnValidThread()); if (!clipboard_ptr_) return; clipboard_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnClipboardInstanceClosed()); } void ArcBridgeService::OnCrashCollectorInstanceReady( CrashCollectorInstancePtr crash_collector_ptr) { DCHECK(CalledOnValidThread()); temporary_crash_collector_ptr_ = std::move(crash_collector_ptr); temporary_crash_collector_ptr_.QueryVersion( base::Bind(&ArcBridgeService::OnCrashCollectorVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnCrashCollectorVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); crash_collector_ptr_ = std::move(temporary_crash_collector_ptr_); crash_collector_ptr_.set_connection_error_handler( base::Bind(&ArcBridgeService::CloseCrashCollectorChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnCrashCollectorInstanceReady()); } void ArcBridgeService::CloseCrashCollectorChannel() { DCHECK(CalledOnValidThread()); if (!crash_collector_ptr_) return; crash_collector_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnCrashCollectorInstanceClosed()); } void ArcBridgeService::OnImeInstanceReady(ImeInstancePtr ime_ptr) { DCHECK(CalledOnValidThread()); temporary_ime_ptr_ = std::move(ime_ptr); temporary_ime_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnImeVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnImeVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); ime_ptr_ = std::move(temporary_ime_ptr_); ime_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseImeChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnImeInstanceReady()); } void ArcBridgeService::CloseImeChannel() { DCHECK(CalledOnValidThread()); if (!ime_ptr_) return; ime_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnImeInstanceClosed()); } void ArcBridgeService::OnInputInstanceReady(InputInstancePtr input_ptr) { DCHECK(CalledOnValidThread()); temporary_input_ptr_ = std::move(input_ptr); temporary_input_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnInputVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnInputVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); input_ptr_ = std::move(temporary_input_ptr_); input_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseInputChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnInputInstanceReady()); } void ArcBridgeService::CloseInputChannel() { DCHECK(CalledOnValidThread()); if (!input_ptr_) return; input_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnInputInstanceClosed()); } void ArcBridgeService::OnIntentHelperInstanceReady( IntentHelperInstancePtr intent_helper_ptr) { DCHECK(CalledOnValidThread()); temporary_intent_helper_ptr_ = std::move(intent_helper_ptr); temporary_intent_helper_ptr_.QueryVersion( base::Bind(&ArcBridgeService::OnIntentHelperVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnIntentHelperVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); intent_helper_ptr_ = std::move(temporary_intent_helper_ptr_); intent_helper_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseIntentHelperChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnIntentHelperInstanceReady()); } void ArcBridgeService::CloseIntentHelperChannel() { DCHECK(CalledOnValidThread()); if (!intent_helper_ptr_) return; intent_helper_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnIntentHelperInstanceClosed()); } void ArcBridgeService::OnNetInstanceReady(NetInstancePtr net_ptr) { DCHECK(CalledOnValidThread()); temporary_net_ptr_ = std::move(net_ptr); temporary_net_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnNetVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnNetVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); net_ptr_ = std::move(temporary_net_ptr_); net_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseNetChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnNetInstanceReady()); } void ArcBridgeService::CloseNetChannel() { DCHECK(CalledOnValidThread()); if (!net_ptr_) return; net_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnNetInstanceClosed()); } void ArcBridgeService::OnNotificationsInstanceReady( NotificationsInstancePtr notifications_ptr) { DCHECK(CalledOnValidThread()); temporary_notifications_ptr_ = std::move(notifications_ptr); temporary_notifications_ptr_.QueryVersion( base::Bind(&ArcBridgeService::OnNotificationsVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnNotificationsVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); notifications_ptr_ = std::move(temporary_notifications_ptr_); notifications_ptr_.set_connection_error_handler( base::Bind(&ArcBridgeService::CloseNotificationsChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnNotificationsInstanceReady()); } void ArcBridgeService::CloseNotificationsChannel() { DCHECK(CalledOnValidThread()); if (!notifications_ptr_) return; notifications_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnNotificationsInstanceClosed()); } void ArcBridgeService::OnPolicyInstanceReady(PolicyInstancePtr policy_ptr) { DCHECK(CalledOnValidThread()); temporary_policy_ptr_ = std::move(policy_ptr); temporary_policy_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnPolicyVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnPolicyVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); policy_ptr_ = std::move(temporary_policy_ptr_); policy_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::ClosePolicyChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnPolicyInstanceReady()); } void ArcBridgeService::ClosePolicyChannel() { DCHECK(CalledOnValidThread()); if (!policy_ptr_) return; policy_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnPolicyInstanceClosed()); } void ArcBridgeService::OnPowerInstanceReady(PowerInstancePtr power_ptr) { DCHECK(CalledOnValidThread()); temporary_power_ptr_ = std::move(power_ptr); temporary_power_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnPowerVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnPowerVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); power_ptr_ = std::move(temporary_power_ptr_); power_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::ClosePowerChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnPowerInstanceReady()); } void ArcBridgeService::ClosePowerChannel() { DCHECK(CalledOnValidThread()); if (!power_ptr_) return; power_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnPowerInstanceClosed()); } void ArcBridgeService::OnProcessInstanceReady(ProcessInstancePtr process_ptr) { DCHECK(CalledOnValidThread()); temporary_process_ptr_ = std::move(process_ptr); temporary_process_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnProcessVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnProcessVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); process_ptr_ = std::move(temporary_process_ptr_); process_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseProcessChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnProcessInstanceReady()); } void ArcBridgeService::CloseProcessChannel() { DCHECK(CalledOnValidThread()); if (!process_ptr_) return; process_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnProcessInstanceClosed()); } void ArcBridgeService::OnVideoInstanceReady(VideoInstancePtr video_ptr) { DCHECK(CalledOnValidThread()); temporary_video_ptr_ = std::move(video_ptr); temporary_video_ptr_.QueryVersion(base::Bind( &ArcBridgeService::OnVideoVersionReady, weak_factory_.GetWeakPtr())); } void ArcBridgeService::OnVideoVersionReady(int32_t version) { DCHECK(CalledOnValidThread()); video_ptr_ = std::move(temporary_video_ptr_); video_ptr_.set_connection_error_handler(base::Bind( &ArcBridgeService::CloseVideoChannel, weak_factory_.GetWeakPtr())); FOR_EACH_OBSERVER(Observer, observer_list(), OnVideoInstanceReady()); } void ArcBridgeService::CloseVideoChannel() { DCHECK(CalledOnValidThread()); if (!video_ptr_) return; video_ptr_.reset(); FOR_EACH_OBSERVER(Observer, observer_list(), OnVideoInstanceClosed()); } void ArcBridgeService::SetState(State state) { DCHECK(CalledOnValidThread()); // DCHECK on enum classes not supported. DCHECK(state_ != state); state_ = state; FOR_EACH_OBSERVER(Observer, observer_list(), OnStateChanged(state_)); } void ArcBridgeService::SetAvailable(bool available) { DCHECK(CalledOnValidThread()); DCHECK(available_ != available); available_ = available; FOR_EACH_OBSERVER(Observer, observer_list(), OnAvailableChanged(available_)); } bool ArcBridgeService::CalledOnValidThread() { return thread_checker_.CalledOnValidThread(); } void ArcBridgeService::CloseAllChannels() { // Call all the error handlers of all the channels to both close the channel // and notify any observers that the channel is closed. CloseAppChannel(); CloseAudioChannel(); CloseAuthChannel(); CloseBluetoothChannel(); CloseClipboardChannel(); CloseCrashCollectorChannel(); CloseImeChannel(); CloseInputChannel(); CloseIntentHelperChannel(); CloseNetChannel(); CloseNotificationsChannel(); ClosePolicyChannel(); ClosePowerChannel(); CloseProcessChannel(); CloseVideoChannel(); } } // namespace arc