| // 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 |