1 // Copyright 2014 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/file_system_provider/mount_path_util.h" 6 7 #include <vector> 8 9 #include "base/stl_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h" 13 #include "chrome/browser/chromeos/file_system_provider/service.h" 14 #include "chrome/browser/chromeos/profiles/profile_helper.h" 15 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile_manager.h" 17 #include "components/user_manager/user.h" 18 #include "components/user_manager/user_manager.h" 19 #include "content/public/browser/browser_thread.h" 20 21 using content::BrowserThread; 22 23 namespace chromeos { 24 namespace file_system_provider { 25 namespace util { 26 27 namespace { 28 29 // Root mount path for all of the provided file systems. 30 const base::FilePath::CharType kProvidedMountPointRoot[] = 31 FILE_PATH_LITERAL("/provided"); 32 33 } // namespace 34 35 // Escapes the file system id so it can be used as a file/directory name. 36 // This is based on net/base/escape.cc: net::(anonymous namespace)::Escape 37 std::string EscapeFileSystemId(const std::string& file_system_id) { 38 std::string escaped; 39 for (size_t i = 0; i < file_system_id.size(); ++i) { 40 const char c = file_system_id[i]; 41 if (c == '%' || c == '.' || c == '/') { 42 base::StringAppendF(&escaped, "%%%02X", c); 43 } else { 44 escaped.push_back(c); 45 } 46 } 47 return escaped; 48 } 49 50 base::FilePath GetMountPath(Profile* profile, 51 const std::string& extension_id, 52 const std::string& file_system_id) { 53 user_manager::User* const user = 54 user_manager::UserManager::IsInitialized() 55 ? chromeos::ProfileHelper::Get()->GetUserByProfile( 56 profile->GetOriginalProfile()) 57 : NULL; 58 const std::string safe_file_system_id = EscapeFileSystemId(file_system_id); 59 const std::string username_suffix = user ? user->username_hash() : ""; 60 return base::FilePath(kProvidedMountPointRoot).AppendASCII( 61 extension_id + ":" + safe_file_system_id + ":" + username_suffix); 62 } 63 64 bool IsFileSystemProviderLocalPath(const base::FilePath& local_path) { 65 std::vector<base::FilePath::StringType> components; 66 local_path.GetComponents(&components); 67 68 if (components.size() < 3) 69 return false; 70 71 if (components[0] != FILE_PATH_LITERAL("/")) 72 return false; 73 74 if (components[1] != kProvidedMountPointRoot + 1 /* no leading slash */) 75 return false; 76 77 return true; 78 } 79 80 FileSystemURLParser::FileSystemURLParser(const storage::FileSystemURL& url) 81 : url_(url), file_system_(NULL) { 82 } 83 84 FileSystemURLParser::~FileSystemURLParser() { 85 } 86 87 bool FileSystemURLParser::Parse() { 88 DCHECK_CURRENTLY_ON(BrowserThread::UI); 89 90 if (url_.type() != storage::kFileSystemTypeProvided) 91 return false; 92 93 // First, find the service handling the mount point of the URL. 94 const std::vector<Profile*>& profiles = 95 g_browser_process->profile_manager()->GetLoadedProfiles(); 96 97 for (size_t i = 0; i < profiles.size(); ++i) { 98 Profile* original_profile = profiles[i]->GetOriginalProfile(); 99 100 if (original_profile != profiles[i] || 101 chromeos::ProfileHelper::IsSigninProfile(original_profile)) { 102 continue; 103 } 104 105 Service* const service = Service::Get(original_profile); 106 if (!service) 107 continue; 108 109 ProvidedFileSystemInterface* const file_system = 110 service->GetProvidedFileSystem(url_.filesystem_id()); 111 if (!file_system) 112 continue; 113 114 // Strip the mount path name from the local path, to extract the file path 115 // within the provided file system. 116 file_system_ = file_system; 117 std::vector<base::FilePath::StringType> components; 118 url_.path().GetComponents(&components); 119 if (components.size() < 3) 120 return false; 121 122 file_path_ = base::FilePath::FromUTF8Unsafe("/"); 123 for (size_t i = 3; i < components.size(); ++i) { 124 // TODO(mtomasz): This could be optimized, to avoid unnecessary copies. 125 file_path_ = file_path_.Append(components[i]); 126 } 127 128 return true; 129 } 130 131 // Nothing has been found. 132 return false; 133 } 134 135 LocalPathParser::LocalPathParser(Profile* profile, 136 const base::FilePath& local_path) 137 : profile_(profile), local_path_(local_path), file_system_(NULL) { 138 } 139 140 LocalPathParser::~LocalPathParser() { 141 } 142 143 bool LocalPathParser::Parse() { 144 DCHECK_CURRENTLY_ON(BrowserThread::UI); 145 146 if (!IsFileSystemProviderLocalPath(local_path_)) 147 return false; 148 149 std::vector<base::FilePath::StringType> components; 150 local_path_.GetComponents(&components); 151 152 if (components.size() < 3) 153 return false; 154 155 const std::string mount_point_name = components[2]; 156 157 Service* const service = Service::Get(profile_); 158 if (!service) 159 return false; 160 161 ProvidedFileSystemInterface* const file_system = 162 service->GetProvidedFileSystem(mount_point_name); 163 if (!file_system) 164 return false; 165 166 // Strip the mount point path from the virtual path, to extract the file 167 // path within the provided file system. 168 file_system_ = file_system; 169 file_path_ = base::FilePath::FromUTF8Unsafe("/"); 170 for (size_t i = 3; i < components.size(); ++i) { 171 file_path_ = file_path_.Append(components[i]); 172 } 173 174 return true; 175 } 176 177 } // namespace util 178 } // namespace file_system_provider 179 } // namespace chromeos 180