#include "chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h"
#include <sys/statvfs.h>
-#include <sys/types.h>
-#include <utime.h>
-#include "base/path_service.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h"
#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
+#include "chrome/browser/chromeos/file_manager/volume_manager.h"
#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/extensions/api/file_browser_private.h"
+#include "chrome/common/extensions/api/file_browser_private_internal.h"
#include "chromeos/disks/disk_mount_manager.h"
-#include "content/public/browser/browser_context.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/storage_partition.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_file_util.h"
#include "webkit/browser/fileapi/file_system_operation_context.h"
#include "webkit/common/fileapi/file_system_util.h"
using chromeos::disks::DiskMountManager;
-using content::BrowserContext;
using content::BrowserThread;
using content::ChildProcessSecurityPolicy;
-using content::WebContents;
+using file_manager::util::EntryDefinition;
+using file_manager::util::FileDefinition;
using fileapi::FileSystemURL;
namespace extensions {
namespace {
-// Error messages.
-const char kFileError[] = "File error %d";
-
-const DiskMountManager::Disk* GetVolumeAsDisk(const std::string& mount_path) {
- DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
-
- DiskMountManager::MountPointMap::const_iterator mount_point_it =
- disk_mount_manager->mount_points().find(mount_path);
- if (mount_point_it == disk_mount_manager->mount_points().end())
- return NULL;
-
- const DiskMountManager::Disk* disk = disk_mount_manager->FindDiskBySourcePath(
- mount_point_it->second.source_path);
-
- return (disk && disk->is_hidden()) ? NULL : disk;
-}
-
-base::DictionaryValue* CreateValueFromDisk(
- Profile* profile,
- const std::string& extension_id,
- const DiskMountManager::Disk* volume) {
- base::DictionaryValue* volume_info = new base::DictionaryValue();
-
- std::string mount_path;
- if (!volume->mount_path().empty()) {
- base::FilePath relative_mount_path;
- file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
- profile, extension_id, base::FilePath(volume->mount_path()),
- &relative_mount_path);
- mount_path = relative_mount_path.value();
- }
-
- volume_info->SetString("devicePath", volume->device_path());
- volume_info->SetString("mountPath", mount_path);
- volume_info->SetString("systemPath", volume->system_path());
- volume_info->SetString("filePath", volume->file_path());
- volume_info->SetString("deviceLabel", volume->device_label());
- volume_info->SetString("driveLabel", volume->drive_label());
- volume_info->SetString(
- "deviceType",
- DiskMountManager::DeviceTypeToString(volume->device_type()));
- volume_info->SetDouble("totalSize",
- static_cast<double>(volume->total_size_in_bytes()));
- volume_info->SetBoolean("isParent", volume->is_parent());
- volume_info->SetBoolean("isReadOnly", volume->is_read_only());
- volume_info->SetBoolean("hasMedia", volume->has_media());
- volume_info->SetBoolean("isOnBootDevice", volume->on_boot_device());
-
- return volume_info;
-}
-
-base::DictionaryValue* CreateDownloadsVolumeMetadata() {
- base::DictionaryValue* volume_info = new base::DictionaryValue;
- volume_info->SetString("mountPath", "Downloads");
- volume_info->SetBoolean("isReadOnly", false);
- return volume_info;
-}
-
-// Sets permissions for the Drive mount point so Files.app can access files
-// in the mount point directory. It's safe to call this function even if
-// Drive is disabled by the setting (i.e. prefs::kDisableDrive is true).
-void SetDriveMountPointPermissions(
- Profile* profile,
- const std::string& extension_id,
- content::RenderViewHost* render_view_host) {
- if (!render_view_host ||
- !render_view_host->GetSiteInstance() || !render_view_host->GetProcess()) {
- return;
- }
-
- fileapi::ExternalFileSystemBackend* backend =
- file_manager::util::GetFileSystemContextForRenderViewHost(
- profile, render_view_host)->external_backend();
- if (!backend)
- return;
-
- const base::FilePath mount_point = drive::util::GetDriveMountPointPath();
- // Grant R/W permissions to drive 'folder'. File API layer still
- // expects this to be satisfied.
- ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFile(
- render_view_host->GetProcess()->GetID(), mount_point);
-
- base::FilePath mount_point_virtual;
- if (backend->GetVirtualPath(mount_point, &mount_point_virtual))
- backend->GrantFileAccessToExtension(extension_id, mount_point_virtual);
-}
-
// Retrieves total and remaining available size on |mount_path|.
void GetSizeStatsOnBlockingPool(const std::string& mount_path,
uint64* total_size,
uint64* remaining_size) {
struct statvfs stat = {}; // Zero-clear
if (HANDLE_EINTR(statvfs(mount_path.c_str(), &stat)) == 0) {
- *total_size =
- static_cast<uint64>(stat.f_blocks) * stat.f_frsize;
- *remaining_size =
- static_cast<uint64>(stat.f_bavail) * stat.f_frsize;
+ *total_size = static_cast<uint64>(stat.f_blocks) * stat.f_frsize;
+ *remaining_size = static_cast<uint64>(stat.f_bavail) * stat.f_frsize;
}
}
fileapi::FileSystemOperationRunner::OperationID operation_id,
const FileSystemURL& source_url,
const FileSystemURL& destination_url,
- base::PlatformFileError error) {
+ base::File::Error error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
file_manager::EventRouter* event_router =
fileapi::FileSystemOperationRunner::OperationID* operation_id,
const FileSystemURL& source_url,
const FileSystemURL& destination_url,
- base::PlatformFileError error) {
+ base::File::Error error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(
return *operation_id;
}
-void OnCopyCancelled(base::PlatformFileError error) {
+void OnCopyCancelled(base::File::Error error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// We just ignore the status if the copy is actually cancelled or not,
// because failing cancellation means the operation is not running now.
- DLOG_IF(WARNING, error != base::PLATFORM_FILE_OK)
+ DLOG_IF(WARNING, error != base::File::FILE_OK)
<< "Failed to cancel copy: " << error;
}
} // namespace
void FileBrowserPrivateRequestFileSystemFunction::DidFail(
- base::PlatformFileError error_code) {
+ base::File::Error error_code) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- error_ = base::StringPrintf(kFileError, static_cast<int>(error_code));
+ SetError(base::StringPrintf("File error %d", static_cast<int>(error_code)));
SendResponse(false);
}
SetupFileSystemAccessPermissions(
scoped_refptr<fileapi::FileSystemContext> file_system_context,
int child_id,
+ Profile* profile,
scoped_refptr<const extensions::Extension> extension) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFile(
child_id, root_dirs[i]);
}
+
+ // Grant R/W permissions to profile-specific directories (Drive, Downloads)
+ // from other profiles. Those directories may not be mounted at this moment
+ // yet, so we need to do this separately from the above loop over
+ // GetRootDirectories().
+ const std::vector<Profile*>& profiles =
+ g_browser_process->profile_manager()->GetLoadedProfiles();
+ for (size_t i = 0; i < profiles.size(); ++i) {
+ if (!profiles[i]->IsOffTheRecord()) {
+ file_manager::util::SetupProfileFileAccessPermissions(child_id,
+ profiles[i]);
+ }
+ }
+
return true;
}
-bool FileBrowserPrivateRequestFileSystemFunction::RunImpl() {
+bool FileBrowserPrivateRequestFileSystemFunction::RunAsync() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
using extensions::api::file_browser_private::RequestFileSystem::Params;
const scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- // TODO(satorux): Handle the file system ID. crbug.com/284963.
- DCHECK_EQ("compatible", params->file_system_id);
-
if (!dispatcher() || !render_view_host() || !render_view_host()->GetProcess())
return false;
set_log_on_completion(true);
+ using file_manager::VolumeManager;
+ using file_manager::VolumeInfo;
+ VolumeManager* volume_manager = VolumeManager::Get(GetProfile());
+ if (!volume_manager)
+ return false;
+
+ VolumeInfo volume_info;
+ if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info)) {
+ DidFail(base::File::FILE_ERROR_NOT_FOUND);
+ return false;
+ }
+
scoped_refptr<fileapi::FileSystemContext> file_system_context =
file_manager::util::GetFileSystemContextForRenderViewHost(
GetProfile(), render_view_host());
// Set up file permission access.
const int child_id = render_view_host()->GetProcess()->GetID();
- if (!SetupFileSystemAccessPermissions(file_system_context,
- child_id,
- GetExtension())) {
- DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
+ if (!SetupFileSystemAccessPermissions(
+ file_system_context, child_id, GetProfile(), extension())) {
+ DidFail(base::File::FILE_ERROR_SECURITY);
return false;
}
- // Set permissions for the Drive mount point immediately when we kick of
- // first instance of file manager. The actual mount event will be sent to
- // UI only when we perform proper authentication.
- //
- // Note that we call this function even when Drive is disabled by the
- // setting. Otherwise, we need to call this when the setting is changed at
- // a later time, which complicates the code.
- SetDriveMountPointPermissions(
- GetProfile(), extension_id(), render_view_host());
+ FileDefinition file_definition;
+ if (!file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
+ GetProfile(),
+ extension_id(),
+ volume_info.mount_path,
+ &file_definition.virtual_path)) {
+ DidFail(base::File::FILE_ERROR_INVALID_OPERATION);
+ return false;
+ }
+ file_definition.is_directory = true;
+
+ file_manager::util::ConvertFileDefinitionToEntryDefinition(
+ GetProfile(),
+ extension_id(),
+ file_definition,
+ base::Bind(
+ &FileBrowserPrivateRequestFileSystemFunction::OnEntryDefinition,
+ this));
+ return true;
+}
- fileapi::FileSystemInfo info =
- fileapi::GetFileSystemInfoForChromeOS(source_url_.GetOrigin());
+void FileBrowserPrivateRequestFileSystemFunction::OnEntryDefinition(
+ const EntryDefinition& entry_definition) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DictionaryValue* dict = new DictionaryValue();
+ if (entry_definition.error != base::File::FILE_OK) {
+ DidFail(entry_definition.error);
+ return;
+ }
+
+ if (!entry_definition.is_directory) {
+ DidFail(base::File::FILE_ERROR_NOT_A_DIRECTORY);
+ return;
+ }
+
+ base::DictionaryValue* dict = new base::DictionaryValue();
SetResult(dict);
- dict->SetString("name", info.name);
- dict->SetString("root_url", info.root_url.spec());
+ dict->SetString("name", entry_definition.file_system_name);
+ dict->SetString("root_url", entry_definition.file_system_root_url);
dict->SetInteger("error", drive::FILE_ERROR_OK);
SendResponse(true);
- return true;
}
void FileWatchFunctionBase::Respond(bool success) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- SetResult(Value::CreateBooleanValue(success));
+ SetResult(new base::FundamentalValue(success));
SendResponse(success);
}
-bool FileWatchFunctionBase::RunImpl() {
+bool FileWatchFunctionBase::RunAsync() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!render_view_host() || !render_view_host()->GetProcess())
Respond(true);
}
-bool FileBrowserPrivateGetSizeStatsFunction::RunImpl() {
+bool FileBrowserPrivateGetSizeStatsFunction::RunAsync() {
using extensions::api::file_browser_private::GetSizeStats::Params;
const scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- base::FilePath file_path = file_manager::util::GetLocalPathFromURL(
- render_view_host(), GetProfile(), GURL(params->mount_path));
- if (file_path.empty())
+ using file_manager::VolumeManager;
+ using file_manager::VolumeInfo;
+ VolumeManager* volume_manager = VolumeManager::Get(GetProfile());
+ if (!volume_manager)
+ return false;
+
+ VolumeInfo volume_info;
+ if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info))
return false;
- if (file_path == drive::util::GetDriveMountPointPath()) {
+ if (volume_info.type == file_manager::VOLUME_TYPE_GOOGLE_DRIVE) {
drive::FileSystemInterface* file_system =
drive::util::GetFileSystemByProfile(GetProfile());
if (!file_system) {
BrowserThread::PostBlockingPoolTaskAndReply(
FROM_HERE,
base::Bind(&GetSizeStatsOnBlockingPool,
- file_path.value(),
+ volume_info.mount_path.value(),
total_size,
remaining_size),
base::Bind(&FileBrowserPrivateGetSizeStatsFunction::
SendResponse(true);
}
-bool FileBrowserPrivateValidatePathNameLengthFunction::RunImpl() {
+bool FileBrowserPrivateValidatePathNameLengthFunction::RunAsync() {
using extensions::api::file_browser_private::ValidatePathNameLength::Params;
const scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
SendResponse(true);
}
-bool FileBrowserPrivateFormatDeviceFunction::RunImpl() {
- using extensions::api::file_browser_private::FormatDevice::Params;
+bool FileBrowserPrivateFormatVolumeFunction::RunAsync() {
+ using extensions::api::file_browser_private::FormatVolume::Params;
const scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- base::FilePath file_path = file_manager::util::GetLocalPathFromURL(
- render_view_host(), GetProfile(), GURL(params->mount_path));
- if (file_path.empty())
+ using file_manager::VolumeManager;
+ using file_manager::VolumeInfo;
+ VolumeManager* volume_manager = VolumeManager::Get(GetProfile());
+ if (!volume_manager)
+ return false;
+
+ VolumeInfo volume_info;
+ if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info))
return false;
- DiskMountManager::GetInstance()->FormatMountedDevice(file_path.value());
+ DiskMountManager::GetInstance()->FormatMountedDevice(
+ volume_info.mount_path.AsUTF8Unsafe());
SendResponse(true);
return true;
}
-bool FileBrowserPrivateStartCopyFunction::RunImpl() {
+bool FileBrowserPrivateStartCopyFunction::RunAsync() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
using extensions::api::file_browser_private::StartCopy::Params;
if (params->source_url.empty() || params->parent.empty() ||
params->new_name.empty()) {
- error_ = base::IntToString(fileapi::PlatformFileErrorToWebFileError(
- base::PLATFORM_FILE_ERROR_INVALID_URL));
+ // Error code in format of DOMError.name.
+ SetError("EncodingError");
return false;
}
file_manager::util::GetFileSystemContextForRenderViewHost(
GetProfile(), render_view_host());
+ // |parent| may have a trailing slash if it is a root directory.
+ std::string destination_url_string = params->parent;
+ if (destination_url_string[destination_url_string.size() - 1] != '/')
+ destination_url_string += '/';
+ destination_url_string += net::EscapePath(params->new_name);
+
fileapi::FileSystemURL source_url(
file_system_context->CrackURL(GURL(params->source_url)));
- fileapi::FileSystemURL destination_url(file_system_context->CrackURL(
- GURL(params->parent + "/" + params->new_name)));
+ fileapi::FileSystemURL destination_url(
+ file_system_context->CrackURL(GURL(destination_url_string)));
if (!source_url.is_valid() || !destination_url.is_valid()) {
- error_ = base::IntToString(fileapi::PlatformFileErrorToWebFileError(
- base::PLATFORM_FILE_ERROR_INVALID_URL));
+ // Error code in format of DOMError.name.
+ SetError("EncodingError");
return false;
}
int operation_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- SetResult(Value::CreateIntegerValue(operation_id));
+ SetResult(new base::FundamentalValue(operation_id));
SendResponse(true);
}
-bool FileBrowserPrivateCancelCopyFunction::RunImpl() {
+bool FileBrowserPrivateCancelCopyFunction::RunAsync() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- using extensions::api::file_browser_private::CancelCopy::Params;
+ using extensions::api::file_browser_private::CancelCopy::Params;
const scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
return true;
}
+bool FileBrowserPrivateInternalResolveIsolatedEntriesFunction::RunAsync() {
+ using extensions::api::file_browser_private_internal::ResolveIsolatedEntries::
+ Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ scoped_refptr<fileapi::FileSystemContext> file_system_context =
+ file_manager::util::GetFileSystemContextForRenderViewHost(
+ GetProfile(), render_view_host());
+ DCHECK(file_system_context);
+
+ const fileapi::ExternalFileSystemBackend* external_backend =
+ file_system_context->external_backend();
+ DCHECK(external_backend);
+
+ file_manager::util::FileDefinitionList file_definition_list;
+ for (size_t i = 0; i < params->urls.size(); ++i) {
+ FileSystemURL fileSystemUrl =
+ file_system_context->CrackURL(GURL(params->urls[i]));
+ DCHECK(external_backend->CanHandleType(fileSystemUrl.type()));
+
+ FileDefinition file_definition;
+ const bool result =
+ file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
+ GetProfile(),
+ extension_->id(),
+ fileSystemUrl.path(),
+ &file_definition.virtual_path);
+ if (!result)
+ continue;
+ // The API only supports isolated files.
+ file_definition.is_directory = false;
+ file_definition_list.push_back(file_definition);
+ }
+
+ file_manager::util::ConvertFileDefinitionListToEntryDefinitionList(
+ GetProfile(),
+ extension_->id(),
+ file_definition_list, // Safe, since copied internally.
+ base::Bind(
+ &FileBrowserPrivateInternalResolveIsolatedEntriesFunction::
+ RunAsyncAfterConvertFileDefinitionListToEntryDefinitionList,
+ this));
+ return true;
+}
+
+void FileBrowserPrivateInternalResolveIsolatedEntriesFunction::
+ RunAsyncAfterConvertFileDefinitionListToEntryDefinitionList(scoped_ptr<
+ file_manager::util::EntryDefinitionList> entry_definition_list) {
+ using extensions::api::file_browser_private_internal::EntryDescription;
+ std::vector<linked_ptr<EntryDescription> > entries;
+
+ for (size_t i = 0; i < entry_definition_list->size(); ++i) {
+ if (entry_definition_list->at(i).error != base::File::FILE_OK)
+ continue;
+ linked_ptr<EntryDescription> entry(new EntryDescription);
+ entry->file_system_name = entry_definition_list->at(i).file_system_name;
+ entry->file_system_root = entry_definition_list->at(i).file_system_root_url;
+ entry->file_full_path =
+ "/" + entry_definition_list->at(i).full_path.AsUTF8Unsafe();
+ entry->file_is_directory = entry_definition_list->at(i).is_directory;
+ entries.push_back(entry);
+ }
+
+ results_ = extensions::api::file_browser_private_internal::
+ ResolveIsolatedEntries::Results::Create(entries);
+ SendResponse(true);
+}
} // namespace extensions