private_api_mount.cc revision 3240926e260ce088908e02ac07a6cf7b0c0cbf44
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_mount.h"
6
7#include "base/format_macros.h"
8#include "base/values.h"
9#include "chrome/browser/chromeos/drive/drive_integration_service.h"
10#include "chrome/browser/chromeos/drive/file_system_interface.h"
11#include "chrome/browser/chromeos/drive/file_system_util.h"
12#include "chrome/browser/chromeos/drive/logging.h"
13#include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
14#include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h"
15#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
16#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
17#include "chrome/browser/profiles/profile.h"
18#include "chromeos/disks/disk_mount_manager.h"
19#include "content/public/browser/browser_thread.h"
20#include "ui/shell_dialogs/selected_file_info.h"
21
22using chromeos::disks::DiskMountManager;
23using content::BrowserThread;
24
25namespace file_manager {
26namespace {
27
28// Creates a dictionary describing the mount point of |mount_point_info|.
29base::DictionaryValue* CreateValueFromMountPoint(
30    Profile* profile,
31    const DiskMountManager::MountPointInfo& mount_point_info,
32    const std::string& extension_id) {
33
34  base::DictionaryValue *mount_info = new base::DictionaryValue();
35
36  mount_info->SetString("mountType",
37                        DiskMountManager::MountTypeToString(
38                            mount_point_info.mount_type));
39  mount_info->SetString("sourcePath", mount_point_info.source_path);
40
41  base::FilePath relative_mount_path;
42  // Convert mount point path to relative path with the external file system
43  // exposed within File API.
44  if (util::ConvertFileToRelativeFileSystemPath(
45          profile,
46          extension_id,
47          base::FilePath(mount_point_info.mount_path),
48          &relative_mount_path)) {
49    mount_info->SetString("mountPath", relative_mount_path.value());
50  }
51
52  mount_info->SetString("mountCondition",
53                        DiskMountManager::MountConditionToString(
54                            mount_point_info.mount_condition));
55
56  return mount_info;
57}
58
59}  // namespace
60
61AddMountFunction::AddMountFunction() {
62}
63
64AddMountFunction::~AddMountFunction() {
65}
66
67bool AddMountFunction::RunImpl() {
68  // The third argument is simply ignored.
69  if (args_->GetSize() != 2 && args_->GetSize() != 3) {
70    error_ = "Invalid argument count";
71    return false;
72  }
73
74  std::string file_url;
75  if (!args_->GetString(0, &file_url)) {
76    return false;
77  }
78
79  std::string mount_type_str;
80  if (!args_->GetString(1, &mount_type_str)) {
81    return false;
82  }
83
84  drive::util::Log(logging::LOG_INFO,
85                   "%s[%d] called. (source: '%s', type:'%s')",
86                   name().c_str(),
87                   request_id(),
88                   file_url.empty() ? "(none)" : file_url.c_str(),
89                   mount_type_str.c_str());
90  set_log_on_completion(true);
91
92  // Set default return source path to the empty string.
93  SetResult(new base::StringValue(""));
94
95  chromeos::MountType mount_type =
96      DiskMountManager::MountTypeFromString(mount_type_str);
97  switch (mount_type) {
98    case chromeos::MOUNT_TYPE_INVALID: {
99      error_ = "Invalid mount type";
100      SendResponse(false);
101      break;
102    }
103    case chromeos::MOUNT_TYPE_GOOGLE_DRIVE: {
104      // Dispatch fake 'mounted' event because JS code depends on it.
105      // TODO(hashimoto): Remove this redanduncy.
106      FileBrowserPrivateAPI::Get(profile_)->event_router()->
107          OnFileSystemMounted();
108
109      // Pass back the drive mount point path as source path.
110      const std::string& drive_path =
111          drive::util::GetDriveMountPointPathAsString();
112      SetResult(new base::StringValue(drive_path));
113      SendResponse(true);
114      break;
115    }
116    default: {
117      const base::FilePath path = util::GetLocalPathFromURL(
118          render_view_host(), profile(), GURL(file_url));
119
120      if (path.empty()) {
121        SendResponse(false);
122        break;
123      }
124
125      const base::FilePath::StringType display_name = path.BaseName().value();
126
127      // Check if the source path is under Drive cache directory.
128      if (drive::util::IsUnderDriveMountPoint(path)) {
129        drive::DriveIntegrationService* integration_service =
130            drive::DriveIntegrationServiceFactory::GetForProfile(profile_);
131        drive::FileSystemInterface* file_system =
132            integration_service ? integration_service->file_system() : NULL;
133        if (!file_system) {
134          SendResponse(false);
135          break;
136        }
137        file_system->MarkCacheFileAsMounted(
138            drive::util::ExtractDrivePath(path),
139            base::Bind(&AddMountFunction::OnMountedStateSet,
140                       this, mount_type_str, display_name));
141      } else {
142        OnMountedStateSet(mount_type_str, display_name,
143                          drive::FILE_ERROR_OK, path);
144      }
145      break;
146    }
147  }
148
149  return true;
150}
151
152void AddMountFunction::OnMountedStateSet(
153    const std::string& mount_type,
154    const base::FilePath::StringType& file_name,
155    drive::FileError error,
156    const base::FilePath& file_path) {
157  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
158
159  if (error != drive::FILE_ERROR_OK) {
160    SendResponse(false);
161    return;
162  }
163
164  DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
165  // Pass back the actual source path of the mount point.
166  SetResult(new base::StringValue(file_path.value()));
167  SendResponse(true);
168  // MountPath() takes a std::string.
169  disk_mount_manager->MountPath(
170      file_path.AsUTF8Unsafe(), base::FilePath(file_name).Extension(),
171      file_name, DiskMountManager::MountTypeFromString(mount_type));
172}
173
174RemoveMountFunction::RemoveMountFunction() {
175}
176
177RemoveMountFunction::~RemoveMountFunction() {
178}
179
180bool RemoveMountFunction::RunImpl() {
181  if (args_->GetSize() != 1) {
182    return false;
183  }
184
185  std::string mount_path;
186  if (!args_->GetString(0, &mount_path)) {
187    return false;
188  }
189
190  drive::util::Log(logging::LOG_INFO,
191                   "%s[%d] called. (mount_path: '%s')",
192                   name().c_str(),
193                   request_id(),
194                   mount_path.c_str());
195  set_log_on_completion(true);
196
197  std::vector<GURL> file_paths;
198  file_paths.push_back(GURL(mount_path));
199  util::GetSelectedFileInfo(
200      render_view_host(),
201      profile(),
202      file_paths,
203      util::NEED_LOCAL_PATH_FOR_OPENING,
204      base::Bind(&RemoveMountFunction::GetSelectedFileInfoResponse, this));
205  return true;
206}
207
208void RemoveMountFunction::GetSelectedFileInfoResponse(
209    const std::vector<ui::SelectedFileInfo>& files) {
210  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
211
212  if (files.size() != 1) {
213    SendResponse(false);
214    return;
215  }
216
217  // TODO(tbarzic): Send response when callback is received, it would make more
218  // sense than remembering issued unmount requests in file manager and showing
219  // errors for them when MountCompleted event is received.
220  DiskMountManager::GetInstance()->UnmountPath(
221      files[0].local_path.value(),
222      chromeos::UNMOUNT_OPTIONS_NONE,
223      DiskMountManager::UnmountPathCallback());
224  SendResponse(true);
225}
226
227GetMountPointsFunction::GetMountPointsFunction() {
228}
229
230GetMountPointsFunction::~GetMountPointsFunction() {
231}
232
233bool GetMountPointsFunction::RunImpl() {
234  if (args_->GetSize())
235    return false;
236
237  base::ListValue *mounts = new base::ListValue();
238  SetResult(mounts);
239
240  DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
241  DiskMountManager::MountPointMap mount_points =
242      disk_mount_manager->mount_points();
243
244  std::string log_string = "[";
245  const char *separator = "";
246  for (DiskMountManager::MountPointMap::const_iterator it =
247           mount_points.begin();
248       it != mount_points.end();
249       ++it) {
250    mounts->Append(CreateValueFromMountPoint(profile_,
251                                             it->second,
252                                             extension_->id()));
253    log_string += separator + it->first;
254    separator = ", ";
255  }
256
257  log_string += "]";
258
259  drive::util::Log(logging::LOG_INFO,
260                   "%s[%d] succeeded. (results: '%s', %" PRIuS " mount points)",
261                   name().c_str(),
262                   request_id(),
263                   log_string.c_str(),
264                   mount_points.size());
265
266  SendResponse(true);
267  return true;
268}
269
270}  // namespace file_manager
271