| Index: chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc
|
| diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc
|
| index aa1b86890526123ae9f5168754b6ce218dc540b8..00aac3e1a84f0924291b835a313efc8337e13e6a 100644
|
| --- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc
|
| +++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc
|
| @@ -4,16 +4,43 @@
|
|
|
| #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h"
|
|
|
| +#include "base/files/file.h"
|
| #include "base/logging.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_document.h"
|
| +#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h"
|
| +#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_instance_util.h"
|
| #include "content/public/browser/browser_thread.h"
|
| +#include "url/gurl.h"
|
|
|
| using content::BrowserThread;
|
| +using EntryList = storage::AsyncFileUtil::EntryList;
|
|
|
| namespace arc {
|
|
|
| +namespace {
|
| +
|
| +base::FilePath StripBaseName(const base::FilePath& path) {
|
| + base::FilePath dirname = path.DirName();
|
| + // base::FilePath::DirName() returns kCurrentDirectory if the path does not
|
| + // contain separators. In this case we want an empty path.
|
| + if (dirname.value() == base::FilePath::kCurrentDirectory) {
|
| + return base::FilePath();
|
| + }
|
| + return dirname;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| ArcDocumentsProviderRoot::ArcDocumentsProviderRoot(
|
| const std::string& authority,
|
| - const std::string& root_document_id) {}
|
| + const std::string& root_document_id)
|
| + : authority_(authority),
|
| + root_directory_(
|
| + base::MakeUnique<ArcDocumentsProviderDocument>(root_document_id,
|
| + true)),
|
| + weak_ptr_factory_(this) {}
|
|
|
| ArcDocumentsProviderRoot::~ArcDocumentsProviderRoot() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| @@ -23,14 +50,177 @@ void ArcDocumentsProviderRoot::GetFileInfo(
|
| const base::FilePath& path,
|
| const GetFileInfoCallback& callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - NOTIMPLEMENTED(); // TODO(crbug.com/671511): Implement this function.
|
| + // Skip a cache update if possible.
|
| + ArcDocumentsProviderDocument* entry = root_directory_->Lookup(path);
|
| + if (entry) {
|
| + GetFileInfoAfterCacheUpdate(path, callback);
|
| + return;
|
| + }
|
| + DCHECK(!path.empty());
|
| + UpdateDirectoryCacheUpTo(
|
| + StripBaseName(path),
|
| + base::Bind(&ArcDocumentsProviderRoot::GetFileInfoAfterCacheUpdate,
|
| + weak_ptr_factory_.GetWeakPtr(), path, callback));
|
| }
|
|
|
| void ArcDocumentsProviderRoot::ReadDirectory(
|
| const base::FilePath& path,
|
| const ReadDirectoryCallback& callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - NOTIMPLEMENTED(); // TODO(crbug.com/671511): Implement this function.
|
| + if (path.empty()) {
|
| + ReadDirectoryAfterCacheUpdate(path, callback);
|
| + return;
|
| + }
|
| + UpdateDirectoryCacheUpTo(
|
| + StripBaseName(path),
|
| + base::Bind(&ArcDocumentsProviderRoot::ReadDirectoryAfterCacheUpdate,
|
| + weak_ptr_factory_.GetWeakPtr(), path, callback));
|
| +}
|
| +
|
| +void ArcDocumentsProviderRoot::GetFileInfoAfterCacheUpdate(
|
| + const base::FilePath& path,
|
| + const GetFileInfoCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + ArcDocumentsProviderDocument* entry = root_directory_->Lookup(path);
|
| + if (!entry) {
|
| + callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info());
|
| + return;
|
| + }
|
| + file_system_instance_util::GetDocumentOnIOThread(
|
| + authority_, entry->document_id(),
|
| + base::Bind(&ArcDocumentsProviderRoot::GetFileInfoWithDocument,
|
| + weak_ptr_factory_.GetWeakPtr(), callback));
|
| +}
|
| +
|
| +void ArcDocumentsProviderRoot::GetFileInfoWithDocument(
|
| + const GetFileInfoCallback& callback,
|
| + mojom::DocumentPtr document) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + if (document.is_null()) {
|
| + callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info());
|
| + return;
|
| + }
|
| +
|
| + base::File::Info info;
|
| + info.size = document->size;
|
| + info.is_directory = document->mime_type == kAndroidDirectoryMimeType;
|
| + info.is_symbolic_link = false;
|
| + info.last_modified = info.last_accessed = info.creation_time =
|
| + base::Time::FromDoubleT(document->last_modified / 1000.0);
|
| + callback.Run(base::File::FILE_OK, info);
|
| +}
|
| +
|
| +void ArcDocumentsProviderRoot::ReadDirectoryAfterCacheUpdate(
|
| + const base::FilePath& path,
|
| + const ReadDirectoryCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + ArcDocumentsProviderDocument* parent_directory =
|
| + root_directory_->Lookup(path);
|
| + if (!parent_directory || !parent_directory->is_directory()) {
|
| + callback.Run(base::File::FILE_ERROR_NOT_FOUND, EntryList(),
|
| + false /* has_more */);
|
| + return;
|
| + }
|
| + file_system_instance_util::GetChildDocumentsOnIOThread(
|
| + authority_, parent_directory->document_id(),
|
| + base::Bind(&ArcDocumentsProviderRoot::ReadDirectoryWithChildDocuments,
|
| + weak_ptr_factory_.GetWeakPtr(), path, callback));
|
| +}
|
| +
|
| +void ArcDocumentsProviderRoot::ReadDirectoryWithChildDocuments(
|
| + const base::FilePath& path,
|
| + const ReadDirectoryCallback& callback,
|
| + base::Optional<std::vector<mojom::DocumentPtr>> children) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + if (!children) {
|
| + callback.Run(base::File::FILE_ERROR_NOT_FOUND, EntryList(),
|
| + false /* has_more */);
|
| + return;
|
| + }
|
| +
|
| + ArcDocumentsProviderDocument* parent_directory =
|
| + root_directory_->Lookup(path);
|
| + if (!parent_directory || !parent_directory->is_directory()) {
|
| + callback.Run(base::File::FILE_ERROR_NOT_FOUND, EntryList(),
|
| + false /* has_more */);
|
| + return;
|
| + }
|
| + parent_directory->UpdateWithChildDocuments(children.value());
|
| +
|
| + std::vector<storage::DirectoryEntry> entry_list;
|
| + for (const auto& pair : parent_directory->children()) {
|
| + entry_list.emplace_back(pair.first, pair.second->is_directory()
|
| + ? storage::DirectoryEntry::DIRECTORY
|
| + : storage::DirectoryEntry::FILE);
|
| + }
|
| + callback.Run(base::File::FILE_OK, entry_list, false /* has_more */);
|
| +}
|
| +
|
| +void ArcDocumentsProviderRoot::UpdateDirectoryCacheUpTo(
|
| + const base::FilePath& path,
|
| + const base::Closure& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + UpdateDirectoryCacheIter(base::FilePath(), path, callback);
|
| +}
|
| +
|
| +void ArcDocumentsProviderRoot::UpdateDirectoryCacheIter(
|
| + const base::FilePath& parent_directory_path,
|
| + const base::FilePath& remaining_path,
|
| + const base::Closure& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + ArcDocumentsProviderDocument* parent_directory =
|
| + root_directory_->Lookup(parent_directory_path);
|
| + if (!parent_directory || !parent_directory->is_directory()) {
|
| + callback.Run();
|
| + return;
|
| + }
|
| +
|
| + file_system_instance_util::GetChildDocumentsOnIOThread(
|
| + authority_, parent_directory->document_id(),
|
| + base::Bind(
|
| + &ArcDocumentsProviderRoot::UpdateDirectoryCacheIterWithChildDocuments,
|
| + weak_ptr_factory_.GetWeakPtr(), parent_directory_path, remaining_path,
|
| + callback));
|
| +}
|
| +
|
| +void ArcDocumentsProviderRoot::UpdateDirectoryCacheIterWithChildDocuments(
|
| + const base::FilePath& parent_directory_path,
|
| + const base::FilePath& remaining_path,
|
| + const base::Closure& callback,
|
| + base::Optional<std::vector<mojom::DocumentPtr>> children) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + if (!children) {
|
| + callback.Run();
|
| + return;
|
| + }
|
| +
|
| + ArcDocumentsProviderDocument* parent_directory =
|
| + root_directory_->Lookup(parent_directory_path);
|
| + if (!parent_directory || !parent_directory->is_directory()) {
|
| + callback.Run();
|
| + return;
|
| + }
|
| + parent_directory->UpdateWithChildDocuments(children.value());
|
| +
|
| + if (remaining_path.empty()) {
|
| + callback.Run();
|
| + return;
|
| + }
|
| +
|
| + using Components = std::vector<base::FilePath::StringType>;
|
| + Components components;
|
| + remaining_path.GetComponents(&components);
|
| + DCHECK(!components.empty());
|
| +
|
| + base::FilePath next_parent_directory_path =
|
| + parent_directory_path.Append(components[0]);
|
| + base::FilePath next_remaining_path =
|
| + base::FilePath::FromUTF8Unsafe(base::JoinString(
|
| + Components(components.begin() + 1, components.end()), "/"));
|
| +
|
| + UpdateDirectoryCacheIter(next_parent_directory_path, next_remaining_path,
|
| + callback);
|
| }
|
|
|
| } // namespace arc
|
|
|