Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.cc

Issue 297803011: [SyncFS] Run LocalToRemoteSyncer as SyncTask (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h " 5 #include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h "
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/callback.h" 10 #include "base/callback.h"
11 #include "base/format_macros.h" 11 #include "base/format_macros.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/sequenced_task_runner.h" 14 #include "base/sequenced_task_runner.h"
15 #include "base/task_runner_util.h" 15 #include "base/task_runner_util.h"
16 #include "chrome/browser/drive/drive_api_util.h" 16 #include "chrome/browser/drive/drive_api_util.h"
17 #include "chrome/browser/drive/drive_service_interface.h" 17 #include "chrome/browser/drive/drive_service_interface.h"
18 #include "chrome/browser/drive/drive_uploader.h" 18 #include "chrome/browser/drive/drive_uploader.h"
19 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h" 19 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
20 #include "chrome/browser/sync_file_system/drive_backend/folder_creator.h" 20 #include "chrome/browser/sync_file_system/drive_backend/folder_creator.h"
21 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 21 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
22 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" 22 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
23 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 23 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
24 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
25 #include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
24 #include "chrome/browser/sync_file_system/logger.h" 26 #include "chrome/browser/sync_file_system/logger.h"
25 #include "google_apis/drive/drive_api_parser.h" 27 #include "google_apis/drive/drive_api_parser.h"
26 #include "webkit/common/fileapi/file_system_util.h" 28 #include "webkit/common/fileapi/file_system_util.h"
27 29
28 namespace sync_file_system { 30 namespace sync_file_system {
29 namespace drive_backend { 31 namespace drive_backend {
30 32
31 namespace { 33 namespace {
32 34
33 scoped_ptr<FileTracker> FindTrackerByID(MetadataDatabase* metadata_database, 35 scoped_ptr<FileTracker> FindTrackerByID(MetadataDatabase* metadata_database,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 needs_remote_change_listing_(false), 69 needs_remote_change_listing_(false),
68 weak_ptr_factory_(this) { 70 weak_ptr_factory_(this) {
69 DCHECK(local_is_missing_ || 71 DCHECK(local_is_missing_ ||
70 local_change.file_type() == local_metadata.file_type) 72 local_change.file_type() == local_metadata.file_type)
71 << local_change.DebugString() << " metadata:" << local_metadata.file_type; 73 << local_change.DebugString() << " metadata:" << local_metadata.file_type;
72 } 74 }
73 75
74 LocalToRemoteSyncer::~LocalToRemoteSyncer() { 76 LocalToRemoteSyncer::~LocalToRemoteSyncer() {
75 } 77 }
76 78
77 void LocalToRemoteSyncer::RunExclusive(const SyncStatusCallback& callback) { 79 void LocalToRemoteSyncer::RunPreflight(scoped_ptr<SyncTaskToken> token) {
80 scoped_ptr<BlockingFactor> blocking_factor(new BlockingFactor);
81 blocking_factor->exclusive = true;
82 SyncTaskManager::UpdateBlockingFactor(
83 token.Pass(), blocking_factor.Pass(),
84 base::Bind(&LocalToRemoteSyncer::RunExclusive,
85 weak_ptr_factory_.GetWeakPtr()));
86 }
87
88 void LocalToRemoteSyncer::RunExclusive(scoped_ptr<SyncTaskToken> token) {
78 if (!IsContextReady()) { 89 if (!IsContextReady()) {
79 util::Log(logging::LOG_VERBOSE, FROM_HERE, 90 util::Log(logging::LOG_VERBOSE, FROM_HERE,
80 "[Local -> Remote] Context not ready."); 91 "[Local -> Remote] Context not ready.");
81 NOTREACHED(); 92 NOTREACHED();
82 callback.Run(SYNC_STATUS_FAILED); 93 SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
83 return; 94 return;
84 } 95 }
85 96
86 SyncStatusCallback wrapped_callback = base::Bind(
87 &LocalToRemoteSyncer::SyncCompleted, weak_ptr_factory_.GetWeakPtr(),
88 callback);
89
90 util::Log(logging::LOG_VERBOSE, FROM_HERE, 97 util::Log(logging::LOG_VERBOSE, FROM_HERE,
91 "[Local -> Remote] Start: %s on %s@%s %s", 98 "[Local -> Remote] Start: %s on %s@%s %s",
92 local_change_.DebugString().c_str(), 99 local_change_.DebugString().c_str(),
93 url_.path().AsUTF8Unsafe().c_str(), 100 url_.path().AsUTF8Unsafe().c_str(),
94 url_.origin().host().c_str(), 101 url_.origin().host().c_str(),
95 local_is_missing_ ? "(missing)" : ""); 102 local_is_missing_ ? "(missing)" : "");
96 103
97 if (local_is_missing_ && !local_change_.IsDelete()) { 104 if (local_is_missing_ && !local_change_.IsDelete()) {
98 // Stray file, we can just return. 105 // Stray file, we can just return.
99 util::Log(logging::LOG_VERBOSE, FROM_HERE, 106 util::Log(logging::LOG_VERBOSE, FROM_HERE,
100 "[Local -> Remote]: Missing file for non-delete change"); 107 "[Local -> Remote]: Missing file for non-delete change");
101 callback.Run(SYNC_STATUS_OK); 108 SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK);
102 return; 109 return;
103 } 110 }
104 111
105 std::string app_id = url_.origin().host(); 112 std::string app_id = url_.origin().host();
106 base::FilePath path = url_.path(); 113 base::FilePath path = url_.path();
107 114
108 scoped_ptr<FileTracker> active_ancestor_tracker(new FileTracker); 115 scoped_ptr<FileTracker> active_ancestor_tracker(new FileTracker);
109 base::FilePath active_ancestor_path; 116 base::FilePath active_ancestor_path;
110 if (!metadata_database()->FindNearestActiveAncestor( 117 if (!metadata_database()->FindNearestActiveAncestor(
111 app_id, path, 118 app_id, path,
112 active_ancestor_tracker.get(), &active_ancestor_path)) { 119 active_ancestor_tracker.get(), &active_ancestor_path)) {
113 // The app is disabled or not registered. 120 // The app is disabled or not registered.
114 util::Log(logging::LOG_VERBOSE, FROM_HERE, 121 util::Log(logging::LOG_VERBOSE, FROM_HERE,
115 "[Local -> Remote]: App is disabled or not registered"); 122 "[Local -> Remote]: App is disabled or not registered");
116 callback.Run(SYNC_STATUS_UNKNOWN_ORIGIN); 123 SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_UNKNOWN_ORIGIN);
117 return; 124 return;
118 } 125 }
119 DCHECK(active_ancestor_tracker->active()); 126 DCHECK(active_ancestor_tracker->active());
120 DCHECK(active_ancestor_tracker->has_synced_details()); 127 DCHECK(active_ancestor_tracker->has_synced_details());
121 const FileDetails& active_ancestor_details = 128 const FileDetails& active_ancestor_details =
122 active_ancestor_tracker->synced_details(); 129 active_ancestor_tracker->synced_details();
123 130
124 // TODO(tzik): Consider handling 131 // TODO(tzik): Consider handling
125 // active_ancestor_tracker->synced_details().missing() case. 132 // active_ancestor_tracker->synced_details().missing() case.
126 133
127 DCHECK(active_ancestor_details.file_kind() == FILE_KIND_FILE || 134 DCHECK(active_ancestor_details.file_kind() == FILE_KIND_FILE ||
128 active_ancestor_details.file_kind() == FILE_KIND_FOLDER); 135 active_ancestor_details.file_kind() == FILE_KIND_FOLDER);
129 136
130 base::FilePath missing_entries; 137 base::FilePath missing_entries;
131 if (active_ancestor_path.empty()) { 138 if (active_ancestor_path.empty()) {
132 missing_entries = path; 139 missing_entries = path;
133 } else if (active_ancestor_path != path) { 140 } else if (active_ancestor_path != path) {
134 bool should_success = active_ancestor_path.AppendRelativePath( 141 if (!active_ancestor_path.AppendRelativePath(path, &missing_entries)) {
135 path, &missing_entries);
136 if (!should_success) {
137 NOTREACHED() << "[Local -> Remote]: Detected invalid ancestor: " 142 NOTREACHED() << "[Local -> Remote]: Detected invalid ancestor: "
138 << active_ancestor_path.value(); 143 << active_ancestor_path.value();
139 callback.Run(SYNC_STATUS_FAILED); 144 SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
140 return; 145 return;
141 } 146 }
142 } 147 }
143 148
144 std::vector<base::FilePath::StringType> missing_components; 149 std::vector<base::FilePath::StringType> missing_components;
145 fileapi::VirtualPath::GetComponents(missing_entries, &missing_components); 150 fileapi::VirtualPath::GetComponents(missing_entries, &missing_components);
146 151
147 if (!missing_components.empty()) { 152 if (!missing_components.empty()) {
148 if (local_is_missing_) { 153 if (local_is_missing_) {
149 util::Log(logging::LOG_VERBOSE, FROM_HERE, 154 util::Log(logging::LOG_VERBOSE, FROM_HERE,
150 "[Local -> Remote]: Both local and remote are marked missing"); 155 "[Local -> Remote]: Both local and remote are marked missing");
151 // !IsDelete() but SYNC_FILE_TYPE_UNKNOWN could happen when a file is 156 // !IsDelete() but SYNC_FILE_TYPE_UNKNOWN could happen when a file is
152 // deleted by recursive deletion (which is not recorded by tracker) 157 // deleted by recursive deletion (which is not recorded by tracker)
153 // but there're remaining changes for the same file in the tracker. 158 // but there're remaining changes for the same file in the tracker.
154 159
155 // Local file is deleted and remote file is missing, already deleted or 160 // Local file is deleted and remote file is missing, already deleted or
156 // not yet synced. There is nothing to do for the file. 161 // not yet synced. There is nothing to do for the file.
157 callback.Run(SYNC_STATUS_OK); 162 SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK);
158 return; 163 return;
159 } 164 }
160 } 165 }
161 166
167 SyncStatusCallback callback = base::Bind(
168 &LocalToRemoteSyncer::SyncCompleted, weak_ptr_factory_.GetWeakPtr(),
169 base::Passed(&token));
170
162 if (missing_components.size() > 1) { 171 if (missing_components.size() > 1) {
163 // The original target doesn't have remote file and parent. 172 // The original target doesn't have remote file and parent.
164 // Try creating the parent first. 173 // Try creating the parent first.
165 if (active_ancestor_details.file_kind() == FILE_KIND_FOLDER) { 174 if (active_ancestor_details.file_kind() == FILE_KIND_FOLDER) {
166 remote_parent_folder_tracker_ = active_ancestor_tracker.Pass(); 175 remote_parent_folder_tracker_ = active_ancestor_tracker.Pass();
167 target_path_ = active_ancestor_path.Append(missing_components[0]); 176 target_path_ = active_ancestor_path.Append(missing_components[0]);
168 util::Log(logging::LOG_VERBOSE, FROM_HERE, 177 util::Log(logging::LOG_VERBOSE, FROM_HERE,
169 "[Local -> Remote]: Detected missing parent folder."); 178 "[Local -> Remote]: Detected missing parent folder.");
170 CreateRemoteFolder(wrapped_callback); 179 CreateRemoteFolder(callback);
171 return; 180 return;
172 } 181 }
173 182
174 DCHECK(active_ancestor_details.file_kind() == FILE_KIND_FILE); 183 DCHECK(active_ancestor_details.file_kind() == FILE_KIND_FILE);
175 remote_parent_folder_tracker_ = 184 remote_parent_folder_tracker_ =
176 FindTrackerByID(metadata_database(), 185 FindTrackerByID(metadata_database(),
177 active_ancestor_tracker->parent_tracker_id()); 186 active_ancestor_tracker->parent_tracker_id());
178 remote_file_tracker_ = active_ancestor_tracker.Pass(); 187 remote_file_tracker_ = active_ancestor_tracker.Pass();
179 target_path_ = active_ancestor_path; 188 target_path_ = active_ancestor_path;
180 util::Log(logging::LOG_VERBOSE, FROM_HERE, 189 util::Log(logging::LOG_VERBOSE, FROM_HERE,
181 "[Local -> Remote]: Detected non-folder file in its path."); 190 "[Local -> Remote]: Detected non-folder file in its path.");
182 DeleteRemoteFile(base::Bind(&LocalToRemoteSyncer::DidDeleteForCreateFolder, 191 DeleteRemoteFile(base::Bind(&LocalToRemoteSyncer::DidDeleteForCreateFolder,
183 weak_ptr_factory_.GetWeakPtr(), 192 weak_ptr_factory_.GetWeakPtr(),
184 wrapped_callback)); 193 callback));
185
186 return; 194 return;
187 } 195 }
188 196
189 if (missing_components.empty()) { 197 if (missing_components.empty()) {
190 // The original target has remote active file/folder. 198 // The original target has remote active file/folder.
191 remote_parent_folder_tracker_ = 199 remote_parent_folder_tracker_ =
192 FindTrackerByID(metadata_database(), 200 FindTrackerByID(metadata_database(),
193 active_ancestor_tracker->parent_tracker_id()); 201 active_ancestor_tracker->parent_tracker_id());
194 remote_file_tracker_ = active_ancestor_tracker.Pass(); 202 remote_file_tracker_ = active_ancestor_tracker.Pass();
195 target_path_ = url_.path(); 203 target_path_ = url_.path();
196 DCHECK(target_path_ == active_ancestor_path); 204 DCHECK(target_path_ == active_ancestor_path);
197 205
198 if (remote_file_tracker_->dirty()) { 206 if (remote_file_tracker_->dirty()) {
199 util::Log(logging::LOG_VERBOSE, FROM_HERE, 207 util::Log(logging::LOG_VERBOSE, FROM_HERE,
200 "[Local -> Remote]: Detected conflicting dirty tracker:%" 208 "[Local -> Remote]: Detected conflicting dirty tracker:%"
201 PRId64, remote_file_tracker_->tracker_id()); 209 PRId64, remote_file_tracker_->tracker_id());
202 // Both local and remote file has pending modification. 210 // Both local and remote file has pending modification.
203 HandleConflict(wrapped_callback); 211 HandleConflict(callback);
204 return; 212 return;
205 } 213 }
206 214
207 // Non-conflicting file/folder update case. 215 // Non-conflicting file/folder update case.
208 HandleExistingRemoteFile(wrapped_callback); 216 HandleExistingRemoteFile(callback);
209 return; 217 return;
210 } 218 }
211 219
212 DCHECK(local_change_.IsAddOrUpdate()); 220 DCHECK(local_change_.IsAddOrUpdate());
213 DCHECK_EQ(1u, missing_components.size()); 221 DCHECK_EQ(1u, missing_components.size());
214 // The original target has remote parent folder and doesn't have remote active 222 // The original target has remote parent folder and doesn't have remote active
215 // file. 223 // file.
216 // Upload the file as a new file or create a folder. 224 // Upload the file as a new file or create a folder.
217 remote_parent_folder_tracker_ = active_ancestor_tracker.Pass(); 225 remote_parent_folder_tracker_ = active_ancestor_tracker.Pass();
218 target_path_ = url_.path(); 226 target_path_ = url_.path();
219 DCHECK(target_path_ == active_ancestor_path.Append(missing_components[0])); 227 DCHECK(target_path_ == active_ancestor_path.Append(missing_components[0]));
220 if (local_change_.file_type() == SYNC_FILE_TYPE_FILE) { 228 if (local_change_.file_type() == SYNC_FILE_TYPE_FILE) {
221 util::Log(logging::LOG_VERBOSE, FROM_HERE, 229 util::Log(logging::LOG_VERBOSE, FROM_HERE,
222 "[Local -> Remote]: Detected a new file."); 230 "[Local -> Remote]: Detected a new file.");
223 UploadNewFile(wrapped_callback); 231 UploadNewFile(callback);
224 return; 232 return;
225 } 233 }
226 util::Log(logging::LOG_VERBOSE, FROM_HERE, 234 util::Log(logging::LOG_VERBOSE, FROM_HERE,
227 "[Local -> Remote]: Detected a new folder."); 235 "[Local -> Remote]: Detected a new folder.");
228 CreateRemoteFolder(wrapped_callback); 236 CreateRemoteFolder(callback);
229 } 237 }
230 238
231 void LocalToRemoteSyncer::SyncCompleted(const SyncStatusCallback& callback, 239 void LocalToRemoteSyncer::SyncCompleted(scoped_ptr<SyncTaskToken> token,
232 SyncStatusCode status) { 240 SyncStatusCode status) {
233 if (status == SYNC_STATUS_OK && target_path_ != url_.path()) 241 if (status == SYNC_STATUS_OK && target_path_ != url_.path())
234 status = SYNC_STATUS_RETRY; 242 status = SYNC_STATUS_RETRY;
235 243
236 if (needs_remote_change_listing_) 244 if (needs_remote_change_listing_)
237 status = SYNC_STATUS_FILE_BUSY; 245 status = SYNC_STATUS_FILE_BUSY;
238 246
239 util::Log(logging::LOG_VERBOSE, FROM_HERE, 247 util::Log(logging::LOG_VERBOSE, FROM_HERE,
240 "[Local -> Remote]: Finished: action=%s, status=%s for %s@%s", 248 "[Local -> Remote]: Finished: action=%s, status=%s for %s@%s",
241 SyncActionToString(sync_action_), 249 SyncActionToString(sync_action_),
242 SyncStatusCodeToString(status), 250 SyncStatusCodeToString(status),
243 target_path_.AsUTF8Unsafe().c_str(), 251 target_path_.AsUTF8Unsafe().c_str(),
244 url_.origin().host().c_str()); 252 url_.origin().host().c_str());
245 253
246 callback.Run(status); 254 SyncTaskManager::NotifyTaskDone(token.Pass(), status);
247 } 255 }
248 256
249 void LocalToRemoteSyncer::HandleConflict(const SyncStatusCallback& callback) { 257 void LocalToRemoteSyncer::HandleConflict(const SyncStatusCallback& callback) {
250 DCHECK(remote_file_tracker_); 258 DCHECK(remote_file_tracker_);
251 DCHECK(remote_file_tracker_->has_synced_details()); 259 DCHECK(remote_file_tracker_->has_synced_details());
252 DCHECK(remote_file_tracker_->active()); 260 DCHECK(remote_file_tracker_->active());
253 DCHECK(remote_file_tracker_->dirty()); 261 DCHECK(remote_file_tracker_->dirty());
254 262
255 if (local_is_missing_) { 263 if (local_is_missing_) {
256 callback.Run(SYNC_STATUS_OK); 264 callback.Run(SYNC_STATUS_OK);
257 return; 265 return;
258 } 266 }
259 267
260 if (local_change_.IsFile()) { 268 if (local_change_.IsFile()) {
261 UploadNewFile(callback); 269 UploadNewFile(callback);
262 return; 270 return;
263 } 271 }
264 272
265 DCHECK(local_change_.IsDirectory()); 273 DCHECK(local_change_.IsDirectory());
266 // Check if we can reuse the remote folder. 274 // Check if we can reuse the remote folder.
267 FileMetadata remote_file_metadata; 275 FileMetadata remote_file_metadata;
268 bool should_success = metadata_database()->FindFileByFileID( 276 if (!metadata_database()->FindFileByFileID(
269 remote_file_tracker_->file_id(), &remote_file_metadata); 277 remote_file_tracker_->file_id(), &remote_file_metadata)) {
270 if (!should_success) {
271 NOTREACHED(); 278 NOTREACHED();
272 CreateRemoteFolder(callback); 279 CreateRemoteFolder(callback);
273 return; 280 return;
274 } 281 }
275 282
276 const FileDetails& remote_details = remote_file_metadata.details(); 283 const FileDetails& remote_details = remote_file_metadata.details();
277 base::FilePath title = fileapi::VirtualPath::BaseName(target_path_); 284 base::FilePath title = fileapi::VirtualPath::BaseName(target_path_);
278 if (!remote_details.missing() && 285 if (!remote_details.missing() &&
279 remote_details.file_kind() == FILE_KIND_FOLDER && 286 remote_details.file_kind() == FILE_KIND_FOLDER &&
280 remote_details.title() == title.AsUTF8Unsafe() && 287 remote_details.title() == title.AsUTF8Unsafe() &&
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 463
457 void LocalToRemoteSyncer::DidUpdateDatabaseForUploadExistingFile( 464 void LocalToRemoteSyncer::DidUpdateDatabaseForUploadExistingFile(
458 const SyncStatusCallback& callback, 465 const SyncStatusCallback& callback,
459 SyncStatusCode status) { 466 SyncStatusCode status) {
460 if (status != SYNC_STATUS_OK) { 467 if (status != SYNC_STATUS_OK) {
461 callback.Run(status); 468 callback.Run(status);
462 return; 469 return;
463 } 470 }
464 471
465 FileMetadata file; 472 FileMetadata file;
466 bool should_success = metadata_database()->FindFileByFileID( 473 if (!metadata_database()->FindFileByFileID(
467 remote_file_tracker_->file_id(), &file); 474 remote_file_tracker_->file_id(), &file)) {
468 if (!should_success) {
469 NOTREACHED(); 475 NOTREACHED();
470 callback.Run(SYNC_STATUS_FAILED); 476 callback.Run(SYNC_STATUS_FAILED);
471 return; 477 return;
472 } 478 }
473 479
474 const FileDetails& details = file.details(); 480 const FileDetails& details = file.details();
475 base::FilePath title = fileapi::VirtualPath::BaseName(target_path_); 481 base::FilePath title = fileapi::VirtualPath::BaseName(target_path_);
476 if (!details.missing() && 482 if (!details.missing() &&
477 details.file_kind() == FILE_KIND_FILE && 483 details.file_kind() == FILE_KIND_FILE &&
478 details.title() == title.AsUTF8Unsafe() && 484 details.title() == title.AsUTF8Unsafe() &&
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 set_used_network(true); 691 set_used_network(true);
686 return sync_context_->GetDriveUploader(); 692 return sync_context_->GetDriveUploader();
687 } 693 }
688 694
689 MetadataDatabase* LocalToRemoteSyncer::metadata_database() { 695 MetadataDatabase* LocalToRemoteSyncer::metadata_database() {
690 return sync_context_->GetMetadataDatabase(); 696 return sync_context_->GetMetadataDatabase();
691 } 697 }
692 698
693 } // namespace drive_backend 699 } // namespace drive_backend
694 } // namespace sync_file_system 700 } // namespace sync_file_system
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698