| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/dbus/fusebox_service_provider.h" |
| |
| #include <sys/stat.h> |
| |
| #include "ash/constants/ash_features.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "dbus/message.h" |
| #include "third_party/cros_system_api/dbus/service_constants.h" |
| |
| // This file provides the "D-Bus protocol logic" half of the FuseBox server, |
| // coupled with the "business logic" half in fusebox_server.cc. |
| |
| namespace ash { |
| |
| namespace { |
| |
| void OnExportedCallback(const std::string& interface_name, |
| const std::string& method_name, |
| bool success) { |
| LOG_IF(ERROR, !success) << "Failed to export " << interface_name << "." |
| << method_name; |
| } |
| |
| template <typename T> |
| void ReplyToProtoMethod(dbus::MethodCall* method_call, |
| dbus::ExportedObject::ResponseSender sender, |
| const T& proto) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| |
| std::unique_ptr<dbus::Response> response = |
| dbus::Response::FromMethodCall(method_call); |
| dbus::MessageWriter writer(response.get()); |
| |
| writer.AppendProtoAsArrayOfBytes(proto); |
| |
| std::move(sender).Run(std::move(response)); |
| } |
| |
| } // namespace |
| |
| FuseBoxServiceProvider::FuseBoxServiceProvider() : server_(this) {} |
| |
| FuseBoxServiceProvider::~FuseBoxServiceProvider() = default; |
| |
| void FuseBoxServiceProvider::Start(scoped_refptr<dbus::ExportedObject> object) { |
| exported_object_ = object; |
| |
| ExportProtoMethod(fusebox::kClose2Method, &fusebox::Server::Close2); |
| ExportProtoMethod(fusebox::kCreateMethod, &fusebox::Server::Create); |
| ExportProtoMethod(fusebox::kFlushMethod, &fusebox::Server::Flush); |
| ExportProtoMethod(fusebox::kMkDirMethod, &fusebox::Server::MkDir); |
| ExportProtoMethod(fusebox::kOpen2Method, &fusebox::Server::Open2); |
| ExportProtoMethod(fusebox::kRead2Method, &fusebox::Server::Read2); |
| ExportProtoMethod(fusebox::kReadDir2Method, &fusebox::Server::ReadDir2); |
| ExportProtoMethod(fusebox::kRenameMethod, &fusebox::Server::Rename); |
| ExportProtoMethod(fusebox::kRmDirMethod, &fusebox::Server::RmDir); |
| ExportProtoMethod(fusebox::kStat2Method, &fusebox::Server::Stat2); |
| ExportProtoMethod(fusebox::kTruncateMethod, &fusebox::Server::Truncate); |
| ExportProtoMethod(fusebox::kUnlinkMethod, &fusebox::Server::Unlink); |
| ExportProtoMethod(fusebox::kWrite2Method, &fusebox::Server::Write2); |
| |
| ExportProtoMethod(fusebox::kListStoragesMethod, |
| &fusebox::Server::ListStorages); |
| } |
| |
| void FuseBoxServiceProvider::OnRegisterFSURLPrefix(const std::string& subdir) { |
| if (!exported_object_) { |
| return; |
| } |
| dbus::Signal signal(fusebox::kFuseBoxServiceInterface, |
| fusebox::kStorageAttachedSignal); |
| dbus::MessageWriter writer(&signal); |
| writer.AppendString(subdir); |
| exported_object_->SendSignal(&signal); |
| } |
| |
| void FuseBoxServiceProvider::OnUnregisterFSURLPrefix( |
| const std::string& subdir) { |
| if (!exported_object_) { |
| return; |
| } |
| dbus::Signal signal(fusebox::kFuseBoxServiceInterface, |
| fusebox::kStorageDetachedSignal); |
| dbus::MessageWriter writer(&signal); |
| writer.AppendString(subdir); |
| exported_object_->SendSignal(&signal); |
| } |
| |
| template <typename RequestProto, typename ResponseProto> |
| void FuseBoxServiceProvider::ServeProtoMethod( |
| ServerMethodPtr<RequestProto, ResponseProto> method, |
| dbus::MethodCall* method_call, |
| dbus::ExportedObject::ResponseSender sender) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| dbus::MessageReader reader(method_call); |
| RequestProto request_proto; |
| if (!reader.PopArrayOfBytesAsProto(&request_proto)) { |
| ResponseProto response_proto; |
| response_proto.set_posix_error_code(EINVAL); |
| ReplyToProtoMethod(method_call, std::move(sender), response_proto); |
| return; |
| } |
| (server_.*method)(request_proto, |
| base::BindOnce(&ReplyToProtoMethod<ResponseProto>, |
| method_call, std::move(sender))); |
| } |
| |
| template <typename RequestProto, typename ResponseProto> |
| void FuseBoxServiceProvider::ExportProtoMethod( |
| const std::string& method_name, |
| ServerMethodPtr<RequestProto, ResponseProto> method) { |
| exported_object_->ExportMethod( |
| fusebox::kFuseBoxServiceInterface, method_name, |
| base::BindRepeating( |
| &FuseBoxServiceProvider::ServeProtoMethod<RequestProto, |
| ResponseProto>, |
| weak_ptr_factory_.GetWeakPtr(), method), |
| base::BindOnce(&OnExportedCallback)); |
| } |
| |
| } // namespace ash |