Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / drive_backend / metadata_db_migration_util.cc
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/drive_backend/metadata_db_migration_util.h"
6
7 #include "base/files/file_path.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string_util.h"
10 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
11 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
12 #include "url/gurl.h"
13 #include "webkit/common/fileapi/file_system_types.h"
14 #include "webkit/common/fileapi/file_system_util.h"
15
16 namespace sync_file_system {
17 namespace drive_backend {
18
19 namespace {
20
21 const base::FilePath::CharType kV0FormatPathPrefix[] =
22     FILE_PATH_LITERAL("drive/");
23 const char kWapiFileIdPrefix[] = "file:";
24 const char kWapiFolderIdPrefix[] = "folder:";
25
26 }  // namespace
27
28 bool ParseV0FormatFileSystemURL(const GURL& url,
29                                 GURL* origin,
30                                 base::FilePath* path) {
31   fileapi::FileSystemType mount_type;
32   base::FilePath virtual_path;
33
34   if (!fileapi::ParseFileSystemSchemeURL(
35           url, origin, &mount_type, &virtual_path) ||
36       mount_type != fileapi::kFileSystemTypeExternal) {
37     NOTREACHED() << "Failed to parse filesystem scheme URL " << url.spec();
38     return false;
39   }
40
41   base::FilePath::StringType prefix =
42       base::FilePath(kV0FormatPathPrefix).NormalizePathSeparators().value();
43   if (virtual_path.value().substr(0, prefix.size()) != prefix)
44     return false;
45
46   *path = base::FilePath(virtual_path.value().substr(prefix.size()));
47   return true;
48 }
49
50 std::string AddWapiFilePrefix(const std::string& resource_id) {
51   DCHECK(!StartsWithASCII(resource_id, kWapiFileIdPrefix, true));
52   DCHECK(!StartsWithASCII(resource_id, kWapiFolderIdPrefix, true));
53
54   if (resource_id.empty() ||
55       StartsWithASCII(resource_id, kWapiFileIdPrefix, true) ||
56       StartsWithASCII(resource_id, kWapiFolderIdPrefix, true))
57     return resource_id;
58   return kWapiFileIdPrefix + resource_id;
59 }
60
61 std::string AddWapiFolderPrefix(const std::string& resource_id) {
62   DCHECK(!StartsWithASCII(resource_id, kWapiFileIdPrefix, true));
63   DCHECK(!StartsWithASCII(resource_id, kWapiFolderIdPrefix, true));
64
65   if (resource_id.empty() ||
66       StartsWithASCII(resource_id, kWapiFileIdPrefix, true) ||
67       StartsWithASCII(resource_id, kWapiFolderIdPrefix, true))
68     return resource_id;
69   return kWapiFolderIdPrefix + resource_id;
70 }
71
72 std::string AddWapiIdPrefix(const std::string& resource_id,
73                             DriveMetadata_ResourceType type) {
74   switch (type) {
75     case DriveMetadata_ResourceType_RESOURCE_TYPE_FILE:
76       return AddWapiFilePrefix(resource_id);
77     case DriveMetadata_ResourceType_RESOURCE_TYPE_FOLDER:
78       return AddWapiFolderPrefix(resource_id);
79   }
80   NOTREACHED();
81   return resource_id;
82 }
83
84 std::string RemoveWapiIdPrefix(const std::string& resource_id) {
85   std::string value;
86   if (RemovePrefix(resource_id, kWapiFileIdPrefix, &value))
87     return value;
88   if (RemovePrefix(resource_id, kWapiFolderIdPrefix, &value))
89     return value;
90   return resource_id;
91 }
92
93 SyncStatusCode MigrateDatabaseFromV0ToV1(leveldb::DB* db) {
94   // Version 0 database format:
95   //   key: "CHANGE_STAMP"
96   //   value: <Largest Changestamp>
97   //
98   //   key: "SYNC_ROOT_DIR"
99   //   value: <Resource ID of the sync root directory>
100   //
101   //   key: "METADATA: " +
102   //        <FileSystemURL serialized by SerializeSyncableFileSystemURL>
103   //   value: <Serialized DriveMetadata>
104   //
105   //   key: "BSYNC_ORIGIN: " + <URL string of a batch sync origin>
106   //   value: <Resource ID of the drive directory for the origin>
107   //
108   //   key: "ISYNC_ORIGIN: " + <URL string of a incremental sync origin>
109   //   value: <Resource ID of the drive directory for the origin>
110   //
111   // Version 1 database format (changed keys/fields are marked with '*'):
112   // * key: "VERSION" (new)
113   // * value: 1
114   //
115   //   key: "CHANGE_STAMP"
116   //   value: <Largest Changestamp>
117   //
118   //   key: "SYNC_ROOT_DIR"
119   //   value: <Resource ID of the sync root directory>
120   //
121   // * key: "METADATA: " + <Origin and URL> (changed)
122   // * value: <Serialized DriveMetadata>
123   //
124   //   key: "BSYNC_ORIGIN: " + <URL string of a batch sync origin>
125   //   value: <Resource ID of the drive directory for the origin>
126   //
127   //   key: "ISYNC_ORIGIN: " + <URL string of a incremental sync origin>
128   //   value: <Resource ID of the drive directory for the origin>
129   //
130   //   key: "DISABLED_ORIGIN: " + <URL string of a disabled origin>
131   //   value: <Resource ID of the drive directory for the origin>
132
133   const char kDatabaseVersionKey[] = "VERSION";
134   const char kDriveMetadataKeyPrefix[] = "METADATA: ";
135   const char kMetadataKeySeparator = ' ';
136
137   leveldb::WriteBatch write_batch;
138   write_batch.Put(kDatabaseVersionKey, "1");
139
140   scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
141   for (itr->Seek(kDriveMetadataKeyPrefix); itr->Valid(); itr->Next()) {
142     std::string key = itr->key().ToString();
143     if (!StartsWithASCII(key, kDriveMetadataKeyPrefix, true))
144       break;
145     std::string serialized_url;
146     RemovePrefix(key, kDriveMetadataKeyPrefix, &serialized_url);
147
148     GURL origin;
149     base::FilePath path;
150     bool success = ParseV0FormatFileSystemURL(
151         GURL(serialized_url), &origin, &path);
152     DCHECK(success) << serialized_url;
153     std::string new_key = kDriveMetadataKeyPrefix + origin.spec() +
154         kMetadataKeySeparator + path.AsUTF8Unsafe();
155
156     write_batch.Put(new_key, itr->value());
157     write_batch.Delete(key);
158   }
159
160   return LevelDBStatusToSyncStatusCode(
161       db->Write(leveldb::WriteOptions(), &write_batch));
162 }
163
164 SyncStatusCode MigrateDatabaseFromV1ToV2(leveldb::DB* db) {
165   // Strips prefix of WAPI resource ID, and discards batch sync origins.
166   // (i.e. "file:xxxx" => "xxxx", "folder:yyyy" => "yyyy")
167   //
168   // Version 2 database format (changed keys/fields are marked with '*'):
169   //   key: "VERSION"
170   // * value: 2
171   //
172   //   key: "CHANGE_STAMP"
173   //   value: <Largest Changestamp>
174   //
175   //   key: "SYNC_ROOT_DIR"
176   // * value: <Resource ID of the sync root directory> (striped)
177   //
178   //   key: "METADATA: " + <Origin and URL>
179   // * value: <Serialized DriveMetadata> (stripped)
180   //
181   // * key: "BSYNC_ORIGIN: " + <URL string of a batch sync origin> (deleted)
182   // * value: <Resource ID of the drive directory for the origin> (deleted)
183   //
184   //   key: "ISYNC_ORIGIN: " + <URL string of a incremental sync origin>
185   // * value: <Resource ID of the drive directory for the origin> (stripped)
186   //
187   //   key: "DISABLED_ORIGIN: " + <URL string of a disabled origin>
188   // * value: <Resource ID of the drive directory for the origin> (stripped)
189
190   const char kDatabaseVersionKey[] = "VERSION";
191   const char kSyncRootDirectoryKey[] = "SYNC_ROOT_DIR";
192   const char kDriveMetadataKeyPrefix[] = "METADATA: ";
193   const char kDriveBatchSyncOriginKeyPrefix[] = "BSYNC_ORIGIN: ";
194   const char kDriveIncrementalSyncOriginKeyPrefix[] = "ISYNC_ORIGIN: ";
195   const char kDriveDisabledOriginKeyPrefix[] = "DISABLED_ORIGIN: ";
196
197   leveldb::WriteBatch write_batch;
198   write_batch.Put(kDatabaseVersionKey, "2");
199
200   scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
201   for (itr->SeekToFirst(); itr->Valid(); itr->Next()) {
202     std::string key = itr->key().ToString();
203
204     // Strip resource id for the sync root directory.
205     if (StartsWithASCII(key, kSyncRootDirectoryKey, true)) {
206       write_batch.Put(key, RemoveWapiIdPrefix(itr->value().ToString()));
207       continue;
208     }
209
210     // Strip resource ids in the drive metadata.
211     if (StartsWithASCII(key, kDriveMetadataKeyPrefix, true)) {
212       DriveMetadata metadata;
213       bool success = metadata.ParseFromString(itr->value().ToString());
214       DCHECK(success);
215
216       metadata.set_resource_id(RemoveWapiIdPrefix(metadata.resource_id()));
217       std::string metadata_string;
218       metadata.SerializeToString(&metadata_string);
219
220       write_batch.Put(key, metadata_string);
221       continue;
222     }
223
224     // Deprecate legacy batch sync origin entries that are no longer needed.
225     if (StartsWithASCII(key, kDriveBatchSyncOriginKeyPrefix, true)) {
226       write_batch.Delete(key);
227       continue;
228     }
229
230     // Strip resource ids of the incremental sync origins.
231     if (StartsWithASCII(key, kDriveIncrementalSyncOriginKeyPrefix, true)) {
232       write_batch.Put(key, RemoveWapiIdPrefix(itr->value().ToString()));
233       continue;
234     }
235
236     // Strip resource ids of the disabled sync origins.
237     if (StartsWithASCII(key, kDriveDisabledOriginKeyPrefix, true)) {
238       write_batch.Put(key, RemoveWapiIdPrefix(itr->value().ToString()));
239       continue;
240     }
241   }
242
243   return LevelDBStatusToSyncStatusCode(
244       db->Write(leveldb::WriteOptions(), &write_batch));
245 }
246
247 SyncStatusCode MigrateDatabaseFromV4ToV3(leveldb::DB* db) {
248   // Rollback from version 4 to version 3.
249   // Please see metadata_database_index.cc for version 3 format, and
250   // metadata_database_index_on_disk.cc for version 4 format.
251
252   const char kDatabaseVersionKey[] = "VERSION";
253   const char kServiceMetadataKey[] = "SERVICE";
254   const char kFileMetadataKeyPrefix[] = "FILE: ";
255   const char kFileTrackerKeyPrefix[] = "TRACKER: ";
256
257   // Key prefixes used in version 4.
258   const char kAppRootIDByAppIDKeyPrefix[] = "APP_ROOT: ";
259   const char kActiveTrackerIDByFileIDKeyPrefix[] = "ACTIVE_FILE: ";
260   const char kTrackerIDByFileIDKeyPrefix[] = "TRACKER_FILE: ";
261   const char kMultiTrackerByFileIDKeyPrefix[] = "MULTI_FILE: ";
262   const char kActiveTrackerIDByParentAndTitleKeyPrefix[] = "ACTIVE_PATH: ";
263   const char kTrackerIDByParentAndTitleKeyPrefix[] = "TRACKER_PATH: ";
264   const char kMultiBackingParentAndTitleKeyPrefix[] = "MULTI_PATH: ";
265   const char kDirtyIDKeyPrefix[] = "DIRTY: ";
266   const char kDemotedDirtyIDKeyPrefix[] = "DEMOTED_DIRTY: ";
267
268   leveldb::WriteBatch write_batch;
269   write_batch.Put(kDatabaseVersionKey, "3");
270
271   scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
272   for (itr->SeekToFirst(); itr->Valid(); itr->Next()) {
273     std::string key = itr->key().ToString();
274
275     // Do nothing for valid entries in both versions.
276     if (StartsWithASCII(key, kServiceMetadataKey, true) ||
277         StartsWithASCII(key, kFileMetadataKeyPrefix, true) ||
278         StartsWithASCII(key, kFileTrackerKeyPrefix, true)) {
279       continue;
280     }
281
282     // Drop entries used in version 4 only.
283     if (StartsWithASCII(key, kAppRootIDByAppIDKeyPrefix, true) ||
284         StartsWithASCII(key, kActiveTrackerIDByFileIDKeyPrefix, true) ||
285         StartsWithASCII(key, kTrackerIDByFileIDKeyPrefix, true) ||
286         StartsWithASCII(key, kMultiTrackerByFileIDKeyPrefix, true) ||
287         StartsWithASCII(key, kActiveTrackerIDByParentAndTitleKeyPrefix, true) ||
288         StartsWithASCII(key, kTrackerIDByParentAndTitleKeyPrefix, true) ||
289         StartsWithASCII(key, kMultiBackingParentAndTitleKeyPrefix, true) ||
290         StartsWithASCII(key, kDirtyIDKeyPrefix, true) ||
291         StartsWithASCII(key, kDemotedDirtyIDKeyPrefix, true)) {
292       write_batch.Delete(key);
293       continue;
294     }
295
296     DVLOG(3) << "Unknown key: " << key << " was found.";
297   }
298
299   return LevelDBStatusToSyncStatusCode(
300       db->Write(leveldb::WriteOptions(), &write_batch));
301 }
302
303 }  // namespace drive_backend
304 }  // namespace sync_file_system