syncable_file_system_util.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 V2 Sync FileSystem.
26const char kEnableSyncFileSystemV2[] = "enable-syncfs-v2";
27
28// A command switch to specify comma-separated app IDs to enable V2 Sync
29// FileSystem.
30const char kSyncFileSystemV2Whitelist[] = "syncfs-v2-whitelist";
31
32const char kSyncableMountName[] = "syncfs";
33const char kSyncableMountNameForInternalSync[] = "syncfs-internal";
34
35const base::FilePath::CharType kSyncFileSystemDir[] =
36    FILE_PATH_LITERAL("Sync FileSystem");
37
38// Flags to enable features for testing.
39bool g_is_syncfs_v2_enabled = true;
40
41void Noop() {}
42
43}  // namespace
44
45void RegisterSyncableFileSystem() {
46  ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
47      kSyncableMountName,
48      fileapi::kFileSystemTypeSyncable,
49      fileapi::FileSystemMountOption(),
50      base::FilePath());
51  ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
52      kSyncableMountNameForInternalSync,
53      fileapi::kFileSystemTypeSyncableForInternalSync,
54      fileapi::FileSystemMountOption(),
55      base::FilePath());
56}
57
58void RevokeSyncableFileSystem() {
59  ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
60      kSyncableMountName);
61  ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
62      kSyncableMountNameForInternalSync);
63}
64
65GURL GetSyncableFileSystemRootURI(const GURL& origin) {
66  return GURL(fileapi::GetExternalFileSystemRootURIString(
67      origin, kSyncableMountName));
68}
69
70FileSystemURL CreateSyncableFileSystemURL(const GURL& origin,
71                                          const base::FilePath& path) {
72  base::FilePath path_for_url = path;
73  if (fileapi::VirtualPath::IsAbsolute(path.value()))
74    path_for_url = base::FilePath(path.value().substr(1));
75
76  return ExternalMountPoints::GetSystemInstance()->CreateExternalFileSystemURL(
77      origin, kSyncableMountName, path_for_url);
78}
79
80FileSystemURL CreateSyncableFileSystemURLForSync(
81    fileapi::FileSystemContext* file_system_context,
82    const FileSystemURL& syncable_url) {
83  return ExternalMountPoints::GetSystemInstance()->CreateExternalFileSystemURL(
84      syncable_url.origin(),
85      kSyncableMountNameForInternalSync,
86      syncable_url.path());
87}
88
89bool SerializeSyncableFileSystemURL(const FileSystemURL& url,
90                                    std::string* serialized_url) {
91  if (!url.is_valid() || url.type() != fileapi::kFileSystemTypeSyncable)
92    return false;
93  *serialized_url =
94      GetSyncableFileSystemRootURI(url.origin()).spec() +
95      url.path().AsUTF8Unsafe();
96  return true;
97}
98
99bool DeserializeSyncableFileSystemURL(
100    const std::string& serialized_url, FileSystemURL* url) {
101#if !defined(FILE_PATH_USES_WIN_SEPARATORS)
102  DCHECK(serialized_url.find('\\') == std::string::npos);
103#endif  // FILE_PATH_USES_WIN_SEPARATORS
104
105  FileSystemURL deserialized =
106      ExternalMountPoints::GetSystemInstance()->CrackURL(GURL(serialized_url));
107  if (!deserialized.is_valid() ||
108      deserialized.type() != fileapi::kFileSystemTypeSyncable) {
109    return false;
110  }
111
112  *url = deserialized;
113  return true;
114}
115
116bool IsV2Enabled() {
117  return g_is_syncfs_v2_enabled ||
118        CommandLine::ForCurrentProcess()->HasSwitch(kEnableSyncFileSystemV2);
119}
120
121bool IsV2EnabledForOrigin(const GURL& origin) {
122  if (IsV2Enabled())
123    return true;
124
125  // Spark release channel.
126  if (origin.host() == "kcjgcakhgelcejampmijgkjkadfcncjl")
127    return true;
128  // Spark dev channel.
129  if (origin.host() == "pnoffddplpippgcfjdhbmhkofpnaalpg")
130    return true;
131
132  CommandLine command_line = *CommandLine::ForCurrentProcess();
133  if (command_line.HasSwitch(kSyncFileSystemV2Whitelist)) {
134    std::string app_ids_string =
135        command_line.GetSwitchValueASCII(kSyncFileSystemV2Whitelist);
136    if (app_ids_string.find(origin.host()) == std::string::npos)
137      return false;
138    std::vector<std::string> app_ids;
139    Tokenize(app_ids_string, ",", &app_ids);
140    for (size_t i = 0; i < app_ids.size(); ++i) {
141      if (origin.host() == app_ids[i])
142        return true;
143    }
144  }
145
146  return false;
147}
148
149base::FilePath GetSyncFileSystemDir(const base::FilePath& profile_base_dir) {
150  if (IsV2Enabled())
151    return profile_base_dir.Append(kSyncFileSystemDir);
152  return profile_base_dir.Append(kSyncFileSystemDir);
153}
154
155ScopedDisableSyncFSV2::ScopedDisableSyncFSV2() {
156  was_enabled_ = IsV2Enabled();
157  g_is_syncfs_v2_enabled = false;
158}
159
160ScopedDisableSyncFSV2::~ScopedDisableSyncFSV2() {
161  DCHECK(!IsV2Enabled());
162  g_is_syncfs_v2_enabled = was_enabled_;
163}
164
165void RunSoon(const tracked_objects::Location& from_here,
166             const base::Closure& callback) {
167  base::MessageLoop::current()->PostTask(from_here, callback);
168}
169
170base::Closure NoopClosure() {
171  return base::Bind(&Noop);
172}
173
174}  // namespace sync_file_system
175