blob: c0cc2ca60a95a72934f811676a45520a0bad7d0e [file] [log] [blame]
// Copyright 2017 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 "chromeos/dbus/smb_provider_client.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/weak_ptr.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
namespace chromeos {
namespace {
smbprovider::ErrorType GetErrorFromReader(dbus::MessageReader* reader) {
int32_t int_error;
if (!reader->PopInt32(&int_error) ||
!smbprovider::ErrorType_IsValid(int_error)) {
DLOG(ERROR)
<< "SmbProviderClient: Failed to get an error from the response";
return smbprovider::ERROR_DBUS_PARSE_FAILED;
}
return static_cast<smbprovider::ErrorType>(int_error);
}
smbprovider::ErrorType GetErrorAndProto(
dbus::Response* response,
google::protobuf::MessageLite* protobuf_out) {
if (!response) {
DLOG(ERROR) << "Failed to call smbprovider";
return smbprovider::ERROR_DBUS_PARSE_FAILED;
}
dbus::MessageReader reader(response);
smbprovider::ErrorType error(GetErrorFromReader(&reader));
if (error != smbprovider::ERROR_OK) {
return error;
}
if (!reader.PopArrayOfBytesAsProto(protobuf_out)) {
DLOG(ERROR) << "Failed to parse protobuf.";
return smbprovider::ERROR_DBUS_PARSE_FAILED;
}
return smbprovider::ERROR_OK;
}
class SmbProviderClientImpl : public SmbProviderClient {
public:
SmbProviderClientImpl() : weak_ptr_factory_(this) {}
~SmbProviderClientImpl() override {}
void Mount(const base::FilePath& share_path,
MountCallback callback) override {
dbus::MethodCall method_call(smbprovider::kSmbProviderInterface,
smbprovider::kMountMethod);
dbus::MessageWriter writer(&method_call);
smbprovider::MountOptions mount_options;
mount_options.set_path(share_path.value());
writer.AppendProtoAsArrayOfBytes(mount_options);
proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::Bind(&SmbProviderClientImpl::HandleMountCallback,
weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)));
}
void Unmount(int32_t mount_id, UnmountCallback callback) override {
dbus::MethodCall method_call(smbprovider::kSmbProviderInterface,
smbprovider::kUnmountMethod);
dbus::MessageWriter writer(&method_call);
smbprovider::UnmountOptions unmount_options;
unmount_options.set_mount_id(mount_id);
writer.AppendProtoAsArrayOfBytes(unmount_options);
proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::Bind(&SmbProviderClientImpl::HandleUnmountCallback,
weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)));
}
void ReadDirectory(int32_t mount_id,
const base::FilePath& directory_path,
ReadDirectoryCallback callback) override {
dbus::MethodCall method_call(smbprovider::kSmbProviderInterface,
smbprovider::kReadDirectoryMethod);
dbus::MessageWriter writer(&method_call);
smbprovider::ReadDirectoryOptions read_directory_options;
read_directory_options.set_mount_id(mount_id);
read_directory_options.set_directory_path(directory_path.value());
writer.AppendProtoAsArrayOfBytes(read_directory_options);
proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&SmbProviderClientImpl::HandleProtoCallback<
smbprovider::DirectoryEntryList>,
weak_ptr_factory_.GetWeakPtr(),
base::Passed(&callback)));
}
void GetMetadataEntry(int32_t mount_id,
const base::FilePath& entry_path,
GetMetdataEntryCallback callback) override {
dbus::MethodCall method_call(smbprovider::kSmbProviderInterface,
smbprovider::kGetMetadataEntryMethod);
dbus::MessageWriter writer(&method_call);
smbprovider::GetMetadataEntryOptions get_metadata_entry_options;
get_metadata_entry_options.set_mount_id(mount_id);
get_metadata_entry_options.set_entry_path(entry_path.value());
writer.AppendProtoAsArrayOfBytes(get_metadata_entry_options);
proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&SmbProviderClientImpl::HandleProtoCallback<
smbprovider::DirectoryEntry>,
weak_ptr_factory_.GetWeakPtr(),
base::Passed(&callback)));
}
protected:
// DBusClient override.
void Init(dbus::Bus* bus) override {
proxy_ = bus->GetObjectProxy(
smbprovider::kSmbProviderServiceName,
dbus::ObjectPath(smbprovider::kSmbProviderServicePath));
DCHECK(proxy_);
}
private:
// Handles D-Bus callback for mount.
void HandleMountCallback(MountCallback callback, dbus::Response* response) {
if (!response) {
DLOG(ERROR) << "Mount: failed to call smbprovider";
std::move(callback).Run(smbprovider::ERROR_DBUS_PARSE_FAILED, -1);
return;
}
dbus::MessageReader reader(response);
smbprovider::ErrorType error = GetErrorFromReader(&reader);
if (error != smbprovider::ERROR_OK) {
std::move(callback).Run(error, -1);
return;
}
int32_t mount_id = -1;
if (!reader.PopInt32(&mount_id) || mount_id < 0) {
DLOG(ERROR) << "Mount: failed to parse mount id";
std::move(callback).Run(smbprovider::ERROR_DBUS_PARSE_FAILED, -1);
return;
}
std::move(callback).Run(smbprovider::ERROR_OK, mount_id);
}
// Handles D-Bus callback for unmount.
void HandleUnmountCallback(UnmountCallback callback,
dbus::Response* response) {
if (!response) {
DLOG(ERROR) << "Unmount: failed to call smbprovider";
std::move(callback).Run(smbprovider::ERROR_DBUS_PARSE_FAILED);
}
dbus::MessageReader reader(response);
std::move(callback).Run(GetErrorFromReader(&reader));
}
// Handles D-Bus responses for methods that return an error and a protobuf
// object.
template <class T>
void HandleProtoCallback(base::OnceCallback<void(smbprovider::ErrorType error,
const T& response)> callback,
dbus::Response* response) {
T proto;
smbprovider::ErrorType error(GetErrorAndProto(response, &proto));
std::move(callback).Run(error, proto);
}
dbus::ObjectProxy* proxy_ = nullptr;
// Note: This should remain the last member so it'll be destroyed and
// invalidate its weak pointers before any other members are destroyed.
base::WeakPtrFactory<SmbProviderClientImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(SmbProviderClientImpl);
};
} // namespace
SmbProviderClient::SmbProviderClient() {}
SmbProviderClient::~SmbProviderClient() {}
// static
SmbProviderClient* SmbProviderClient::Create() {
return new SmbProviderClientImpl();
}
} // namespace chromeos