1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h"
7 #include <sys/statvfs.h>
9 #include "base/posix/eintr_wrapper.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/task_runner_util.h"
13 #include "base/threading/sequenced_worker_pool.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chromeos/drive/drive.pb.h"
16 #include "chrome/browser/chromeos/drive/file_system_interface.h"
17 #include "chrome/browser/chromeos/drive/file_system_util.h"
18 #include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
19 #include "chrome/browser/chromeos/extensions/file_manager/event_router_factory.h"
20 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
21 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
22 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
23 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "chrome/common/extensions/api/file_manager_private.h"
27 #include "chrome/common/extensions/api/file_manager_private_internal.h"
28 #include "chromeos/disks/disk_mount_manager.h"
29 #include "content/public/browser/child_process_security_policy.h"
30 #include "content/public/browser/render_process_host.h"
31 #include "content/public/browser/render_view_host.h"
32 #include "content/public/common/url_constants.h"
33 #include "net/base/escape.h"
34 #include "storage/browser/fileapi/file_system_context.h"
35 #include "storage/browser/fileapi/file_system_file_util.h"
36 #include "storage/browser/fileapi/file_system_operation_context.h"
37 #include "storage/browser/fileapi/file_system_operation_runner.h"
38 #include "storage/browser/fileapi/file_system_url.h"
39 #include "storage/common/fileapi/file_system_info.h"
40 #include "storage/common/fileapi/file_system_types.h"
41 #include "storage/common/fileapi/file_system_util.h"
43 using chromeos::disks::DiskMountManager;
44 using content::BrowserThread;
45 using content::ChildProcessSecurityPolicy;
46 using file_manager::util::EntryDefinition;
47 using file_manager::util::FileDefinition;
48 using storage::FileSystemURL;
50 namespace extensions {
53 // Retrieves total and remaining available size on |mount_path|.
54 void GetSizeStatsOnBlockingPool(const std::string& mount_path,
56 uint64* remaining_size) {
57 struct statvfs stat = {}; // Zero-clear
58 if (HANDLE_EINTR(statvfs(mount_path.c_str(), &stat)) == 0) {
59 *total_size = static_cast<uint64>(stat.f_blocks) * stat.f_frsize;
60 *remaining_size = static_cast<uint64>(stat.f_bavail) * stat.f_frsize;
64 // Retrieves the maximum file name length of the file system of |path|.
65 // Returns 0 if it could not be queried.
66 size_t GetFileNameMaxLengthOnBlockingPool(const std::string& path) {
67 struct statvfs stat = {};
68 if (HANDLE_EINTR(statvfs(path.c_str(), &stat)) != 0) {
69 // The filesystem seems not supporting statvfs(). Assume it to be a commonly
70 // used bound 255, and log the failure.
71 LOG(ERROR) << "Cannot statvfs() the name length limit for: " << path;
74 return stat.f_namemax;
77 // Returns EventRouter for the |profile_id| if available.
78 file_manager::EventRouter* GetEventRouterByProfileId(void* profile_id) {
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
81 // |profile_id| needs to be checked with ProfileManager::IsValidProfile
83 Profile* profile = reinterpret_cast<Profile*>(profile_id);
84 if (!g_browser_process->profile_manager()->IsValidProfile(profile))
87 return file_manager::EventRouterFactory::GetForProfile(profile);
90 // Notifies the copy progress to extensions via event router.
91 void NotifyCopyProgress(
93 storage::FileSystemOperationRunner::OperationID operation_id,
94 storage::FileSystemOperation::CopyProgressType type,
95 const FileSystemURL& source_url,
96 const FileSystemURL& destination_url,
98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
100 file_manager::EventRouter* event_router =
101 GetEventRouterByProfileId(profile_id);
103 event_router->OnCopyProgress(
105 source_url.ToGURL(), destination_url.ToGURL(), size);
109 // Callback invoked periodically on progress update of Copy().
112 storage::FileSystemOperationRunner::OperationID* operation_id,
113 storage::FileSystemOperation::CopyProgressType type,
114 const FileSystemURL& source_url,
115 const FileSystemURL& destination_url,
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
119 BrowserThread::PostTask(
120 BrowserThread::UI, FROM_HERE,
121 base::Bind(&NotifyCopyProgress,
122 profile_id, *operation_id, type,
123 source_url, destination_url, size));
126 // Notifies the copy completion to extensions via event router.
127 void NotifyCopyCompletion(
129 storage::FileSystemOperationRunner::OperationID operation_id,
130 const FileSystemURL& source_url,
131 const FileSystemURL& destination_url,
132 base::File::Error error) {
133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
135 file_manager::EventRouter* event_router =
136 GetEventRouterByProfileId(profile_id);
138 event_router->OnCopyCompleted(
140 source_url.ToGURL(), destination_url.ToGURL(), error);
143 // Callback invoked upon completion of Copy() (regardless of succeeded or
145 void OnCopyCompleted(
147 storage::FileSystemOperationRunner::OperationID* operation_id,
148 const FileSystemURL& source_url,
149 const FileSystemURL& destination_url,
150 base::File::Error error) {
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
153 BrowserThread::PostTask(
154 BrowserThread::UI, FROM_HERE,
155 base::Bind(&NotifyCopyCompletion,
156 profile_id, *operation_id,
157 source_url, destination_url, error));
160 // Starts the copy operation via FileSystemOperationRunner.
161 storage::FileSystemOperationRunner::OperationID StartCopyOnIOThread(
163 scoped_refptr<storage::FileSystemContext> file_system_context,
164 const FileSystemURL& source_url,
165 const FileSystemURL& destination_url) {
166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
168 // Note: |operation_id| is owned by the callback for
169 // FileSystemOperationRunner::Copy(). It is always called in the next message
170 // loop or later, so at least during this invocation it should alive.
171 storage::FileSystemOperationRunner::OperationID* operation_id =
172 new storage::FileSystemOperationRunner::OperationID;
173 *operation_id = file_system_context->operation_runner()->Copy(
176 storage::FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED,
177 base::Bind(&OnCopyProgress, profile_id, base::Unretained(operation_id)),
178 base::Bind(&OnCopyCompleted,
180 base::Owned(operation_id),
183 return *operation_id;
186 void OnCopyCancelled(base::File::Error error) {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
189 // We just ignore the status if the copy is actually cancelled or not,
190 // because failing cancellation means the operation is not running now.
191 DLOG_IF(WARNING, error != base::File::FILE_OK)
192 << "Failed to cancel copy: " << error;
195 // Cancels the running copy operation identified by |operation_id|.
196 void CancelCopyOnIOThread(
197 scoped_refptr<storage::FileSystemContext> file_system_context,
198 storage::FileSystemOperationRunner::OperationID operation_id) {
199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
201 file_system_context->operation_runner()->Cancel(
202 operation_id, base::Bind(&OnCopyCancelled));
205 // Converts a status code to a bool value and calls the |callback| with it.
206 void StatusCallbackToResponseCallback(
207 const base::Callback<void(bool)>& callback,
208 base::File::Error result) {
209 callback.Run(result == base::File::FILE_OK);
214 void FileManagerPrivateRequestFileSystemFunction::DidFail(
215 base::File::Error error_code) {
216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
218 SetError(base::StringPrintf("File error %d", static_cast<int>(error_code)));
223 FileManagerPrivateRequestFileSystemFunction::SetupFileSystemAccessPermissions(
224 scoped_refptr<storage::FileSystemContext> file_system_context,
227 scoped_refptr<const extensions::Extension> extension) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
230 if (!extension.get())
233 storage::ExternalFileSystemBackend* backend =
234 file_system_context->external_backend();
238 // Grant full access to File API from this component extension.
239 backend->GrantFullAccessToExtension(extension_->id());
241 // Grant R/W file permissions to the renderer hosting component
242 // extension for all paths exposed by our local file system backend.
243 std::vector<base::FilePath> root_dirs = backend->GetRootDirectories();
244 for (size_t i = 0; i < root_dirs.size(); ++i) {
245 ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFile(
246 child_id, root_dirs[i]);
249 // Grant R/W permissions to profile-specific directories (Drive, Downloads)
250 // from other profiles. Those directories may not be mounted at this moment
251 // yet, so we need to do this separately from the above loop over
252 // GetRootDirectories().
253 const std::vector<Profile*>& profiles =
254 g_browser_process->profile_manager()->GetLoadedProfiles();
255 for (size_t i = 0; i < profiles.size(); ++i) {
256 if (!profiles[i]->IsOffTheRecord()) {
257 file_manager::util::SetupProfileFileAccessPermissions(child_id,
262 // Grant permission to request externalfile scheme. The permission is needed
263 // to start drag for external file URL.
264 ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
265 child_id, content::kExternalFileScheme);
270 bool FileManagerPrivateRequestFileSystemFunction::RunAsync() {
271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
272 using extensions::api::file_manager_private::RequestFileSystem::Params;
273 const scoped_ptr<Params> params(Params::Create(*args_));
274 EXTENSION_FUNCTION_VALIDATE(params);
276 if (!dispatcher() || !render_view_host() || !render_view_host()->GetProcess())
279 set_log_on_completion(true);
281 using file_manager::VolumeManager;
282 using file_manager::VolumeInfo;
283 VolumeManager* const volume_manager = VolumeManager::Get(GetProfile());
287 VolumeInfo volume_info;
288 if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info)) {
289 DidFail(base::File::FILE_ERROR_NOT_FOUND);
293 scoped_refptr<storage::FileSystemContext> file_system_context =
294 file_manager::util::GetFileSystemContextForRenderViewHost(
295 GetProfile(), render_view_host());
297 // Set up file permission access.
298 const int child_id = render_view_host()->GetProcess()->GetID();
299 if (!SetupFileSystemAccessPermissions(
300 file_system_context, child_id, GetProfile(), extension())) {
301 DidFail(base::File::FILE_ERROR_SECURITY);
305 FileDefinition file_definition;
306 if (!file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
309 volume_info.mount_path,
310 &file_definition.virtual_path)) {
311 DidFail(base::File::FILE_ERROR_INVALID_OPERATION);
314 file_definition.is_directory = true;
316 file_manager::util::ConvertFileDefinitionToEntryDefinition(
321 &FileManagerPrivateRequestFileSystemFunction::OnEntryDefinition,
326 void FileManagerPrivateRequestFileSystemFunction::OnEntryDefinition(
327 const EntryDefinition& entry_definition) {
328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
330 if (entry_definition.error != base::File::FILE_OK) {
331 DidFail(entry_definition.error);
335 if (!entry_definition.is_directory) {
336 DidFail(base::File::FILE_ERROR_NOT_A_DIRECTORY);
340 base::DictionaryValue* dict = new base::DictionaryValue();
342 dict->SetString("name", entry_definition.file_system_name);
343 dict->SetString("root_url", entry_definition.file_system_root_url);
344 dict->SetInteger("error", drive::FILE_ERROR_OK);
348 void FileWatchFunctionBase::Respond(bool success) {
349 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
351 SetResult(new base::FundamentalValue(success));
352 SendResponse(success);
355 bool FileWatchFunctionBase::RunAsync() {
356 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
358 if (!render_view_host() || !render_view_host()->GetProcess())
361 // First param is url of a file to watch.
363 if (!args_->GetString(0, &url) || url.empty())
366 scoped_refptr<storage::FileSystemContext> file_system_context =
367 file_manager::util::GetFileSystemContextForRenderViewHost(
368 GetProfile(), render_view_host());
370 const FileSystemURL file_system_url =
371 file_system_context->CrackURL(GURL(url));
372 if (file_system_url.path().empty()) {
377 PerformFileWatchOperation(file_system_context, file_system_url,
382 void FileManagerPrivateAddFileWatchFunction::PerformFileWatchOperation(
383 scoped_refptr<storage::FileSystemContext> file_system_context,
384 const storage::FileSystemURL& file_system_url,
385 const std::string& extension_id) {
386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
388 file_manager::EventRouter* const event_router =
389 file_manager::EventRouterFactory::GetForProfile(GetProfile());
391 storage::WatcherManager* const watcher_manager =
392 file_system_context->GetWatcherManager(file_system_url.type());
393 if (watcher_manager) {
394 watcher_manager->AddWatcher(
395 file_system_url, false /* recursive */,
397 &StatusCallbackToResponseCallback,
398 base::Bind(&FileManagerPrivateAddFileWatchFunction::Respond, this)),
399 base::Bind(&file_manager::EventRouter::OnWatcherManagerNotification,
400 event_router->GetWeakPtr(), file_system_url, extension_id));
404 // Obsolete. Fallback code if storage::WatcherManager is not implemented.
405 event_router->AddFileWatch(
406 file_system_url.path(), file_system_url.virtual_path(), extension_id,
407 base::Bind(&FileManagerPrivateAddFileWatchFunction::Respond, this));
410 void FileManagerPrivateRemoveFileWatchFunction::PerformFileWatchOperation(
411 scoped_refptr<storage::FileSystemContext> file_system_context,
412 const storage::FileSystemURL& file_system_url,
413 const std::string& extension_id) {
414 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
416 file_manager::EventRouter* const event_router =
417 file_manager::EventRouterFactory::GetForProfile(GetProfile());
419 storage::WatcherManager* const watcher_manager =
420 file_system_context->GetWatcherManager(file_system_url.type());
421 if (watcher_manager) {
422 watcher_manager->RemoveWatcher(
423 file_system_url, false /* recursive */,
424 base::Bind(&StatusCallbackToResponseCallback,
425 base::Bind(&FileWatchFunctionBase::Respond, this)));
429 // Obsolete. Fallback code if storage::WatcherManager is not implemented.
430 event_router->RemoveFileWatch(file_system_url.path(), extension_id);
434 bool FileManagerPrivateGetSizeStatsFunction::RunAsync() {
435 using extensions::api::file_manager_private::GetSizeStats::Params;
436 const scoped_ptr<Params> params(Params::Create(*args_));
437 EXTENSION_FUNCTION_VALIDATE(params);
439 using file_manager::VolumeManager;
440 using file_manager::VolumeInfo;
441 VolumeManager* volume_manager = VolumeManager::Get(GetProfile());
445 VolumeInfo volume_info;
446 if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info))
449 if (volume_info.type == file_manager::VOLUME_TYPE_GOOGLE_DRIVE) {
450 drive::FileSystemInterface* file_system =
451 drive::util::GetFileSystemByProfile(GetProfile());
453 // |file_system| is NULL if Drive is disabled.
454 // If stats couldn't be gotten for drive, result should be left
455 // undefined. See comments in GetDriveAvailableSpaceCallback().
460 file_system->GetAvailableSpace(
461 base::Bind(&FileManagerPrivateGetSizeStatsFunction::
462 GetDriveAvailableSpaceCallback,
465 uint64* total_size = new uint64(0);
466 uint64* remaining_size = new uint64(0);
467 BrowserThread::PostBlockingPoolTaskAndReply(
469 base::Bind(&GetSizeStatsOnBlockingPool,
470 volume_info.mount_path.value(),
473 base::Bind(&FileManagerPrivateGetSizeStatsFunction::
474 GetSizeStatsCallback,
476 base::Owned(total_size),
477 base::Owned(remaining_size)));
482 void FileManagerPrivateGetSizeStatsFunction::GetDriveAvailableSpaceCallback(
483 drive::FileError error,
486 if (error == drive::FILE_ERROR_OK) {
487 const uint64 bytes_total_unsigned = bytes_total;
488 const uint64 bytes_remaining_unsigned = bytes_total - bytes_used;
489 GetSizeStatsCallback(&bytes_total_unsigned,
490 &bytes_remaining_unsigned);
492 // If stats couldn't be gotten for drive, result should be left undefined.
497 void FileManagerPrivateGetSizeStatsFunction::GetSizeStatsCallback(
498 const uint64* total_size,
499 const uint64* remaining_size) {
500 base::DictionaryValue* sizes = new base::DictionaryValue();
503 sizes->SetDouble("totalSize", static_cast<double>(*total_size));
504 sizes->SetDouble("remainingSize", static_cast<double>(*remaining_size));
509 bool FileManagerPrivateValidatePathNameLengthFunction::RunAsync() {
510 using extensions::api::file_manager_private::ValidatePathNameLength::Params;
511 const scoped_ptr<Params> params(Params::Create(*args_));
512 EXTENSION_FUNCTION_VALIDATE(params);
514 scoped_refptr<storage::FileSystemContext> file_system_context =
515 file_manager::util::GetFileSystemContextForRenderViewHost(
516 GetProfile(), render_view_host());
518 storage::FileSystemURL filesystem_url(
519 file_system_context->CrackURL(GURL(params->parent_directory_url)));
520 if (!chromeos::FileSystemBackend::CanHandleURL(filesystem_url))
523 // No explicit limit on the length of Drive file names.
524 if (filesystem_url.type() == storage::kFileSystemTypeDrive) {
525 SetResult(new base::FundamentalValue(true));
530 base::PostTaskAndReplyWithResult(
531 BrowserThread::GetBlockingPool(),
533 base::Bind(&GetFileNameMaxLengthOnBlockingPool,
534 filesystem_url.path().AsUTF8Unsafe()),
535 base::Bind(&FileManagerPrivateValidatePathNameLengthFunction::
536 OnFilePathLimitRetrieved,
537 this, params->name.size()));
541 void FileManagerPrivateValidatePathNameLengthFunction::OnFilePathLimitRetrieved(
542 size_t current_length,
544 SetResult(new base::FundamentalValue(current_length <= max_length));
548 bool FileManagerPrivateFormatVolumeFunction::RunAsync() {
549 using extensions::api::file_manager_private::FormatVolume::Params;
550 const scoped_ptr<Params> params(Params::Create(*args_));
551 EXTENSION_FUNCTION_VALIDATE(params);
553 using file_manager::VolumeManager;
554 using file_manager::VolumeInfo;
555 VolumeManager* volume_manager = VolumeManager::Get(GetProfile());
559 VolumeInfo volume_info;
560 if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info))
563 DiskMountManager::GetInstance()->FormatMountedDevice(
564 volume_info.mount_path.AsUTF8Unsafe());
569 bool FileManagerPrivateStartCopyFunction::RunAsync() {
570 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
572 using extensions::api::file_manager_private::StartCopy::Params;
573 const scoped_ptr<Params> params(Params::Create(*args_));
574 EXTENSION_FUNCTION_VALIDATE(params);
576 if (params->source_url.empty() || params->parent.empty() ||
577 params->new_name.empty()) {
578 // Error code in format of DOMError.name.
579 SetError("EncodingError");
583 scoped_refptr<storage::FileSystemContext> file_system_context =
584 file_manager::util::GetFileSystemContextForRenderViewHost(
585 GetProfile(), render_view_host());
587 // |parent| may have a trailing slash if it is a root directory.
588 std::string destination_url_string = params->parent;
589 if (destination_url_string[destination_url_string.size() - 1] != '/')
590 destination_url_string += '/';
591 destination_url_string += net::EscapePath(params->new_name);
593 storage::FileSystemURL source_url(
594 file_system_context->CrackURL(GURL(params->source_url)));
595 storage::FileSystemURL destination_url(
596 file_system_context->CrackURL(GURL(destination_url_string)));
598 if (!source_url.is_valid() || !destination_url.is_valid()) {
599 // Error code in format of DOMError.name.
600 SetError("EncodingError");
604 return BrowserThread::PostTaskAndReplyWithResult(
607 base::Bind(&StartCopyOnIOThread,
612 base::Bind(&FileManagerPrivateStartCopyFunction::RunAfterStartCopy,
616 void FileManagerPrivateStartCopyFunction::RunAfterStartCopy(
618 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
620 SetResult(new base::FundamentalValue(operation_id));
624 bool FileManagerPrivateCancelCopyFunction::RunAsync() {
625 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
627 using extensions::api::file_manager_private::CancelCopy::Params;
628 const scoped_ptr<Params> params(Params::Create(*args_));
629 EXTENSION_FUNCTION_VALIDATE(params);
631 scoped_refptr<storage::FileSystemContext> file_system_context =
632 file_manager::util::GetFileSystemContextForRenderViewHost(
633 GetProfile(), render_view_host());
635 // We don't much take care about the result of cancellation.
636 BrowserThread::PostTask(
639 base::Bind(&CancelCopyOnIOThread, file_system_context, params->copy_id));
644 bool FileManagerPrivateInternalResolveIsolatedEntriesFunction::RunAsync() {
645 using extensions::api::file_manager_private_internal::ResolveIsolatedEntries::
647 const scoped_ptr<Params> params(Params::Create(*args_));
648 EXTENSION_FUNCTION_VALIDATE(params);
650 scoped_refptr<storage::FileSystemContext> file_system_context =
651 file_manager::util::GetFileSystemContextForRenderViewHost(
652 GetProfile(), render_view_host());
653 DCHECK(file_system_context.get());
655 const storage::ExternalFileSystemBackend* external_backend =
656 file_system_context->external_backend();
657 DCHECK(external_backend);
659 file_manager::util::FileDefinitionList file_definition_list;
660 for (size_t i = 0; i < params->urls.size(); ++i) {
661 FileSystemURL fileSystemUrl =
662 file_system_context->CrackURL(GURL(params->urls[i]));
663 DCHECK(external_backend->CanHandleType(fileSystemUrl.type()));
665 FileDefinition file_definition;
667 file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
670 fileSystemUrl.path(),
671 &file_definition.virtual_path);
674 // The API only supports isolated files.
675 file_definition.is_directory = false;
676 file_definition_list.push_back(file_definition);
679 file_manager::util::ConvertFileDefinitionListToEntryDefinitionList(
682 file_definition_list, // Safe, since copied internally.
684 &FileManagerPrivateInternalResolveIsolatedEntriesFunction::
685 RunAsyncAfterConvertFileDefinitionListToEntryDefinitionList,
690 void FileManagerPrivateInternalResolveIsolatedEntriesFunction::
691 RunAsyncAfterConvertFileDefinitionListToEntryDefinitionList(scoped_ptr<
692 file_manager::util::EntryDefinitionList> entry_definition_list) {
693 using extensions::api::file_manager_private_internal::EntryDescription;
694 std::vector<linked_ptr<EntryDescription> > entries;
696 for (size_t i = 0; i < entry_definition_list->size(); ++i) {
697 if (entry_definition_list->at(i).error != base::File::FILE_OK)
699 linked_ptr<EntryDescription> entry(new EntryDescription);
700 entry->file_system_name = entry_definition_list->at(i).file_system_name;
701 entry->file_system_root = entry_definition_list->at(i).file_system_root_url;
702 entry->file_full_path =
703 "/" + entry_definition_list->at(i).full_path.AsUTF8Unsafe();
704 entry->file_is_directory = entry_definition_list->at(i).is_directory;
705 entries.push_back(entry);
708 results_ = extensions::api::file_manager_private_internal::
709 ResolveIsolatedEntries::Results::Create(entries);
712 } // namespace extensions