| // 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/dbus/component_updater_service_provider.h" |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/files/file_path.h" |
| #include "base/task/post_task.h" |
| #include "chrome/browser/component_updater/cros_component_installer_chromeos.h" |
| #include "content/public/browser/browser_task_traits.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "dbus/bus.h" |
| #include "dbus/message.h" |
| #include "third_party/cros_system_api/dbus/service_constants.h" |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs"; |
| const char kErrorInternalError[] = "org.freedesktop.DBus.Error.InternalError"; |
| |
| std::string ErrorToString( |
| component_updater::CrOSComponentManager::Error error) { |
| switch (error) { |
| case component_updater::CrOSComponentManager::Error::NONE: |
| return "NONE"; |
| case component_updater::CrOSComponentManager::Error::UNKNOWN_COMPONENT: |
| return "UNKNOWN_COMPONENT"; |
| case component_updater::CrOSComponentManager::Error::INSTALL_FAILURE: |
| return "INSTALL_FAILURE"; |
| case component_updater::CrOSComponentManager::Error::MOUNT_FAILURE: |
| return "MOUNT_FAILURE"; |
| case component_updater::CrOSComponentManager::Error:: |
| COMPATIBILITY_CHECK_FAILED: |
| return "COMPATIBILITY_CHECK_FAILED"; |
| case component_updater::CrOSComponentManager::Error::NOT_FOUND: |
| return "NOT_FOUND"; |
| case component_updater::CrOSComponentManager::Error::ERROR_MAX: |
| return "ERROR_MAX"; |
| } |
| return "Unknown error code"; |
| } |
| |
| } // namespace |
| |
| ComponentUpdaterServiceProvider::ComponentUpdaterServiceProvider( |
| component_updater::CrOSComponentManager* cros_component_manager) |
| : weak_ptr_factory_(this) { |
| DCHECK(cros_component_manager); |
| |
| cros_component_manager_ = cros_component_manager; |
| cros_component_manager_->SetDelegate(this); |
| } |
| |
| ComponentUpdaterServiceProvider::~ComponentUpdaterServiceProvider() { |
| cros_component_manager_->SetDelegate(nullptr); |
| } |
| |
| void ComponentUpdaterServiceProvider::Start( |
| scoped_refptr<dbus::ExportedObject> exported_object) { |
| exported_object->ExportMethod( |
| kComponentUpdaterServiceInterface, |
| kComponentUpdaterServiceLoadComponentMethod, |
| base::Bind(&ComponentUpdaterServiceProvider::LoadComponent, |
| weak_ptr_factory_.GetWeakPtr()), |
| base::Bind(&ComponentUpdaterServiceProvider::OnExported, |
| weak_ptr_factory_.GetWeakPtr())); |
| |
| exported_object->ExportMethod( |
| kComponentUpdaterServiceInterface, |
| kComponentUpdaterServiceUnloadComponentMethod, |
| base::Bind(&ComponentUpdaterServiceProvider::UnloadComponent, |
| weak_ptr_factory_.GetWeakPtr()), |
| base::Bind(&ComponentUpdaterServiceProvider::OnExported, |
| weak_ptr_factory_.GetWeakPtr())); |
| |
| exported_object_ = exported_object; |
| } |
| |
| void ComponentUpdaterServiceProvider::EmitInstalledSignal( |
| const std::string& component) { |
| base::PostTaskWithTraits( |
| FROM_HERE, {content::BrowserThread::UI}, |
| base::BindOnce( |
| &ComponentUpdaterServiceProvider::EmitInstalledSignalInternal, |
| weak_ptr_factory_.GetWeakPtr(), component)); |
| } |
| |
| void ComponentUpdaterServiceProvider::OnExported( |
| const std::string& interface_name, |
| const std::string& method_name, |
| bool success) { |
| if (!success) { |
| LOG(ERROR) << "Failed to export " << interface_name << "." << method_name; |
| } |
| } |
| |
| void ComponentUpdaterServiceProvider::LoadComponent( |
| dbus::MethodCall* method_call, |
| dbus::ExportedObject::ResponseSender response_sender) { |
| dbus::MessageReader reader(method_call); |
| std::string component_name; |
| // |mount| is an optional parameter, and by default is true. |
| bool mount = true; |
| if (reader.PopString(&component_name)) { |
| // dbus::MessageReader::PopBool sets its out-param to false on failure. |
| // Resets |mount| to its default value on failure. |
| if (!reader.PopBool(&mount)) |
| mount = true; |
| cros_component_manager_->Load( |
| component_name, |
| mount |
| ? component_updater::CrOSComponentManager::MountPolicy::kMount |
| : component_updater::CrOSComponentManager::MountPolicy::kDontMount, |
| component_updater::CrOSComponentManager::UpdatePolicy::kDontForce, |
| base::Bind(&ComponentUpdaterServiceProvider::OnLoadComponent, |
| weak_ptr_factory_.GetWeakPtr(), method_call, |
| response_sender)); |
| } else { |
| std::unique_ptr<dbus::ErrorResponse> error_response = |
| dbus::ErrorResponse::FromMethodCall( |
| method_call, kErrorInvalidArgs, |
| "Need a string and a boolean parameter."); |
| response_sender.Run(std::move(error_response)); |
| } |
| } |
| |
| void ComponentUpdaterServiceProvider::OnLoadComponent( |
| dbus::MethodCall* method_call, |
| dbus::ExportedObject::ResponseSender response_sender, |
| component_updater::CrOSComponentManager::Error error, |
| const base::FilePath& result) { |
| if (error != component_updater::CrOSComponentManager::Error::NONE) { |
| LOG(ERROR) << "Component updater Load API error: " << ErrorToString(error); |
| } |
| |
| std::unique_ptr<dbus::Response> response = |
| dbus::Response::FromMethodCall(method_call); |
| dbus::MessageWriter writer(response.get()); |
| writer.AppendString(result.value()); |
| response_sender.Run(std::move(response)); |
| } |
| |
| void ComponentUpdaterServiceProvider::UnloadComponent( |
| dbus::MethodCall* method_call, |
| dbus::ExportedObject::ResponseSender response_sender) { |
| dbus::MessageReader reader(method_call); |
| std::string component_name; |
| if (reader.PopString(&component_name)) { |
| if (cros_component_manager_->Unload(component_name)) { |
| response_sender.Run(dbus::Response::FromMethodCall(method_call)); |
| } else { |
| response_sender.Run(dbus::ErrorResponse::FromMethodCall( |
| method_call, kErrorInternalError, "Failed to unload component")); |
| } |
| } else { |
| response_sender.Run(dbus::ErrorResponse::FromMethodCall( |
| method_call, kErrorInvalidArgs, |
| "Missing component name string argument.")); |
| } |
| } |
| |
| void ComponentUpdaterServiceProvider::EmitInstalledSignalInternal( |
| const std::string& component) { |
| DCHECK(exported_object_); |
| |
| dbus::Signal signal( |
| chromeos::kComponentUpdaterServiceInterface, |
| chromeos::kComponentUpdaterServiceComponentInstalledSignal); |
| |
| dbus::MessageWriter writer(&signal); |
| writer.AppendString(component); |
| exported_object_->SendSignal(&signal); |
| } |
| |
| } // namespace chromeos |