Commit d6fea463 authored by Allen Vicencio's avatar Allen Vicencio Committed by Commit Bot

Implement ReadFile for SmbFileSystem

Implements ReadFile for SmbFileSystem. This will allow files to be read
from the files app.

Bug: chromium:757625
Change-Id: I3bae2b3c631ef78941a3f403f31c45c98afdf33a
Reviewed-on: https://chromium-review.googlesource.com/848413Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Commit-Queue: Allen Vicencio <allenvic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#530394}
parent 211f0d2e
......@@ -5,10 +5,12 @@
#include "chrome/browser/chromeos/smb_client/smb_file_system.h"
#include "base/memory/ptr_util.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/chromeos/file_system_provider/service.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/smb_provider_client.h"
#include "net/base/io_buffer.h"
namespace chromeos {
......@@ -249,7 +251,11 @@ AbortCallback SmbFileSystem::ReadFile(
int64_t offset,
int length,
const ReadChunkReceivedCallback& callback) {
NOTIMPLEMENTED();
GetSmbProviderClient()->ReadFile(
GetMountId(), file_handle, offset, length,
base::BindOnce(&SmbFileSystem::HandleRequestReadFileCallback,
weak_ptr_factory_.GetWeakPtr(), length,
scoped_refptr<net::IOBuffer>(buffer), callback));
return CreateAbortCallback();
}
......@@ -437,6 +443,38 @@ base::File::Error SmbFileSystem::RunUnmountCallback(
return error;
}
void SmbFileSystem::HandleRequestReadFileCallback(
int32_t length,
scoped_refptr<net::IOBuffer> buffer,
const ReadChunkReceivedCallback& callback,
smbprovider::ErrorType error,
const base::ScopedFD& fd) const {
if (error != smbprovider::ERROR_OK) {
callback.Run(0 /* chunk_length */, false /* has_more */,
TranslateError(error));
return;
}
int32_t total_read = 0;
while (total_read < length) {
// read() may return less than the requested amount of bytes. If this
// happens, try to read the remaining bytes.
const int32_t bytes_read = HANDLE_EINTR(
read(fd.get(), buffer->data() + total_read, length - total_read));
if (bytes_read < 0) {
// This is an error case, return an error immediately.
callback.Run(0 /* chunk_length */, false /* has_more */,
base::File::FILE_ERROR_IO);
return;
}
if (bytes_read == 0) {
break;
}
total_read += bytes_read;
}
callback.Run(total_read, false /* has_more */, base::File::FILE_OK);
}
base::WeakPtr<file_system_provider::ProvidedFileSystemInterface>
SmbFileSystem::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
......
......@@ -206,6 +206,12 @@ class SmbFileSystem : public file_system_provider::ProvidedFileSystemInterface {
const std::string& file_system_id,
file_system_provider::Service::UnmountReason reason);
void HandleRequestReadFileCallback(int32_t length,
scoped_refptr<net::IOBuffer> buffer,
const ReadChunkReceivedCallback& callback,
smbprovider::ErrorType error,
const base::ScopedFD& fd) const;
int32_t GetMountId() const;
SmbProviderClient* GetSmbProviderClient() const;
......
......@@ -62,4 +62,15 @@ void FakeSmbProviderClient::CloseFile(int32_t mount_id,
FROM_HERE, base::BindOnce(std::move(callback), smbprovider::ERROR_OK));
}
void FakeSmbProviderClient::ReadFile(int32_t mount_id,
int32_t file_id,
int64_t offset,
int32_t length,
ReadFileCallback callback) {
base::ScopedFD fd;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), smbprovider::ERROR_OK,
std::move(fd)));
}
} // namespace chromeos
......@@ -34,6 +34,11 @@ class CHROMEOS_EXPORT FakeSmbProviderClient : public SmbProviderClient {
void CloseFile(int32_t mount_id,
int32_t file_id,
StatusCallback callback) override;
void ReadFile(int32_t mount_id,
int32_t file_id,
int64_t offset,
int32_t length,
ReadFileCallback callback) override;
private:
DISALLOW_COPY_AND_ASSIGN(FakeSmbProviderClient);
......
......@@ -112,6 +112,20 @@ class SmbProviderClientImpl : public SmbProviderClient {
&SmbProviderClientImpl::HandleCloseFileCallback, &callback);
}
void ReadFile(int32_t mount_id,
int32_t file_id,
int64_t offset,
int32_t length,
ReadFileCallback callback) override {
smbprovider::ReadFileOptions options;
options.set_mount_id(mount_id);
options.set_file_id(file_id);
options.set_offset(offset);
options.set_length(length);
CallMethod(smbprovider::kReadFileMethod, options,
&SmbProviderClientImpl::HandleReadFileCallback, &callback);
}
protected:
// DBusClient override.
void Init(dbus::Bus* bus) override {
......@@ -200,11 +214,35 @@ class SmbProviderClientImpl : public SmbProviderClient {
if (!response) {
DLOG(ERROR) << "CloseFile: failed to call smbprovider";
std::move(callback).Run(smbprovider::ERROR_DBUS_PARSE_FAILED);
return;
}
dbus::MessageReader reader(response);
std::move(callback).Run(GetErrorFromReader(&reader));
}
// Handles D-Bus callback for ReadFile.
void HandleReadFileCallback(ReadFileCallback callback,
dbus::Response* response) {
base::ScopedFD fd;
if (!response) {
LOG(ERROR) << "ReadFile: failed to call smbprovider";
std::move(callback).Run(smbprovider::ERROR_DBUS_PARSE_FAILED, fd);
return;
}
dbus::MessageReader reader(response);
smbprovider::ErrorType error = GetErrorFromReader(&reader);
if (error != smbprovider::ERROR_OK) {
std::move(callback).Run(error, fd);
return;
}
if (!reader.PopFileDescriptor(&fd)) {
LOG(ERROR) << "ReadFile: failed to parse file descriptor";
std::move(callback).Run(smbprovider::ERROR_DBUS_PARSE_FAILED, fd);
return;
}
std::move(callback).Run(smbprovider::ERROR_OK, fd);
}
// Handles D-Bus responses for methods that return an error and a protobuf
// object.
template <class T>
......
......@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/files/scoped_file.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/dbus/dbus_client.h"
#include "chromeos/dbus/smbprovider/directory_entry.pb.h"
......@@ -31,6 +32,8 @@ class CHROMEOS_EXPORT SmbProviderClient : public DBusClient {
base::OnceCallback<void(smbprovider::ErrorType error,
const smbprovider::DirectoryEntryList& entries)>;
using StatusCallback = base::OnceCallback<void(smbprovider::ErrorType error)>;
using ReadFileCallback = base::OnceCallback<void(smbprovider::ErrorType error,
const base::ScopedFD& fd)>;
~SmbProviderClient() override;
......@@ -76,6 +79,16 @@ class CHROMEOS_EXPORT SmbProviderClient : public DBusClient {
int32_t file_id,
StatusCallback callback) = 0;
// Calls ReadFile. Using the corresponding mount |mount_id|, this reads the
// file with handle |file_id| from |offset| and reads up to |length| in bytes.
// The data read is saved to a temporary file and is returned as a file
// descriptor in the supplied ReadFileCallback.
virtual void ReadFile(int32_t mount_id,
int32_t file_id,
int64_t offset,
int32_t length,
ReadFileCallback callback) = 0;
protected:
// Create() should be used instead.
SmbProviderClient();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment