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