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
RegisterSyncableFileSystem()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
RevokeSyncableFileSystem()65 void RevokeSyncableFileSystem() {
66 ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
67 kSyncableMountName);
68 ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
69 kSyncableMountNameForInternalSync);
70 }
71
GetSyncableFileSystemRootURI(const GURL & origin)72 GURL GetSyncableFileSystemRootURI(const GURL& origin) {
73 return GURL(fileapi::GetExternalFileSystemRootURIString(
74 origin, kSyncableMountName));
75 }
76
CreateSyncableFileSystemURL(const GURL & origin,const base::FilePath & path)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
CreateSyncableFileSystemURLForSync(fileapi::FileSystemContext * file_system_context,const FileSystemURL & syncable_url)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
SerializeSyncableFileSystemURL(const FileSystemURL & url,std::string * serialized_url)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
DeserializeSyncableFileSystemURL(const std::string & serialized_url,FileSystemURL * url)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
SetEnableSyncFSDirectoryOperation(bool flag)123 void SetEnableSyncFSDirectoryOperation(bool flag) {
124 g_is_directory_operation_enabled = flag;
125 }
126
IsSyncFSDirectoryOperationEnabled()127 bool IsSyncFSDirectoryOperationEnabled() {
128 return IsSyncFSDirectoryOperationEnabled(GURL());
129 }
130
IsSyncFSDirectoryOperationEnabled(const GURL & origin)131 bool IsSyncFSDirectoryOperationEnabled(const GURL& origin) {
132 return g_is_directory_operation_enabled ||
133 CommandLine::ForCurrentProcess()->HasSwitch(
134 kEnableSyncFSDirectoryOperation) ||
135 IsV2EnabledForOrigin(origin);
136 }
137
IsV2Enabled()138 bool IsV2Enabled() {
139 return g_is_syncfs_v2_enabled ||
140 CommandLine::ForCurrentProcess()->HasSwitch(kEnableSyncFileSystemV2);
141 }
142
IsV2EnabledForOrigin(const GURL & origin)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
GetSyncFileSystemDir(const base::FilePath & profile_base_dir)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
ScopedEnableSyncFSDirectoryOperation()179 ScopedEnableSyncFSDirectoryOperation::ScopedEnableSyncFSDirectoryOperation() {
180 was_enabled_ = IsSyncFSDirectoryOperationEnabled(GURL());
181 SetEnableSyncFSDirectoryOperation(true);
182 }
183
~ScopedEnableSyncFSDirectoryOperation()184 ScopedEnableSyncFSDirectoryOperation::~ScopedEnableSyncFSDirectoryOperation() {
185 DCHECK(IsSyncFSDirectoryOperationEnabled(GURL()));
186 SetEnableSyncFSDirectoryOperation(was_enabled_);
187 }
188
ScopedDisableSyncFSV2()189 ScopedDisableSyncFSV2::ScopedDisableSyncFSV2() {
190 was_enabled_ = IsV2Enabled();
191 g_is_syncfs_v2_enabled = false;
192 }
193
~ScopedDisableSyncFSV2()194 ScopedDisableSyncFSV2::~ScopedDisableSyncFSV2() {
195 DCHECK(!IsV2Enabled());
196 g_is_syncfs_v2_enabled = was_enabled_;
197 }
198
RunSoon(const tracked_objects::Location & from_here,const base::Closure & callback)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