• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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