Home | History | Annotate | Download | only in file_manager
      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 
     22 using chromeos::disks::DiskMountManager;
     23 using content::BrowserThread;
     24 
     25 namespace file_manager {
     26 namespace {
     27 
     28 // Creates a dictionary describing the mount point of |mount_point_info|.
     29 base::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 
     61 AddMountFunction::AddMountFunction() {
     62 }
     63 
     64 AddMountFunction::~AddMountFunction() {
     65 }
     66 
     67 bool 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 
    152 void 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 
    174 RemoveMountFunction::RemoveMountFunction() {
    175 }
    176 
    177 RemoveMountFunction::~RemoveMountFunction() {
    178 }
    179 
    180 bool 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 
    208 void 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 
    227 GetMountPointsFunction::GetMountPointsFunction() {
    228 }
    229 
    230 GetMountPointsFunction::~GetMountPointsFunction() {
    231 }
    232 
    233 bool 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