OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h" | 5 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h" |
6 | 6 |
7 #include "base/bind.h" | |
8 #include "base/files/file.h" | |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/ptr_util.h" | |
11 #include "base/strings/string_util.h" | |
12 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_document.h" | |
13 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" | |
14 #include "chrome/browser/chromeos/arc/fileapi/arc_file_system_instance_util.h" | |
8 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
16 #include "url/gurl.h" | |
9 | 17 |
10 using content::BrowserThread; | 18 using content::BrowserThread; |
19 using EntryList = storage::AsyncFileUtil::EntryList; | |
11 | 20 |
12 namespace arc { | 21 namespace arc { |
13 | 22 |
23 namespace { | |
24 | |
25 base::FilePath StripBaseName(const base::FilePath& path) { | |
26 base::FilePath dirname = path.DirName(); | |
27 // 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
| |
28 // contain separators. In this case we want an empty path. | |
29 if (dirname.value() == base::FilePath::kCurrentDirectory) { | |
30 return base::FilePath(); | |
31 } | |
32 return dirname; | |
33 } | |
34 | |
35 } // namespace | |
36 | |
14 ArcDocumentsProviderRoot::ArcDocumentsProviderRoot( | 37 ArcDocumentsProviderRoot::ArcDocumentsProviderRoot( |
15 const std::string& authority, | 38 const std::string& authority, |
16 const std::string& root_document_id) {} | 39 const std::string& root_document_id) |
40 : authority_(authority), | |
41 root_directory_( | |
42 base::MakeUnique<ArcDocumentsProviderDocument>(root_document_id, | |
43 true)), | |
44 weak_ptr_factory_(this) {} | |
17 | 45 |
18 ArcDocumentsProviderRoot::~ArcDocumentsProviderRoot() { | 46 ArcDocumentsProviderRoot::~ArcDocumentsProviderRoot() { |
19 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 47 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
20 } | 48 } |
21 | 49 |
22 void ArcDocumentsProviderRoot::GetFileInfo( | 50 void ArcDocumentsProviderRoot::GetFileInfo( |
23 const base::FilePath& path, | 51 const base::FilePath& path, |
24 const GetFileInfoCallback& callback) { | 52 const GetFileInfoCallback& callback) { |
25 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 53 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
26 NOTIMPLEMENTED(); // TODO(crbug.com/671511): Implement this function. | 54 // 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
| |
55 ArcDocumentsProviderDocument* entry = root_directory_->Lookup(path); | |
56 if (entry) { | |
57 GetFileInfoAfterCacheUpdate(path, callback); | |
58 return; | |
59 } | |
60 DCHECK(!path.empty()); | |
61 UpdateDirectoryCacheUpTo( | |
62 StripBaseName(path), | |
63 base::Bind(&ArcDocumentsProviderRoot::GetFileInfoAfterCacheUpdate, | |
64 weak_ptr_factory_.GetWeakPtr(), path, callback)); | |
27 } | 65 } |
28 | 66 |
29 void ArcDocumentsProviderRoot::ReadDirectory( | 67 void ArcDocumentsProviderRoot::ReadDirectory( |
30 const base::FilePath& path, | 68 const base::FilePath& path, |
31 const ReadDirectoryCallback& callback) { | 69 const ReadDirectoryCallback& callback) { |
32 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 70 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
33 NOTIMPLEMENTED(); // TODO(crbug.com/671511): Implement this function. | 71 if (path.empty()) { |
72 ReadDirectoryAfterCacheUpdate(path, callback); | |
73 return; | |
74 } | |
75 UpdateDirectoryCacheUpTo( | |
76 StripBaseName(path), | |
77 base::Bind(&ArcDocumentsProviderRoot::ReadDirectoryAfterCacheUpdate, | |
78 weak_ptr_factory_.GetWeakPtr(), path, callback)); | |
79 } | |
80 | |
81 void ArcDocumentsProviderRoot::GetFileInfoAfterCacheUpdate( | |
82 const base::FilePath& path, | |
83 const GetFileInfoCallback& callback) { | |
84 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
85 ArcDocumentsProviderDocument* entry = root_directory_->Lookup(path); | |
86 if (!entry) { | |
87 callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info()); | |
88 return; | |
89 } | |
90 file_system_instance_util::GetDocumentOnIOThread( | |
91 authority_, entry->document_id(), | |
92 base::Bind(&ArcDocumentsProviderRoot::GetFileInfoWithDocument, | |
93 weak_ptr_factory_.GetWeakPtr(), callback)); | |
94 } | |
95 | |
96 void ArcDocumentsProviderRoot::GetFileInfoWithDocument( | |
97 const GetFileInfoCallback& callback, | |
98 mojom::DocumentPtr document) { | |
99 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
100 if (document.is_null()) { | |
101 callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info()); | |
102 return; | |
103 } | |
104 | |
105 base::File::Info info; | |
106 info.size = document->size; | |
107 info.is_directory = document->mime_type == kAndroidDirectoryMimeType; | |
108 info.is_symbolic_link = false; | |
109 info.last_modified = info.last_accessed = info.creation_time = | |
110 base::Time::FromJavaTime(document->last_modified); | |
111 callback.Run(base::File::FILE_OK, info); | |
112 } | |
113 | |
114 void ArcDocumentsProviderRoot::ReadDirectoryAfterCacheUpdate( | |
115 const base::FilePath& path, | |
116 const ReadDirectoryCallback& callback) { | |
117 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
118 ArcDocumentsProviderDocument* parent_directory = | |
119 root_directory_->Lookup(path); | |
120 if (!parent_directory || !parent_directory->is_directory()) { | |
121 callback.Run(base::File::FILE_ERROR_NOT_FOUND, EntryList(), | |
122 false /* has_more */); | |
123 return; | |
124 } | |
125 file_system_instance_util::GetChildDocumentsOnIOThread( | |
126 authority_, parent_directory->document_id(), | |
127 base::Bind(&ArcDocumentsProviderRoot::ReadDirectoryWithChildDocuments, | |
128 weak_ptr_factory_.GetWeakPtr(), path, callback)); | |
129 } | |
130 | |
131 void ArcDocumentsProviderRoot::ReadDirectoryWithChildDocuments( | |
132 const base::FilePath& path, | |
133 const ReadDirectoryCallback& callback, | |
134 base::Optional<std::vector<mojom::DocumentPtr>> children) { | |
135 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
136 if (!children) { | |
137 callback.Run(base::File::FILE_ERROR_NOT_FOUND, EntryList(), | |
138 false /* has_more */); | |
139 return; | |
140 } | |
141 | |
142 ArcDocumentsProviderDocument* parent_directory = | |
143 root_directory_->Lookup(path); | |
144 if (!parent_directory || !parent_directory->is_directory()) { | |
145 callback.Run(base::File::FILE_ERROR_NOT_FOUND, EntryList(), | |
146 false /* has_more */); | |
147 return; | |
148 } | |
149 parent_directory->UpdateWithChildDocuments(children.value()); | |
150 | |
151 std::vector<storage::DirectoryEntry> entry_list; | |
152 for (const auto& pair : parent_directory->children()) { | |
153 entry_list.emplace_back(pair.first, pair.second->is_directory() | |
154 ? storage::DirectoryEntry::DIRECTORY | |
155 : storage::DirectoryEntry::FILE); | |
156 } | |
157 callback.Run(base::File::FILE_OK, entry_list, false /* has_more */); | |
158 } | |
159 | |
160 void ArcDocumentsProviderRoot::UpdateDirectoryCacheUpTo( | |
161 const base::FilePath& path, | |
162 const base::Closure& callback) { | |
163 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
164 UpdateDirectoryCacheIter(base::FilePath(), path, callback); | |
165 } | |
166 | |
167 void ArcDocumentsProviderRoot::UpdateDirectoryCacheIter( | |
168 const base::FilePath& parent_directory_path, | |
169 const base::FilePath& remaining_path, | |
170 const base::Closure& callback) { | |
171 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
172 | |
173 ArcDocumentsProviderDocument* parent_directory = | |
174 root_directory_->Lookup(parent_directory_path); | |
175 if (!parent_directory || !parent_directory->is_directory()) { | |
176 callback.Run(); | |
177 return; | |
178 } | |
179 | |
180 file_system_instance_util::GetChildDocumentsOnIOThread( | |
181 authority_, parent_directory->document_id(), | |
182 base::Bind( | |
183 &ArcDocumentsProviderRoot::UpdateDirectoryCacheIterWithChildDocuments, | |
184 weak_ptr_factory_.GetWeakPtr(), parent_directory_path, remaining_path, | |
185 callback)); | |
186 } | |
187 | |
188 void ArcDocumentsProviderRoot::UpdateDirectoryCacheIterWithChildDocuments( | |
189 const base::FilePath& parent_directory_path, | |
190 const base::FilePath& remaining_path, | |
191 const base::Closure& callback, | |
192 base::Optional<std::vector<mojom::DocumentPtr>> children) { | |
193 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
194 if (!children) { | |
195 callback.Run(); | |
196 return; | |
197 } | |
198 | |
199 ArcDocumentsProviderDocument* parent_directory = | |
200 root_directory_->Lookup(parent_directory_path); | |
201 if (!parent_directory || !parent_directory->is_directory()) { | |
202 callback.Run(); | |
203 return; | |
204 } | |
205 parent_directory->UpdateWithChildDocuments(children.value()); | |
206 | |
207 if (remaining_path.empty()) { | |
208 callback.Run(); | |
209 return; | |
210 } | |
211 | |
212 using Components = std::vector<base::FilePath::StringType>; | |
213 Components components; | |
214 remaining_path.GetComponents(&components); | |
215 DCHECK(!components.empty()); | |
216 | |
217 base::FilePath next_parent_directory_path = | |
218 parent_directory_path.Append(components[0]); | |
219 base::FilePath next_remaining_path = | |
220 base::FilePath::FromUTF8Unsafe(base::JoinString( | |
221 Components(components.begin() + 1, components.end()), "/")); | |
222 | |
223 UpdateDirectoryCacheIter(next_parent_directory_path, next_remaining_path, | |
224 callback); | |
34 } | 225 } |
35 | 226 |
36 } // namespace arc | 227 } // namespace arc |
OLD | NEW |