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_util.h"
9 #include "base/files/file_path.h"
10 #include "base/message_loop/message_loop.h"
11 #include "chrome/browser/chromeos/drive/drive.pb.h"
12 #include "chrome/browser/chromeos/drive/file_errors.h"
13 #include "chrome/browser/chromeos/drive/file_system_interface.h"
14 #include "chrome/browser/chromeos/drive/file_system_util.h"
15 #include "chrome/browser/chromeos/file_manager/app_id.h"
16 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
17 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
18 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/extensions/api/file_browser_private.h"
21 #include "ui/shell_dialogs/selected_file_info.h"
22 #include "webkit/browser/fileapi/file_system_context.h"
23 #include "webkit/browser/fileapi/file_system_url.h"
25 namespace file_browser_private = extensions::api::file_browser_private;
27 namespace file_manager {
31 // The struct is used for GetSelectedFileInfo().
32 struct GetSelectedFileInfoParams {
33 GetSelectedFileInfoLocalPathOption local_path_option;
34 GetSelectedFileInfoCallback callback;
35 std::vector<base::FilePath> file_paths;
36 std::vector<ui::SelectedFileInfo> selected_files;
39 // Forward declarations of helper functions for GetSelectedFileInfo().
40 void ContinueGetSelectedFileInfo(Profile* profile,
41 scoped_ptr<GetSelectedFileInfoParams> params,
42 drive::FileError error,
43 const base::FilePath& local_file_path,
44 scoped_ptr<drive::ResourceEntry> entry);
46 // Part of GetSelectedFileInfo().
47 void GetSelectedFileInfoInternal(Profile* profile,
48 scoped_ptr<GetSelectedFileInfoParams> params) {
50 drive::FileSystemInterface* file_system =
51 drive::util::GetFileSystemByProfile(profile);
53 for (size_t i = params->selected_files.size();
54 i < params->file_paths.size(); ++i) {
55 const base::FilePath& file_path = params->file_paths[i];
57 if (!drive::util::IsUnderDriveMountPoint(file_path)) {
58 params->selected_files.push_back(
59 ui::SelectedFileInfo(file_path, base::FilePath()));
61 // |file_system| is NULL if Drive is disabled.
63 ContinueGetSelectedFileInfo(profile,
65 drive::FILE_ERROR_FAILED,
67 scoped_ptr<drive::ResourceEntry>());
70 // When the caller of the select file dialog wants local file paths,
71 // we should retrieve Drive files onto the local cache.
72 switch (params->local_path_option) {
73 case NO_LOCAL_PATH_RESOLUTION:
74 params->selected_files.push_back(
75 ui::SelectedFileInfo(file_path, base::FilePath()));
77 case NEED_LOCAL_PATH_FOR_OPENING:
79 drive::util::ExtractDrivePath(file_path),
80 base::Bind(&ContinueGetSelectedFileInfo,
82 base::Passed(¶ms)));
83 return; // Remaining work is done in ContinueGetSelectedFileInfo.
84 case NEED_LOCAL_PATH_FOR_SAVING:
85 file_system->GetFileForSaving(
86 drive::util::ExtractDrivePath(file_path),
87 base::Bind(&ContinueGetSelectedFileInfo,
89 base::Passed(¶ms)));
90 return; // Remaining work is done in ContinueGetSelectedFileInfo.
94 params->callback.Run(params->selected_files);
97 // Part of GetSelectedFileInfo().
98 void ContinueGetSelectedFileInfo(Profile* profile,
99 scoped_ptr<GetSelectedFileInfoParams> params,
100 drive::FileError error,
101 const base::FilePath& local_file_path,
102 scoped_ptr<drive::ResourceEntry> entry) {
105 const int index = params->selected_files.size();
106 const base::FilePath& file_path = params->file_paths[index];
107 base::FilePath local_path;
108 if (error == drive::FILE_ERROR_OK) {
109 local_path = local_file_path;
111 DLOG(ERROR) << "Failed to get " << file_path.value()
112 << " with error code: " << error;
114 params->selected_files.push_back(ui::SelectedFileInfo(file_path, local_path));
115 GetSelectedFileInfoInternal(profile, params.Pass());
120 void VolumeInfoToVolumeMetadata(
122 const VolumeInfo& volume_info,
123 file_browser_private::VolumeMetadata* volume_metadata) {
124 DCHECK(volume_metadata);
125 DCHECK(!volume_info.mount_path.empty());
127 // Convert mount point path to relative path with the external file system
128 // exposed within File API.
129 base::FilePath relative_mount_path;
130 if (ConvertAbsoluteFilePathToRelativeFileSystemPath(
131 profile, kFileManagerAppId, base::FilePath(volume_info.mount_path),
132 &relative_mount_path)) {
133 volume_metadata->mount_path = "/" + relative_mount_path.AsUTF8Unsafe();
136 volume_metadata->volume_id = volume_info.volume_id;
138 // TODO(kinaba): fill appropriate information once multi-profile support is
140 volume_metadata->profile.display_name = profile->GetProfileName();
141 volume_metadata->profile.is_current_profile = true;
143 if (!volume_info.source_path.empty()) {
144 volume_metadata->source_path.reset(
145 new std::string(volume_info.source_path.AsUTF8Unsafe()));
148 switch (volume_info.type) {
149 case VOLUME_TYPE_GOOGLE_DRIVE:
150 volume_metadata->volume_type =
151 file_browser_private::VOLUME_TYPE_DRIVE;
153 case VOLUME_TYPE_DOWNLOADS_DIRECTORY:
154 volume_metadata->volume_type =
155 file_browser_private::VOLUME_TYPE_DOWNLOADS;
157 case VOLUME_TYPE_REMOVABLE_DISK_PARTITION:
158 volume_metadata->volume_type =
159 file_browser_private::VOLUME_TYPE_REMOVABLE;
161 case VOLUME_TYPE_MOUNTED_ARCHIVE_FILE:
162 volume_metadata->volume_type = file_browser_private::VOLUME_TYPE_ARCHIVE;
164 case VOLUME_TYPE_CLOUD_DEVICE:
165 volume_metadata->volume_type =
166 file_browser_private::VOLUME_TYPE_CLOUD_DEVICE;
170 // Fill device_type iff the volume is removable partition.
171 if (volume_info.type == VOLUME_TYPE_REMOVABLE_DISK_PARTITION) {
172 switch (volume_info.device_type) {
173 case chromeos::DEVICE_TYPE_UNKNOWN:
174 volume_metadata->device_type =
175 file_browser_private::DEVICE_TYPE_UNKNOWN;
177 case chromeos::DEVICE_TYPE_USB:
178 volume_metadata->device_type = file_browser_private::DEVICE_TYPE_USB;
180 case chromeos::DEVICE_TYPE_SD:
181 volume_metadata->device_type = file_browser_private::DEVICE_TYPE_SD;
183 case chromeos::DEVICE_TYPE_OPTICAL_DISC:
184 case chromeos::DEVICE_TYPE_DVD:
185 volume_metadata->device_type =
186 file_browser_private::DEVICE_TYPE_OPTICAL;
188 case chromeos::DEVICE_TYPE_MOBILE:
189 volume_metadata->device_type = file_browser_private::DEVICE_TYPE_MOBILE;
192 volume_metadata->device_path.reset(
193 new std::string(volume_info.system_path_prefix.AsUTF8Unsafe()));
194 volume_metadata->device_label.reset(
195 new std::string(volume_info.drive_label));
196 volume_metadata->is_parent_device.reset(
197 new bool(volume_info.is_parent));
199 volume_metadata->device_type =
200 file_browser_private::DEVICE_TYPE_NONE;
203 volume_metadata->is_read_only = volume_info.is_read_only;
205 switch (volume_info.mount_condition) {
206 case chromeos::disks::MOUNT_CONDITION_NONE:
207 volume_metadata->mount_condition =
208 file_browser_private::MOUNT_CONDITION_NONE;
210 case chromeos::disks::MOUNT_CONDITION_UNKNOWN_FILESYSTEM:
211 volume_metadata->mount_condition =
212 file_browser_private::MOUNT_CONDITION_UNKNOWN;
214 case chromeos::disks::MOUNT_CONDITION_UNSUPPORTED_FILESYSTEM:
215 volume_metadata->mount_condition =
216 file_browser_private::MOUNT_CONDITION_UNSUPPORTED;
221 base::FilePath GetLocalPathFromURL(content::RenderViewHost* render_view_host,
224 DCHECK(render_view_host);
227 scoped_refptr<fileapi::FileSystemContext> file_system_context =
228 util::GetFileSystemContextForRenderViewHost(profile, render_view_host);
230 const fileapi::FileSystemURL filesystem_url(
231 file_system_context->CrackURL(url));
233 if (!chromeos::FileSystemBackend::CanHandleURL(filesystem_url))
234 return base::FilePath();
235 return filesystem_url.path();
238 void GetSelectedFileInfo(content::RenderViewHost* render_view_host,
240 const std::vector<GURL>& file_urls,
241 GetSelectedFileInfoLocalPathOption local_path_option,
242 GetSelectedFileInfoCallback callback) {
243 DCHECK(render_view_host);
246 scoped_ptr<GetSelectedFileInfoParams> params(new GetSelectedFileInfoParams);
247 params->local_path_option = local_path_option;
248 params->callback = callback;
250 for (size_t i = 0; i < file_urls.size(); ++i) {
251 const GURL& file_url = file_urls[i];
252 const base::FilePath path = GetLocalPathFromURL(
253 render_view_host, profile, file_url);
255 DVLOG(1) << "Selected: file path: " << path.value();
256 params->file_paths.push_back(path);
260 base::MessageLoop::current()->PostTask(
262 base::Bind(&GetSelectedFileInfoInternal, profile, base::Passed(¶ms)));
266 } // namespace file_manager