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 // Flags to enable features for testing.
     47 bool g_is_directory_operation_enabled = false;
     48 bool g_is_syncfs_v2_enabled = true;
     49 
     50 }  // namespace
     51 
     52 void RegisterSyncableFileSystem() {
     53   ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
     54       kSyncableMountName,
     55       fileapi::kFileSystemTypeSyncable,
     56       fileapi::FileSystemMountOption(),
     57       base::FilePath());
     58   ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
     59       kSyncableMountNameForInternalSync,
     60       fileapi::kFileSystemTypeSyncableForInternalSync,
     61       fileapi::FileSystemMountOption(),
     62       base::FilePath());
     63 }
     64 
     65 void RevokeSyncableFileSystem() {
     66   ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
     67       kSyncableMountName);
     68   ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
     69       kSyncableMountNameForInternalSync);
     70 }
     71 
     72 GURL GetSyncableFileSystemRootURI(const GURL& origin) {
     73   return GURL(fileapi::GetExternalFileSystemRootURIString(
     74       origin, kSyncableMountName));
     75 }
     76 
     77 FileSystemURL CreateSyncableFileSystemURL(const GURL& origin,
     78                                           const base::FilePath& path) {
     79   base::FilePath path_for_url = path;
     80   if (fileapi::VirtualPath::IsAbsolute(path.value()))
     81     path_for_url = base::FilePath(path.value().substr(1));
     82 
     83   return ExternalMountPoints::GetSystemInstance()->CreateExternalFileSystemURL(
     84       origin, kSyncableMountName, path_for_url);
     85 }
     86 
     87 FileSystemURL CreateSyncableFileSystemURLForSync(
     88     fileapi::FileSystemContext* file_system_context,
     89     const FileSystemURL& syncable_url) {
     90   return ExternalMountPoints::GetSystemInstance()->CreateExternalFileSystemURL(
     91       syncable_url.origin(),
     92       kSyncableMountNameForInternalSync,
     93       syncable_url.path());
     94 }
     95 
     96 bool SerializeSyncableFileSystemURL(const FileSystemURL& url,
     97                                     std::string* serialized_url) {
     98   if (!url.is_valid() || url.type() != fileapi::kFileSystemTypeSyncable)
     99     return false;
    100   *serialized_url =
    101       GetSyncableFileSystemRootURI(url.origin()).spec() +
    102       url.path().AsUTF8Unsafe();
    103   return true;
    104 }
    105 
    106 bool DeserializeSyncableFileSystemURL(
    107     const std::string& serialized_url, FileSystemURL* url) {
    108 #if !defined(FILE_PATH_USES_WIN_SEPARATORS)
    109   DCHECK(serialized_url.find('\\') == std::string::npos);
    110 #endif  // FILE_PATH_USES_WIN_SEPARATORS
    111 
    112   FileSystemURL deserialized =
    113       ExternalMountPoints::GetSystemInstance()->CrackURL(GURL(serialized_url));
    114   if (!deserialized.is_valid() ||
    115       deserialized.type() != fileapi::kFileSystemTypeSyncable) {
    116     return false;
    117   }
    118 
    119   *url = deserialized;
    120   return true;
    121 }
    122 
    123 void SetEnableSyncFSDirectoryOperation(bool flag) {
    124   g_is_directory_operation_enabled = flag;
    125 }
    126 
    127 bool IsSyncFSDirectoryOperationEnabled() {
    128   return IsSyncFSDirectoryOperationEnabled(GURL());
    129 }
    130 
    131 bool IsSyncFSDirectoryOperationEnabled(const GURL& origin) {
    132   return g_is_directory_operation_enabled ||
    133       CommandLine::ForCurrentProcess()->HasSwitch(
    134           kEnableSyncFSDirectoryOperation) ||
    135       IsV2EnabledForOrigin(origin);
    136 }
    137 
    138 bool IsV2Enabled() {
    139   return g_is_syncfs_v2_enabled ||
    140         CommandLine::ForCurrentProcess()->HasSwitch(kEnableSyncFileSystemV2);
    141 }
    142 
    143 bool IsV2EnabledForOrigin(const GURL& origin) {
    144   if (IsV2Enabled())
    145     return true;
    146 
    147   // Spark release channel.
    148   if (origin.host() == "kcjgcakhgelcejampmijgkjkadfcncjl")
    149     return true;
    150   // Spark dev channel.
    151   if (origin.host() == "pnoffddplpippgcfjdhbmhkofpnaalpg")
    152     return true;
    153 
    154   CommandLine command_line = *CommandLine::ForCurrentProcess();
    155   if (command_line.HasSwitch(kSyncFileSystemV2Whitelist)) {
    156     std::string app_ids_string =
    157         command_line.GetSwitchValueASCII(kSyncFileSystemV2Whitelist);
    158     if (app_ids_string.find(origin.host()) == std::string::npos)
    159       return false;
    160     std::vector<std::string> app_ids;
    161     Tokenize(app_ids_string, ",", &app_ids);
    162     for (size_t i = 0; i < app_ids.size(); ++i) {
    163       if (origin.host() == app_ids[i])
    164         return true;
    165     }
    166   }
    167 
    168   return false;
    169 }
    170 
    171 base::FilePath GetSyncFileSystemDir(const base::FilePath& profile_base_dir) {
    172   if (IsV2Enabled())
    173     return profile_base_dir.Append(kSyncFileSystemDir);
    174   if (IsSyncFSDirectoryOperationEnabled())
    175     return profile_base_dir.Append(kSyncFileSystemDirDev);
    176   return profile_base_dir.Append(kSyncFileSystemDir);
    177 }
    178 
    179 ScopedEnableSyncFSDirectoryOperation::ScopedEnableSyncFSDirectoryOperation() {
    180   was_enabled_ = IsSyncFSDirectoryOperationEnabled(GURL());
    181   SetEnableSyncFSDirectoryOperation(true);
    182 }
    183 
    184 ScopedEnableSyncFSDirectoryOperation::~ScopedEnableSyncFSDirectoryOperation() {
    185   DCHECK(IsSyncFSDirectoryOperationEnabled(GURL()));
    186   SetEnableSyncFSDirectoryOperation(was_enabled_);
    187 }
    188 
    189 ScopedDisableSyncFSV2::ScopedDisableSyncFSV2() {
    190   was_enabled_ = IsV2Enabled();
    191   g_is_syncfs_v2_enabled = false;
    192 }
    193 
    194 ScopedDisableSyncFSV2::~ScopedDisableSyncFSV2() {
    195   DCHECK(!IsV2Enabled());
    196   g_is_syncfs_v2_enabled = was_enabled_;
    197 }
    198 
    199 void RunSoon(const tracked_objects::Location& from_here,
    200              const base::Closure& callback) {
    201   base::MessageLoop::current()->PostTask(from_here, callback);
    202 }
    203 
    204 }  // namespace sync_file_system
    205