• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
6 
7 #include <string>
8 
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/drive_integration_service.h"
13 #include "chrome/browser/chromeos/drive/file_errors.h"
14 #include "chrome/browser/chromeos/drive/file_system_interface.h"
15 #include "chrome/browser/chromeos/drive/file_system_util.h"
16 #include "chrome/browser/chromeos/file_manager/app_id.h"
17 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
18 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
19 #include "chrome/browser/chromeos/file_manager/path_util.h"
20 #include "chrome/browser/chromeos/file_manager/snapshot_manager.h"
21 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
22 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/common/extensions/api/file_browser_private.h"
25 #include "content/public/browser/child_process_security_policy.h"
26 #include "ui/shell_dialogs/selected_file_info.h"
27 #include "webkit/browser/fileapi/file_system_context.h"
28 #include "webkit/browser/fileapi/file_system_url.h"
29 
30 namespace file_browser_private = extensions::api::file_browser_private;
31 
32 namespace file_manager {
33 namespace util {
34 namespace {
35 
36 // The struct is used for GetSelectedFileInfo().
37 struct GetSelectedFileInfoParams {
38   GetSelectedFileInfoLocalPathOption local_path_option;
39   GetSelectedFileInfoCallback callback;
40   std::vector<base::FilePath> file_paths;
41   std::vector<ui::SelectedFileInfo> selected_files;
42 };
43 
44 // The callback type for GetFileNativeLocalPathFor{Opening,Saving}. It receives
45 // the resolved local path when successful, and receives empty path for failure.
46 typedef base::Callback<void(const base::FilePath&)> LocalPathCallback;
47 
48 // Converts a callback from Drive file system to LocalPathCallback.
OnDriveGetFile(const base::FilePath & path,const LocalPathCallback & callback,drive::FileError error,const base::FilePath & local_file_path,scoped_ptr<drive::ResourceEntry> entry)49 void OnDriveGetFile(const base::FilePath& path,
50                     const LocalPathCallback& callback,
51                     drive::FileError error,
52                     const base::FilePath& local_file_path,
53                     scoped_ptr<drive::ResourceEntry> entry) {
54   if (error != drive::FILE_ERROR_OK)
55     DLOG(ERROR) << "Failed to get " << path.value() << " with: " << error;
56   callback.Run(local_file_path);
57 }
58 
59 // Gets a resolved local file path of a non native |path| for file opening.
GetFileNativeLocalPathForOpening(Profile * profile,const base::FilePath & path,const LocalPathCallback & callback)60 void GetFileNativeLocalPathForOpening(Profile* profile,
61                                       const base::FilePath& path,
62                                       const LocalPathCallback& callback) {
63   if (drive::util::IsUnderDriveMountPoint(path)) {
64     drive::FileSystemInterface* file_system =
65         drive::util::GetFileSystemByProfile(profile);
66     if (!file_system) {
67       DLOG(ERROR) << "Drive file selected while disabled: " << path.value();
68       callback.Run(base::FilePath());
69       return;
70     }
71     file_system->GetFile(drive::util::ExtractDrivePath(path),
72                          base::Bind(&OnDriveGetFile, path, callback));
73     return;
74   }
75 
76   VolumeManager::Get(profile)->snapshot_manager()->CreateManagedSnapshot(
77       path, callback);
78 }
79 
80 // Gets a resolved local file path of a non native |path| for file saving.
GetFileNativeLocalPathForSaving(Profile * profile,const base::FilePath & path,const LocalPathCallback & callback)81 void GetFileNativeLocalPathForSaving(Profile* profile,
82                                      const base::FilePath& path,
83                                      const LocalPathCallback& callback) {
84   if (drive::util::IsUnderDriveMountPoint(path)) {
85     drive::FileSystemInterface* file_system =
86         drive::util::GetFileSystemByProfile(profile);
87     if (!file_system) {
88       DLOG(ERROR) << "Drive file selected while disabled: " << path.value();
89       callback.Run(base::FilePath());
90       return;
91     }
92     file_system->GetFileForSaving(drive::util::ExtractDrivePath(path),
93                                   base::Bind(&OnDriveGetFile, path, callback));
94     return;
95   }
96 
97   // TODO(kinaba): For now, the only writable non-local volume is Drive.
98   NOTREACHED();
99   callback.Run(base::FilePath());
100 }
101 
102 // Forward declarations of helper functions for GetSelectedFileInfo().
103 void ContinueGetSelectedFileInfo(Profile* profile,
104                                  scoped_ptr<GetSelectedFileInfoParams> params,
105                                  const base::FilePath& local_file_path);
106 
107 // Part of GetSelectedFileInfo().
GetSelectedFileInfoInternal(Profile * profile,scoped_ptr<GetSelectedFileInfoParams> params)108 void GetSelectedFileInfoInternal(Profile* profile,
109                                  scoped_ptr<GetSelectedFileInfoParams> params) {
110   DCHECK(profile);
111 
112   for (size_t i = params->selected_files.size();
113        i < params->file_paths.size(); ++i) {
114     const base::FilePath& file_path = params->file_paths[i];
115 
116     if (file_manager::util::IsUnderNonNativeLocalPath(profile, file_path)) {
117       // When the caller of the select file dialog wants local file paths, and
118       // the selected path does not point to a native local path (e.g., Drive,
119       // MTP, or provided file system), we should resolve the path.
120       switch (params->local_path_option) {
121         case NO_LOCAL_PATH_RESOLUTION:
122           break;  // No special handling needed.
123         case NEED_LOCAL_PATH_FOR_OPENING:
124           GetFileNativeLocalPathForOpening(
125               profile,
126               file_path,
127               base::Bind(&ContinueGetSelectedFileInfo,
128                          profile,
129                          base::Passed(&params)));
130           return;  // Remaining work is done in ContinueGetSelectedFileInfo.
131         case NEED_LOCAL_PATH_FOR_SAVING:
132           GetFileNativeLocalPathForSaving(
133               profile,
134               file_path,
135               base::Bind(&ContinueGetSelectedFileInfo,
136                          profile,
137                          base::Passed(&params)));
138           return;  // Remaining work is done in ContinueGetSelectedFileInfo.
139       }
140     }
141     params->selected_files.push_back(
142         ui::SelectedFileInfo(file_path, base::FilePath()));
143   }
144   params->callback.Run(params->selected_files);
145 }
146 
147 // Part of GetSelectedFileInfo().
ContinueGetSelectedFileInfo(Profile * profile,scoped_ptr<GetSelectedFileInfoParams> params,const base::FilePath & local_path)148 void ContinueGetSelectedFileInfo(Profile* profile,
149                                  scoped_ptr<GetSelectedFileInfoParams> params,
150                                  const base::FilePath& local_path) {
151   const int index = params->selected_files.size();
152   const base::FilePath& file_path = params->file_paths[index];
153   params->selected_files.push_back(ui::SelectedFileInfo(file_path, local_path));
154   GetSelectedFileInfoInternal(profile, params.Pass());
155 }
156 
157 }  // namespace
158 
VolumeInfoToVolumeMetadata(Profile * profile,const VolumeInfo & volume_info,file_browser_private::VolumeMetadata * volume_metadata)159 void VolumeInfoToVolumeMetadata(
160     Profile* profile,
161     const VolumeInfo& volume_info,
162     file_browser_private::VolumeMetadata* volume_metadata) {
163   DCHECK(volume_metadata);
164 
165   volume_metadata->volume_id = volume_info.volume_id;
166 
167   // TODO(kinaba): fill appropriate information once multi-profile support is
168   // implemented.
169   volume_metadata->profile.display_name = profile->GetProfileName();
170   volume_metadata->profile.is_current_profile = true;
171 
172   if (!volume_info.source_path.empty()) {
173     volume_metadata->source_path.reset(
174         new std::string(volume_info.source_path.AsUTF8Unsafe()));
175   }
176 
177   if (volume_info.type == VOLUME_TYPE_PROVIDED) {
178     volume_metadata->extension_id.reset(
179         new std::string(volume_info.extension_id));
180 
181     volume_metadata->file_system_id.reset(
182         new std::string(volume_info.file_system_id));
183   }
184 
185   volume_metadata->volume_label.reset(
186       new std::string(volume_info.volume_label));
187 
188   switch (volume_info.type) {
189     case VOLUME_TYPE_GOOGLE_DRIVE:
190       volume_metadata->volume_type =
191           file_browser_private::VOLUME_TYPE_DRIVE;
192       break;
193     case VOLUME_TYPE_DOWNLOADS_DIRECTORY:
194       volume_metadata->volume_type =
195           file_browser_private::VOLUME_TYPE_DOWNLOADS;
196       break;
197     case VOLUME_TYPE_REMOVABLE_DISK_PARTITION:
198       volume_metadata->volume_type =
199           file_browser_private::VOLUME_TYPE_REMOVABLE;
200       break;
201     case VOLUME_TYPE_MOUNTED_ARCHIVE_FILE:
202       volume_metadata->volume_type = file_browser_private::VOLUME_TYPE_ARCHIVE;
203       break;
204     case VOLUME_TYPE_CLOUD_DEVICE:
205       volume_metadata->volume_type =
206           file_browser_private::VOLUME_TYPE_CLOUD_DEVICE;
207       break;
208     case VOLUME_TYPE_PROVIDED:
209       volume_metadata->volume_type = file_browser_private::VOLUME_TYPE_PROVIDED;
210       break;
211     case VOLUME_TYPE_MTP:
212       volume_metadata->volume_type = file_browser_private::VOLUME_TYPE_MTP;
213       break;
214     case VOLUME_TYPE_TESTING:
215       volume_metadata->volume_type =
216           file_browser_private::VOLUME_TYPE_TESTING;
217       break;
218     case NUM_VOLUME_TYPE:
219       NOTREACHED();
220       break;
221   }
222 
223   // Fill device_type iff the volume is removable partition.
224   if (volume_info.type == VOLUME_TYPE_REMOVABLE_DISK_PARTITION) {
225     switch (volume_info.device_type) {
226       case chromeos::DEVICE_TYPE_UNKNOWN:
227         volume_metadata->device_type =
228             file_browser_private::DEVICE_TYPE_UNKNOWN;
229         break;
230       case chromeos::DEVICE_TYPE_USB:
231         volume_metadata->device_type = file_browser_private::DEVICE_TYPE_USB;
232         break;
233       case chromeos::DEVICE_TYPE_SD:
234         volume_metadata->device_type = file_browser_private::DEVICE_TYPE_SD;
235         break;
236       case chromeos::DEVICE_TYPE_OPTICAL_DISC:
237       case chromeos::DEVICE_TYPE_DVD:
238         volume_metadata->device_type =
239             file_browser_private::DEVICE_TYPE_OPTICAL;
240         break;
241       case chromeos::DEVICE_TYPE_MOBILE:
242         volume_metadata->device_type = file_browser_private::DEVICE_TYPE_MOBILE;
243         break;
244     }
245     volume_metadata->device_path.reset(
246         new std::string(volume_info.system_path_prefix.AsUTF8Unsafe()));
247     volume_metadata->is_parent_device.reset(
248         new bool(volume_info.is_parent));
249   } else {
250     volume_metadata->device_type =
251         file_browser_private::DEVICE_TYPE_NONE;
252   }
253 
254   volume_metadata->is_read_only = volume_info.is_read_only;
255 
256   switch (volume_info.mount_condition) {
257     case chromeos::disks::MOUNT_CONDITION_NONE:
258       volume_metadata->mount_condition =
259           file_browser_private::MOUNT_CONDITION_NONE;
260       break;
261     case chromeos::disks::MOUNT_CONDITION_UNKNOWN_FILESYSTEM:
262       volume_metadata->mount_condition =
263           file_browser_private::MOUNT_CONDITION_UNKNOWN;
264       break;
265     case chromeos::disks::MOUNT_CONDITION_UNSUPPORTED_FILESYSTEM:
266       volume_metadata->mount_condition =
267           file_browser_private::MOUNT_CONDITION_UNSUPPORTED;
268       break;
269   }
270 }
271 
GetLocalPathFromURL(content::RenderViewHost * render_view_host,Profile * profile,const GURL & url)272 base::FilePath GetLocalPathFromURL(content::RenderViewHost* render_view_host,
273                                    Profile* profile,
274                                    const GURL& url) {
275   DCHECK(render_view_host);
276   DCHECK(profile);
277 
278   scoped_refptr<fileapi::FileSystemContext> file_system_context =
279       util::GetFileSystemContextForRenderViewHost(profile, render_view_host);
280 
281   const fileapi::FileSystemURL filesystem_url(
282       file_system_context->CrackURL(url));
283   base::FilePath path;
284   if (!chromeos::FileSystemBackend::CanHandleURL(filesystem_url))
285     return base::FilePath();
286   return filesystem_url.path();
287 }
288 
GetSelectedFileInfo(content::RenderViewHost * render_view_host,Profile * profile,const std::vector<GURL> & file_urls,GetSelectedFileInfoLocalPathOption local_path_option,GetSelectedFileInfoCallback callback)289 void GetSelectedFileInfo(content::RenderViewHost* render_view_host,
290                          Profile* profile,
291                          const std::vector<GURL>& file_urls,
292                          GetSelectedFileInfoLocalPathOption local_path_option,
293                          GetSelectedFileInfoCallback callback) {
294   DCHECK(render_view_host);
295   DCHECK(profile);
296 
297   scoped_ptr<GetSelectedFileInfoParams> params(new GetSelectedFileInfoParams);
298   params->local_path_option = local_path_option;
299   params->callback = callback;
300 
301   for (size_t i = 0; i < file_urls.size(); ++i) {
302     const GURL& file_url = file_urls[i];
303     const base::FilePath path = GetLocalPathFromURL(
304         render_view_host, profile, file_url);
305     if (!path.empty()) {
306       DVLOG(1) << "Selected: file path: " << path.value();
307       params->file_paths.push_back(path);
308     }
309   }
310 
311   base::MessageLoop::current()->PostTask(
312       FROM_HERE,
313       base::Bind(&GetSelectedFileInfoInternal, profile, base::Passed(&params)));
314 }
315 
SetupProfileFileAccessPermissions(int render_view_process_id,Profile * profile)316 void SetupProfileFileAccessPermissions(int render_view_process_id,
317                                        Profile* profile) {
318   const base::FilePath paths[] = {
319     drive::util::GetDriveMountPointPath(profile),
320     util::GetDownloadsFolderForProfile(profile),
321   };
322   for (size_t i = 0; i < arraysize(paths); ++i) {
323     content::ChildProcessSecurityPolicy::GetInstance(
324         )->GrantCreateReadWriteFile(render_view_process_id, paths[i]);
325   }
326 }
327 
GetLogger(Profile * profile)328 drive::EventLogger* GetLogger(Profile* profile) {
329   drive::DriveIntegrationService* service =
330       drive::DriveIntegrationServiceFactory::FindForProfileRegardlessOfStates(
331           profile);
332   return service ? service->event_logger() : NULL;
333 }
334 
335 }  // namespace util
336 }  // namespace file_manager
337