Home | History | Annotate | Download | only in sync_file_system
      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/sync_file_system/syncable_file_system_util.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/command_line.h"
     10 #include "base/location.h"
     11 #include "base/strings/string_util.h"
     12 #include "webkit/browser/fileapi/external_mount_points.h"
     13 #include "webkit/browser/fileapi/file_observers.h"
     14 #include "webkit/browser/fileapi/file_system_context.h"
     15 #include "webkit/common/fileapi/file_system_util.h"
     16 
     17 using fileapi::ExternalMountPoints;
     18 using fileapi::FileSystemContext;
     19 using fileapi::FileSystemURL;
     20 
     21 namespace sync_file_system {
     22 
     23 namespace {
     24 
     25 // A command switch to enable syncing directory operations in Sync FileSystem
     26 // API. (http://crbug.com/161442)
     27 // TODO(kinuko): this command-line switch should be temporary.
     28 const char kEnableSyncFSDirectoryOperation[] =
     29     "enable-syncfs-directory-operation";
     30 
     31 // A command switch to enable V2 Sync FileSystem.
     32 const char kEnableSyncFileSystemV2[] = "enable-syncfs-v2";
     33 
     34 // A command switch to specify comma-separated app IDs to enable V2 Sync
     35 // FileSystem.
     36 const char kSyncFileSystemV2Whitelist[] = "syncfs-v2-whitelist";
     37 
     38 const char kSyncableMountName[] = "syncfs";
     39 const char kSyncableMountNameForInternalSync[] = "syncfs-internal";
     40 
     41 const base::FilePath::CharType kSyncFileSystemDir[] =
     42     FILE_PATH_LITERAL("Sync FileSystem");
     43 const base::FilePath::CharType kSyncFileSystemDirDev[] =
     44     FILE_PATH_LITERAL("Sync FileSystem Dev");
     45 
     46 bool is_directory_operation_enabled = false;
     47 
     48 }  // namespace
     49 
     50 void RegisterSyncableFileSystem() {
     51   ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
     52       kSyncableMountName,
     53       fileapi::kFileSystemTypeSyncable,
     54       fileapi::FileSystemMountOption(),
     55       base::FilePath());
     56   ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
     57       kSyncableMountNameForInternalSync,
     58       fileapi::kFileSystemTypeSyncableForInternalSync,
     59       fileapi::FileSystemMountOption(),
     60       base::FilePath());
     61 }
     62 
     63 void RevokeSyncableFileSystem() {
     64   ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
     65       kSyncableMountName);
     66   ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
     67       kSyncableMountNameForInternalSync);
     68 }
     69 
     70 GURL GetSyncableFileSystemRootURI(const GURL& origin) {
     71   return GURL(fileapi::GetExternalFileSystemRootURIString(
     72       origin, kSyncableMountName));
     73 }
     74 
     75 FileSystemURL CreateSyncableFileSystemURL(const GURL& origin,
     76                                           const base::FilePath& path) {
     77   base::FilePath path_for_url = path;
     78   if (fileapi::VirtualPath::IsAbsolute(path.value()))
     79     path_for_url = base::FilePath(path.value().substr(1));
     80 
     81   return ExternalMountPoints::GetSystemInstance()->CreateExternalFileSystemURL(
     82       origin, kSyncableMountName, path_for_url);
     83 }
     84 
     85 FileSystemURL CreateSyncableFileSystemURLForSync(
     86     fileapi::FileSystemContext* file_system_context,
     87     const FileSystemURL& syncable_url) {
     88   return ExternalMountPoints::GetSystemInstance()->CreateExternalFileSystemURL(
     89       syncable_url.origin(),
     90       kSyncableMountNameForInternalSync,
     91       syncable_url.path());
     92 }
     93 
     94 bool SerializeSyncableFileSystemURL(const FileSystemURL& url,
     95                                     std::string* serialized_url) {
     96   if (!url.is_valid() || url.type() != fileapi::kFileSystemTypeSyncable)
     97     return false;
     98   *serialized_url =
     99       GetSyncableFileSystemRootURI(url.origin()).spec() +
    100       url.path().AsUTF8Unsafe();
    101   return true;
    102 }
    103 
    104 bool DeserializeSyncableFileSystemURL(
    105     const std::string& serialized_url, FileSystemURL* url) {
    106 #if !defined(FILE_PATH_USES_WIN_SEPARATORS)
    107   DCHECK(serialized_url.find('\\') == std::string::npos);
    108 #endif  // FILE_PATH_USES_WIN_SEPARATORS
    109 
    110   FileSystemURL deserialized =
    111       ExternalMountPoints::GetSystemInstance()->CrackURL(GURL(serialized_url));
    112   if (!deserialized.is_valid() ||
    113       deserialized.type() != fileapi::kFileSystemTypeSyncable) {
    114     return false;
    115   }
    116 
    117   *url = deserialized;
    118   return true;
    119 }
    120 
    121 void SetEnableSyncFSDirectoryOperation(bool flag) {
    122   is_directory_operation_enabled = flag;
    123 }
    124 
    125 bool IsSyncFSDirectoryOperationEnabled() {
    126   return IsSyncFSDirectoryOperationEnabled(GURL());
    127 }
    128 
    129 bool IsSyncFSDirectoryOperationEnabled(const GURL& origin) {
    130   return is_directory_operation_enabled ||
    131       CommandLine::ForCurrentProcess()->HasSwitch(
    132           kEnableSyncFSDirectoryOperation) ||
    133       IsV2EnabledForOrigin(origin);
    134 }
    135 
    136 bool IsV2Enabled() {
    137   return CommandLine::ForCurrentProcess()->HasSwitch(kEnableSyncFileSystemV2);
    138 }
    139 
    140 bool IsV2EnabledForOrigin(const GURL& origin) {
    141   if (IsV2Enabled())
    142     return true;
    143 
    144   // TODO: Support static whitelisting as well.
    145 
    146   CommandLine command_line = *CommandLine::ForCurrentProcess();
    147   if (command_line.HasSwitch(kSyncFileSystemV2Whitelist)) {
    148     std::string app_ids_string =
    149         command_line.GetSwitchValueASCII(kSyncFileSystemV2Whitelist);
    150     if (app_ids_string.find(origin.host()) == std::string::npos)
    151       return false;
    152     std::vector<std::string> app_ids;
    153     Tokenize(app_ids_string, ",", &app_ids);
    154     for (size_t i = 0; i < app_ids.size(); ++i) {
    155       if (origin.host() == app_ids[i])
    156         return true;
    157     }
    158   }
    159 
    160   return false;
    161 }
    162 
    163 base::FilePath GetSyncFileSystemDir(const base::FilePath& profile_base_dir) {
    164   if (IsV2Enabled())
    165     return profile_base_dir.Append(kSyncFileSystemDir);
    166   if (IsSyncFSDirectoryOperationEnabled())
    167     return profile_base_dir.Append(kSyncFileSystemDirDev);
    168   return profile_base_dir.Append(kSyncFileSystemDir);
    169 }
    170 
    171 ScopedEnableSyncFSDirectoryOperation::ScopedEnableSyncFSDirectoryOperation() {
    172   was_enabled_ = IsSyncFSDirectoryOperationEnabled(GURL());
    173   SetEnableSyncFSDirectoryOperation(true);
    174 }
    175 
    176 ScopedEnableSyncFSDirectoryOperation::~ScopedEnableSyncFSDirectoryOperation() {
    177   DCHECK(IsSyncFSDirectoryOperationEnabled(GURL()));
    178   SetEnableSyncFSDirectoryOperation(was_enabled_);
    179 }
    180 
    181 void RunSoon(const tracked_objects::Location& from_here,
    182              const base::Closure& callback) {
    183   base::MessageLoop::current()->PostTask(from_here, callback);
    184 }
    185 
    186 }  // namespace sync_file_system
    187