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..87cd8b468a6bbee5625dbac532e12596cd8922d3 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,44 @@ |
#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h" |
+#include "base/bind.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 |
hashimoto
2016/12/19 06:40:48
Why don't you give this class absolute paths?
Thi
Shuhei Takahashi
2016/12/19 10:01:56
N/A
hashimoto
2016/12/20 04:55:07
ping?
Shuhei Takahashi
2016/12/20 06:08:24
Oh, since StripBaseName() is removed in the latest
hashimoto
2016/12/20 06:24:18
Thanks for the explanation.
sg
|
+ // 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 +51,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. |
hashimoto
2016/12/19 06:40:48
Caching should consist of two parts: remembering d
Shuhei Takahashi
2016/12/19 10:01:56
N/A
|
+ 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::FromJavaTime(document->last_modified); |
+ 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 |