syncable_file_system_util.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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
46bool is_directory_operation_enabled = false;
47
48}  // namespace
49
50void 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
63void RevokeSyncableFileSystem() {
64  ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
65      kSyncableMountName);
66  ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
67      kSyncableMountNameForInternalSync);
68}
69
70GURL GetSyncableFileSystemRootURI(const GURL& origin) {
71  return GURL(fileapi::GetExternalFileSystemRootURIString(
72      origin, kSyncableMountName));
73}
74
75FileSystemURL 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
85FileSystemURL 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
94bool 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
104bool 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
121void SetEnableSyncFSDirectoryOperation(bool flag) {
122  is_directory_operation_enabled = flag;
123}
124
125bool IsSyncFSDirectoryOperationEnabled() {
126  return IsSyncFSDirectoryOperationEnabled(GURL());
127}
128
129bool IsSyncFSDirectoryOperationEnabled(const GURL& origin) {
130  return is_directory_operation_enabled ||
131      CommandLine::ForCurrentProcess()->HasSwitch(
132          kEnableSyncFSDirectoryOperation) ||
133      IsV2EnabledForOrigin(origin);
134}
135
136bool IsV2Enabled() {
137  return CommandLine::ForCurrentProcess()->HasSwitch(kEnableSyncFileSystemV2);
138}
139
140bool 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
163base::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
171ScopedEnableSyncFSDirectoryOperation::ScopedEnableSyncFSDirectoryOperation() {
172  was_enabled_ = IsSyncFSDirectoryOperationEnabled(GURL());
173  SetEnableSyncFSDirectoryOperation(true);
174}
175
176ScopedEnableSyncFSDirectoryOperation::~ScopedEnableSyncFSDirectoryOperation() {
177  DCHECK(IsSyncFSDirectoryOperationEnabled(GURL()));
178  SetEnableSyncFSDirectoryOperation(was_enabled_);
179}
180
181void 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