syncable_file_system_util.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 17using fileapi::ExternalMountPoints; 18using fileapi::FileSystemContext; 19using fileapi::FileSystemURL; 20 21namespace sync_file_system { 22 23namespace { 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. 28const char kEnableSyncFSDirectoryOperation[] = 29 "enable-syncfs-directory-operation"; 30 31// A command switch to enable V2 Sync FileSystem. 32const char kEnableSyncFileSystemV2[] = "enable-syncfs-v2"; 33 34// A command switch to specify comma-separated app IDs to enable V2 Sync 35// FileSystem. 36const char kSyncFileSystemV2Whitelist[] = "syncfs-v2-whitelist"; 37 38const char kSyncableMountName[] = "syncfs"; 39const char kSyncableMountNameForInternalSync[] = "syncfs-internal"; 40 41const base::FilePath::CharType kSyncFileSystemDir[] = 42 FILE_PATH_LITERAL("Sync FileSystem"); 43const base::FilePath::CharType kSyncFileSystemDirDev[] = 44 FILE_PATH_LITERAL("Sync FileSystem Dev"); 45 46// Flags to enable features for testing. 47bool g_is_directory_operation_enabled = false; 48bool g_is_syncfs_v2_enabled = false; 49 50} // namespace 51 52void 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 65void RevokeSyncableFileSystem() { 66 ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( 67 kSyncableMountName); 68 ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( 69 kSyncableMountNameForInternalSync); 70} 71 72GURL GetSyncableFileSystemRootURI(const GURL& origin) { 73 return GURL(fileapi::GetExternalFileSystemRootURIString( 74 origin, kSyncableMountName)); 75} 76 77FileSystemURL 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 87FileSystemURL 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 96bool 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 106bool 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 123void SetEnableSyncFSDirectoryOperation(bool flag) { 124 g_is_directory_operation_enabled = flag; 125} 126 127bool IsSyncFSDirectoryOperationEnabled() { 128 return IsSyncFSDirectoryOperationEnabled(GURL()); 129} 130 131bool IsSyncFSDirectoryOperationEnabled(const GURL& origin) { 132 return g_is_directory_operation_enabled || 133 CommandLine::ForCurrentProcess()->HasSwitch( 134 kEnableSyncFSDirectoryOperation) || 135 IsV2EnabledForOrigin(origin); 136} 137 138bool IsV2Enabled() { 139 return g_is_syncfs_v2_enabled || 140 CommandLine::ForCurrentProcess()->HasSwitch(kEnableSyncFileSystemV2); 141} 142 143bool 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 171base::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 179ScopedEnableSyncFSDirectoryOperation::ScopedEnableSyncFSDirectoryOperation() { 180 was_enabled_ = IsSyncFSDirectoryOperationEnabled(GURL()); 181 SetEnableSyncFSDirectoryOperation(true); 182} 183 184ScopedEnableSyncFSDirectoryOperation::~ScopedEnableSyncFSDirectoryOperation() { 185 DCHECK(IsSyncFSDirectoryOperationEnabled(GURL())); 186 SetEnableSyncFSDirectoryOperation(was_enabled_); 187} 188 189ScopedEnableSyncFSV2::ScopedEnableSyncFSV2() { 190 was_enabled_ = IsV2Enabled(); 191 g_is_syncfs_v2_enabled = true; 192} 193 194ScopedEnableSyncFSV2::~ScopedEnableSyncFSV2() { 195 DCHECK(IsV2Enabled()); 196 g_is_syncfs_v2_enabled = was_enabled_; 197} 198 199void 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