diff options
5 files changed, 829 insertions, 789 deletions
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.cc index 126933e..a6f1f90 100644 --- a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.cc +++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.cc @@ -4,207 +4,41 @@ #include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h" -#include <sys/stat.h> -#include <sys/statvfs.h> -#include <sys/types.h> -#include <utime.h> - #include <map> #include "base/bind.h" #include "base/files/file_path.h" #include "base/logging.h" -#include "base/memory/scoped_vector.h" -#include "base/posix/eintr_wrapper.h" -#include "base/strings/stringprintf.h" -#include "base/threading/sequenced_worker_pool.h" #include "base/time/time.h" #include "base/values.h" -#include "chrome/browser/chromeos/drive/drive.pb.h" #include "chrome/browser/chromeos/drive/drive_integration_service.h" -#include "chrome/browser/chromeos/drive/file_system_interface.h" -#include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/chromeos/drive/logging.h" #include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api_factory.h" -#include "chrome/browser/chromeos/extensions/file_manager/file_handler_util.h" #include "chrome/browser/chromeos/extensions/file_manager/file_manager_event_router.h" -#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h" #include "chrome/browser/chromeos/extensions/file_manager/private_api_dialog.h" #include "chrome/browser/chromeos/extensions/file_manager/private_api_drive.h" +#include "chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h" #include "chrome/browser/chromeos/extensions/file_manager/private_api_mount.h" #include "chrome/browser/chromeos/extensions/file_manager/private_api_strings.h" #include "chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h" #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h" #include "chrome/browser/chromeos/extensions/file_manager/zip_file_creator.h" -#include "chrome/browser/chromeos/fileapi/file_system_backend.h" #include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h" #include "chrome/browser/extensions/extension_function_registry.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" -#include "chrome/browser/google_apis/gdata_wapi_parser.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" -#include "chrome/common/extensions/extension_icon_set.h" -#include "chrome/common/extensions/manifest_handlers/icons_handler.h" #include "chrome/common/pref_names.h" -#include "chromeos/disks/disk_mount_manager.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 "content/public/common/page_zoom.h" -#include "net/base/escape.h" -#include "net/base/network_change_notifier.h" -#include "ui/shell_dialogs/selected_file_info.h" #include "url/gurl.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/browser/fileapi/file_system_url.h" -#include "webkit/common/fileapi/file_system_types.h" -#include "webkit/common/fileapi/file_system_util.h" - -using extensions::app_file_handler_util::FindFileHandlersForFiles; -using extensions::app_file_handler_util::PathAndMimeTypeSet; -using chromeos::disks::DiskMountManager; -using content::BrowserContext; -using content::BrowserThread; -using content::ChildProcessSecurityPolicy; -using content::WebContents; -using extensions::Extension; + using extensions::ZipFileCreator; -using fileapi::FileSystemURL; namespace file_manager { -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::ConvertFileToRelativeFileSystemPath( - 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; -} - -// 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; - } - - content::SiteInstance* site_instance = render_view_host->GetSiteInstance(); - fileapi::ExternalFileSystemBackend* backend = - BrowserContext::GetStoragePartition(profile, site_instance)-> - GetFileSystemContext()->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_bfree) * stat.f_frsize; - } -} - -// Retrieves the maximum file name length of the file system of |path|. -// Returns 0 if it could not be queried. -size_t GetFileNameMaxLengthOnBlockingPool(const std::string& path) { - struct statvfs stat = {}; - if (statvfs(path.c_str(), &stat) != 0) { - // The filesystem seems not supporting statvfs(). Assume it to be a commonly - // used bound 255, and log the failure. - LOG(ERROR) << "Cannot statvfs() the name length limit for: " << path; - return 255; - } - return stat.f_namemax; -} - -// Sets last modified date. -bool SetLastModifiedOnBlockingPool(const base::FilePath& local_path, - time_t timestamp) { - if (local_path.empty()) - return false; - - struct stat stat_buffer; - if (stat(local_path.value().c_str(), &stat_buffer) != 0) - return false; - - struct utimbuf times; - times.actime = stat_buffer.st_atime; - times.modtime = timestamp; - return utime(local_path.value().c_str(), ×) == 0; -} - -} // namespace FileBrowserPrivateAPI::FileBrowserPrivateAPI(Profile* profile) : event_router_(new FileManagerEventRouter(profile)) { @@ -242,18 +76,21 @@ FileBrowserPrivateAPI::FileBrowserPrivateAPI(Profile* profile) // Hundreds of strings for the file manager. registry->RegisterFunction<GetStringsFunction>(); - registry->RegisterFunction<LogoutUserFunction>(); - registry->RegisterFunction<GetVolumeMetadataFunction>(); + // File system related functions. registry->RegisterFunction<RequestFileSystemFunction>(); registry->RegisterFunction<AddFileWatchFunction>(); registry->RegisterFunction<RemoveFileWatchFunction>(); + registry->RegisterFunction<SetLastModifiedFunction>(); registry->RegisterFunction<GetSizeStatsFunction>(); + registry->RegisterFunction<GetVolumeMetadataFunction>(); + registry->RegisterFunction<ValidatePathNameLengthFunction>(); registry->RegisterFunction<FormatDeviceFunction>(); + + // Misc functions. + registry->RegisterFunction<LogoutUserFunction>(); registry->RegisterFunction<GetPreferencesFunction>(); registry->RegisterFunction<SetPreferencesFunction>(); - registry->RegisterFunction<SetLastModifiedFunction>(); registry->RegisterFunction<ZipSelectionFunction>(); - registry->RegisterFunction<ValidatePathNameLengthFunction>(); registry->RegisterFunction<ZoomFunction>(); event_router_->ObserveFileSystemEvents(); } @@ -281,385 +118,6 @@ bool LogoutUserFunction::RunImpl() { return true; } -RequestFileSystemFunction::RequestFileSystemFunction() { -} - -RequestFileSystemFunction::~RequestFileSystemFunction() { -} - -void RequestFileSystemFunction::DidOpenFileSystem( - scoped_refptr<fileapi::FileSystemContext> file_system_context, - base::PlatformFileError result, - const std::string& name, - const GURL& root_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (result != base::PLATFORM_FILE_OK) { - DidFail(result); - return; - } - - // RenderViewHost may have gone while the task is posted asynchronously. - if (!render_view_host()) { - DidFail(base::PLATFORM_FILE_ERROR_FAILED); - return; - } - - // 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); - return; - } - - // 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(profile_, extension_id(), render_view_host()); - - DictionaryValue* dict = new DictionaryValue(); - SetResult(dict); - dict->SetString("name", name); - dict->SetString("path", root_path.spec()); - dict->SetInteger("error", drive::FILE_ERROR_OK); - SendResponse(true); -} - -void RequestFileSystemFunction::DidFail( - base::PlatformFileError error_code) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - error_ = base::StringPrintf(kFileError, static_cast<int>(error_code)); - SendResponse(false); -} - -bool RequestFileSystemFunction::SetupFileSystemAccessPermissions( - scoped_refptr<fileapi::FileSystemContext> file_system_context, - int child_id, - scoped_refptr<const extensions::Extension> extension) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (!extension.get()) - return false; - - // Make sure that only component extension can access the entire - // local file system. - if (extension_->location() != extensions::Manifest::COMPONENT) { - NOTREACHED() << "Private method access by non-component extension " - << extension->id(); - return false; - } - - fileapi::ExternalFileSystemBackend* backend = - file_system_context->external_backend(); - if (!backend) - return false; - - // Grant full access to File API from this component extension. - backend->GrantFullAccessToExtension(extension_->id()); - - // Grant R/W file permissions to the renderer hosting component - // extension for all paths exposed by our local file system backend. - std::vector<base::FilePath> root_dirs = backend->GetRootDirectories(); - for (size_t i = 0; i < root_dirs.size(); ++i) { - ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFile( - child_id, root_dirs[i]); - } - return true; -} - -bool RequestFileSystemFunction::RunImpl() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (!dispatcher() || !render_view_host() || !render_view_host()->GetProcess()) - return false; - - set_log_on_completion(true); - - content::SiteInstance* site_instance = render_view_host()->GetSiteInstance(); - scoped_refptr<fileapi::FileSystemContext> file_system_context = - BrowserContext::GetStoragePartition(profile_, site_instance)-> - GetFileSystemContext(); - - const GURL origin_url = source_url_.GetOrigin(); - file_system_context->OpenFileSystem( - origin_url, - fileapi::kFileSystemTypeExternal, - fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, - base::Bind(&RequestFileSystemFunction::DidOpenFileSystem, - this, - file_system_context)); - return true; -} - -FileWatchFunctionBase::FileWatchFunctionBase() { -} - -FileWatchFunctionBase::~FileWatchFunctionBase() { -} - -void FileWatchFunctionBase::Respond(bool success) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - SetResult(Value::CreateBooleanValue(success)); - SendResponse(success); -} - -bool FileWatchFunctionBase::RunImpl() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (!render_view_host() || !render_view_host()->GetProcess()) - return false; - - // First param is url of a file to watch. - std::string url; - if (!args_->GetString(0, &url) || url.empty()) - return false; - - content::SiteInstance* site_instance = render_view_host()->GetSiteInstance(); - scoped_refptr<fileapi::FileSystemContext> file_system_context = - BrowserContext::GetStoragePartition(profile(), site_instance)-> - GetFileSystemContext(); - - FileSystemURL file_watch_url = file_system_context->CrackURL(GURL(url)); - base::FilePath local_path = file_watch_url.path(); - base::FilePath virtual_path = file_watch_url.virtual_path(); - if (local_path.empty()) { - Respond(false); - return true; - } - PerformFileWatchOperation(local_path, virtual_path, extension_id()); - - return true; -} - -AddFileWatchFunction::AddFileWatchFunction() { -} - -AddFileWatchFunction::~AddFileWatchFunction() { -} - -void AddFileWatchFunction::PerformFileWatchOperation( - const base::FilePath& local_path, - const base::FilePath& virtual_path, - const std::string& extension_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - FileManagerEventRouter* event_router = - FileBrowserPrivateAPI::Get(profile_)->event_router(); - event_router->AddFileWatch( - local_path, - virtual_path, - extension_id, - base::Bind(&AddFileWatchFunction::Respond, this)); -} - -RemoveFileWatchFunction::RemoveFileWatchFunction() { -} - -RemoveFileWatchFunction::~RemoveFileWatchFunction() { -} - -void RemoveFileWatchFunction::PerformFileWatchOperation( - const base::FilePath& local_path, - const base::FilePath& unused, - const std::string& extension_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - FileManagerEventRouter* event_router = - FileBrowserPrivateAPI::Get(profile_)->event_router(); - event_router->RemoveFileWatch(local_path, extension_id); - Respond(true); -} - -SetLastModifiedFunction::SetLastModifiedFunction() { -} - -SetLastModifiedFunction::~SetLastModifiedFunction() { -} - -bool SetLastModifiedFunction::RunImpl() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (args_->GetSize() != 2) { - return false; - } - - std::string file_url; - if (!args_->GetString(0, &file_url)) - return false; - - std::string timestamp; - if (!args_->GetString(1, ×tamp)) - return false; - - base::FilePath local_path = GetLocalPathFromURL( - render_view_host(), profile(), GURL(file_url)); - - base::PostTaskAndReplyWithResult( - BrowserThread::GetBlockingPool(), - FROM_HERE, - base::Bind(&SetLastModifiedOnBlockingPool, - local_path, - strtoul(timestamp.c_str(), NULL, 0)), - base::Bind(&SetLastModifiedFunction::SendResponse, - this)); - return true; -} - -GetSizeStatsFunction::GetSizeStatsFunction() { -} - -GetSizeStatsFunction::~GetSizeStatsFunction() { -} - -bool GetSizeStatsFunction::RunImpl() { - if (args_->GetSize() != 1) { - return false; - } - - std::string mount_url; - if (!args_->GetString(0, &mount_url)) - return false; - - base::FilePath file_path = GetLocalPathFromURL( - render_view_host(), profile(), GURL(mount_url)); - if (file_path.empty()) - return false; - - if (file_path == drive::util::GetDriveMountPointPath()) { - drive::DriveIntegrationService* integration_service = - drive::DriveIntegrationServiceFactory::GetForProfile(profile_); - // |integration_service| is NULL if Drive is disabled. - if (!integration_service) { - // If stats couldn't be gotten for drive, result should be left - // undefined. See comments in GetDriveAvailableSpaceCallback(). - SendResponse(true); - return true; - } - - drive::FileSystemInterface* file_system = - integration_service->file_system(); - - file_system->GetAvailableSpace( - base::Bind(&GetSizeStatsFunction::GetDriveAvailableSpaceCallback, - this)); - - } else { - uint64* total_size = new uint64(0); - uint64* remaining_size = new uint64(0); - BrowserThread::PostBlockingPoolTaskAndReply( - FROM_HERE, - base::Bind(&GetSizeStatsOnBlockingPool, - file_path.value(), - total_size, - remaining_size), - base::Bind(&GetSizeStatsFunction::GetSizeStatsCallback, - this, - base::Owned(total_size), - base::Owned(remaining_size))); - } - return true; -} - -void GetSizeStatsFunction::GetDriveAvailableSpaceCallback( - drive::FileError error, - int64 bytes_total, - int64 bytes_used) { - if (error == drive::FILE_ERROR_OK) { - const uint64 bytes_total_unsigned = bytes_total; - const uint64 bytes_remaining_unsigned = bytes_total - bytes_used; - GetSizeStatsCallback(&bytes_total_unsigned, - &bytes_remaining_unsigned); - } else { - // If stats couldn't be gotten for drive, result should be left undefined. - SendResponse(true); - } -} - -void GetSizeStatsFunction::GetSizeStatsCallback( - const uint64* total_size, - const uint64* remaining_size) { - base::DictionaryValue* sizes = new base::DictionaryValue(); - SetResult(sizes); - - sizes->SetDouble("totalSize", static_cast<double>(*total_size)); - sizes->SetDouble("remainingSize", static_cast<double>(*remaining_size)); - - SendResponse(true); -} - -FormatDeviceFunction::FormatDeviceFunction() { -} - -FormatDeviceFunction::~FormatDeviceFunction() { -} - -bool FormatDeviceFunction::RunImpl() { - if (args_->GetSize() != 1) { - return false; - } - - std::string volume_file_url; - if (!args_->GetString(0, &volume_file_url)) { - NOTREACHED(); - return false; - } - - base::FilePath file_path = GetLocalPathFromURL( - render_view_host(), profile(), GURL(volume_file_url)); - if (file_path.empty()) - return false; - - DiskMountManager::GetInstance()->FormatMountedDevice(file_path.value()); - SendResponse(true); - return true; -} - -GetVolumeMetadataFunction::GetVolumeMetadataFunction() { -} - -GetVolumeMetadataFunction::~GetVolumeMetadataFunction() { -} - -bool GetVolumeMetadataFunction::RunImpl() { - if (args_->GetSize() != 1) { - error_ = "Invalid argument count"; - return false; - } - - std::string volume_mount_url; - if (!args_->GetString(0, &volume_mount_url)) { - NOTREACHED(); - return false; - } - - base::FilePath file_path = GetLocalPathFromURL( - render_view_host(), profile(), GURL(volume_mount_url)); - if (file_path.empty()) { - error_ = "Invalid mount path."; - return false; - } - - results_.reset(); - - const DiskMountManager::Disk* volume = GetVolumeAsDisk(file_path.value()); - if (volume) { - DictionaryValue* volume_info = - CreateValueFromDisk(profile_, extension_->id(), volume); - SetResult(volume_info); - } - - SendResponse(true); - return true; -} - GetPreferencesFunction::GetPreferencesFunction() { } @@ -803,54 +261,6 @@ void ZipSelectionFunction::OnZipDone(bool success) { Release(); } -ValidatePathNameLengthFunction::ValidatePathNameLengthFunction() { -} - -ValidatePathNameLengthFunction::~ValidatePathNameLengthFunction() { -} - -bool ValidatePathNameLengthFunction::RunImpl() { - std::string parent_url; - if (!args_->GetString(0, &parent_url)) - return false; - - std::string name; - if (!args_->GetString(1, &name)) - return false; - - content::SiteInstance* site_instance = render_view_host()->GetSiteInstance(); - scoped_refptr<fileapi::FileSystemContext> file_system_context = - BrowserContext::GetStoragePartition(profile(), site_instance)-> - GetFileSystemContext(); - fileapi::FileSystemURL filesystem_url( - file_system_context->CrackURL(GURL(parent_url))); - if (!chromeos::FileSystemBackend::CanHandleURL(filesystem_url)) - return false; - - // No explicit limit on the length of Drive file names. - if (filesystem_url.type() == fileapi::kFileSystemTypeDrive) { - SetResult(new base::FundamentalValue(true)); - SendResponse(true); - return true; - } - - base::PostTaskAndReplyWithResult( - BrowserThread::GetBlockingPool(), - FROM_HERE, - base::Bind(&GetFileNameMaxLengthOnBlockingPool, - filesystem_url.path().AsUTF8Unsafe()), - base::Bind(&ValidatePathNameLengthFunction::OnFilePathLimitRetrieved, - this, name.size())); - return true; -} - -void ValidatePathNameLengthFunction::OnFilePathLimitRetrieved( - size_t current_length, - size_t max_length) { - SetResult(new base::FundamentalValue(current_length <= max_length)); - SendResponse(true); -} - ZoomFunction::ZoomFunction() { } diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h index af4059e..b9e929b 100644 --- a/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h +++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h @@ -11,10 +11,8 @@ #include <vector> #include "base/memory/scoped_ptr.h" -#include "base/platform_file.h" #include "base/prefs/pref_service.h" #include "base/time/time.h" -#include "chrome/browser/chromeos/drive/file_errors.h" #include "chrome/browser/chromeos/extensions/file_manager/private_api_base.h" #include "chrome/browser/chromeos/extensions/file_manager/zip_file_creator.h" #include "chrome/browser/extensions/extension_function.h" @@ -24,10 +22,6 @@ class FileManagerEventRouter; class GURL; class Profile; -namespace fileapi { -class FileSystemContext; -} - namespace file_manager { // Manages and registers the fileBrowserPrivate API with the extension system. @@ -66,173 +60,6 @@ class LogoutUserFunction : public SyncExtensionFunction { virtual bool RunImpl() OVERRIDE; }; -// Implements the chrome.fileBrowserPrivate.requestFileSystem method. -class RequestFileSystemFunction : public LoggedAsyncExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.requestFileSystem", - FILEBROWSERPRIVATE_REQUESTFILESYSTEM) - - RequestFileSystemFunction(); - - protected: - virtual ~RequestFileSystemFunction(); - - // AsyncExtensionFunction overrides. - virtual bool RunImpl() OVERRIDE; - - private: - void RespondSuccessOnUIThread(const std::string& name, - const GURL& root_path); - void RespondFailedOnUIThread(base::PlatformFileError error_code); - - // Called when FileSystemContext::OpenFileSystem() is done. - void DidOpenFileSystem( - scoped_refptr<fileapi::FileSystemContext> file_system_context, - base::PlatformFileError result, - const std::string& name, - const GURL& root_path); - - // Called when something goes wrong. Records the error to |error_| per the - // error code and reports that the private API function failed. - void DidFail(base::PlatformFileError error_code); - - // Sets up file system access permissions to the extension identified by - // |child_id|. - bool SetupFileSystemAccessPermissions( - scoped_refptr<fileapi::FileSystemContext> file_system_context, - int child_id, - scoped_refptr<const extensions::Extension> extension); -}; - -// Base class for AddFileWatchFunction and RemoveFileWatchFunction. Although -// it's called "FileWatch", the class and its sub classes are used only for -// watching changes in directories. -class FileWatchFunctionBase : public LoggedAsyncExtensionFunction { - public: - FileWatchFunctionBase(); - - protected: - virtual ~FileWatchFunctionBase(); - - // Performs a file watch operation (ex. adds or removes a file watch). - virtual void PerformFileWatchOperation( - const base::FilePath& local_path, - const base::FilePath& virtual_path, - const std::string& extension_id) = 0; - - // AsyncExtensionFunction overrides. - virtual bool RunImpl() OVERRIDE; - - // Calls SendResponse() with |success| converted to base::Value. - void Respond(bool success); -}; - -// Implements the chrome.fileBrowserPrivate.addFileWatch method. -// Starts watching changes in directories. -class AddFileWatchFunction : public FileWatchFunctionBase { - public: - DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.addFileWatch", - FILEBROWSERPRIVATE_ADDFILEWATCH) - - AddFileWatchFunction(); - - protected: - virtual ~AddFileWatchFunction(); - - // FileWatchFunctionBase override. - virtual void PerformFileWatchOperation( - const base::FilePath& local_path, - const base::FilePath& virtual_path, - const std::string& extension_id) OVERRIDE; -}; - - -// Implements the chrome.fileBrowserPrivate.removeFileWatch method. -// Stops watching changes in directories. -class RemoveFileWatchFunction : public FileWatchFunctionBase { - public: - DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.removeFileWatch", - FILEBROWSERPRIVATE_REMOVEFILEWATCH) - - RemoveFileWatchFunction(); - - protected: - virtual ~RemoveFileWatchFunction(); - - // FileWatchFunctionBase override. - virtual void PerformFileWatchOperation( - const base::FilePath& local_path, - const base::FilePath& virtual_path, - const std::string& extension_id) OVERRIDE; -}; - -// Formats Device given its mount path. -class FormatDeviceFunction : public LoggedAsyncExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.formatDevice", - FILEBROWSERPRIVATE_FORMATDEVICE) - - FormatDeviceFunction(); - - protected: - virtual ~FormatDeviceFunction(); - - // AsyncExtensionFunction overrides. - virtual bool RunImpl() OVERRIDE; -}; - -// Sets last modified date in seconds of local file -class SetLastModifiedFunction : public LoggedAsyncExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.setLastModified", - FILEBROWSERPRIVATE_SETLASTMODIFIED) - - SetLastModifiedFunction(); - - protected: - virtual ~SetLastModifiedFunction(); - - // AsyncExtensionFunction overrides. - virtual bool RunImpl() OVERRIDE; -}; - -class GetSizeStatsFunction : public LoggedAsyncExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.getSizeStats", - FILEBROWSERPRIVATE_GETSIZESTATS) - - GetSizeStatsFunction(); - - protected: - virtual ~GetSizeStatsFunction(); - - // AsyncExtensionFunction overrides. - virtual bool RunImpl() OVERRIDE; - - private: - void GetDriveAvailableSpaceCallback(drive::FileError error, - int64 bytes_total, - int64 bytes_used); - - void GetSizeStatsCallback(const uint64* total_size, - const uint64* remaining_size); -}; - -// Retrieves devices meta-data. Expects volume's device path as an argument. -class GetVolumeMetadataFunction : public LoggedAsyncExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.getVolumeMetadata", - FILEBROWSERPRIVATE_GETVOLUMEMETADATA) - - GetVolumeMetadataFunction(); - - protected: - virtual ~GetVolumeMetadataFunction(); - - // AsyncExtensionFunction overrides. - virtual bool RunImpl() OVERRIDE; -}; - // Read setting value. class GetPreferencesFunction : public SyncExtensionFunction { public: @@ -283,23 +110,6 @@ class ZipSelectionFunction : public LoggedAsyncExtensionFunction, scoped_refptr<extensions::ZipFileCreator> zip_file_creator_; }; -// Implements the chrome.fileBrowserPrivate.validatePathNameLength method. -class ValidatePathNameLengthFunction : public LoggedAsyncExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.validatePathNameLength", - FILEBROWSERPRIVATE_VALIDATEPATHNAMELENGTH) - - ValidatePathNameLengthFunction(); - - protected: - virtual ~ValidatePathNameLengthFunction(); - - void OnFilePathLimitRetrieved(size_t current_length, size_t max_length); - - // AsyncExtensionFunction overrides. - virtual bool RunImpl() OVERRIDE; -}; - // Changes the zoom level of the file manager by internally calling // RenderViewHost::Zoom(). TODO(hirono): Remove this function once the zoom // level change is supported for all apps. crbug.com/227175. diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc new file mode 100644 index 0000000..15088dc --- /dev/null +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc @@ -0,0 +1,600 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h" + +#include <sys/stat.h> +#include <sys/statvfs.h> +#include <sys/types.h> +#include <utime.h> + +#include "base/posix/eintr_wrapper.h" +#include "base/strings/stringprintf.h" +#include "base/task_runner_util.h" +#include "base/threading/sequenced_worker_pool.h" +#include "chrome/browser/chromeos/drive/drive.pb.h" +#include "chrome/browser/chromeos/drive/drive_integration_service.h" +#include "chrome/browser/chromeos/drive/file_system_interface.h" +#include "chrome/browser/chromeos/drive/file_system_util.h" +#include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h" +#include "chrome/browser/chromeos/extensions/file_manager/file_manager_event_router.h" +#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h" +#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h" +#include "chrome/browser/chromeos/fileapi/file_system_backend.h" +#include "chrome/browser/profiles/profile.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/browser/fileapi/file_system_url.h" +#include "webkit/common/fileapi/file_system_types.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 fileapi::FileSystemURL; + +namespace file_manager { +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::ConvertFileToRelativeFileSystemPath( + 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; +} + +// 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; + } + + content::SiteInstance* site_instance = render_view_host->GetSiteInstance(); + fileapi::ExternalFileSystemBackend* backend = + BrowserContext::GetStoragePartition(profile, site_instance)-> + GetFileSystemContext()->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_bfree) * stat.f_frsize; + } +} + +// Retrieves the maximum file name length of the file system of |path|. +// Returns 0 if it could not be queried. +size_t GetFileNameMaxLengthOnBlockingPool(const std::string& path) { + struct statvfs stat = {}; + if (statvfs(path.c_str(), &stat) != 0) { + // The filesystem seems not supporting statvfs(). Assume it to be a commonly + // used bound 255, and log the failure. + LOG(ERROR) << "Cannot statvfs() the name length limit for: " << path; + return 255; + } + return stat.f_namemax; +} + +// Sets last modified date. +bool SetLastModifiedOnBlockingPool(const base::FilePath& local_path, + time_t timestamp) { + if (local_path.empty()) + return false; + + struct stat stat_buffer; + if (stat(local_path.value().c_str(), &stat_buffer) != 0) + return false; + + struct utimbuf times; + times.actime = stat_buffer.st_atime; + times.modtime = timestamp; + return utime(local_path.value().c_str(), ×) == 0; +} + +} // namespace + +RequestFileSystemFunction::RequestFileSystemFunction() { +} + +RequestFileSystemFunction::~RequestFileSystemFunction() { +} + +void RequestFileSystemFunction::DidOpenFileSystem( + scoped_refptr<fileapi::FileSystemContext> file_system_context, + base::PlatformFileError result, + const std::string& name, + const GURL& root_path) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (result != base::PLATFORM_FILE_OK) { + DidFail(result); + return; + } + + // RenderViewHost may have gone while the task is posted asynchronously. + if (!render_view_host()) { + DidFail(base::PLATFORM_FILE_ERROR_FAILED); + return; + } + + // 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); + return; + } + + // 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(profile_, extension_id(), render_view_host()); + + DictionaryValue* dict = new DictionaryValue(); + SetResult(dict); + dict->SetString("name", name); + dict->SetString("path", root_path.spec()); + dict->SetInteger("error", drive::FILE_ERROR_OK); + SendResponse(true); +} + +void RequestFileSystemFunction::DidFail( + base::PlatformFileError error_code) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + error_ = base::StringPrintf(kFileError, static_cast<int>(error_code)); + SendResponse(false); +} + +bool RequestFileSystemFunction::SetupFileSystemAccessPermissions( + scoped_refptr<fileapi::FileSystemContext> file_system_context, + int child_id, + scoped_refptr<const extensions::Extension> extension) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (!extension.get()) + return false; + + // Make sure that only component extension can access the entire + // local file system. + if (extension_->location() != extensions::Manifest::COMPONENT) { + NOTREACHED() << "Private method access by non-component extension " + << extension->id(); + return false; + } + + fileapi::ExternalFileSystemBackend* backend = + file_system_context->external_backend(); + if (!backend) + return false; + + // Grant full access to File API from this component extension. + backend->GrantFullAccessToExtension(extension_->id()); + + // Grant R/W file permissions to the renderer hosting component + // extension for all paths exposed by our local file system backend. + std::vector<base::FilePath> root_dirs = backend->GetRootDirectories(); + for (size_t i = 0; i < root_dirs.size(); ++i) { + ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFile( + child_id, root_dirs[i]); + } + return true; +} + +bool RequestFileSystemFunction::RunImpl() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (!dispatcher() || !render_view_host() || !render_view_host()->GetProcess()) + return false; + + set_log_on_completion(true); + + content::SiteInstance* site_instance = render_view_host()->GetSiteInstance(); + scoped_refptr<fileapi::FileSystemContext> file_system_context = + BrowserContext::GetStoragePartition(profile_, site_instance)-> + GetFileSystemContext(); + + const GURL origin_url = source_url_.GetOrigin(); + file_system_context->OpenFileSystem( + origin_url, + fileapi::kFileSystemTypeExternal, + fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, + base::Bind(&RequestFileSystemFunction::DidOpenFileSystem, + this, + file_system_context)); + return true; +} + +FileWatchFunctionBase::FileWatchFunctionBase() { +} + +FileWatchFunctionBase::~FileWatchFunctionBase() { +} + +void FileWatchFunctionBase::Respond(bool success) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + SetResult(Value::CreateBooleanValue(success)); + SendResponse(success); +} + +bool FileWatchFunctionBase::RunImpl() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (!render_view_host() || !render_view_host()->GetProcess()) + return false; + + // First param is url of a file to watch. + std::string url; + if (!args_->GetString(0, &url) || url.empty()) + return false; + + content::SiteInstance* site_instance = render_view_host()->GetSiteInstance(); + scoped_refptr<fileapi::FileSystemContext> file_system_context = + BrowserContext::GetStoragePartition(profile(), site_instance)-> + GetFileSystemContext(); + + FileSystemURL file_watch_url = file_system_context->CrackURL(GURL(url)); + base::FilePath local_path = file_watch_url.path(); + base::FilePath virtual_path = file_watch_url.virtual_path(); + if (local_path.empty()) { + Respond(false); + return true; + } + PerformFileWatchOperation(local_path, virtual_path, extension_id()); + + return true; +} + +AddFileWatchFunction::AddFileWatchFunction() { +} + +AddFileWatchFunction::~AddFileWatchFunction() { +} + +void AddFileWatchFunction::PerformFileWatchOperation( + const base::FilePath& local_path, + const base::FilePath& virtual_path, + const std::string& extension_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + FileManagerEventRouter* event_router = + FileBrowserPrivateAPI::Get(profile_)->event_router(); + event_router->AddFileWatch( + local_path, + virtual_path, + extension_id, + base::Bind(&AddFileWatchFunction::Respond, this)); +} + +RemoveFileWatchFunction::RemoveFileWatchFunction() { +} + +RemoveFileWatchFunction::~RemoveFileWatchFunction() { +} + +void RemoveFileWatchFunction::PerformFileWatchOperation( + const base::FilePath& local_path, + const base::FilePath& unused, + const std::string& extension_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + FileManagerEventRouter* event_router = + FileBrowserPrivateAPI::Get(profile_)->event_router(); + event_router->RemoveFileWatch(local_path, extension_id); + Respond(true); +} + +SetLastModifiedFunction::SetLastModifiedFunction() { +} + +SetLastModifiedFunction::~SetLastModifiedFunction() { +} + +bool SetLastModifiedFunction::RunImpl() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (args_->GetSize() != 2) { + return false; + } + + std::string file_url; + if (!args_->GetString(0, &file_url)) + return false; + + std::string timestamp; + if (!args_->GetString(1, ×tamp)) + return false; + + base::FilePath local_path = GetLocalPathFromURL( + render_view_host(), profile(), GURL(file_url)); + + base::PostTaskAndReplyWithResult( + BrowserThread::GetBlockingPool(), + FROM_HERE, + base::Bind(&SetLastModifiedOnBlockingPool, + local_path, + strtoul(timestamp.c_str(), NULL, 0)), + base::Bind(&SetLastModifiedFunction::SendResponse, + this)); + return true; +} + +GetSizeStatsFunction::GetSizeStatsFunction() { +} + +GetSizeStatsFunction::~GetSizeStatsFunction() { +} + +bool GetSizeStatsFunction::RunImpl() { + if (args_->GetSize() != 1) { + return false; + } + + std::string mount_url; + if (!args_->GetString(0, &mount_url)) + return false; + + base::FilePath file_path = GetLocalPathFromURL( + render_view_host(), profile(), GURL(mount_url)); + if (file_path.empty()) + return false; + + if (file_path == drive::util::GetDriveMountPointPath()) { + drive::DriveIntegrationService* integration_service = + drive::DriveIntegrationServiceFactory::GetForProfile(profile_); + // |integration_service| is NULL if Drive is disabled. + if (!integration_service) { + // If stats couldn't be gotten for drive, result should be left + // undefined. See comments in GetDriveAvailableSpaceCallback(). + SendResponse(true); + return true; + } + + drive::FileSystemInterface* file_system = + integration_service->file_system(); + + file_system->GetAvailableSpace( + base::Bind(&GetSizeStatsFunction::GetDriveAvailableSpaceCallback, + this)); + + } else { + uint64* total_size = new uint64(0); + uint64* remaining_size = new uint64(0); + BrowserThread::PostBlockingPoolTaskAndReply( + FROM_HERE, + base::Bind(&GetSizeStatsOnBlockingPool, + file_path.value(), + total_size, + remaining_size), + base::Bind(&GetSizeStatsFunction::GetSizeStatsCallback, + this, + base::Owned(total_size), + base::Owned(remaining_size))); + } + return true; +} + +void GetSizeStatsFunction::GetDriveAvailableSpaceCallback( + drive::FileError error, + int64 bytes_total, + int64 bytes_used) { + if (error == drive::FILE_ERROR_OK) { + const uint64 bytes_total_unsigned = bytes_total; + const uint64 bytes_remaining_unsigned = bytes_total - bytes_used; + GetSizeStatsCallback(&bytes_total_unsigned, + &bytes_remaining_unsigned); + } else { + // If stats couldn't be gotten for drive, result should be left undefined. + SendResponse(true); + } +} + +void GetSizeStatsFunction::GetSizeStatsCallback( + const uint64* total_size, + const uint64* remaining_size) { + base::DictionaryValue* sizes = new base::DictionaryValue(); + SetResult(sizes); + + sizes->SetDouble("totalSize", static_cast<double>(*total_size)); + sizes->SetDouble("remainingSize", static_cast<double>(*remaining_size)); + + SendResponse(true); +} + +GetVolumeMetadataFunction::GetVolumeMetadataFunction() { +} + +GetVolumeMetadataFunction::~GetVolumeMetadataFunction() { +} + +bool GetVolumeMetadataFunction::RunImpl() { + if (args_->GetSize() != 1) { + error_ = "Invalid argument count"; + return false; + } + + std::string volume_mount_url; + if (!args_->GetString(0, &volume_mount_url)) { + NOTREACHED(); + return false; + } + + base::FilePath file_path = GetLocalPathFromURL( + render_view_host(), profile(), GURL(volume_mount_url)); + if (file_path.empty()) { + error_ = "Invalid mount path."; + return false; + } + + results_.reset(); + + const DiskMountManager::Disk* volume = GetVolumeAsDisk(file_path.value()); + if (volume) { + DictionaryValue* volume_info = + CreateValueFromDisk(profile_, extension_->id(), volume); + SetResult(volume_info); + } + + SendResponse(true); + return true; +} + +ValidatePathNameLengthFunction::ValidatePathNameLengthFunction() { +} + +ValidatePathNameLengthFunction::~ValidatePathNameLengthFunction() { +} + +bool ValidatePathNameLengthFunction::RunImpl() { + std::string parent_url; + if (!args_->GetString(0, &parent_url)) + return false; + + std::string name; + if (!args_->GetString(1, &name)) + return false; + + content::SiteInstance* site_instance = render_view_host()->GetSiteInstance(); + scoped_refptr<fileapi::FileSystemContext> file_system_context = + BrowserContext::GetStoragePartition(profile(), site_instance)-> + GetFileSystemContext(); + fileapi::FileSystemURL filesystem_url( + file_system_context->CrackURL(GURL(parent_url))); + if (!chromeos::FileSystemBackend::CanHandleURL(filesystem_url)) + return false; + + // No explicit limit on the length of Drive file names. + if (filesystem_url.type() == fileapi::kFileSystemTypeDrive) { + SetResult(new base::FundamentalValue(true)); + SendResponse(true); + return true; + } + + base::PostTaskAndReplyWithResult( + BrowserThread::GetBlockingPool(), + FROM_HERE, + base::Bind(&GetFileNameMaxLengthOnBlockingPool, + filesystem_url.path().AsUTF8Unsafe()), + base::Bind(&ValidatePathNameLengthFunction::OnFilePathLimitRetrieved, + this, name.size())); + return true; +} + +void ValidatePathNameLengthFunction::OnFilePathLimitRetrieved( + size_t current_length, + size_t max_length) { + SetResult(new base::FundamentalValue(current_length <= max_length)); + SendResponse(true); +} + +FormatDeviceFunction::FormatDeviceFunction() { +} + +FormatDeviceFunction::~FormatDeviceFunction() { +} + +bool FormatDeviceFunction::RunImpl() { + if (args_->GetSize() != 1) { + return false; + } + + std::string volume_file_url; + if (!args_->GetString(0, &volume_file_url)) { + NOTREACHED(); + return false; + } + + base::FilePath file_path = GetLocalPathFromURL( + render_view_host(), profile(), GURL(volume_file_url)); + if (file_path.empty()) + return false; + + DiskMountManager::GetInstance()->FormatMountedDevice(file_path.value()); + SendResponse(true); + return true; +} + +} // namespace file_manager diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h new file mode 100644 index 0000000..d4e4f13 --- /dev/null +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h @@ -0,0 +1,218 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This file provides file system related API functions. + +#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_PRIVATE_API_FILE_SYSTEM_H_ +#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_PRIVATE_API_FILE_SYSTEM_H_ + +#include <string> + +#include "base/platform_file.h" +#include "chrome/browser/chromeos/drive/file_errors.h" +#include "chrome/browser/chromeos/extensions/file_manager/private_api_base.h" + +class GURL; + +namespace base { +class FilePath; +} + +namespace fileapi { +class FileSystemContext; +} + +namespace file_manager { + +// Implements the chrome.fileBrowserPrivate.requestFileSystem method. +class RequestFileSystemFunction : public LoggedAsyncExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.requestFileSystem", + FILEBROWSERPRIVATE_REQUESTFILESYSTEM) + + RequestFileSystemFunction(); + + protected: + virtual ~RequestFileSystemFunction(); + + // AsyncExtensionFunction overrides. + virtual bool RunImpl() OVERRIDE; + + private: + void RespondSuccessOnUIThread(const std::string& name, + const GURL& root_path); + void RespondFailedOnUIThread(base::PlatformFileError error_code); + + // Called when FileSystemContext::OpenFileSystem() is done. + void DidOpenFileSystem( + scoped_refptr<fileapi::FileSystemContext> file_system_context, + base::PlatformFileError result, + const std::string& name, + const GURL& root_path); + + // Called when something goes wrong. Records the error to |error_| per the + // error code and reports that the private API function failed. + void DidFail(base::PlatformFileError error_code); + + // Sets up file system access permissions to the extension identified by + // |child_id|. + bool SetupFileSystemAccessPermissions( + scoped_refptr<fileapi::FileSystemContext> file_system_context, + int child_id, + scoped_refptr<const extensions::Extension> extension); +}; + +// Base class for AddFileWatchFunction and RemoveFileWatchFunction. Although +// it's called "FileWatch", the class and its sub classes are used only for +// watching changes in directories. +class FileWatchFunctionBase : public LoggedAsyncExtensionFunction { + public: + FileWatchFunctionBase(); + + protected: + virtual ~FileWatchFunctionBase(); + + // Performs a file watch operation (ex. adds or removes a file watch). + virtual void PerformFileWatchOperation( + const base::FilePath& local_path, + const base::FilePath& virtual_path, + const std::string& extension_id) = 0; + + // AsyncExtensionFunction overrides. + virtual bool RunImpl() OVERRIDE; + + // Calls SendResponse() with |success| converted to base::Value. + void Respond(bool success); +}; + +// Implements the chrome.fileBrowserPrivate.addFileWatch method. +// Starts watching changes in directories. +class AddFileWatchFunction : public FileWatchFunctionBase { + public: + DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.addFileWatch", + FILEBROWSERPRIVATE_ADDFILEWATCH) + + AddFileWatchFunction(); + + protected: + virtual ~AddFileWatchFunction(); + + // FileWatchFunctionBase override. + virtual void PerformFileWatchOperation( + const base::FilePath& local_path, + const base::FilePath& virtual_path, + const std::string& extension_id) OVERRIDE; +}; + + +// Implements the chrome.fileBrowserPrivate.removeFileWatch method. +// Stops watching changes in directories. +class RemoveFileWatchFunction : public FileWatchFunctionBase { + public: + DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.removeFileWatch", + FILEBROWSERPRIVATE_REMOVEFILEWATCH) + + RemoveFileWatchFunction(); + + protected: + virtual ~RemoveFileWatchFunction(); + + // FileWatchFunctionBase override. + virtual void PerformFileWatchOperation( + const base::FilePath& local_path, + const base::FilePath& virtual_path, + const std::string& extension_id) OVERRIDE; +}; + +// Implements the chrome.fileBrowserPrivate.setLastModified method. +// Sets last modified date in seconds of local file +class SetLastModifiedFunction : public LoggedAsyncExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.setLastModified", + FILEBROWSERPRIVATE_SETLASTMODIFIED) + + SetLastModifiedFunction(); + + protected: + virtual ~SetLastModifiedFunction(); + + // AsyncExtensionFunction overrides. + virtual bool RunImpl() OVERRIDE; +}; + +// Implements the chrome.fileBrowserPrivate.getSizeStats method. +class GetSizeStatsFunction : public LoggedAsyncExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.getSizeStats", + FILEBROWSERPRIVATE_GETSIZESTATS) + + GetSizeStatsFunction(); + + protected: + virtual ~GetSizeStatsFunction(); + + // AsyncExtensionFunction overrides. + virtual bool RunImpl() OVERRIDE; + + private: + void GetDriveAvailableSpaceCallback(drive::FileError error, + int64 bytes_total, + int64 bytes_used); + + void GetSizeStatsCallback(const uint64* total_size, + const uint64* remaining_size); +}; + +// Implements the chrome.fileBrowserPrivate.getVolumeMetadata method. +// Retrieves devices meta-data. Expects volume's device path as an argument. +class GetVolumeMetadataFunction : public LoggedAsyncExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.getVolumeMetadata", + FILEBROWSERPRIVATE_GETVOLUMEMETADATA) + + GetVolumeMetadataFunction(); + + protected: + virtual ~GetVolumeMetadataFunction(); + + // AsyncExtensionFunction overrides. + virtual bool RunImpl() OVERRIDE; +}; + +// Implements the chrome.fileBrowserPrivate.validatePathNameLength method. +class ValidatePathNameLengthFunction : public LoggedAsyncExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.validatePathNameLength", + FILEBROWSERPRIVATE_VALIDATEPATHNAMELENGTH) + + ValidatePathNameLengthFunction(); + + protected: + virtual ~ValidatePathNameLengthFunction(); + + void OnFilePathLimitRetrieved(size_t current_length, size_t max_length); + + // AsyncExtensionFunction overrides. + virtual bool RunImpl() OVERRIDE; +}; + +// Implements the chrome.fileBrowserPrivate.formatDevice method. +// Formats Device given its mount path. +class FormatDeviceFunction : public LoggedAsyncExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.formatDevice", + FILEBROWSERPRIVATE_FORMATDEVICE) + + FormatDeviceFunction(); + + protected: + virtual ~FormatDeviceFunction(); + + // AsyncExtensionFunction overrides. + virtual bool RunImpl() OVERRIDE; +}; + +} // namespace file_manager + +#endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_PRIVATE_API_FILE_SYSTEM_H_ diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index ff7274f..fb7de84 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -843,6 +843,8 @@ 'browser/chromeos/extensions/file_manager/private_api_dialog.h', 'browser/chromeos/extensions/file_manager/private_api_drive.cc', 'browser/chromeos/extensions/file_manager/private_api_drive.h', + 'browser/chromeos/extensions/file_manager/private_api_file_system.cc', + 'browser/chromeos/extensions/file_manager/private_api_file_system.h', 'browser/chromeos/extensions/file_manager/private_api_mount.cc', 'browser/chromeos/extensions/file_manager/private_api_mount.h', 'browser/chromeos/extensions/file_manager/private_api_strings.cc', |