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