Home | History | Annotate | Download | only in file_system_provider
      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