Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / file_manager / private_api_mount.cc
blob201918b22168db0647d8832186a2d20c97b5d239
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/extensions/file_manager/private_api_mount.h"
7 #include <string>
9 #include "base/files/file_util.h"
10 #include "base/format_macros.h"
11 #include "base/memory/weak_ptr.h"
12 #include "chrome/browser/chromeos/drive/file_system_util.h"
13 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
14 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
15 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/extensions/api/file_manager_private.h"
18 #include "chromeos/disks/disk_mount_manager.h"
19 #include "components/drive/event_logger.h"
20 #include "components/drive/file_system_interface.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "google_apis/drive/task_util.h"
23 #include "ui/shell_dialogs/selected_file_info.h"
25 using chromeos::disks::DiskMountManager;
26 using content::BrowserThread;
27 namespace file_manager_private = extensions::api::file_manager_private;
29 namespace extensions {
31 namespace {
33 // Does chmod o+r for the given path to ensure the file is readable from avfs.
34 void EnsureReadableFilePermissionOnBlockingPool(
35 const base::FilePath& path,
36 const base::Callback<void(drive::FileError, const base::FilePath&)>&
37 callback) {
38 int mode = 0;
39 if (!base::GetPosixFilePermissions(path, &mode) ||
40 !base::SetPosixFilePermissions(path, mode | S_IROTH)) {
41 callback.Run(drive::FILE_ERROR_ACCESS_DENIED, base::FilePath());
42 return;
44 callback.Run(drive::FILE_ERROR_OK, path);
47 } // namespace
49 bool FileManagerPrivateAddMountFunction::RunAsync() {
50 using file_manager_private::AddMount::Params;
51 const scoped_ptr<Params> params(Params::Create(*args_));
52 EXTENSION_FUNCTION_VALIDATE(params);
54 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
55 if (logger) {
56 logger->Log(logging::LOG_INFO, "%s[%d] called. (source: '%s')", name(),
57 request_id(),
58 params->source.empty() ? "(none)" : params->source.c_str());
60 set_log_on_completion(true);
62 const base::FilePath path = file_manager::util::GetLocalPathFromURL(
63 render_frame_host(), GetProfile(), GURL(params->source));
65 if (path.empty())
66 return false;
68 // Check if the source path is under Drive cache directory.
69 if (drive::util::IsUnderDriveMountPoint(path)) {
70 drive::FileSystemInterface* file_system =
71 drive::util::GetFileSystemByProfile(GetProfile());
72 if (!file_system)
73 return false;
75 // Ensure that the cache file exists.
76 const base::FilePath drive_path = drive::util::ExtractDrivePath(path);
77 file_system->GetFile(
78 drive_path,
79 base::Bind(&FileManagerPrivateAddMountFunction::RunAfterGetDriveFile,
80 this,
81 drive_path));
82 } else {
83 file_manager::VolumeManager* volume_manager =
84 file_manager::VolumeManager::Get(GetProfile());
85 DCHECK(volume_manager);
87 bool is_under_downloads = false;
88 const std::vector<base::WeakPtr<file_manager::Volume>> volumes =
89 volume_manager->GetVolumeList();
90 for (const auto& volume : volumes) {
91 if (volume->type() == file_manager::VOLUME_TYPE_DOWNLOADS_DIRECTORY &&
92 volume->mount_path().IsParent(path)) {
93 is_under_downloads = true;
94 break;
98 if (is_under_downloads) {
99 // For files under downloads, change the file permission and make it
100 // readable from avfs/fuse if needed.
101 BrowserThread::PostBlockingPoolTask(
102 FROM_HERE,
103 base::Bind(&EnsureReadableFilePermissionOnBlockingPool,
104 path,
105 google_apis::CreateRelayCallback(
106 base::Bind(&FileManagerPrivateAddMountFunction::
107 RunAfterMarkCacheFileAsMounted,
108 this,
109 path.BaseName()))));
110 } else {
111 RunAfterMarkCacheFileAsMounted(
112 path.BaseName(), drive::FILE_ERROR_OK, path);
115 return true;
118 void FileManagerPrivateAddMountFunction::RunAfterGetDriveFile(
119 const base::FilePath& drive_path,
120 drive::FileError error,
121 const base::FilePath& cache_path,
122 scoped_ptr<drive::ResourceEntry> entry) {
123 DCHECK_CURRENTLY_ON(BrowserThread::UI);
125 if (error != drive::FILE_ERROR_OK) {
126 SendResponse(false);
127 return;
130 drive::FileSystemInterface* const file_system =
131 drive::util::GetFileSystemByProfile(GetProfile());
132 if (!file_system) {
133 SendResponse(false);
134 return;
137 file_system->MarkCacheFileAsMounted(
138 drive_path,
139 base::Bind(
140 &FileManagerPrivateAddMountFunction::RunAfterMarkCacheFileAsMounted,
141 this,
142 drive_path.BaseName()));
145 void FileManagerPrivateAddMountFunction::RunAfterMarkCacheFileAsMounted(
146 const base::FilePath& display_name,
147 drive::FileError error,
148 const base::FilePath& file_path) {
149 DCHECK_CURRENTLY_ON(BrowserThread::UI);
151 if (error != drive::FILE_ERROR_OK) {
152 SendResponse(false);
153 return;
156 // Pass back the actual source path of the mount point.
157 SetResult(new base::StringValue(file_path.AsUTF8Unsafe()));
158 SendResponse(true);
160 // MountPath() takes a std::string.
161 DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
162 disk_mount_manager->MountPath(
163 file_path.AsUTF8Unsafe(),
164 base::FilePath(display_name.Extension()).AsUTF8Unsafe(),
165 display_name.AsUTF8Unsafe(),
166 chromeos::MOUNT_TYPE_ARCHIVE);
169 bool FileManagerPrivateRemoveMountFunction::RunAsync() {
170 using file_manager_private::RemoveMount::Params;
171 const scoped_ptr<Params> params(Params::Create(*args_));
172 EXTENSION_FUNCTION_VALIDATE(params);
174 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
175 if (logger) {
176 logger->Log(logging::LOG_INFO, "%s[%d] called. (volume_id: '%s')", name(),
177 request_id(), params->volume_id.c_str());
179 set_log_on_completion(true);
181 using file_manager::VolumeManager;
182 using file_manager::Volume;
183 VolumeManager* const volume_manager = VolumeManager::Get(GetProfile());
184 DCHECK(volume_manager);
186 base::WeakPtr<Volume> volume =
187 volume_manager->FindVolumeById(params->volume_id);
188 if (!volume.get())
189 return false;
191 // TODO(tbarzic): Send response when callback is received, it would make more
192 // sense than remembering issued unmount requests in file manager and showing
193 // errors for them when MountCompleted event is received.
194 switch (volume->type()) {
195 case file_manager::VOLUME_TYPE_REMOVABLE_DISK_PARTITION:
196 case file_manager::VOLUME_TYPE_MOUNTED_ARCHIVE_FILE: {
197 DiskMountManager::GetInstance()->UnmountPath(
198 volume->mount_path().value(), chromeos::UNMOUNT_OPTIONS_NONE,
199 DiskMountManager::UnmountPathCallback());
200 break;
202 case file_manager::VOLUME_TYPE_PROVIDED: {
203 chromeos::file_system_provider::Service* service =
204 chromeos::file_system_provider::Service::Get(GetProfile());
205 DCHECK(service);
206 // TODO(mtomasz): Pass a more detailed error than just a bool.
207 if (!service->RequestUnmount(volume->extension_id(),
208 volume->file_system_id())) {
209 return false;
211 break;
213 default:
214 // Requested unmounting a device which is not unmountable.
215 return false;
218 SendResponse(true);
219 return true;
222 bool FileManagerPrivateGetVolumeMetadataListFunction::RunAsync() {
223 if (args_->GetSize())
224 return false;
226 const std::vector<base::WeakPtr<file_manager::Volume>>& volume_list =
227 file_manager::VolumeManager::Get(GetProfile())->GetVolumeList();
229 std::string log_string;
230 std::vector<linked_ptr<file_manager_private::VolumeMetadata> > result;
231 for (const auto& volume : volume_list) {
232 linked_ptr<file_manager_private::VolumeMetadata> volume_metadata(
233 new file_manager_private::VolumeMetadata);
234 file_manager::util::VolumeToVolumeMetadata(GetProfile(), *volume.get(),
235 volume_metadata.get());
236 result.push_back(volume_metadata);
237 if (!log_string.empty())
238 log_string += ", ";
239 log_string += volume->mount_path().AsUTF8Unsafe();
242 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
243 if (logger) {
244 logger->Log(logging::LOG_INFO,
245 "%s[%d] succeeded. (results: '[%s]', %" PRIuS " mount points)",
246 name(), request_id(), log_string.c_str(), result.size());
249 results_ =
250 file_manager_private::GetVolumeMetadataList::Results::Create(result);
251 SendResponse(true);
252 return true;
255 } // namespace extensions