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