blob: a6fd97218f7e2003a857de9e73d78fa7bab22649 [file] [log] [blame]
// Copyright (c) 2012 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_browser_private_api.h"
#include <sys/statvfs.h>
#include <utility>
#include "base/base64.h"
#include "base/bind.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/i18n/case_conversion.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/singleton.h"
#include "base/string_split.h"
#include "base/stringprintf.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/extensions/file_handler_util.h"
#include "chrome/browser/chromeos/extensions/file_manager_util.h"
#include "chrome/browser/chromeos/gdata/drive.pb.h"
#include "chrome/browser/chromeos/gdata/drive_file_system_util.h"
#include "chrome/browser/chromeos/gdata/drive_service_interface.h"
#include "chrome/browser/chromeos/gdata/drive_system_service.h"
#include "chrome/browser/chromeos/gdata/drive_webapps_registry.h"
#include "chrome/browser/chromeos/system/statistics_provider.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/process_map.h"
#include "chrome/browser/google_apis/operation_registry.h"
#include "chrome/browser/google_apis/gdata_util.h"
#include "chrome/browser/google_apis/gdata_wapi_parser.h"
#include "chrome/browser/intents/web_intents_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/views/select_file_dialog_extension.h"
#include "chrome/browser/ui/webui/extensions/extension_icon_source.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/file_browser_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 "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "grit/platform_locale_settings.h"
#include "net/base/escape.h"
#include "net/base/mime_util.h"
#include "ui/base/dialogs/selected_file_info.h"
#include "ui/base/l10n/l10n_util.h"
#include "webkit/chromeos/fileapi/cros_mount_point_provider.h"
#include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_file_util.h"
#include "webkit/fileapi/file_system_operation_context.h"
#include "webkit/fileapi/file_system_types.h"
#include "webkit/fileapi/file_system_url.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/glue/web_intent_service_data.h"
using chromeos::disks::DiskMountManager;
using content::BrowserContext;
using content::BrowserThread;
using content::ChildProcessSecurityPolicy;
using content::SiteInstance;
using content::WebContents;
using extensions::Extension;
using file_handler_util::FileTaskExecutor;
using gdata::InstalledApp;
namespace {
// Default icon path for drive docs.
const char kDefaultIcon[] = "images/filetype_generic.png";
const int kPreferredIconSize = 16;
// Error messages.
const char kFileError[] = "File error %d";
const char kInvalidFileUrl[] = "Invalid file URL";
const char kVolumeDevicePathNotFound[] = "Device path not found";
// Unescape rules used for parsing query parameters.
const net::UnescapeRule::Type kUnescapeRuleForQueryParameters =
net::UnescapeRule::SPACES |
net::UnescapeRule::URL_SPECIAL_CHARS |
net::UnescapeRule::REPLACE_PLUS_WITH_SPACE;
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 DiskMountManager::Disk* volume) {
base::DictionaryValue* volume_info = new base::DictionaryValue();
std::string mount_path;
if (!volume->mount_path().empty()) {
FilePath relative_mount_path;
file_manager_util::ConvertFileToRelativeFileSystemPath(profile,
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->SetInteger("totalSize", 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* CreateValueFromMountPoint(Profile* profile,
const DiskMountManager::MountPointInfo& mount_point_info,
const GURL& extension_source_url) {
base::DictionaryValue *mount_info = new base::DictionaryValue();
mount_info->SetString("mountType",
DiskMountManager::MountTypeToString(
mount_point_info.mount_type));
mount_info->SetString("sourcePath", mount_point_info.source_path);
FilePath relative_mount_path;
// Convert mount point path to relative path with the external file system
// exposed within File API.
if (file_manager_util::ConvertFileToRelativeFileSystemPath(profile,
FilePath(mount_point_info.mount_path),
&relative_mount_path)) {
mount_info->SetString("mountPath", relative_mount_path.value());
}
mount_info->SetString("mountCondition",
DiskMountManager::MountConditionToString(
mount_point_info.mount_condition));
return mount_info;
}
// Gives the extension renderer |host| file |permissions| for the given |path|.
void GrantFilePermissionsToHost(content::RenderViewHost* host,
const FilePath& path,
int permissions) {
ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile(
host->GetProcess()->GetID(), path, permissions);
}
void AddDriveMountPoint(
Profile* profile,
const std::string& extension_id,
content::RenderViewHost* render_view_host) {
fileapi::ExternalFileSystemMountPointProvider* provider =
BrowserContext::GetDefaultStoragePartition(profile)->
GetFileSystemContext()->external_provider();
if (!provider)
return;
const FilePath mount_point = gdata::util::GetDriveMountPointPath();
if (!render_view_host || !render_view_host->GetProcess())
return;
// Grant R/W permissions to drive 'folder'. File API layer still
// expects this to be satisfied.
GrantFilePermissionsToHost(render_view_host,
mount_point,
file_handler_util::GetReadWritePermissions());
// Grant R/W permission for tmp and pinned cache folder.
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile);
// |system_service| is NULL if incognito window / guest login.
if (!system_service || !system_service->file_system())
return;
gdata::DriveCache* cache = system_service->cache();
// We check permissions for raw cache file paths only for read-only
// operations (when fileEntry.file() is called), so read only permissions
// should be sufficient for all cache paths. For the rest of supported
// operations the file access check is done for drive/ paths.
GrantFilePermissionsToHost(render_view_host,
cache->GetCacheDirectoryPath(
gdata::DriveCache::CACHE_TYPE_TMP),
file_handler_util::GetReadOnlyPermissions());
GrantFilePermissionsToHost(
render_view_host,
cache->GetCacheDirectoryPath(
gdata::DriveCache::CACHE_TYPE_PERSISTENT),
file_handler_util::GetReadOnlyPermissions());
FilePath mount_point_virtual;
if (provider->GetVirtualPath(mount_point, &mount_point_virtual))
provider->GrantFileAccessToExtension(extension_id, mount_point_virtual);
}
// Finds an icon in the list of icons. If unable to find an icon of the exact
// size requested, returns one with the next larger size. If all icons are
// smaller than the preferred size, we'll return the largest one available.
// Icons must be sorted by the icon size, smallest to largest. If there are no
// icons in the list, returns an empty URL.
GURL FindPreferredIcon(const InstalledApp::IconList& icons,
int preferred_size) {
GURL result;
if (icons.empty())
return result;
result = icons.rbegin()->second;
for (InstalledApp::IconList::const_reverse_iterator iter = icons.rbegin();
iter != icons.rend() && iter->first >= preferred_size; ++iter) {
result = iter->second;
}
return result;
}
// Finds the title of the given Web Intents |action|, if the passed extension
// supports this action for all specified |mime_types|. Returns true and
// provides the |title| as output on success.
bool FindTitleForActionWithTypes(
const Extension* extension,
const std::string& action,
const std::set<std::string>& mime_types,
std::string* title) {
DCHECK(!mime_types.empty());
std::set<std::string> pending(mime_types.begin(), mime_types.end());
std::string found_title;
for (std::vector<webkit_glue::WebIntentServiceData>::const_iterator data =
extension->intents_services().begin();
data != extension->intents_services().end(); ++data) {
if (pending.empty())
break;
if (UTF16ToUTF8(data->action) != action)
continue;
std::set<std::string>::iterator pending_iter = pending.begin();
while (pending_iter != pending.end()) {
std::set<std::string>::iterator current = pending_iter++;
if (net::MatchesMimeType(UTF16ToUTF8(data->type), *current))
pending.erase(current);
}
if (found_title.empty())
found_title = UTF16ToUTF8(data->title);
}
// Not all mime-types have been found.
if (!pending.empty())
return false;
*title = found_title;
return true;
}
// Retrieves total and remaining available size on |mount_path|.
void GetSizeStatsOnFileThread(const std::string& mount_path,
size_t* total_size_kb,
size_t* remaining_size_kb) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
uint64_t total_size_in_bytes = 0;
uint64_t remaining_size_in_bytes = 0;
struct statvfs stat = {}; // Zero-clear
if (statvfs(mount_path.c_str(), &stat) == 0) {
total_size_in_bytes =
static_cast<uint64_t>(stat.f_blocks) * stat.f_frsize;
remaining_size_in_bytes =
static_cast<uint64_t>(stat.f_bfree) * stat.f_frsize;
}
*total_size_kb = static_cast<size_t>(total_size_in_bytes / 1024);
*remaining_size_kb = static_cast<size_t>(remaining_size_in_bytes / 1024);
}
// Given a |url| and a file system type |desired_type|, return the virtual
// FilePath associated with it. If the file isn't of the |desired_type| or can't
// be parsed, then return an empty FilePath.
FilePath GetVirtualPathFromURL(const GURL& url) {
fileapi::FileSystemURL filesystem_url(url);
if (!filesystem_url.is_valid() ||
(filesystem_url.type() != fileapi::kFileSystemTypeDrive &&
filesystem_url.type() != fileapi::kFileSystemTypeNativeMedia &&
filesystem_url.type() != fileapi::kFileSystemTypeNativeLocal)) {
return FilePath();
}
return filesystem_url.virtual_path();
}
// Make a set of unique filename suffixes out of the list of file URLs.
std::set<std::string> GetUniqueSuffixes(base::ListValue* file_url_list) {
std::set<std::string> suffixes;
for (size_t i = 0; i < file_url_list->GetSize(); ++i) {
std::string url;
if (!file_url_list->GetString(i, &url))
return std::set<std::string>();
FilePath path = GetVirtualPathFromURL(GURL(url));
if (path.empty())
return std::set<std::string>();
// We'll skip empty suffixes.
if (!path.Extension().empty())
suffixes.insert(path.Extension());
}
return suffixes;
}
// Make a set of unique MIME types out of the list of MIME types.
std::set<std::string> GetUniqueMimeTypes(base::ListValue* mime_type_list) {
std::set<std::string> mime_types;
for (size_t i = 0; i < mime_type_list->GetSize(); ++i) {
std::string mime_type;
if (!mime_type_list->GetString(i, &mime_type))
return std::set<std::string>();
// We'll skip empty MIME types.
if (!mime_type.empty())
mime_types.insert(mime_type);
}
return mime_types;
}
void LogDefaultTask(const std::set<std::string>& mime_types,
const std::set<std::string>& suffixes,
const std::string& task_id) {
if (!mime_types.empty()) {
std::string mime_types_str;
for (std::set<std::string>::const_iterator iter = mime_types.begin();
iter != mime_types.end(); ++iter) {
if (iter == mime_types.begin()) {
mime_types_str = *iter;
} else {
mime_types_str += ", " + *iter;
}
}
VLOG(1) << "Associating task " << task_id
<< " with the following MIME types: ";
VLOG(1) << " " << mime_types_str;
}
if (!suffixes.empty()) {
std::string suffixes_str;
for (std::set<std::string>::const_iterator iter = suffixes.begin();
iter != suffixes.end(); ++iter) {
if (iter == suffixes.begin()) {
suffixes_str = *iter;
} else {
suffixes_str += ", " + *iter;
}
}
VLOG(1) << "Associating task " << task_id
<< " with the following suffixes: ";
VLOG(1) << " " << suffixes_str;
}
}
} // namespace
class RequestLocalFileSystemFunction::LocalFileSystemCallbackDispatcher {
public:
static fileapi::FileSystemContext::OpenFileSystemCallback CreateCallback(
RequestLocalFileSystemFunction* function,
scoped_refptr<fileapi::FileSystemContext> file_system_context,
int child_id,
scoped_refptr<const Extension> extension) {
return base::Bind(
&LocalFileSystemCallbackDispatcher::DidOpenFileSystem,
base::Owned(new LocalFileSystemCallbackDispatcher(
function, file_system_context, child_id, extension)));
}
void DidOpenFileSystem(base::PlatformFileError result,
const std::string& name,
const GURL& root_path) {
if (result != base::PLATFORM_FILE_OK) {
DidFail(result);
return;
}
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
// Set up file permission access.
if (!SetupFileSystemAccessPermissions()) {
DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
return;
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
&RequestLocalFileSystemFunction::RespondSuccessOnUIThread,
function_,
name,
root_path));
}
void DidFail(base::PlatformFileError error_code) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
&RequestLocalFileSystemFunction::RespondFailedOnUIThread,
function_,
error_code));
}
private:
LocalFileSystemCallbackDispatcher(
RequestLocalFileSystemFunction* function,
scoped_refptr<fileapi::FileSystemContext> file_system_context,
int child_id,
scoped_refptr<const Extension> extension)
: function_(function),
file_system_context_(file_system_context),
child_id_(child_id),
extension_(extension) {
DCHECK(function_);
}
// Grants file system access permissions to file browser component.
bool SetupFileSystemAccessPermissions() {
if (!extension_.get())
return false;
// Make sure that only component extension can access the entire
// local file system.
if (extension_->location() != Extension::COMPONENT) {
NOTREACHED() << "Private method access by non-component extension "
<< extension_->id();
return false;
}
fileapi::ExternalFileSystemMountPointProvider* provider =
file_system_context_->external_provider();
if (!provider)
return false;
// Grant full access to File API from this component extension.
provider->GrantFullAccessToExtension(extension_->id());
// Grant R/W file permissions to the renderer hosting component
// extension for all paths exposed by our local file system provider.
std::vector<FilePath> root_dirs = provider->GetRootDirectories();
for (size_t i = 0; i < root_dirs.size(); ++i) {
ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile(
child_id_, root_dirs[i],
file_handler_util::GetReadWritePermissions());
}
return true;
}
RequestLocalFileSystemFunction* function_;
scoped_refptr<fileapi::FileSystemContext> file_system_context_;
// Renderer process id.
int child_id_;
// Extension source URL.
scoped_refptr<const Extension> extension_;
DISALLOW_COPY_AND_ASSIGN(LocalFileSystemCallbackDispatcher);
};
void RequestLocalFileSystemFunction::RequestOnFileThread(
scoped_refptr<fileapi::FileSystemContext> file_system_context,
const GURL& source_url,
int child_id) {
GURL origin_url = source_url.GetOrigin();
file_system_context->OpenFileSystem(
origin_url, fileapi::kFileSystemTypeExternal, false, // create
LocalFileSystemCallbackDispatcher::CreateCallback(
this,
file_system_context,
child_id,
GetExtension()));
}
bool RequestLocalFileSystemFunction::RunImpl() {
if (!dispatcher() || !render_view_host() || !render_view_host()->GetProcess())
return false;
scoped_refptr<fileapi::FileSystemContext> file_system_context =
BrowserContext::GetDefaultStoragePartition(profile_)->
GetFileSystemContext();
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(
&RequestLocalFileSystemFunction::RequestOnFileThread,
this,
file_system_context,
source_url_,
render_view_host()->GetProcess()->GetID()));
// Will finish asynchronously.
return true;
}
void RequestLocalFileSystemFunction::RespondSuccessOnUIThread(
const std::string& name, const GURL& root_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Add 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.
if (gdata::util::IsGDataAvailable(profile_))
AddDriveMountPoint(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", gdata::DRIVE_FILE_OK);
SendResponse(true);
}
void RequestLocalFileSystemFunction::RespondFailedOnUIThread(
base::PlatformFileError error_code) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
error_ = base::StringPrintf(kFileError, static_cast<int>(error_code));
SendResponse(false);
}
bool FileWatchBrowserFunctionBase::GetLocalFilePath(
const GURL& file_url, FilePath* local_path, FilePath* virtual_path) {
fileapi::FileSystemURL url(file_url);
if (!chromeos::CrosMountPointProvider::CanHandleURL(url))
return false;
*local_path = url.path();
*virtual_path = url.virtual_path();
return true;
}
void FileWatchBrowserFunctionBase::RespondOnUIThread(bool success) {
SetResult(Value::CreateBooleanValue(success));
SendResponse(success);
}
bool FileWatchBrowserFunctionBase::RunImpl() {
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;
GURL file_watch_url(url);
scoped_refptr<fileapi::FileSystemContext> file_system_context =
BrowserContext::GetDefaultStoragePartition(profile_)->
GetFileSystemContext();
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(
&FileWatchBrowserFunctionBase::RunFileWatchOperationOnFileThread,
this,
file_system_context,
FileBrowserEventRouterFactory::GetForProfile(profile_),
file_watch_url,
extension_id()));
return true;
}
void FileWatchBrowserFunctionBase::RunFileWatchOperationOnFileThread(
scoped_refptr<fileapi::FileSystemContext> file_system_context,
scoped_refptr<FileBrowserEventRouter> event_router,
const GURL& file_url, const std::string& extension_id) {
FilePath local_path;
FilePath virtual_path;
if (!GetLocalFilePath(file_url, &local_path, &virtual_path) ||
local_path == FilePath()) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
&FileWatchBrowserFunctionBase::RespondOnUIThread,
this,
false));
}
if (!PerformFileWatchOperation(event_router,
local_path,
virtual_path,
extension_id)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
&FileWatchBrowserFunctionBase::RespondOnUIThread,
this,
false));
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
&FileWatchBrowserFunctionBase::RespondOnUIThread,
this,
true));
}
bool AddFileWatchBrowserFunction::PerformFileWatchOperation(
scoped_refptr<FileBrowserEventRouter> event_router,
const FilePath& local_path, const FilePath& virtual_path,
const std::string& extension_id) {
return event_router->AddFileWatch(local_path, virtual_path, extension_id);
}
bool RemoveFileWatchBrowserFunction::PerformFileWatchOperation(
scoped_refptr<FileBrowserEventRouter> event_router,
const FilePath& local_path, const FilePath& unused,
const std::string& extension_id) {
event_router->RemoveFileWatch(local_path, extension_id);
return true;
}
// static
void GetFileTasksFileBrowserFunction::IntersectAvailableDriveTasks(
gdata::DriveWebAppsRegistry* registry,
const FileInfoList& file_info_list,
WebAppInfoMap* app_info,
std::set<std::string>* available_tasks) {
for (FileInfoList::const_iterator file_iter = file_info_list.begin();
file_iter != file_info_list.end(); ++file_iter) {
if (file_iter->file_path.empty())
continue;
ScopedVector<gdata::DriveWebAppInfo> info;
registry->GetWebAppsForFile(file_iter->file_path,
file_iter->mime_type, &info);
std::vector<gdata::DriveWebAppInfo*> info_ptrs;
info.release(&info_ptrs); // so they don't go away prematurely.
std::set<std::string> tasks_for_this_file;
for (std::vector<gdata::DriveWebAppInfo*>::iterator
apps = info_ptrs.begin(); apps != info_ptrs.end(); ++apps) {
std::pair<WebAppInfoMap::iterator, bool> insert_result =
app_info->insert(std::make_pair((*apps)->app_id, *apps));
// TODO(gspencer): For now, the action id is always "open-with", but we
// could add any actions that the drive app supports.
std::string task_id = file_handler_util::MakeTaskID(
(*apps)->app_id, file_handler_util::kTaskDrive, "open-with");
tasks_for_this_file.insert(task_id);
// If we failed to insert a task_id because there was a duplicate, then we
// must delete it (since we own it).
if (!insert_result.second)
delete *apps;
}
if (file_iter == file_info_list.begin()) {
*available_tasks = tasks_for_this_file;
} else {
std::set<std::string> intersection;
std::set_intersection(available_tasks->begin(),
available_tasks->end(),
tasks_for_this_file.begin(),
tasks_for_this_file.end(),
std::inserter(intersection,
intersection.begin()));
*available_tasks = intersection;
}
}
}
void GetFileTasksFileBrowserFunction::FindDefaultDriveTasks(
const FileInfoList& file_info_list,
const std::set<std::string>& available_tasks,
std::set<std::string>* default_tasks) {
std::set<std::string> default_task_ids;
for (FileInfoList::const_iterator file_iter = file_info_list.begin();
file_iter != file_info_list.end(); ++file_iter) {
std::string task_id = file_handler_util::GetDefaultTaskIdFromPrefs(
profile_, file_iter->mime_type, file_iter->file_path.Extension());
if (available_tasks.find(task_id) != available_tasks.end()) {
VLOG(1) << "Found default task for " << file_iter->file_path.value()
<< ": " << task_id;
default_tasks->insert(task_id);
}
}
}
// static
void GetFileTasksFileBrowserFunction::CreateDriveTasks(
gdata::DriveWebAppsRegistry* registry,
const WebAppInfoMap& app_info,
const std::set<std::string>& available_tasks,
const std::set<std::string>& default_tasks,
ListValue* result_list,
bool* default_already_set) {
*default_already_set = false;
// OK, now we traverse the intersection of available applications for this
// list of files, adding a task for each one that is found.
for (std::set<std::string>::const_iterator app_iter = available_tasks.begin();
app_iter != available_tasks.end(); ++app_iter) {
std::string app_id;
std::string task_type;
bool result = file_handler_util::CrackTaskID(
*app_iter, &app_id, &task_type, NULL);
DCHECK(result) << "Unable to parse Drive task id: " << *app_iter;
DCHECK_EQ(task_type, file_handler_util::kTaskDrive);
WebAppInfoMap::const_iterator info_iter = app_info.find(app_id);
DCHECK(info_iter != app_info.end());
gdata::DriveWebAppInfo* info = info_iter->second;
DictionaryValue* task = new DictionaryValue;
task->SetString("taskId", *app_iter);
task->SetString("title", info->app_name);
GURL best_icon = FindPreferredIcon(info->app_icons,
kPreferredIconSize);
if (!best_icon.is_empty()) {
task->SetString("iconUrl", best_icon.spec());
}
task->SetBoolean("driveApp", true);
// Once we set a default app, we don't want to set any more.
if (!(*default_already_set) &&
default_tasks.find(*app_iter) != default_tasks.end()) {
task->SetBoolean("isDefault", true);
*default_already_set = true;
} else {
task->SetBoolean("isDefault", false);
}
result_list->Append(task);
}
}
// Find special tasks here for Drive (Blox) apps. Iterate through matching drive
// apps and add them, with generated task ids. Extension ids will be the app_ids
// from drive. We'll know that they are drive apps because the extension id will
// begin with kDriveTaskExtensionPrefix.
bool GetFileTasksFileBrowserFunction::FindDriveAppTasks(
const FileInfoList& file_info_list,
ListValue* result_list,
bool* default_already_set) {
if (file_info_list.empty())
return true;
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
// |system_service| is NULL if incognito window / guest login. We return true
// in this case because there might be other extension tasks, even if we don't
// have any to add.
if (!system_service || !system_service->webapps_registry())
return true;
gdata::DriveWebAppsRegistry* registry = system_service->webapps_registry();
// Map of app_id to DriveWebAppInfo so we can look up the apps we've found
// after taking the intersection of available apps.
std::map<std::string, gdata::DriveWebAppInfo*> app_info;
// Set of application IDs. This will end up with the intersection of the
// application IDs that apply to the paths in |file_paths|.
std::set<std::string> available_tasks;
IntersectAvailableDriveTasks(registry, file_info_list,
&app_info, &available_tasks);
std::set<std::string> default_tasks;
FindDefaultDriveTasks(file_info_list, available_tasks, &default_tasks);
CreateDriveTasks(registry, app_info, available_tasks, default_tasks,
result_list, default_already_set);
// We own the pointers in |app_info|, so we need to delete them.
STLDeleteContainerPairSecondPointers(app_info.begin(), app_info.end());
return true;
}
// Find Web Intent platform apps that support the View task, and add them to
// the |result_list|. These will be marked as kTaskWebIntent.
bool GetFileTasksFileBrowserFunction::FindWebIntentTasks(
const std::vector<GURL>& file_urls,
ListValue* result_list) {
DCHECK(!file_urls.empty());
ExtensionService* service = profile_->GetExtensionService();
if (!service)
return false;
std::set<std::string> mime_types;
for (std::vector<GURL>::const_iterator iter = file_urls.begin();
iter != file_urls.end(); ++iter) {
const FilePath file = FilePath(GURL(iter->spec()).ExtractFileName());
const FilePath::StringType file_extension =
StringToLowerASCII(file.Extension());
// TODO(thorogood): Rearchitect this call so it can run on the File thread;
// GetMimeTypeFromFile requires this on Linux. Right now, we use
// Chrome-level knowledge only.
std::string mime_type;
if (file_extension.empty() || !net::GetWellKnownMimeTypeFromExtension(
file_extension.substr(1), &mime_type)) {
// If the file doesn't have an extension or its mime-type cannot be
// determined, then indicate that it has the empty mime-type. This will
// only be matched if the Web Intents accepts "*" or "*/*".
mime_types.insert("");
} else {
mime_types.insert(mime_type);
}
}
for (ExtensionSet::const_iterator iter = service->extensions()->begin();
iter != service->extensions()->end();
++iter) {
const Extension* extension = *iter;
// We don't support using hosted apps to open files.
if (!extension->is_platform_app())
continue;
if (profile_->IsOffTheRecord() &&
!service->IsIncognitoEnabled(extension->id()))
continue;
std::string title;
if (!FindTitleForActionWithTypes(
extension, web_intents::kActionView, mime_types, &title))
continue;
DictionaryValue* task = new DictionaryValue;
std::string task_id = file_handler_util::MakeTaskID(extension->id(),
file_handler_util::kTaskWebIntent, web_intents::kActionView);
task->SetString("taskId", task_id);
task->SetString("title", title);
task->SetBoolean("isDefault", false);
GURL best_icon = extension->GetIconURL(kPreferredIconSize,
ExtensionIconSet::MATCH_BIGGER);
if (!best_icon.is_empty())
task->SetString("iconUrl", best_icon.spec());
else
task->SetString("iconUrl", kDefaultIcon);
task->SetBoolean("driveApp", false);
result_list->Append(task);
}
return true;
}
bool GetFileTasksFileBrowserFunction::RunImpl() {
// First argument is the list of files to get tasks for.
ListValue* files_list = NULL;
if (!args_->GetList(0, &files_list))
return false;
// Second argument is the list of mime types of each of the files in the list.
ListValue* mime_types_list = NULL;
if (!args_->GetList(1, &mime_types_list))
return false;
// MIME types can either be empty, or there needs to be one for each file.
if (mime_types_list->GetSize() != files_list->GetSize() &&
mime_types_list->GetSize() != 0)
return false;
// Collect all the URLs, convert them to GURLs, and crack all the urls into
// file paths.
FileInfoList info_list;
std::vector<GURL> file_urls;
for (size_t i = 0; i < files_list->GetSize(); ++i) {
FileInfo info;
std::string file_url;
if (!files_list->GetString(i, &file_url))
return false;
info.file_url = GURL(file_url);
file_urls.push_back(info.file_url);
if (mime_types_list->GetSize() != 0 &&
!mime_types_list->GetString(i, &info.mime_type))
return false;
fileapi::FileSystemURL file_system_url(info.file_url);
if (chromeos::CrosMountPointProvider::CanHandleURL(file_system_url)) {
info.file_path = file_system_url.path();
}
info_list.push_back(info);
}
ListValue* result_list = new ListValue();
SetResult(result_list);
// Find the Drive apps first, because we want them to take precedence
// when setting the default app.
bool default_already_set = false;
if (!FindDriveAppTasks(info_list, result_list, &default_already_set))
return false;
// Take the union of Drive and extension tasks: Because any Drive tasks we
// found must apply to all of the files (intersection), and because the same
// is true of the extensions, we simply take the union of two lists by adding
// the extension tasks to the Drive task list. We know there aren't duplicates
// because they're entirely different kinds of tasks, but there could be both
// kinds of tasks for a file type (an image file, for instance).
std::set<const FileBrowserHandler*> common_tasks;
std::set<const FileBrowserHandler*> default_tasks;
if (!file_handler_util::FindCommonTasks(profile_, file_urls, &common_tasks))
return false;
file_handler_util::FindDefaultTasks(profile_, file_urls,
common_tasks, &default_tasks);
ExtensionService* service = profile_->GetExtensionService();
for (std::set<const FileBrowserHandler*>::const_iterator iter =
common_tasks.begin();
iter != common_tasks.end();
++iter) {
const FileBrowserHandler* handler = *iter;
const std::string extension_id = handler->extension_id();
const Extension* extension = service->GetExtensionById(extension_id, false);
CHECK(extension);
DictionaryValue* task = new DictionaryValue;
task->SetString("taskId", file_handler_util::MakeTaskID(
extension_id, file_handler_util::kTaskFile, handler->id()));
task->SetString("title", handler->title());
// TODO(zelidrag): Figure out how to expose icon URL that task defined in
// manifest instead of the default extension icon.
GURL icon =
ExtensionIconSource::GetIconURL(extension,
extension_misc::EXTENSION_ICON_BITTY,
ExtensionIconSet::MATCH_BIGGER,
false, NULL); // grayscale
task->SetString("iconUrl", icon.spec());
task->SetBoolean("driveApp", false);
// Only set the default if there isn't already a default set.
if (!default_already_set &&
default_tasks.find(*iter) != default_tasks.end()) {
task->SetBoolean("isDefault", true);
default_already_set = true;
} else {
task->SetBoolean("isDefault", false);
}
result_list->Append(task);
}
// Take the union of Web Intents (that platform apps may accept) and all
// previous Drive and extension tasks. As above, we know there aren't
// duplicates because they're entirely different kinds of tasks.
if (!FindWebIntentTasks(file_urls, result_list))
return false;
if (VLOG_IS_ON(1)) {
std::string result_json;
base::JSONWriter::WriteWithOptions(
result_list,
base::JSONWriter::OPTIONS_DO_NOT_ESCAPE |
base::JSONWriter::OPTIONS_PRETTY_PRINT,
&result_json);
VLOG(1) << "GetFileTasks result:\n" << result_json;
}
SendResponse(true);
return true;
}
ExecuteTasksFileBrowserFunction::ExecuteTasksFileBrowserFunction() {}
void ExecuteTasksFileBrowserFunction::OnTaskExecuted(bool success) {
SendResponse(success);
}
ExecuteTasksFileBrowserFunction::~ExecuteTasksFileBrowserFunction() {}
bool ExecuteTasksFileBrowserFunction::RunImpl() {
// First param is task id that was to the extension with getFileTasks call.
std::string task_id;
if (!args_->GetString(0, &task_id) || !task_id.size())
return false;
// TODO(kaznacheev): Crack the task_id here, store it in the Executor
// and avoid passing it around.
// The second param is the list of files that need to be executed with this
// task.
ListValue* files_list = NULL;
if (!args_->GetList(1, &files_list))
return false;
std::string extension_id;
std::string task_type;
std::string action_id;
if (!file_handler_util::CrackTaskID(
task_id, &extension_id, &task_type, &action_id)) {
LOG(WARNING) << "Invalid task " << task_id;
return false;
}
if (!files_list->GetSize())
return true;
std::vector<GURL> file_urls;
for (size_t i = 0; i < files_list->GetSize(); i++) {
std::string origin_file_url;
if (!files_list->GetString(i, &origin_file_url)) {
error_ = kInvalidFileUrl;
return false;
}
file_urls.push_back(GURL(origin_file_url));
}
scoped_refptr<FileTaskExecutor> executor(
FileTaskExecutor::Create(profile(),
source_url(),
extension_id,
task_type,
action_id));
if (!executor->ExecuteAndNotify(
file_urls,
base::Bind(&ExecuteTasksFileBrowserFunction::OnTaskExecuted, this)))
return false;
SetResult(new base::FundamentalValue(true));
return true;
}
SetDefaultTaskFileBrowserFunction::SetDefaultTaskFileBrowserFunction() {}
SetDefaultTaskFileBrowserFunction::~SetDefaultTaskFileBrowserFunction() {}
bool SetDefaultTaskFileBrowserFunction::RunImpl() {
// First param is task id that was to the extension with setDefaultTask call.
std::string task_id;
if (!args_->GetString(0, &task_id) || !task_id.size())
return false;
base::ListValue* file_url_list;
if (!args_->GetList(1, &file_url_list))
return false;
std::set<std::string> suffixes = GetUniqueSuffixes(file_url_list);
// MIME types are an optional parameter.
base::ListValue* mime_type_list;
std::set<std::string> mime_types;
if (args_->GetList(2, &mime_type_list) && !mime_type_list->empty()) {
if (mime_type_list->GetSize() != file_url_list->GetSize())
return false;
mime_types = GetUniqueMimeTypes(mime_type_list);
}
if (VLOG_IS_ON(1))
LogDefaultTask(mime_types, suffixes, task_id);
// If there weren't any mime_types, and all the suffixes were blank,
// then we "succeed", but don't actually associate with anything.
// Otherwise, any time we set the default on a file with no extension
// on the local drive, we'd fail.
// TODO(gspencer): Fix file manager so that it never tries to set default in
// cases where extensionless local files are part of the selection.
if (suffixes.empty() && mime_types.empty()) {
SetResult(new base::FundamentalValue(true));
return true;
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
&file_handler_util::UpdateDefaultTask,
profile_, task_id, suffixes, mime_types));
SetResult(new base::FundamentalValue(true));
return true;
}
FileBrowserFunction::FileBrowserFunction() {
}
FileBrowserFunction::~FileBrowserFunction() {
}
int32 FileBrowserFunction::GetTabId() const {
if (!dispatcher()) {
LOG(WARNING) << "No dispatcher";
return 0;
}
if (!dispatcher()->delegate()) {
LOG(WARNING) << "No delegate";
return 0;
}
WebContents* web_contents =
dispatcher()->delegate()->GetAssociatedWebContents();
if (!web_contents) {
LOG(WARNING) << "No associated tab contents";
return 0;
}
return ExtensionTabUtil::GetTabId(web_contents);
}
void FileBrowserFunction::GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
const UrlList& file_urls,
GetLocalPathsCallback callback) {
scoped_refptr<fileapi::FileSystemContext> file_system_context =
BrowserContext::GetDefaultStoragePartition(profile())->
GetFileSystemContext();
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(
&FileBrowserFunction::GetLocalPathsOnFileThread,
this,
file_system_context, file_urls, callback));
}
// GetFileSystemRootPathOnFileThread can only be called from the file thread,
// so here we are. This function takes a vector of virtual paths, converts
// them to local paths and calls |callback| with the result vector, on the UI
// thread.
// TODO(kinuko): We no longer call GetFileSystemRootPathOnFileThread and
// we can likely remove this cross-thread helper method.
void FileBrowserFunction::GetLocalPathsOnFileThread(
scoped_refptr<fileapi::FileSystemContext> file_system_context,
const UrlList& file_urls,
GetLocalPathsCallback callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
std::vector<ui::SelectedFileInfo> selected_files;
GURL origin_url = source_url().GetOrigin();
size_t len = file_urls.size();
selected_files.reserve(len);
for (size_t i = 0; i < len; ++i) {
FilePath local_path;
const GURL& file_url = file_urls[i];
// If "localPath" parameter is set, use it as the real path.
// TODO(satorux): Eventually, we should be able to get the real path
// from DriveFileSystem instead of passing through with filesystem
// URLs. crosbug.com/27510.
//
// TODO(satorux): GURL::query() is not yet supported for filesystem:
// URLs. For now, use GURL::spec() to get the query portion. Should
// get rid of the hack once query() is supported: crbug.com/114484.
const std::string::size_type query_start = file_url.spec().find('?');
if (query_start != std::string::npos) {
const std::string query = file_url.spec().substr(query_start + 1);
std::vector<std::pair<std::string, std::string> > parameters;
if (base::SplitStringIntoKeyValuePairs(
query, '=', '&', &parameters)) {
for (size_t i = 0; i < parameters.size(); ++i) {
if (parameters[i].first == "localPath") {
const std::string unescaped_value =
net::UnescapeURLComponent(parameters[i].second,
kUnescapeRuleForQueryParameters);
local_path = FilePath::FromUTF8Unsafe(unescaped_value);
break;
}
}
}
}
// Extract the path from |file_url|.
fileapi::FileSystemURL url(file_url);
if (!chromeos::CrosMountPointProvider::CanHandleURL(url))
continue;
if (!url.path().empty()) {
DVLOG(1) << "Selected: file path: " << url.path().value()
<< " local path: " << local_path.value();
selected_files.push_back(
ui::SelectedFileInfo(url.path(), local_path));
}
}
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(callback, selected_files));
}
bool SelectFileFunction::RunImpl() {
if (args_->GetSize() != 2) {
return false;
}
std::string file_url;
args_->GetString(0, &file_url);
UrlList file_paths;
file_paths.push_back(GURL(file_url));
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_paths,
base::Bind(&SelectFileFunction::GetLocalPathsResponseOnUIThread, this));
return true;
}
void SelectFileFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (files.size() != 1) {
SendResponse(false);
return;
}
int index;
args_->GetInteger(1, &index);
int32 tab_id = GetTabId();
SelectFileDialogExtension::OnFileSelected(tab_id, files[0], index);
SendResponse(true);
}
ViewFilesFunction::ViewFilesFunction() {
}
ViewFilesFunction::~ViewFilesFunction() {
}
bool ViewFilesFunction::RunImpl() {
if (args_->GetSize() < 1) {
return false;
}
ListValue* path_list = NULL;
args_->GetList(0, &path_list);
DCHECK(path_list);
std::string internal_task_id;
args_->GetString(1, &internal_task_id);
std::string virtual_path;
size_t len = path_list->GetSize();
UrlList file_urls;
file_urls.reserve(len);
for (size_t i = 0; i < len; ++i) {
path_list->GetString(i, &virtual_path);
file_urls.push_back(GURL(virtual_path));
}
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_urls,
base::Bind(&ViewFilesFunction::GetLocalPathsResponseOnUIThread,
this,
internal_task_id));
return true;
}
void ViewFilesFunction::GetLocalPathsResponseOnUIThread(
const std::string& internal_task_id,
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
bool success = true;
for (SelectedFileInfoList::const_iterator iter = files.begin();
iter != files.end();
++iter) {
bool handled = file_manager_util::ExecuteBuiltinHandler(
GetCurrentBrowser(), iter->file_path, internal_task_id);
if (!handled && files.size() == 1)
success = false;
}
SetResult(Value::CreateBooleanValue(success));
SendResponse(true);
}
SelectFilesFunction::SelectFilesFunction() {
}
SelectFilesFunction::~SelectFilesFunction() {
}
bool SelectFilesFunction::RunImpl() {
if (args_->GetSize() != 1) {
return false;
}
ListValue* path_list = NULL;
args_->GetList(0, &path_list);
DCHECK(path_list);
std::string virtual_path;
size_t len = path_list->GetSize();
UrlList file_urls;
file_urls.reserve(len);
for (size_t i = 0; i < len; ++i) {
path_list->GetString(i, &virtual_path);
file_urls.push_back(GURL(virtual_path));
}
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_urls,
base::Bind(&SelectFilesFunction::GetLocalPathsResponseOnUIThread, this));
return true;
}
void SelectFilesFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
int32 tab_id = GetTabId();
SelectFileDialogExtension::OnMultiFilesSelected(tab_id, files);
SendResponse(true);
}
bool CancelFileDialogFunction::RunImpl() {
int32 tab_id = GetTabId();
SelectFileDialogExtension::OnFileSelectionCanceled(tab_id);
SendResponse(true);
return true;
}
AddMountFunction::AddMountFunction() {
}
AddMountFunction::~AddMountFunction() {
}
bool AddMountFunction::RunImpl() {
// The third argument is simply ignored.
if (args_->GetSize() != 2 && args_->GetSize() != 3) {
error_ = "Invalid argument count";
return false;
}
std::string file_url;
if (!args_->GetString(0, &file_url)) {
return false;
}
std::string mount_type_str;
if (!args_->GetString(1, &mount_type_str)) {
return false;
}
// Set default return source path to the empty string.
SetResult(Value::CreateStringValue(""));
chromeos::MountType mount_type =
DiskMountManager::MountTypeFromString(mount_type_str);
switch (mount_type) {
case chromeos::MOUNT_TYPE_INVALID: {
error_ = "Invalid mount type";
SendResponse(false);
break;
}
case chromeos::MOUNT_TYPE_GDATA: {
const bool success = true;
// Pass back the drive mount point path as source path.
const std::string& drive_path =
gdata::util::GetDriveMountPointPathAsString();
SetResult(Value::CreateStringValue(drive_path));
FileBrowserEventRouterFactory::GetForProfile(profile_)->
MountDrive(base::Bind(&AddMountFunction::SendResponse,
this,
success));
break;
}
default: {
UrlList file_paths;
file_paths.push_back(GURL(file_url));
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_paths,
base::Bind(&AddMountFunction::GetLocalPathsResponseOnUIThread,
this,
mount_type_str));
break;
}
}
return true;
}
void AddMountFunction::GetLocalPathsResponseOnUIThread(
const std::string& mount_type_str,
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!files.size()) {
SendResponse(false);
return;
}
const FilePath& source_path = files[0].local_path;
const FilePath::StringType& display_name = files[0].display_name;
// Check if the source path is under Drive cache directory.
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
gdata::DriveCache* cache = system_service ? system_service->cache() : NULL;
if (cache && cache->IsUnderDriveCacheDirectory(source_path)) {
cache->SetMountedStateOnUIThread(
source_path,
true,
base::Bind(&AddMountFunction::OnMountedStateSet, this, mount_type_str,
display_name));
} else {
OnMountedStateSet(mount_type_str, display_name,
gdata::DRIVE_FILE_OK, source_path);
}
}
void AddMountFunction::OnMountedStateSet(const std::string& mount_type,
const FilePath::StringType& file_name,
gdata::DriveFileError error,
const FilePath& file_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
// Pass back the actual source path of the mount point.
SetResult(Value::CreateStringValue(file_path.value()));
SendResponse(true);
// MountPath() takes a std::string.
disk_mount_manager->MountPath(file_path.AsUTF8Unsafe(),
FilePath(file_name).Extension(), file_name,
DiskMountManager::MountTypeFromString(
mount_type));
}
RemoveMountFunction::RemoveMountFunction() {
}
RemoveMountFunction::~RemoveMountFunction() {
}
bool RemoveMountFunction::RunImpl() {
if (args_->GetSize() != 1) {
return false;
}
std::string mount_path;
if (!args_->GetString(0, &mount_path)) {
return false;
}
UrlList file_paths;
file_paths.push_back(GURL(mount_path));
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_paths,
base::Bind(&RemoveMountFunction::GetLocalPathsResponseOnUIThread, this));
return true;
}
void RemoveMountFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (files.size() != 1) {
SendResponse(false);
return;
}
DiskMountManager::GetInstance()->UnmountPath(files[0].local_path.value());
SendResponse(true);
}
GetMountPointsFunction::GetMountPointsFunction() {
}
GetMountPointsFunction::~GetMountPointsFunction() {
}
bool GetMountPointsFunction::RunImpl() {
if (args_->GetSize())
return false;
base::ListValue *mounts = new base::ListValue();
SetResult(mounts);
DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
DiskMountManager::MountPointMap mount_points =
disk_mount_manager->mount_points();
for (DiskMountManager::MountPointMap::const_iterator it =
mount_points.begin();
it != mount_points.end();
++it) {
mounts->Append(CreateValueFromMountPoint(profile_, it->second,
source_url_));
}
SendResponse(true);
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;
UrlList mount_paths;
mount_paths.push_back(GURL(mount_url));
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
mount_paths,
base::Bind(&GetSizeStatsFunction::GetLocalPathsResponseOnUIThread, this));
return true;
}
void GetSizeStatsFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (files.size() != 1) {
SendResponse(false);
return;
}
if (files[0].file_path == gdata::util::GetDriveMountPointPath()) {
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
gdata::DriveFileSystemInterface* file_system =
system_service->file_system();
file_system->GetAvailableSpace(
base::Bind(&GetSizeStatsFunction::GetDriveAvailableSpaceCallback,
this));
} else {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(
&GetSizeStatsFunction::CallGetSizeStatsOnFileThread,
this,
files[0].file_path.value()));
}
}
void GetSizeStatsFunction::GetDriveAvailableSpaceCallback(
gdata::DriveFileError error,
int64 bytes_total,
int64 bytes_used) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (error == gdata::DRIVE_FILE_OK) {
int64 bytes_remaining = bytes_total - bytes_used;
GetSizeStatsCallbackOnUIThread(static_cast<size_t>(bytes_total/1024),
static_cast<size_t>(bytes_remaining/1024));
} else {
error_ = base::StringPrintf(kFileError, static_cast<int>(error));
SendResponse(false);
}
}
void GetSizeStatsFunction::CallGetSizeStatsOnFileThread(
const std::string& mount_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
size_t total_size_kb = 0;
size_t remaining_size_kb = 0;
GetSizeStatsOnFileThread(mount_path, &total_size_kb, &remaining_size_kb);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
&GetSizeStatsFunction::GetSizeStatsCallbackOnUIThread,
this,
total_size_kb, remaining_size_kb));
}
void GetSizeStatsFunction::GetSizeStatsCallbackOnUIThread(
size_t total_size_kb,
size_t remaining_size_kb) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
base::DictionaryValue* sizes = new base::DictionaryValue();
SetResult(sizes);
sizes->SetInteger("totalSizeKB", total_size_kb);
sizes->SetInteger("remainingSizeKB", remaining_size_kb);
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;
}
UrlList file_paths;
file_paths.push_back(GURL(volume_file_url));
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_paths,
base::Bind(&FormatDeviceFunction::GetLocalPathsResponseOnUIThread, this));
return true;
}
void FormatDeviceFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (files.size() != 1) {
SendResponse(false);
return;
}
DiskMountManager::GetInstance()->FormatMountedDevice(
files[0].file_path.value());
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();
}
UrlList file_paths;
file_paths.push_back(GURL(volume_mount_url));
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_paths,
base::Bind(&GetVolumeMetadataFunction::GetLocalPathsResponseOnUIThread,
this));
return true;
}
void GetVolumeMetadataFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Should contain volume's mount path.
if (files.size() != 1) {
error_ = "Invalid mount path.";
SendResponse(false);
return;
}
results_.reset();
const DiskMountManager::Disk* volume = GetVolumeAsDisk(
files[0].file_path.value());
if (volume) {
DictionaryValue* volume_info =
CreateValueFromDisk(profile_, volume);
SetResult(volume_info);
}
SendResponse(true);
}
bool ToggleFullscreenFunction::RunImpl() {
Browser* browser = GetCurrentBrowser();
if (browser) {
browser->ToggleFullscreenModeWithExtension(
file_manager_util::GetFileBrowserExtensionUrl());
}
return true;
}
bool IsFullscreenFunction::RunImpl() {
Browser* browser = GetCurrentBrowser();
SetResult(Value::CreateBooleanValue(
browser && browser->window() && browser->window()->IsFullscreen()));
return true;
}
bool FileDialogStringsFunction::RunImpl() {
DictionaryValue* dict = new DictionaryValue();
SetResult(dict);
#define SET_STRING(ns, id) \
dict->SetString(#id, l10n_util::GetStringUTF16(ns##_##id))
SET_STRING(IDS, WEB_FONT_FAMILY);
SET_STRING(IDS, WEB_FONT_SIZE);
SET_STRING(IDS_FILE_BROWSER, ROOT_DIRECTORY_LABEL);
SET_STRING(IDS_FILE_BROWSER, ARCHIVE_DIRECTORY_LABEL);
SET_STRING(IDS_FILE_BROWSER, REMOVABLE_DIRECTORY_LABEL);
SET_STRING(IDS_FILE_BROWSER, DOWNLOADS_DIRECTORY_LABEL);
SET_STRING(IDS_FILE_BROWSER, GDATA_DIRECTORY_LABEL);
SET_STRING(IDS_FILE_BROWSER, NAME_COLUMN_LABEL);
SET_STRING(IDS_FILE_BROWSER, SIZE_COLUMN_LABEL);
SET_STRING(IDS_FILE_BROWSER, SIZE_KB);
SET_STRING(IDS_FILE_BROWSER, SIZE_MB);
SET_STRING(IDS_FILE_BROWSER, SIZE_GB);
SET_STRING(IDS_FILE_BROWSER, SIZE_TB);
SET_STRING(IDS_FILE_BROWSER, SIZE_PB);
SET_STRING(IDS_FILE_BROWSER, SHORTCUT_CTRL);
SET_STRING(IDS_FILE_BROWSER, SHORTCUT_ALT);
SET_STRING(IDS_FILE_BROWSER, SHORTCUT_SHIFT);
SET_STRING(IDS_FILE_BROWSER, SHORTCUT_META);
SET_STRING(IDS_FILE_BROWSER, SHORTCUT_SPACE);
SET_STRING(IDS_FILE_BROWSER, SHORTCUT_ENTER);
SET_STRING(IDS_FILE_BROWSER, TYPE_COLUMN_LABEL);
SET_STRING(IDS_FILE_BROWSER, DATE_COLUMN_LABEL);
SET_STRING(IDS_FILE_BROWSER, PREVIEW_COLUMN_LABEL);
SET_STRING(IDS_FILE_BROWSER, OFFLINE_COLUMN_LABEL);
SET_STRING(IDS_FILE_BROWSER, DOWNLOADS_DIRECTORY_WARNING);
SET_STRING(IDS_FILE_BROWSER, ERROR_CREATING_FOLDER);
SET_STRING(IDS_FILE_BROWSER, ERROR_INVALID_CHARACTER);
SET_STRING(IDS_FILE_BROWSER, ERROR_RESERVED_NAME);
SET_STRING(IDS_FILE_BROWSER, ERROR_HIDDEN_NAME);
SET_STRING(IDS_FILE_BROWSER, ERROR_WHITESPACE_NAME);
SET_STRING(IDS_FILE_BROWSER, ERROR_NEW_FOLDER_EMPTY_NAME);
SET_STRING(IDS_FILE_BROWSER, NEW_FOLDER_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, FILENAME_LABEL);
SET_STRING(IDS_FILE_BROWSER, PREPARING_LABEL);
SET_STRING(IDS_FILE_BROWSER, DIMENSIONS_LABEL);
SET_STRING(IDS_FILE_BROWSER, DIMENSIONS_FORMAT);
SET_STRING(IDS_FILE_BROWSER, IMAGE_DIMENSIONS);
SET_STRING(IDS_FILE_BROWSER, VOLUME_LABEL);
SET_STRING(IDS_FILE_BROWSER, READ_ONLY);
SET_STRING(IDS_FILE_BROWSER, ARCHIVE_MOUNT_FAILED);
SET_STRING(IDS_FILE_BROWSER, UNMOUNT_FAILED);
SET_STRING(IDS_FILE_BROWSER, MOUNT_ARCHIVE);
SET_STRING(IDS_FILE_BROWSER, FORMAT_DEVICE_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, UNMOUNT_DEVICE_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, IMPORT_PHOTOS_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, SEARCH_TEXT_LABEL);
SET_STRING(IDS_FILE_BROWSER, ACTION_VIEW);
SET_STRING(IDS_FILE_BROWSER, ACTION_OPEN);
SET_STRING(IDS_FILE_BROWSER, ACTION_OPEN_GDOC);
SET_STRING(IDS_FILE_BROWSER, ACTION_OPEN_GSHEET);
SET_STRING(IDS_FILE_BROWSER, ACTION_OPEN_GSLIDES);
SET_STRING(IDS_FILE_BROWSER, ACTION_WATCH);
SET_STRING(IDS_FILE_BROWSER, ACTION_LISTEN);
SET_STRING(IDS_FILE_BROWSER, INSTALL_CRX);
SET_STRING(IDS_FILE_BROWSER, SEND_TO_DRIVE);
SET_STRING(IDS_FILE_BROWSER, GALLERY_NO_IMAGES);
SET_STRING(IDS_FILE_BROWSER, GALLERY_ITEMS_SELECTED);
SET_STRING(IDS_FILE_BROWSER, GALLERY_MOSAIC);
SET_STRING(IDS_FILE_BROWSER, GALLERY_SLIDE);
SET_STRING(IDS_FILE_BROWSER, GALLERY_DELETE);
SET_STRING(IDS_FILE_BROWSER, GALLERY_SLIDESHOW);
SET_STRING(IDS_FILE_BROWSER, GALLERY_SLIDESHOW_PAUSED);
SET_STRING(IDS_FILE_BROWSER, GALLERY_EDIT);
SET_STRING(IDS_FILE_BROWSER, GALLERY_SHARE);
SET_STRING(IDS_FILE_BROWSER, GALLERY_ENTER_WHEN_DONE);
SET_STRING(IDS_FILE_BROWSER, GALLERY_AUTOFIX);
SET_STRING(IDS_FILE_BROWSER, GALLERY_FIXED);
SET_STRING(IDS_FILE_BROWSER, GALLERY_CROP);
SET_STRING(IDS_FILE_BROWSER, GALLERY_EXPOSURE);
SET_STRING(IDS_FILE_BROWSER, GALLERY_BRIGHTNESS);
SET_STRING(IDS_FILE_BROWSER, GALLERY_CONTRAST);
SET_STRING(IDS_FILE_BROWSER, GALLERY_ROTATE_LEFT);
SET_STRING(IDS_FILE_BROWSER, GALLERY_ROTATE_RIGHT);
SET_STRING(IDS_FILE_BROWSER, GALLERY_UNDO);
SET_STRING(IDS_FILE_BROWSER, GALLERY_REDO);
SET_STRING(IDS_FILE_BROWSER, GALLERY_FILE_EXISTS);
SET_STRING(IDS_FILE_BROWSER, GALLERY_SAVED);
SET_STRING(IDS_FILE_BROWSER, GALLERY_OVERWRITE_ORIGINAL);
SET_STRING(IDS_FILE_BROWSER, GALLERY_OVERWRITE_BUBBLE);
SET_STRING(IDS_FILE_BROWSER, GALLERY_UNSAVED_CHANGES);
SET_STRING(IDS_FILE_BROWSER, GALLERY_READONLY_WARNING);
SET_STRING(IDS_FILE_BROWSER, GALLERY_IMAGE_ERROR);
SET_STRING(IDS_FILE_BROWSER, GALLERY_VIDEO_ERROR);
SET_STRING(IDS_FILE_BROWSER, AUDIO_ERROR);
SET_STRING(IDS_FILE_BROWSER, GALLERY_IMAGE_OFFLINE);
SET_STRING(IDS_FILE_BROWSER, GALLERY_VIDEO_OFFLINE);
SET_STRING(IDS_FILE_BROWSER, AUDIO_OFFLINE);
// Reusing strings, but with alias starting with GALLERY.
dict->SetString("GALLERY_FILE_HIDDEN_NAME",
l10n_util::GetStringUTF16(IDS_FILE_BROWSER_ERROR_HIDDEN_NAME));
dict->SetString("GALLERY_OK_LABEL",
l10n_util::GetStringUTF16(IDS_FILE_BROWSER_OK_LABEL));
dict->SetString("GALLERY_CANCEL_LABEL",
l10n_util::GetStringUTF16(IDS_FILE_BROWSER_CANCEL_LABEL));
dict->SetString("GALLERY_CONFIRM_DELETE_ONE",
l10n_util::GetStringUTF16(IDS_FILE_BROWSER_CONFIRM_DELETE_ONE));
dict->SetString("GALLERY_CONFIRM_DELETE_SOME",
l10n_util::GetStringUTF16(IDS_FILE_BROWSER_CONFIRM_DELETE_SOME));
SET_STRING(IDS_FILE_BROWSER, ACTION_CHOICE_PHOTOS_DRIVE);
SET_STRING(IDS_FILE_BROWSER, ACTION_CHOICE_VIEW_FILES);
SET_STRING(IDS_FILE_BROWSER, ACTION_CHOICE_WATCH_SINGLE_VIDEO);
SET_STRING(IDS_FILE_BROWSER, ACTION_CHOICE_OK);
SET_STRING(IDS_FILE_BROWSER, ACTION_CHOICE_COUNTER_NO_MEDIA);
SET_STRING(IDS_FILE_BROWSER, ACTION_CHOICE_COUNTER);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_TITLE);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_IMPORT_BUTTON);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_CANCEL_BUTTON);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_GDATA_ERROR);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_SOURCE_ERROR);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_UNKNOWN_DATE);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_NEW_ALBUM_NAME);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_SELECT_ALBUM_CAPTION);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_SELECT_ALBUM_CAPTION_PLURAL);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_IMPORTING_ERROR);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_IMPORTING);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_IMPORT_COMPLETE);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_CAPTION);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_DELETE_AFTER);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_NOTHING_PICKED);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_ONE_PICKED);
SET_STRING(IDS_FILE_BROWSER, PHOTO_IMPORT_MANY_PICKED);
SET_STRING(IDS_FILE_BROWSER, CONFIRM_OVERWRITE_FILE);
SET_STRING(IDS_FILE_BROWSER, FILE_ALREADY_EXISTS);
SET_STRING(IDS_FILE_BROWSER, DIRECTORY_ALREADY_EXISTS);
SET_STRING(IDS_FILE_BROWSER, ERROR_RENAMING);
SET_STRING(IDS_FILE_BROWSER, RENAME_PROMPT);
SET_STRING(IDS_FILE_BROWSER, RENAME_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, ERROR_DELETING);
SET_STRING(IDS_FILE_BROWSER, DELETE_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, PASTE_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, COPY_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, CUT_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, OPEN_WITH_BUTTON_LABEL);
SET_STRING(IDS_FILE_BROWSER, TRANSFER_ITEMS_REMAINING);
SET_STRING(IDS_FILE_BROWSER, TRANSFER_CANCELLED);
SET_STRING(IDS_FILE_BROWSER, TRANSFER_TARGET_EXISTS_ERROR);
SET_STRING(IDS_FILE_BROWSER, TRANSFER_FILESYSTEM_ERROR);
SET_STRING(IDS_FILE_BROWSER, TRANSFER_UNEXPECTED_ERROR);
SET_STRING(IDS_FILE_BROWSER, COPY_FILE_NAME);
SET_STRING(IDS_FILE_BROWSER, COPY_ITEMS_REMAINING);
SET_STRING(IDS_FILE_BROWSER, COPY_CANCELLED);
SET_STRING(IDS_FILE_BROWSER, COPY_TARGET_EXISTS_ERROR);
SET_STRING(IDS_FILE_BROWSER, COPY_FILESYSTEM_ERROR);
SET_STRING(IDS_FILE_BROWSER, COPY_UNEXPECTED_ERROR);
SET_STRING(IDS_FILE_BROWSER, MOVE_FILE_NAME);
SET_STRING(IDS_FILE_BROWSER, MOVE_ITEMS_REMAINING);
SET_STRING(IDS_FILE_BROWSER, MOVE_CANCELLED);
SET_STRING(IDS_FILE_BROWSER, MOVE_TARGET_EXISTS_ERROR);
SET_STRING(IDS_FILE_BROWSER, MOVE_FILESYSTEM_ERROR);
SET_STRING(IDS_FILE_BROWSER, MOVE_UNEXPECTED_ERROR);
SET_STRING(IDS_FILE_BROWSER, DELETED_MESSAGE_PLURAL);
SET_STRING(IDS_FILE_BROWSER, DELETED_MESSAGE);
SET_STRING(IDS_FILE_BROWSER, UNDO_DELETE);
SET_STRING(IDS_FILE_BROWSER, CANCEL_LABEL);
SET_STRING(IDS_FILE_BROWSER, OPEN_LABEL);
SET_STRING(IDS_FILE_BROWSER, SAVE_LABEL);
SET_STRING(IDS_FILE_BROWSER, OK_LABEL);
SET_STRING(IDS_FILE_BROWSER, DEFAULT_NEW_FOLDER_NAME);
SET_STRING(IDS_FILE_BROWSER, MORE_FILES);
SET_STRING(IDS_FILE_BROWSER, CONFIRM_DELETE_ONE);
SET_STRING(IDS_FILE_BROWSER, CONFIRM_DELETE_SOME);
SET_STRING(IDS_FILE_BROWSER, UNKNOWN_FILESYSTEM_WARNING);
SET_STRING(IDS_FILE_BROWSER, UNSUPPORTED_FILESYSTEM_WARNING);
SET_STRING(IDS_FILE_BROWSER, FORMATTING_WARNING);
SET_STRING(IDS_FILE_BROWSER, GDATA_MENU_HELP);
SET_STRING(IDS_FILE_BROWSER, GDATA_SHOW_HOSTED_FILES_OPTION);
SET_STRING(IDS_FILE_BROWSER, GDATA_MOBILE_CONNECTION_OPTION);
SET_STRING(IDS_FILE_BROWSER, GDATA_CLEAR_LOCAL_CACHE);
SET_STRING(IDS_FILE_BROWSER, GDATA_SPACE_AVAILABLE);
SET_STRING(IDS_FILE_BROWSER, GDATA_SPACE_AVAILABLE_LONG);
SET_STRING(IDS_FILE_BROWSER, GDATA_WAITING_FOR_SPACE_INFO);
SET_STRING(IDS_FILE_BROWSER, GDATA_FAILED_SPACE_INFO);
SET_STRING(IDS_FILE_BROWSER, GDATA_BUY_MORE_SPACE);
SET_STRING(IDS_FILE_BROWSER, GDATA_BUY_MORE_SPACE_LINK);
SET_STRING(IDS_FILE_BROWSER, GDATA_VISIT_DRIVE_GOOGLE_COM);
SET_STRING(IDS_FILE_BROWSER, SELECT_FOLDER_TITLE);
SET_STRING(IDS_FILE_BROWSER, SELECT_OPEN_FILE_TITLE);
SET_STRING(IDS_FILE_BROWSER, SELECT_OPEN_MULTI_FILE_TITLE);
SET_STRING(IDS_FILE_BROWSER, SELECT_SAVEAS_FILE_TITLE);
SET_STRING(IDS_FILE_BROWSER, COMPUTING_SELECTION);
SET_STRING(IDS_FILE_BROWSER, ONE_FILE_SELECTED);
SET_STRING(IDS_FILE_BROWSER, ONE_DIRECTORY_SELECTED);
SET_STRING(IDS_FILE_BROWSER, MANY_FILES_SELECTED);
SET_STRING(IDS_FILE_BROWSER, MANY_DIRECTORIES_SELECTED);
SET_STRING(IDS_FILE_BROWSER, MANY_ENTRIES_SELECTED);
SET_STRING(IDS_FILE_BROWSER, OFFLINE_HEADER);
SET_STRING(IDS_FILE_BROWSER, OFFLINE_MESSAGE);
SET_STRING(IDS_FILE_BROWSER, OFFLINE_MESSAGE_PLURAL);
SET_STRING(IDS_FILE_BROWSER, HOSTED_OFFLINE_MESSAGE);
SET_STRING(IDS_FILE_BROWSER, HOSTED_OFFLINE_MESSAGE_PLURAL);
SET_STRING(IDS_FILE_BROWSER, CONFIRM_MOBILE_DATA_USE);
SET_STRING(IDS_FILE_BROWSER, CONFIRM_MOBILE_DATA_USE_PLURAL);
SET_STRING(IDS_FILE_BROWSER, GDATA_OUT_OF_SPACE_HEADER);
SET_STRING(IDS_FILE_BROWSER, GDATA_OUT_OF_SPACE_MESSAGE);
SET_STRING(IDS_FILE_BROWSER, GDATA_SERVER_OUT_OF_SPACE_HEADER);
SET_STRING(IDS_FILE_BROWSER, GDATA_SERVER_OUT_OF_SPACE_MESSAGE);
SET_STRING(IDS_FILE_BROWSER, GDATA_WELCOME_TITLE);
SET_STRING(IDS_FILE_BROWSER, GDATA_WELCOME_TEXT_SHORT);
SET_STRING(IDS_FILE_BROWSER, GDATA_WELCOME_TEXT_LONG);
SET_STRING(IDS_FILE_BROWSER, GDATA_WELCOME_DISMISS);
SET_STRING(IDS_FILE_BROWSER, GDATA_WELCOME_TITLE_ALTERNATIVE);
SET_STRING(IDS_FILE_BROWSER, GDATA_WELCOME_GET_STARTED);
SET_STRING(IDS_FILE_BROWSER, NO_ACTION_FOR_FILE);
// MP3 metadata extractor plugin
SET_STRING(IDS_FILE_BROWSER, ID3_ALBUM); // TALB
SET_STRING(IDS_FILE_BROWSER, ID3_BPM); // TBPM
SET_STRING(IDS_FILE_BROWSER, ID3_COMPOSER); // TCOM
SET_STRING(IDS_FILE_BROWSER, ID3_COPYRIGHT_MESSAGE); // TCOP
SET_STRING(IDS_FILE_BROWSER, ID3_DATE); // TDAT
SET_STRING(IDS_FILE_BROWSER, ID3_PLAYLIST_DELAY); // TDLY
SET_STRING(IDS_FILE_BROWSER, ID3_ENCODED_BY); // TENC
SET_STRING(IDS_FILE_BROWSER, ID3_LYRICIST); // TEXT
SET_STRING(IDS_FILE_BROWSER, ID3_FILE_TYPE); // TFLT
SET_STRING(IDS_FILE_BROWSER, ID3_TIME); // TIME
SET_STRING(IDS_FILE_BROWSER, ID3_TITLE); // TIT2
SET_STRING(IDS_FILE_BROWSER, ID3_LENGTH); // TLEN
SET_STRING(IDS_FILE_BROWSER, ID3_FILE_OWNER); // TOWN
SET_STRING(IDS_FILE_BROWSER, ID3_LEAD_PERFORMER); // TPE1
SET_STRING(IDS_FILE_BROWSER, ID3_BAND); // TPE2
SET_STRING(IDS_FILE_BROWSER, ID3_TRACK_NUMBER); // TRCK
SET_STRING(IDS_FILE_BROWSER, ID3_YEAR); // TYER
SET_STRING(IDS_FILE_BROWSER, ID3_COPYRIGHT); // WCOP
SET_STRING(IDS_FILE_BROWSER, ID3_OFFICIAL_AUDIO_FILE_WEBPAGE); // WOAF
SET_STRING(IDS_FILE_BROWSER, ID3_OFFICIAL_ARTIST); // WOAR
SET_STRING(IDS_FILE_BROWSER, ID3_OFFICIAL_AUDIO_SOURCE_WEBPAGE); // WOAS
SET_STRING(IDS_FILE_BROWSER, ID3_PUBLISHERS_OFFICIAL_WEBPAGE); // WPUB
SET_STRING(IDS_FILE_BROWSER, ID3_USER_DEFINED_URL_LINK_FRAME); // WXXX
// File types
SET_STRING(IDS_FILE_BROWSER, FOLDER);
SET_STRING(IDS_FILE_BROWSER, GENERIC_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, NO_EXTENSION_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, DEVICE);
SET_STRING(IDS_FILE_BROWSER, IMAGE_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, VIDEO_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, AUDIO_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, HTML_DOCUMENT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, ZIP_ARCHIVE_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, RAR_ARCHIVE_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, TAR_ARCHIVE_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, TAR_BZIP2_ARCHIVE_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, TAR_GZIP_ARCHIVE_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, PLAIN_TEXT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, PDF_DOCUMENT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, WORD_DOCUMENT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, POWERPOINT_PRESENTATION_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, EXCEL_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, GDOC_DOCUMENT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, GSHEET_DOCUMENT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, GSLIDES_DOCUMENT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, GDRAW_DOCUMENT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, GTABLE_DOCUMENT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, GLINK_DOCUMENT_FILE_TYPE);
SET_STRING(IDS_FILE_BROWSER, GDATA_LOADING);
SET_STRING(IDS_FILE_BROWSER, GDATA_LOADING_PROGRESS);
SET_STRING(IDS_FILE_BROWSER, GDATA_CANNOT_REACH);
SET_STRING(IDS_FILE_BROWSER, GDATA_LEARN_MORE);
SET_STRING(IDS_FILE_BROWSER, GDATA_RETRY);
SET_STRING(IDS_FILE_BROWSER, AUDIO_PLAYER_TITLE);
SET_STRING(IDS_FILE_BROWSER, AUDIO_PLAYER_DEFAULT_ARTIST);
SET_STRING(IDS_FILE_BROWSER, FILE_ERROR_GENERIC);
SET_STRING(IDS_FILE_BROWSER, FILE_ERROR_NOT_FOUND);
SET_STRING(IDS_FILE_BROWSER, FILE_ERROR_SECURITY);
SET_STRING(IDS_FILE_BROWSER, FILE_ERROR_NOT_READABLE);
SET_STRING(IDS_FILE_BROWSER, FILE_ERROR_NO_MODIFICATION_ALLOWED);
SET_STRING(IDS_FILE_BROWSER, FILE_ERROR_INVALID_STATE);
SET_STRING(IDS_FILE_BROWSER, FILE_ERROR_INVALID_MODIFICATION);
SET_STRING(IDS_FILE_BROWSER, FILE_ERROR_PATH_EXISTS);
SET_STRING(IDS_FILE_BROWSER, FILE_ERROR_QUOTA_EXCEEDED);
SET_STRING(IDS_FILE_BROWSER, SEARCH_NO_MATCHING_FILES);
SET_STRING(IDS_FILE_BROWSER, SEARCH_EXPAND);
SET_STRING(IDS_FILE_BROWSER, SEARCH_SPINNER);
SET_STRING(IDS_FILE_BROWSER, CHANGE_DEFAULT_MENU_ITEM);
SET_STRING(IDS_FILE_BROWSER, CHANGE_DEFAULT_CAPTION);
SET_STRING(IDS_FILE_BROWSER, DEFAULT_ACTION_LABEL);
SET_STRING(IDS_FILE_BROWSER, DETAIL_VIEW_TOOLTIP);
SET_STRING(IDS_FILE_BROWSER, THUMBNAIL_VIEW_TOOLTIP);
SET_STRING(IDS_FILE_BROWSER, TIME_TODAY);
SET_STRING(IDS_FILE_BROWSER, TIME_YESTERDAY);
SET_STRING(IDS_FILE_BROWSER, ALL_FILES_FILTER);
#undef SET_STRING
dict->SetBoolean("PDF_VIEW_ENABLED",
file_manager_util::ShouldBeOpenedWithPdfPlugin(profile(), ".pdf"));
ChromeURLDataManager::DataSource::SetFontAndTextDirection(dict);
dict->SetBoolean("ENABLE_GDATA", gdata::util::IsGDataAvailable(profile()));
#if defined(USE_ASH)
dict->SetBoolean("ASH", true);
#else
dict->SetBoolean("ASH", false);
#endif
std::string board;
const char kMachineInfoBoard[] = "CHROMEOS_RELEASE_BOARD";
chromeos::system::StatisticsProvider* provider =
chromeos::system::StatisticsProvider::GetInstance();
if (!provider->GetMachineStatistic(kMachineInfoBoard, &board))
board = "unknown";
dict->SetString(kMachineInfoBoard, board);
return true;
}
GetDriveFilePropertiesFunction::GetDriveFilePropertiesFunction() {
}
GetDriveFilePropertiesFunction::~GetDriveFilePropertiesFunction() {
}
void GetDriveFilePropertiesFunction::DoOperation(
const FilePath& file_path,
base::DictionaryValue* property_dict,
scoped_ptr<gdata::DriveEntryProto> entry_proto) {
DCHECK(property_dict);
// Nothing to do here so simply call OnOperationComplete().
OnOperationComplete(file_path,
property_dict,
gdata::DRIVE_FILE_OK,
entry_proto.Pass());
}
bool GetDriveFilePropertiesFunction::RunImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (args_->GetSize() != 1)
return false;
PrepareResults();
return true;
}
void GetDriveFilePropertiesFunction::PrepareResults() {
args_->GetList(0, &path_list_);
DCHECK(path_list_);
file_properties_.reset(new base::ListValue);
current_index_ = 0;
GetNextFileProperties();
}
void GetDriveFilePropertiesFunction::GetNextFileProperties() {
if (current_index_ >= path_list_->GetSize()) {
// Exit of asynchronous look and return the result.
SetResult(file_properties_.release());
SendResponse(true);
return;
}
std::string file_str;
path_list_->GetString(current_index_, &file_str);
GURL file_url = GURL(file_str);
FilePath file_path = GetVirtualPathFromURL(file_url);
base::DictionaryValue* property_dict = new base::DictionaryValue;
property_dict->SetString("fileUrl", file_url.spec());
file_properties_->Append(property_dict);
// Start getting the file info.
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
system_service->file_system()->GetEntryInfoByPath(
file_path,
base::Bind(&GetDriveFilePropertiesFunction::OnGetFileInfo,
this,
file_path,
property_dict));
}
void GetDriveFilePropertiesFunction::CompleteGetFileProperties() {
current_index_++;
// Could be called from callback. Let finish operation.
MessageLoop::current()->PostTask(FROM_HERE,
Bind(&GetDriveFilePropertiesFunction::GetNextFileProperties, this));
}
void GetDriveFilePropertiesFunction::OnGetFileInfo(
const FilePath& file_path,
base::DictionaryValue* property_dict,
gdata::DriveFileError error,
scoped_ptr<gdata::DriveEntryProto> entry_proto) {
DCHECK(property_dict);
if (entry_proto.get() && !entry_proto->has_file_specific_info())
error = gdata::DRIVE_FILE_ERROR_NOT_FOUND;
if (error == gdata::DRIVE_FILE_OK)
DoOperation(file_path, property_dict, entry_proto.Pass());
else
OnOperationComplete(file_path, property_dict, error, entry_proto.Pass());
}
void GetDriveFilePropertiesFunction::OnOperationComplete(
const FilePath& file_path,
base::DictionaryValue* property_dict,
gdata::DriveFileError error,
scoped_ptr<gdata::DriveEntryProto> entry_proto) {
if (entry_proto.get() && !entry_proto->has_file_specific_info())
error = gdata::DRIVE_FILE_ERROR_NOT_FOUND;
if (error != gdata::DRIVE_FILE_OK) {
property_dict->SetInteger("errorCode", error);
CompleteGetFileProperties();
return;
}
DCHECK(entry_proto.get());
const gdata::DriveFileSpecificInfo& file_specific_info =
entry_proto->file_specific_info();
property_dict->SetString("thumbnailUrl", file_specific_info.thumbnail_url());
if (!file_specific_info.alternate_url().empty())
property_dict->SetString("editUrl", file_specific_info.alternate_url());
if (!entry_proto->content_url().empty()) {
property_dict->SetString("contentUrl", entry_proto->content_url());
}
property_dict->SetBoolean("isHosted",
file_specific_info.is_hosted_document());
property_dict->SetString("contentMimeType",
file_specific_info.content_mime_type());
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
// Get drive WebApps that can accept this file.
ScopedVector<gdata::DriveWebAppInfo> web_apps;
system_service->webapps_registry()->GetWebAppsForFile(
file_path, file_specific_info.content_mime_type(), &web_apps);
if (!web_apps.empty()) {
std::string default_task_id = file_handler_util::GetDefaultTaskIdFromPrefs(
profile_,
file_specific_info.content_mime_type(),
file_path.Extension());
std::string default_app_id;
file_handler_util::CrackTaskID(
default_task_id, &default_app_id, NULL, NULL);
ListValue* apps = new ListValue();
property_dict->Set("driveApps", apps);
for (ScopedVector<gdata::DriveWebAppInfo>::const_iterator it =
web_apps.begin();
it != web_apps.end(); ++it) {
const gdata::DriveWebAppInfo* webapp_info = *it;
DictionaryValue* app = new DictionaryValue();
app->SetString("appId", webapp_info->app_id);
app->SetString("appName", webapp_info->app_name);
GURL app_icon = FindPreferredIcon(webapp_info->app_icons,
kPreferredIconSize);
if (!app_icon.is_empty())
app->SetString("appIcon", app_icon.spec());
GURL doc_icon = FindPreferredIcon(webapp_info->document_icons,
kPreferredIconSize);
if (!doc_icon.is_empty())
app->SetString("docIcon", doc_icon.spec());
app->SetString("objectType", webapp_info->object_type);
app->SetBoolean("isPrimary", default_app_id == webapp_info->app_id);
apps->Append(app);
}
}
if (VLOG_IS_ON(2)) {
std::string result_json;
base::JSONWriter::WriteWithOptions(
property_dict,
base::JSONWriter::OPTIONS_DO_NOT_ESCAPE |
base::JSONWriter::OPTIONS_PRETTY_PRINT,
&result_json);
VLOG(2) << "Drive File Properties:\n" << result_json;
}
system_service->cache()->GetCacheEntryOnUIThread(
entry_proto->resource_id(),
file_specific_info.file_md5(),
base::Bind(
&GetDriveFilePropertiesFunction::CacheStateReceived,
this, property_dict));
}
void GetDriveFilePropertiesFunction::CacheStateReceived(
base::DictionaryValue* property_dict,
bool /* success */,
const gdata::DriveCacheEntry& cache_entry) {
// In case of an error (i.e. success is false), cache_entry.is_*() all
// returns false.
property_dict->SetBoolean("isPinned", cache_entry.is_pinned());
property_dict->SetBoolean("isPresent", cache_entry.is_present());
property_dict->SetBoolean("isDirty", cache_entry.is_dirty());
CompleteGetFileProperties();
}
PinDriveFileFunction::PinDriveFileFunction() {
}
PinDriveFileFunction::~PinDriveFileFunction() {
}
bool PinDriveFileFunction::RunImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (args_->GetSize() != 2 || !args_->GetBoolean(1, &set_pin_))
return false;
PrepareResults();
return true;
}
void PinDriveFileFunction::DoOperation(
const FilePath& file_path,
base::DictionaryValue* properties,
scoped_ptr<gdata::DriveEntryProto> entry_proto) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
// This is subtle but we should take references of resource_id and md5
// before |file_info| is passed to |callback| by base::Passed(). Otherwise,
// file_info->whatever() crashes.
const std::string& resource_id = entry_proto->resource_id();
const std::string& md5 = entry_proto->file_specific_info().file_md5();
const gdata::CacheOperationCallback callback =
base::Bind(&PinDriveFileFunction::OnPinStateSet,
this,
file_path,
properties,
base::Passed(&entry_proto));
if (set_pin_)
system_service->cache()->PinOnUIThread(resource_id, md5, callback);
else
system_service->cache()->UnpinOnUIThread(resource_id, md5, callback);
}
void PinDriveFileFunction::OnPinStateSet(
const FilePath& path,
base::DictionaryValue* properties,
scoped_ptr<gdata::DriveEntryProto> entry_proto,
gdata::DriveFileError error,
const std::string& /* resource_id */,
const std::string& /* md5 */) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
OnOperationComplete(path, properties, error, entry_proto.Pass());
}
GetFileLocationsFunction::GetFileLocationsFunction() {
}
GetFileLocationsFunction::~GetFileLocationsFunction() {
}
bool GetFileLocationsFunction::RunImpl() {
ListValue* file_urls_as_strings = NULL;
if (!args_->GetList(0, &file_urls_as_strings))
return false;
// Convert the list of strings to a list of GURLs.
UrlList file_urls;
for (size_t i = 0; i < file_urls_as_strings->GetSize(); ++i) {
std::string file_url_as_string;
if (!file_urls_as_strings->GetString(i, &file_url_as_string))
return false;
file_urls.push_back(GURL(file_url_as_string));
}
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_urls,
base::Bind(&GetFileLocationsFunction::GetLocalPathsResponseOnUIThread,
this));
return true;
}
void GetFileLocationsFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ListValue* locations = new ListValue;
for (size_t i = 0; i < files.size(); ++i) {
if (gdata::util::IsUnderDriveMountPoint(files[i].file_path)) {
locations->Append(Value::CreateStringValue("drive"));
} else {
locations->Append(Value::CreateStringValue("local"));
}
}
SetResult(locations);
SendResponse(true);
}
GetDriveFilesFunction::GetDriveFilesFunction()
: local_paths_(NULL) {
}
GetDriveFilesFunction::~GetDriveFilesFunction() {
}
bool GetDriveFilesFunction::RunImpl() {
ListValue* file_urls_as_strings = NULL;
if (!args_->GetList(0, &file_urls_as_strings))
return false;
// Convert the list of strings to a list of GURLs.
UrlList file_urls;
for (size_t i = 0; i < file_urls_as_strings->GetSize(); ++i) {
std::string file_url_as_string;
if (!file_urls_as_strings->GetString(i, &file_url_as_string))
return false;
file_urls.push_back(GURL(file_url_as_string));
}
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_urls,
base::Bind(&GetDriveFilesFunction::GetLocalPathsResponseOnUIThread,
this));
return true;
}
void GetDriveFilesFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
for (size_t i = 0; i < files.size(); ++i) {
DCHECK(gdata::util::IsUnderDriveMountPoint(files[i].file_path));
FilePath drive_path = gdata::util::ExtractDrivePath(files[i].file_path);
remaining_drive_paths_.push(drive_path);
}
local_paths_ = new ListValue;
GetFileOrSendResponse();
}
void GetDriveFilesFunction::GetFileOrSendResponse() {
// Send the response if all files are obtained.
if (remaining_drive_paths_.empty()) {
SetResult(local_paths_);
SendResponse(true);
return;
}
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
DCHECK(system_service);
// Get the file on the top of the queue.
FilePath drive_path = remaining_drive_paths_.front();
system_service->file_system()->GetFileByPath(
drive_path,
base::Bind(&GetDriveFilesFunction::OnFileReady, this),
gdata::GetContentCallback());
}
void GetDriveFilesFunction::OnFileReady(
gdata::DriveFileError error,
const FilePath& local_path,
const std::string& unused_mime_type,
gdata::DriveFileType file_type) {
FilePath drive_path = remaining_drive_paths_.front();
if (error == gdata::DRIVE_FILE_OK) {
local_paths_->Append(Value::CreateStringValue(local_path.value()));
DVLOG(1) << "Got " << drive_path.value() << " as " << local_path.value();
// TODO(benchan): If the file is a hosted document, a temporary JSON file
// is created to represent the document. The JSON file is not cached and
// should be deleted after use. We need to somehow communicate with
// file_manager.js to manage the lifetime of the temporary file.
// See crosbug.com/28058.
} else {
local_paths_->Append(Value::CreateStringValue(""));
DVLOG(1) << "Failed to get " << drive_path.value()
<< " with error code: " << error;
}
remaining_drive_paths_.pop();
// Start getting the next file.
GetFileOrSendResponse();
}
GetFileTransfersFunction::GetFileTransfersFunction() {}
GetFileTransfersFunction::~GetFileTransfersFunction() {}
ListValue* GetFileTransfersFunction::GetFileTransfersList() {
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
if (!system_service)
return NULL;
gdata::OperationProgressStatusList list =
system_service->drive_service()->GetProgressStatusList();
return file_manager_util::ProgressStatusVectorToListValue(
profile_, source_url_.GetOrigin(), list);
}
bool GetFileTransfersFunction::RunImpl() {
scoped_ptr<ListValue> progress_status_list(GetFileTransfersList());
if (!progress_status_list.get()) {
SendResponse(false);
return false;
}
SetResult(progress_status_list.release());
SendResponse(true);
return true;
}
CancelFileTransfersFunction::CancelFileTransfersFunction() {}
CancelFileTransfersFunction::~CancelFileTransfersFunction() {}
bool CancelFileTransfersFunction::RunImpl() {
ListValue* url_list = NULL;
if (!args_->GetList(0, &url_list)) {
SendResponse(false);
return false;
}
std::string virtual_path;
size_t len = url_list->GetSize();
UrlList file_urls;
file_urls.reserve(len);
for (size_t i = 0; i < len; ++i) {
url_list->GetString(i, &virtual_path);
file_urls.push_back(GURL(virtual_path));
}
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_urls,
base::Bind(&CancelFileTransfersFunction::GetLocalPathsResponseOnUIThread,
this));
return true;
}
void CancelFileTransfersFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
if (!system_service) {
SendResponse(false);
return;
}
scoped_ptr<ListValue> responses(new ListValue());
for (size_t i = 0; i < files.size(); ++i) {
DCHECK(gdata::util::IsUnderDriveMountPoint(files[i].file_path));
FilePath file_path = gdata::util::ExtractDrivePath(files[i].file_path);
scoped_ptr<DictionaryValue> result(new DictionaryValue());
result->SetBoolean(
"canceled",
system_service->drive_service()->CancelForFilePath(file_path));
GURL file_url;
if (file_manager_util::ConvertFileToFileSystemUrl(profile_,
gdata::util::GetSpecialRemoteRootPath().Append(file_path),
source_url_.GetOrigin(),
&file_url)) {
result->SetString("fileUrl", file_url.spec());
}
responses->Append(result.release());
}
SetResult(responses.release());
SendResponse(true);
}
TransferFileFunction::TransferFileFunction() {}
TransferFileFunction::~TransferFileFunction() {}
bool TransferFileFunction::RunImpl() {
std::string local_file_url;
std::string remote_file_url;
if (!args_->GetString(0, &local_file_url) ||
!args_->GetString(1, &remote_file_url)) {
return false;
}
UrlList file_urls;
file_urls.push_back(GURL(local_file_url));
file_urls.push_back(GURL(remote_file_url));
GetLocalPathsOnFileThreadAndRunCallbackOnUIThread(
file_urls,
base::Bind(&TransferFileFunction::GetLocalPathsResponseOnUIThread,
this));
return true;
}
void TransferFileFunction::GetLocalPathsResponseOnUIThread(
const SelectedFileInfoList& files) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (files.size() != 2U) {
SendResponse(false);
return;
}
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
if (!system_service) {
SendResponse(false);
return;
}
FilePath source_file = files[0].file_path;
FilePath destination_file = files[1].file_path;
bool source_file_under_drive =
gdata::util::IsUnderDriveMountPoint(source_file);
bool destination_file_under_drive =
gdata::util::IsUnderDriveMountPoint(destination_file);
if (source_file_under_drive && !destination_file_under_drive) {
// Transfer a file from gdata to local file system.
source_file = gdata::util::ExtractDrivePath(source_file);
system_service->file_system()->TransferFileFromRemoteToLocal(
source_file,
destination_file,
base::Bind(&TransferFileFunction::OnTransferCompleted, this));
} else if (!source_file_under_drive && destination_file_under_drive) {
// Transfer a file from local to Drive file system
destination_file = gdata::util::ExtractDrivePath(destination_file);
system_service->file_system()->TransferFileFromLocalToRemote(
source_file,
destination_file,
base::Bind(&TransferFileFunction::OnTransferCompleted, this));
} else {
// Local-to-local or Drive-to-Drive file transfers should be done via
// FileEntry.copyTo in the File API and are thus not supported here.
NOTREACHED();
SendResponse(false);
}
}
void TransferFileFunction::OnTransferCompleted(gdata::DriveFileError error) {
if (error == gdata::DRIVE_FILE_OK) {
SendResponse(true);
} else {
error_ = base::StringPrintf("%d", static_cast<int>(
fileapi::PlatformFileErrorToWebFileError(
gdata::util::DriveFileErrorToPlatformError(error))));
SendResponse(false);
}
}
// Read Drive-related preferences.
bool GetDrivePreferencesFunction::RunImpl() {
scoped_ptr<DictionaryValue> value(new DictionaryValue());
const PrefService* service = profile_->GetPrefs();
bool driveEnabled = gdata::util::IsGDataAvailable(profile_);
if (driveEnabled)
AddDriveMountPoint(profile_, extension_id(), render_view_host());
value->SetBoolean("driveEnabled", driveEnabled);
value->SetBoolean("cellularDisabled",
service->GetBoolean(prefs::kDisableGDataOverCellular));
value->SetBoolean("hostedFilesDisabled",
service->GetBoolean(prefs::kDisableGDataHostedFiles));
SetResult(value.release());
return true;
}
// Write Drive-related preferences.
bool SetDrivePreferencesFunction::RunImpl() {
base::DictionaryValue* value = NULL;
if (!args_->GetDictionary(0, &value) || !value)
return false;
PrefService* service = profile_->GetPrefs();
bool tmp;
if (value->GetBoolean("cellularDisabled", &tmp)) {
service->SetBoolean(prefs::kDisableGDataOverCellular, tmp);
}
if (value->GetBoolean("hostedFilesDisabled", &tmp)) {
service->SetBoolean(prefs::kDisableGDataHostedFiles, tmp);
}
return true;
}
SearchDriveFunction::SearchDriveFunction() {}
SearchDriveFunction::~SearchDriveFunction() {}
bool SearchDriveFunction::RunImpl() {
if (!args_->GetString(0, &query_))
return false;
if (!args_->GetString(1, &next_feed_))
return false;
BrowserContext::GetDefaultStoragePartition(profile())->
GetFileSystemContext()->OpenFileSystem(
source_url_.GetOrigin(), fileapi::kFileSystemTypeExternal, false,
base::Bind(&SearchDriveFunction::OnFileSystemOpened, this));
return true;
}
void SearchDriveFunction::OnFileSystemOpened(
base::PlatformFileError result,
const std::string& file_system_name,
const GURL& file_system_url) {
if (result != base::PLATFORM_FILE_OK) {
SendResponse(false);
return;
}
file_system_name_ = file_system_name;
file_system_url_ = file_system_url;
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
if (!system_service || !system_service->file_system()) {
SendResponse(false);
return;
}
system_service->file_system()->Search(
query_, GURL(next_feed_),
base::Bind(&SearchDriveFunction::OnSearch, this));
}
void SearchDriveFunction::OnSearch(
gdata::DriveFileError error,
const GURL& next_feed,
scoped_ptr<std::vector<gdata::SearchResultInfo> > results) {
if (error != gdata::DRIVE_FILE_OK) {
SendResponse(false);
return;
}
DCHECK(results.get());
base::ListValue* entries = new ListValue();
// Convert Drive files to something File API stack can understand.
for (size_t i = 0; i < results->size(); ++i) {
DictionaryValue* entry = new DictionaryValue();
entry->SetString("fileSystemName", file_system_name_);
entry->SetString("fileSystemRoot", file_system_url_.spec());
entry->SetString("fileFullPath", "/" + results->at(i).path.value());
entry->SetBoolean("fileIsDirectory", results->at(i).is_directory);
entries->Append(entry);
}
base::DictionaryValue* result = new DictionaryValue();
result->Set("entries", entries);
result->SetString("nextFeed", next_feed.spec());
SetResult(result);
SendResponse(true);
}
bool ClearDriveCacheFunction::RunImpl() {
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
// |system_service| is NULL if incognito window / guest login.
if (!system_service || !system_service->file_system())
return false;
// TODO(yoshiki): Receive a callback from JS-side and pass it to
// ClearCacheAndRemountFileSystem(). http://crbug.com/140511
system_service->ClearCacheAndRemountFileSystem(base::Callback<void(bool)>());
SendResponse(true);
return true;
}
bool GetNetworkConnectionStateFunction::RunImpl() {
chromeos::NetworkLibrary* network_library =
chromeos::CrosLibrary::Get()->GetNetworkLibrary();
if (!network_library)
return false;
const chromeos::Network* active_network = network_library->active_network();
scoped_ptr<DictionaryValue> value(new DictionaryValue());
value->SetBoolean("online", active_network && active_network->online());
std::string type_string;
if (!active_network)
type_string = "none";
else if (active_network->type() == chromeos::TYPE_CELLULAR)
type_string = "cellular";
else
type_string = "ethernet"; // Currently we do not care about other types.
value->SetString("type", type_string);
SetResult(value.release());
return true;
}
bool RequestDirectoryRefreshFunction::RunImpl() {
std::string file_url_as_string;
if (!args_->GetString(0, &file_url_as_string))
return false;
gdata::DriveSystemService* system_service =
gdata::DriveSystemServiceFactory::GetForProfile(profile_);
if (!system_service || !system_service->file_system())
return false;
FilePath directory_path = GetVirtualPathFromURL(GURL(file_url_as_string));
system_service->file_system()->RequestDirectoryRefresh(directory_path);
return true;
}