private_api_util.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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/path_util.h"
19#include "chrome/browser/chromeos/file_manager/volume_manager.h"
20#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
21#include "chrome/browser/profiles/profile.h"
22#include "chrome/common/extensions/api/file_browser_private.h"
23#include "content/public/browser/child_process_security_policy.h"
24#include "ui/shell_dialogs/selected_file_info.h"
25#include "webkit/browser/fileapi/file_system_context.h"
26#include "webkit/browser/fileapi/file_system_url.h"
27
28namespace file_browser_private = extensions::api::file_browser_private;
29
30namespace file_manager {
31namespace util {
32namespace {
33
34// The struct is used for GetSelectedFileInfo().
35struct GetSelectedFileInfoParams {
36  GetSelectedFileInfoLocalPathOption local_path_option;
37  GetSelectedFileInfoCallback callback;
38  std::vector<base::FilePath> file_paths;
39  std::vector<ui::SelectedFileInfo> selected_files;
40};
41
42// Forward declarations of helper functions for GetSelectedFileInfo().
43void ContinueGetSelectedFileInfo(Profile* profile,
44                                 scoped_ptr<GetSelectedFileInfoParams> params,
45                                 drive::FileError error,
46                                 const base::FilePath& local_file_path,
47                                 scoped_ptr<drive::ResourceEntry> entry);
48
49// Part of GetSelectedFileInfo().
50void GetSelectedFileInfoInternal(Profile* profile,
51                                 scoped_ptr<GetSelectedFileInfoParams> params) {
52  DCHECK(profile);
53  drive::FileSystemInterface* file_system =
54      drive::util::GetFileSystemByProfile(profile);
55
56  for (size_t i = params->selected_files.size();
57       i < params->file_paths.size(); ++i) {
58    const base::FilePath& file_path = params->file_paths[i];
59
60    if (!drive::util::IsUnderDriveMountPoint(file_path)) {
61      params->selected_files.push_back(
62          ui::SelectedFileInfo(file_path, base::FilePath()));
63    } else {
64      // |file_system| is NULL if Drive is disabled.
65      if (!file_system) {
66        ContinueGetSelectedFileInfo(profile,
67                                    params.Pass(),
68                                    drive::FILE_ERROR_FAILED,
69                                    base::FilePath(),
70                                    scoped_ptr<drive::ResourceEntry>());
71        return;
72      }
73      // When the caller of the select file dialog wants local file paths,
74      // we should retrieve Drive files onto the local cache.
75      switch (params->local_path_option) {
76        case NO_LOCAL_PATH_RESOLUTION:
77          params->selected_files.push_back(
78              ui::SelectedFileInfo(file_path, base::FilePath()));
79          break;
80        case NEED_LOCAL_PATH_FOR_OPENING:
81          file_system->GetFile(
82              drive::util::ExtractDrivePath(file_path),
83              base::Bind(&ContinueGetSelectedFileInfo,
84                         profile,
85                         base::Passed(&params)));
86          return;  // Remaining work is done in ContinueGetSelectedFileInfo.
87        case NEED_LOCAL_PATH_FOR_SAVING:
88          file_system->GetFileForSaving(
89              drive::util::ExtractDrivePath(file_path),
90              base::Bind(&ContinueGetSelectedFileInfo,
91                         profile,
92                         base::Passed(&params)));
93          return;  // Remaining work is done in ContinueGetSelectedFileInfo.
94      }
95    }
96  }
97  params->callback.Run(params->selected_files);
98}
99
100// Part of GetSelectedFileInfo().
101void ContinueGetSelectedFileInfo(Profile* profile,
102                                 scoped_ptr<GetSelectedFileInfoParams> params,
103                                 drive::FileError error,
104                                 const base::FilePath& local_file_path,
105                                 scoped_ptr<drive::ResourceEntry> entry) {
106  DCHECK(profile);
107
108  const int index = params->selected_files.size();
109  const base::FilePath& file_path = params->file_paths[index];
110  base::FilePath local_path;
111  if (error == drive::FILE_ERROR_OK) {
112    local_path = local_file_path;
113  } else {
114    DLOG(ERROR) << "Failed to get " << file_path.value()
115                << " with error code: " << error;
116  }
117  params->selected_files.push_back(ui::SelectedFileInfo(file_path, local_path));
118  GetSelectedFileInfoInternal(profile, params.Pass());
119}
120
121}  // namespace
122
123void VolumeInfoToVolumeMetadata(
124    Profile* profile,
125    const VolumeInfo& volume_info,
126    file_browser_private::VolumeMetadata* volume_metadata) {
127  DCHECK(volume_metadata);
128
129  volume_metadata->volume_id = volume_info.volume_id;
130
131  // TODO(kinaba): fill appropriate information once multi-profile support is
132  // implemented.
133  volume_metadata->profile.display_name = profile->GetProfileName();
134  volume_metadata->profile.is_current_profile = true;
135
136  if (!volume_info.source_path.empty()) {
137    volume_metadata->source_path.reset(
138        new std::string(volume_info.source_path.AsUTF8Unsafe()));
139  }
140
141  switch (volume_info.type) {
142    case VOLUME_TYPE_GOOGLE_DRIVE:
143      volume_metadata->volume_type =
144          file_browser_private::VOLUME_TYPE_DRIVE;
145      break;
146    case VOLUME_TYPE_DOWNLOADS_DIRECTORY:
147      volume_metadata->volume_type =
148          file_browser_private::VOLUME_TYPE_DOWNLOADS;
149      break;
150    case VOLUME_TYPE_REMOVABLE_DISK_PARTITION:
151      volume_metadata->volume_type =
152          file_browser_private::VOLUME_TYPE_REMOVABLE;
153      break;
154    case VOLUME_TYPE_MOUNTED_ARCHIVE_FILE:
155      volume_metadata->volume_type = file_browser_private::VOLUME_TYPE_ARCHIVE;
156      break;
157    case VOLUME_TYPE_CLOUD_DEVICE:
158      volume_metadata->volume_type =
159          file_browser_private::VOLUME_TYPE_CLOUD_DEVICE;
160      break;
161    case VOLUME_TYPE_PROVIDED:
162      volume_metadata->volume_type = file_browser_private::VOLUME_TYPE_PROVIDED;
163      break;
164    case VOLUME_TYPE_MTP:
165      volume_metadata->volume_type = file_browser_private::VOLUME_TYPE_MTP;
166      break;
167    case VOLUME_TYPE_TESTING:
168      volume_metadata->volume_type =
169          file_browser_private::VOLUME_TYPE_TESTING;
170      break;
171  }
172
173  // Fill device_type iff the volume is removable partition.
174  if (volume_info.type == VOLUME_TYPE_REMOVABLE_DISK_PARTITION) {
175    switch (volume_info.device_type) {
176      case chromeos::DEVICE_TYPE_UNKNOWN:
177        volume_metadata->device_type =
178            file_browser_private::DEVICE_TYPE_UNKNOWN;
179        break;
180      case chromeos::DEVICE_TYPE_USB:
181        volume_metadata->device_type = file_browser_private::DEVICE_TYPE_USB;
182        break;
183      case chromeos::DEVICE_TYPE_SD:
184        volume_metadata->device_type = file_browser_private::DEVICE_TYPE_SD;
185        break;
186      case chromeos::DEVICE_TYPE_OPTICAL_DISC:
187      case chromeos::DEVICE_TYPE_DVD:
188        volume_metadata->device_type =
189            file_browser_private::DEVICE_TYPE_OPTICAL;
190        break;
191      case chromeos::DEVICE_TYPE_MOBILE:
192        volume_metadata->device_type = file_browser_private::DEVICE_TYPE_MOBILE;
193        break;
194    }
195    volume_metadata->device_path.reset(
196        new std::string(volume_info.system_path_prefix.AsUTF8Unsafe()));
197    volume_metadata->device_label.reset(
198        new std::string(volume_info.drive_label));
199    volume_metadata->is_parent_device.reset(
200        new bool(volume_info.is_parent));
201  } else {
202    volume_metadata->device_type =
203        file_browser_private::DEVICE_TYPE_NONE;
204  }
205
206  volume_metadata->is_read_only = volume_info.is_read_only;
207
208  switch (volume_info.mount_condition) {
209    case chromeos::disks::MOUNT_CONDITION_NONE:
210      volume_metadata->mount_condition =
211          file_browser_private::MOUNT_CONDITION_NONE;
212      break;
213    case chromeos::disks::MOUNT_CONDITION_UNKNOWN_FILESYSTEM:
214      volume_metadata->mount_condition =
215          file_browser_private::MOUNT_CONDITION_UNKNOWN;
216      break;
217    case chromeos::disks::MOUNT_CONDITION_UNSUPPORTED_FILESYSTEM:
218      volume_metadata->mount_condition =
219          file_browser_private::MOUNT_CONDITION_UNSUPPORTED;
220      break;
221  }
222}
223
224base::FilePath GetLocalPathFromURL(content::RenderViewHost* render_view_host,
225                                   Profile* profile,
226                                   const GURL& url) {
227  DCHECK(render_view_host);
228  DCHECK(profile);
229
230  scoped_refptr<fileapi::FileSystemContext> file_system_context =
231      util::GetFileSystemContextForRenderViewHost(profile, render_view_host);
232
233  const fileapi::FileSystemURL filesystem_url(
234      file_system_context->CrackURL(url));
235  base::FilePath path;
236  if (!chromeos::FileSystemBackend::CanHandleURL(filesystem_url))
237    return base::FilePath();
238  return filesystem_url.path();
239}
240
241void GetSelectedFileInfo(content::RenderViewHost* render_view_host,
242                         Profile* profile,
243                         const std::vector<GURL>& file_urls,
244                         GetSelectedFileInfoLocalPathOption local_path_option,
245                         GetSelectedFileInfoCallback callback) {
246  DCHECK(render_view_host);
247  DCHECK(profile);
248
249  scoped_ptr<GetSelectedFileInfoParams> params(new GetSelectedFileInfoParams);
250  params->local_path_option = local_path_option;
251  params->callback = callback;
252
253  for (size_t i = 0; i < file_urls.size(); ++i) {
254    const GURL& file_url = file_urls[i];
255    const base::FilePath path = GetLocalPathFromURL(
256        render_view_host, profile, file_url);
257    if (!path.empty()) {
258      DVLOG(1) << "Selected: file path: " << path.value();
259      params->file_paths.push_back(path);
260    }
261  }
262
263  base::MessageLoop::current()->PostTask(
264      FROM_HERE,
265      base::Bind(&GetSelectedFileInfoInternal, profile, base::Passed(&params)));
266}
267
268void SetupProfileFileAccessPermissions(int render_view_process_id,
269                                       Profile* profile) {
270  const base::FilePath paths[] = {
271    drive::util::GetDriveMountPointPath(profile),
272    util::GetDownloadsFolderForProfile(profile),
273  };
274  for (size_t i = 0; i < arraysize(paths); ++i) {
275    content::ChildProcessSecurityPolicy::GetInstance(
276        )->GrantCreateReadWriteFile(render_view_process_id, paths[i]);
277  }
278}
279
280drive::EventLogger* GetLogger(Profile* profile) {
281  drive::DriveIntegrationService* service =
282      drive::DriveIntegrationServiceFactory::FindForProfileRegardlessOfStates(
283          profile);
284  return service ? service->event_logger() : NULL;
285}
286
287}  // namespace util
288}  // namespace file_manager
289