14ee2ad04344446e610172a0e73949212923014dfSebastian Redl// Copyright 2013 The Chromium Authors. All rights reserved.
22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Use of this source code is governed by a BSD-style license that can be
32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// found in the LICENSE file.
42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/single_thread_task_runner.h"
82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/stl_util.h"
92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/thread_task_runner_handle.h"
10a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl#include "chrome/browser/extensions/extension_util.h"
112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/browser/profiles/profile.h"
122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/browser/sync_file_system/file_change.h"
132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/browser/sync_file_system/local/local_file_change_tracker.h"
147faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redl#include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
150eca89e9890db4d8336ce762a5b359a1d58ca02bArgyrios Kyrtzidis#include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "chrome/browser/sync_file_system/local_change_processor.h"
17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "chrome/browser/sync_file_system/logger.h"
182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "chrome/browser/sync_file_system/sync_file_metadata.h"
192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "content/public/browser/browser_context.h"
202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "content/public/browser/browser_thread.h"
212a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall#include "content/public/browser/site_instance.h"
2289eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis#include "content/public/browser/storage_partition.h"
230b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregor#include "extensions/browser/extension_registry.h"
247a1fad38256eb4c5129359be85ba1ea1678eb5c9John McCall#include "extensions/common/extension_set.h"
252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "storage/browser/fileapi/file_system_context.h"
26a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall#include "storage/browser/fileapi/file_system_url.h"
276ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redl#include "storage/common/blob/scoped_file.h"
287c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner#include "url/gurl.h"
296a5a23f8e7fb65e028c8092bc1d1a1d9dfe2e9bcDouglas Gregor
307c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattnerusing content::BrowserThread;
3183d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroffusing storage::FileSystemURL;
3214f79002e58556798e86168c63e48d533287eda5Douglas Gregor
3310e286aa8d39fb51a21412850265d9dae74613eeChris Lattnernamespace sync_file_system {
343251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregor
3514f79002e58556798e86168c63e48d533287eda5Douglas Gregornamespace {
36bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor
372bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregorvoid PrepareForProcessRemoteChangeCallbackAdapter(
38ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregor    const RemoteChangeProcessor::PrepareChangeCallback& callback,
390a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor    SyncStatusCode status,
4017fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor    const LocalFileSyncInfo& sync_file_info,
4117fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor    storage::ScopedFile snapshot) {
422596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar  callback.Run(status, sync_file_info.metadata, sync_file_info.changes);
432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
44fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer
4514f79002e58556798e86168c63e48d533287eda5Douglas Gregorvoid InvokeCallbackOnNthInvocation(int* count, const base::Closure& callback) {
4603013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer  --*count;
47f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor  if (*count <= 0)
483c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattner    callback.Run();
49cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor}
50f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor
512cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}  // namespace
528538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas GregorLocalFileSyncService::OriginChangeMap::OriginChangeMap()
54ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl    : next_(change_count_map_.end()) {}
555f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerLocalFileSyncService::OriginChangeMap::~OriginChangeMap() {}
565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner
575f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerbool LocalFileSyncService::OriginChangeMap::NextOriginToProcess(GURL* origin) {
586e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer  DCHECK(origin);
59ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl  if (change_count_map_.empty())
606e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer    return false;
616e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer  Map::iterator begin = next_;
625f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  do {
635f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    if (next_ == change_count_map_.end())
646e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer      next_ = change_count_map_.begin();
65ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl    DCHECK_NE(0, next_->second);
66ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl    *origin = next_++->first;
672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    if (!ContainsKey(disabled_origins_, *origin))
682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      return true;
692cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  } while (next_ != begin);
7012b1c7615d4f9a2edc544be499f895f16ac100edChris Lattner  return false;
712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
723397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
73a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redlint64 LocalFileSyncService::OriginChangeMap::GetTotalChangeCount() const {
7489eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis  int64 num_changes = 0;
752cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  for (Map::const_iterator iter = change_count_map_.begin();
762cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor       iter != change_count_map_.end(); ++iter) {
772cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    if (ContainsKey(disabled_origins_, iter->first))
788538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl      continue;
792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    num_changes += iter->second;
8089eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis  }
818538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  return num_changes;
822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid LocalFileSyncService::OriginChangeMap::SetOriginChangeCount(
852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const GURL& origin, int64 changes) {
862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  if (changes != 0) {
872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    change_count_map_[origin] = changes;
882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    return;
892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  }
902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  Map::iterator found = change_count_map_.find(origin);
912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  if (found != change_count_map_.end()) {
922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    if (next_ == found)
933397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl      ++next_;
94b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie    change_count_map_.erase(found);
952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  }
962cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
973397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
982cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid LocalFileSyncService::OriginChangeMap::SetOriginEnabled(
998538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    const GURL& origin, bool enabled) {
1002cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  if (enabled)
1012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    disabled_origins_.erase(origin);
1023397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  else
1032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    disabled_origins_.insert(origin);
1048538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl}
1052cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1062cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// LocalFileSyncService -------------------------------------------------------
1073397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpscoped_ptr<LocalFileSyncService> LocalFileSyncService::Create(
1098538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    Profile* profile) {
1102cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  return make_scoped_ptr(new LocalFileSyncService(profile, NULL));
1112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
1123397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
113df1550fc59b51681d37225934fe4e3acac321621Richard Smithscoped_ptr<LocalFileSyncService> LocalFileSyncService::CreateForTesting(
114df1550fc59b51681d37225934fe4e3acac321621Richard Smith    Profile* profile,
1158538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    leveldb::Env* env) {
1162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  scoped_ptr<LocalFileSyncService> sync_service(
1172cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      new LocalFileSyncService(profile, env));
1183397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  sync_service->sync_context_->set_mock_notify_changes_duration_in_sec(0);
119df1550fc59b51681d37225934fe4e3acac321621Richard Smith  return sync_service.Pass();
1208538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl}
1212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas GregorLocalFileSyncService::~LocalFileSyncService() {
1233397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1268538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlvoid LocalFileSyncService::Shutdown() {
1272cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  sync_context_->RemoveOriginChangeObserver(this);
1282cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  sync_context_->ShutdownOnUIThread();
1293397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  profile_ = NULL;
1302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
1312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1320953e767ff7817f97b3ab20896b229891eeff45bJohn McCallvoid LocalFileSyncService::MaybeInitializeFileSystemContext(
1332cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const GURL& app_origin,
1342cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    storage::FileSystemContext* file_system_context,
1353397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    const SyncStatusCallback& callback) {
1362cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  sync_context_->MaybeInitializeFileSystemContext(
1372cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      app_origin, file_system_context,
1388538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl      base::Bind(&LocalFileSyncService::DidInitializeFileSystemContext,
1392cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                 AsWeakPtr(), app_origin,
1402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                 make_scoped_refptr(file_system_context), callback));
1413397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl}
1422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1438538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlvoid LocalFileSyncService::AddChangeObserver(Observer* observer) {
1442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  change_observers_.AddObserver(observer);
1452cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
1463397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1472cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid LocalFileSyncService::RegisterURLForWaitingSync(
1487e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor    const FileSystemURL& url,
1497e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor    const base::Closure& on_syncable_callback) {
150c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor  sync_context_->RegisterURLForWaitingSync(url, on_syncable_callback);
1518538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl}
1522cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid LocalFileSyncService::ProcessLocalChange(
1543397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    const SyncFileCallback& callback) {
1552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  // Pick an origin to process next.
1562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  GURL origin;
157e86d78cf4754a6aef2cf9a33d847aa15338e276fBob Wilson  if (!origin_change_map_.NextOriginToProcess(&origin)) {
1588538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    callback.Run(SYNC_STATUS_NO_CHANGE_TO_SYNC, FileSystemURL());
1592cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    return;
1602cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  }
1613397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  DCHECK(local_sync_callback_.is_null());
1622cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  DCHECK(!origin.is_empty());
1638538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  DCHECK(ContainsKey(origin_to_contexts_, origin));
1642cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  DVLOG(1) << "Starting ProcessLocalChange";
1663397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  local_sync_callback_ = callback;
168264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola
169264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola  sync_context_->GetFileForLocalSync(
170a49218e17bcbb1acde0245773173e2c0c42f4f19Eli Friedman      origin_to_contexts_[origin],
171425ef72306d4ff6b3698b744353e5f0e56b4b884Rafael Espindola      base::Bind(&LocalFileSyncService::DidGetFileForLocalSync,
172ab8bbf4ebd3e3e6eab913cb044772a62b7581941Douglas Gregor                 AsWeakPtr()));
173264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola}
174f85e193739c953358c865005855253af4f68a497John McCall
1752cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid LocalFileSyncService::SetLocalChangeProcessor(
1762cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    LocalChangeProcessor* local_change_processor) {
1773397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  local_change_processor_ = local_change_processor;
1782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
1798538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
1802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid LocalFileSyncService::SetLocalChangeProcessorCallback(
1812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const GetLocalChangeProcessorCallback& get_local_change_processor) {
1823397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  get_local_change_processor_ = get_local_change_processor;
1832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
1842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid LocalFileSyncService::HasPendingLocalChanges(
1862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const FileSystemURL& url,
1872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const HasPendingLocalChangeCallback& callback) {
1882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  if (!ContainsKey(origin_to_contexts_, url.origin())) {
189c938c1668b4fd12af154e965dd935a89e4801a70Douglas Gregor    base::ThreadTaskRunnerHandle::Get()->PostTask(
19060618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl        FROM_HERE,
19160618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl        base::Bind(callback, SYNC_FILE_ERROR_INVALID_URL, false));
19260618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl    return;
19360618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl  }
19460618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl  sync_context_->HasPendingLocalChanges(
19560618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl      origin_to_contexts_[url.origin()], url, callback);
19660618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl}
19760618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl
1988538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlvoid LocalFileSyncService::PromoteDemotedChanges(
1992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const base::Closure& callback) {
2002cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  if (origin_to_contexts_.empty()) {
2013397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    callback.Run();
202ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    return;
2038538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  }
204ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
205ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  base::Closure completion_callback =
2063397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl      base::Bind(&InvokeCallbackOnNthInvocation,
2072cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                 base::Owned(new int(origin_to_contexts_.size())), callback);
2089763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis  for (OriginToContext::iterator iter = origin_to_contexts_.begin();
2099763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis       iter != origin_to_contexts_.end(); ++iter)
2108538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    sync_context_->PromoteDemotedChanges(iter->first, iter->second,
2112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                                         completion_callback);
2122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
2133397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
214c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregorvoid LocalFileSyncService::GetLocalFileMetadata(
2158538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    const FileSystemURL& url, const SyncFileMetadataCallback& callback) {
2162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  DCHECK(ContainsKey(origin_to_contexts_, url.origin()));
2172cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  sync_context_->GetFileMetadata(origin_to_contexts_[url.origin()],
2183397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl                                 url, callback);
2192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
2208538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
2212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid LocalFileSyncService::PrepareForProcessRemoteChange(
2222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const FileSystemURL& url,
2233397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    const PrepareChangeCallback& callback) {
224395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson  DVLOG(1) << "PrepareForProcessRemoteChange: " << url.DebugString();
2258538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl
226395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson  if (!ContainsKey(origin_to_contexts_, url.origin())) {
227395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson    // This could happen if a remote sync is triggered for the app that hasn't
228ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt    // been initialized in this service.
229ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt    DCHECK(profile_);
230ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt    // The given url.origin() must be for valid installed app.
231ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt    const extensions::Extension* extension =
232ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt        extensions::ExtensionRegistry::Get(profile_)
233ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt            ->enabled_extensions().GetAppByURL(url.origin());
234ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt    if (!extension) {
23534b41d939a1328f484511c6002ba2456db879a29Richard Smith      util::Log(
23634b41d939a1328f484511c6002ba2456db879a29Richard Smith          logging::LOG_WARNING,
23734b41d939a1328f484511c6002ba2456db879a29Richard Smith          FROM_HERE,
23834b41d939a1328f484511c6002ba2456db879a29Richard Smith          "PrepareForProcessRemoteChange called for non-existing origin: %s",
23934b41d939a1328f484511c6002ba2456db879a29Richard Smith          url.origin().spec().c_str());
2403397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
241be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis      // The extension has been uninstalled and this method is called
2422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      // before the remote changes for the origin are removed.
2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      callback.Run(SYNC_STATUS_NO_CHANGE_TO_SYNC,
2442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor                   SyncFileMetadata(), FileChangeList());
2452cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor      return;
2462cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    }
2473397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    GURL site_url =
2482cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        extensions::util::GetSiteForExtensionId(extension->id(), profile_);
2498538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    DCHECK(!site_url.is_empty());
2502cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    scoped_refptr<storage::FileSystemContext> file_system_context =
2512cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        content::BrowserContext::GetStoragePartitionForSite(profile_, site_url)
2523397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl            ->GetFileSystemContext();
2532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    MaybeInitializeFileSystemContext(
2548538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl        url.origin(),
2552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        file_system_context.get(),
2562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor        base::Bind(&LocalFileSyncService::DidInitializeForRemoteSync,
2579d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall                   AsWeakPtr(),
2589d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall                   url,
2599d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall                   file_system_context,
2609d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall                   callback));
2619d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall    return;
2629d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall  }
2639d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall
2641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  DCHECK(ContainsKey(origin_to_contexts_, url.origin()));
2653397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl  sync_context_->PrepareForSync(
26649a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall      origin_to_contexts_[url.origin()], url,
26749a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall      LocalFileSyncContext::SYNC_EXCLUSIVE,
26849a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall      base::Bind(&PrepareForProcessRemoteChangeCallbackAdapter, callback));
2698538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl}
27049a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall
27149a832bd499d6f61c23655f1fac99f0dd229756eJohn McCallvoid LocalFileSyncService::ApplyRemoteChange(
27249a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall    const FileChange& change,
273c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor    const base::FilePath& local_path,
274c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor    const FileSystemURL& url,
275c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor    const SyncStatusCallback& callback) {
276c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  DCHECK(ContainsKey(origin_to_contexts_, url.origin()));
277c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor  util::Log(logging::LOG_VERBOSE, FROM_HERE,
278c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor            "[Remote -> Local] ApplyRemoteChange: %s on %s",
279c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor            change.DebugString().c_str(),
280c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor            url.DebugString().c_str());
2813397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
2822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  sync_context_->ApplyRemoteChange(
283be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis      origin_to_contexts_[url.origin()],
28490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis      change, local_path, url,
28590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis      base::Bind(&LocalFileSyncService::DidApplyRemoteChange, AsWeakPtr(),
28690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis                 callback));
28790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis}
28890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
2893e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smithvoid LocalFileSyncService::FinalizeRemoteSync(
2903e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith    const FileSystemURL& url,
2919763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis    bool clear_local_changes,
2929763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis    const base::Closure& completion_callback) {
2938538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  DCHECK(ContainsKey(origin_to_contexts_, url.origin()));
29490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  sync_context_->FinalizeExclusiveSync(
29590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis      origin_to_contexts_[url.origin()],
29690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis      url, clear_local_changes, completion_callback);
2973397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl}
298ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis
299ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidisvoid LocalFileSyncService::RecordFakeLocalChange(
300ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis    const FileSystemURL& url,
3018538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    const FileChange& change,
30290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    const SyncStatusCallback& callback) {
30390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  DCHECK(ContainsKey(origin_to_contexts_, url.origin()));
30490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  sync_context_->RecordFakeLocalChange(origin_to_contexts_[url.origin()],
3053397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl                                       url, change, callback);
30690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis}
30790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis
308b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikievoid LocalFileSyncService::OnChangesAvailableInOrigins(
30990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    const std::set<GURL>& origins) {
31090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  bool need_notification = false;
31190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  for (std::set<GURL>::const_iterator iter = origins.begin();
3123397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl       iter != origins.end(); ++iter) {
31390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    const GURL& origin = *iter;
31490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis    if (!ContainsKey(origin_to_contexts_, origin)) {
31590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis      // This could happen if this is called for apps/origins that haven't
3164fb86f8c4585e53c21c847ad3de9e3b2de123cd9Chandler Carruth      // been initialized yet, or for apps/origins that are disabled.
3178538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl      // (Local change tracker could call this for uninitialized origins
31890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis      // while it's reading dirty files from the database in the
31990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis      // initialization phase.)
32090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis      pending_origins_with_changes_.insert(origin);
3213397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl      continue;
3228dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis    }
3238dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis    need_notification = true;
3248dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis    SyncFileSystemBackend* backend =
325f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis        SyncFileSystemBackend::GetBackend(origin_to_contexts_[origin]);
326f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis    DCHECK(backend);
327f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis    DCHECK(backend->change_tracker());
3288538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    origin_change_map_.SetOriginChangeCount(
32990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis        origin, backend->change_tracker()->num_changes());
33090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  }
33190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  if (!need_notification)
3323397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    return;
33390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis  int64 num_changes = origin_change_map_.GetTotalChangeCount();
3343acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis  FOR_EACH_OBSERVER(Observer, change_observers_,
3353acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis                    OnLocalChangeAvailable(num_changes));
3363acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis}
3373acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis
3383acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidisvoid LocalFileSyncService::SetOriginEnabled(const GURL& origin, bool enabled) {
3393acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis  if (!ContainsKey(origin_to_contexts_, origin))
3403acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis    return;
3418538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  origin_change_map_.SetOriginEnabled(origin, enabled);
3422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}
3432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
3447536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas GregorLocalFileSyncService::LocalFileSyncService(Profile* profile,
3457536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor                                           leveldb::Env* env_override)
346cded4f649cd4b7ba7d461c25c6482ef52b8d3a2aDouglas Gregor    : profile_(profile),
347cded4f649cd4b7ba7d461c25c6482ef52b8d3a2aDouglas Gregor      sync_context_(new LocalFileSyncContext(
348cded4f649cd4b7ba7d461c25c6482ef52b8d3a2aDouglas Gregor          profile_->GetPath(),
349cded4f649cd4b7ba7d461c25c6482ef52b8d3a2aDouglas Gregor          env_override,
3507536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI).get(),
3517536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)
3527536dd5e6c99584481b7dab68b7e7d8df9c54054Douglas Gregor              .get())),
353075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara      local_change_processor_(NULL) {
354075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
355075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara  sync_context_->AddOriginChangeObserver(this);
356075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara}
357075f8f1b6bed4d1b224c74f87508534cc6392ce6Abramo Bagnara
3583397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redlvoid LocalFileSyncService::DidInitializeFileSystemContext(
359465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara    const GURL& app_origin,
3603acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis    storage::FileSystemContext* file_system_context,
3613acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis    const SyncStatusCallback& callback,
3628538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    SyncStatusCode status) {
3632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  if (status != SYNC_STATUS_OK) {
3642cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    callback.Run(status);
3653397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    return;
3663cb0ebd5f76abcb776f7cb4062bd79e3268c0dc4John McCall  }
36731f17ecbef57b5679c017c375db330546b7b5145John McCall  DCHECK(file_system_context);
3688538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl  origin_to_contexts_[app_origin] = file_system_context;
3693cb0ebd5f76abcb776f7cb4062bd79e3268c0dc4John McCall
3703cb0ebd5f76abcb776f7cb4062bd79e3268c0dc4John McCall  if (pending_origins_with_changes_.find(app_origin) !=
3713397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl      pending_origins_with_changes_.end()) {
372deacbdca554298ccdf636f19c6094a8825ec6b34Douglas Gregor    // We have remaining changes for the origin.
3738538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    pending_origins_with_changes_.erase(app_origin);
374c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall    SyncFileSystemBackend* backend =
375c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall        SyncFileSystemBackend::GetBackend(file_system_context);
3763397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl    DCHECK(backend);
377c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall    DCHECK(backend->change_tracker());
3782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    origin_change_map_.SetOriginChangeCount(
379c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall        app_origin, backend->change_tracker()->num_changes());
380446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff    int64 num_changes = origin_change_map_.GetTotalChangeCount();
381446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff    FOR_EACH_OBSERVER(Observer, change_observers_,
3828538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl                      OnLocalChangeAvailable(num_changes));
3832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  }
3842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor  callback.Run(status);
385d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff}
3863397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
3871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid LocalFileSyncService::DidInitializeForRemoteSync(
3888538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl    const FileSystemURL& url,
3892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    storage::FileSystemContext* file_system_context,
3902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor    const PrepareChangeCallback& callback,
391b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman    SyncStatusCode status) {
392b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman  if (status != SYNC_STATUS_OK) {
393b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman    DVLOG(1) << "FileSystemContext initialization failed for remote sync:"
394b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman             << url.DebugString() << " status=" << status
395b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman             << " (" << SyncStatusCodeToString(status) << ")";
396b001de7458d17c17e6d8b8034c7cfcefd3b70c00Eli Friedman    callback.Run(status, SyncFileMetadata(), FileChangeList());
397a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall    return;
398a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  }
399a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  origin_to_contexts_[url.origin()] = file_system_context;
400a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl  PrepareForProcessRemoteChange(url, callback);
40189eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis}
402a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall
403a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCallvoid LocalFileSyncService::RunLocalSyncCallback(
40489eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis    SyncStatusCode status,
405a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall    const FileSystemURL& url) {
406a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  DVLOG(1) << "Local sync is finished with: " << status
40751bd803fbdade51d674598ed45da3d54190a656cJohn McCall           << " on " << url.DebugString();
408a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  DCHECK(!local_sync_callback_.is_null());
40951bd803fbdade51d674598ed45da3d54190a656cJohn McCall  SyncFileCallback callback = local_sync_callback_;
410a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  local_sync_callback_.Reset();
411a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  callback.Run(status, url);
41251bd803fbdade51d674598ed45da3d54190a656cJohn McCall}
41351bd803fbdade51d674598ed45da3d54190a656cJohn McCall
414a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCallvoid LocalFileSyncService::DidApplyRemoteChange(
415a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall    const SyncStatusCallback& callback,
416a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall    SyncStatusCode status) {
417a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall  util::Log(logging::LOG_VERBOSE, FROM_HERE,
41851bd803fbdade51d674598ed45da3d54190a656cJohn McCall            "[Remote -> Local] ApplyRemoteChange finished --> %s",
41951bd803fbdade51d674598ed45da3d54190a656cJohn McCall            SyncStatusCodeToString(status));
42051bd803fbdade51d674598ed45da3d54190a656cJohn McCall  callback.Run(status);
42151bd803fbdade51d674598ed45da3d54190a656cJohn McCall}
422ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor
423ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregorvoid LocalFileSyncService::DidGetFileForLocalSync(
424ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor    SyncStatusCode status,
425ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor    const LocalFileSyncInfo& sync_file_info,
426ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor    storage::ScopedFile snapshot) {
427ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor  DCHECK(!local_sync_callback_.is_null());
428ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor  if (status != SYNC_STATUS_OK) {
42951bd803fbdade51d674598ed45da3d54190a656cJohn McCall    RunLocalSyncCallback(status, sync_file_info.url);
43051bd803fbdade51d674598ed45da3d54190a656cJohn McCall    return;
43151bd803fbdade51d674598ed45da3d54190a656cJohn McCall  }
43251bd803fbdade51d674598ed45da3d54190a656cJohn McCall  if (sync_file_info.changes.empty()) {
43351bd803fbdade51d674598ed45da3d54190a656cJohn McCall    // There's a slight chance this could happen.
43451bd803fbdade51d674598ed45da3d54190a656cJohn McCall    SyncFileCallback callback = local_sync_callback_;
43551bd803fbdade51d674598ed45da3d54190a656cJohn McCall    local_sync_callback_.Reset();
43651bd803fbdade51d674598ed45da3d54190a656cJohn McCall    ProcessLocalChange(callback);
43751bd803fbdade51d674598ed45da3d54190a656cJohn McCall    return;
43851bd803fbdade51d674598ed45da3d54190a656cJohn McCall  }
43951bd803fbdade51d674598ed45da3d54190a656cJohn McCall
44051bd803fbdade51d674598ed45da3d54190a656cJohn McCall  FileChange next_change = sync_file_info.changes.front();
44151bd803fbdade51d674598ed45da3d54190a656cJohn McCall  DVLOG(1) << "ProcessLocalChange: " << sync_file_info.url.DebugString()
44251bd803fbdade51d674598ed45da3d54190a656cJohn McCall           << " change:" << next_change.DebugString();
44351bd803fbdade51d674598ed45da3d54190a656cJohn McCall
44451bd803fbdade51d674598ed45da3d54190a656cJohn McCall  GetLocalChangeProcessor(sync_file_info.url)->ApplyLocalChange(
44551bd803fbdade51d674598ed45da3d54190a656cJohn McCall      next_change,
44651bd803fbdade51d674598ed45da3d54190a656cJohn McCall      sync_file_info.local_file_path,
447b6ab6c1ca733fda2302a1c5066bdfc6218c89e41Abramo Bagnara      sync_file_info.metadata,
44851bd803fbdade51d674598ed45da3d54190a656cJohn McCall      sync_file_info.url,
44951bd803fbdade51d674598ed45da3d54190a656cJohn McCall      base::Bind(&LocalFileSyncService::ProcessNextChangeForURL,
45051bd803fbdade51d674598ed45da3d54190a656cJohn McCall                 AsWeakPtr(), base::Passed(&snapshot), sync_file_info,
45151bd803fbdade51d674598ed45da3d54190a656cJohn McCall                 next_change, sync_file_info.changes.PopAndGetNewList()));
45251bd803fbdade51d674598ed45da3d54190a656cJohn McCall}
45351bd803fbdade51d674598ed45da3d54190a656cJohn McCall
45451bd803fbdade51d674598ed45da3d54190a656cJohn McCallvoid LocalFileSyncService::ProcessNextChangeForURL(
45551bd803fbdade51d674598ed45da3d54190a656cJohn McCall    storage::ScopedFile snapshot,
45651bd803fbdade51d674598ed45da3d54190a656cJohn McCall    const LocalFileSyncInfo& sync_file_info,
45751bd803fbdade51d674598ed45da3d54190a656cJohn McCall    const FileChange& processed_change,
45851bd803fbdade51d674598ed45da3d54190a656cJohn McCall    const FileChangeList& changes,
45951bd803fbdade51d674598ed45da3d54190a656cJohn McCall    SyncStatusCode status) {
46051bd803fbdade51d674598ed45da3d54190a656cJohn McCall  DVLOG(1) << "Processed one local change: "
46151bd803fbdade51d674598ed45da3d54190a656cJohn McCall           << sync_file_info.url.DebugString()
46251bd803fbdade51d674598ed45da3d54190a656cJohn McCall           << " change:" << processed_change.DebugString()
46351bd803fbdade51d674598ed45da3d54190a656cJohn McCall           << " status:" << status;
46451bd803fbdade51d674598ed45da3d54190a656cJohn McCall
46551bd803fbdade51d674598ed45da3d54190a656cJohn McCall  if (status == SYNC_STATUS_RETRY) {
46651bd803fbdade51d674598ed45da3d54190a656cJohn McCall    GetLocalChangeProcessor(sync_file_info.url)->ApplyLocalChange(
46751bd803fbdade51d674598ed45da3d54190a656cJohn McCall        processed_change,
46851bd803fbdade51d674598ed45da3d54190a656cJohn McCall        sync_file_info.local_file_path,
46951bd803fbdade51d674598ed45da3d54190a656cJohn McCall        sync_file_info.metadata,
47051bd803fbdade51d674598ed45da3d54190a656cJohn McCall        sync_file_info.url,
47151bd803fbdade51d674598ed45da3d54190a656cJohn McCall        base::Bind(&LocalFileSyncService::ProcessNextChangeForURL,
47251bd803fbdade51d674598ed45da3d54190a656cJohn McCall                   AsWeakPtr(), base::Passed(&snapshot),
47351bd803fbdade51d674598ed45da3d54190a656cJohn McCall                   sync_file_info, processed_change, changes));
47451bd803fbdade51d674598ed45da3d54190a656cJohn McCall    return;
47551bd803fbdade51d674598ed45da3d54190a656cJohn McCall  }
47651bd803fbdade51d674598ed45da3d54190a656cJohn McCall
47751bd803fbdade51d674598ed45da3d54190a656cJohn McCall  if (status == SYNC_FILE_ERROR_NOT_FOUND &&
47851bd803fbdade51d674598ed45da3d54190a656cJohn McCall      processed_change.change() == FileChange::FILE_CHANGE_DELETE) {
47951bd803fbdade51d674598ed45da3d54190a656cJohn McCall    // This must be ok (and could happen).
480796aa443ab5ed036f42ef33fed629e1b4b34871bAbramo Bagnara    status = SYNC_STATUS_OK;
481796aa443ab5ed036f42ef33fed629e1b4b34871bAbramo Bagnara  }
482dab60ad68a3a98d687305941a3852e793705f945Douglas Gregor
48351bd803fbdade51d674598ed45da3d54190a656cJohn McCall  const FileSystemURL& url = sync_file_info.url;
48451bd803fbdade51d674598ed45da3d54190a656cJohn McCall  if (status != SYNC_STATUS_OK || changes.empty()) {
48551bd803fbdade51d674598ed45da3d54190a656cJohn McCall    DCHECK(ContainsKey(origin_to_contexts_, url.origin()));
48651bd803fbdade51d674598ed45da3d54190a656cJohn McCall    sync_context_->FinalizeSnapshotSync(
48751bd803fbdade51d674598ed45da3d54190a656cJohn McCall        origin_to_contexts_[url.origin()], url, status,
48851bd803fbdade51d674598ed45da3d54190a656cJohn McCall        base::Bind(&LocalFileSyncService::RunLocalSyncCallback,
48951bd803fbdade51d674598ed45da3d54190a656cJohn McCall                   AsWeakPtr(), status, url));
49051bd803fbdade51d674598ed45da3d54190a656cJohn McCall    return;
49151bd803fbdade51d674598ed45da3d54190a656cJohn McCall  }
492ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
493ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  FileChange next_change = changes.front();
494ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  GetLocalChangeProcessor(url)->ApplyLocalChange(
49551bd803fbdade51d674598ed45da3d54190a656cJohn McCall      changes.front(),
49651bd803fbdade51d674598ed45da3d54190a656cJohn McCall      sync_file_info.local_file_path,
49751bd803fbdade51d674598ed45da3d54190a656cJohn McCall      sync_file_info.metadata,
49851bd803fbdade51d674598ed45da3d54190a656cJohn McCall      url,
499cfb708c354e2f30ccc5cba9d644650f408a1ec3eJohn McCall      base::Bind(&LocalFileSyncService::ProcessNextChangeForURL,
500cfb708c354e2f30ccc5cba9d644650f408a1ec3eJohn McCall                 AsWeakPtr(), base::Passed(&snapshot), sync_file_info,
501cfb708c354e2f30ccc5cba9d644650f408a1ec3eJohn McCall                 next_change, changes.PopAndGetNewList()));
50251bd803fbdade51d674598ed45da3d54190a656cJohn McCall}
50351bd803fbdade51d674598ed45da3d54190a656cJohn McCall
504cfb708c354e2f30ccc5cba9d644650f408a1ec3eJohn McCallLocalChangeProcessor* LocalFileSyncService::GetLocalChangeProcessor(
505cfb708c354e2f30ccc5cba9d644650f408a1ec3eJohn McCall    const FileSystemURL& url) {
506cfb708c354e2f30ccc5cba9d644650f408a1ec3eJohn McCall  if (!get_local_change_processor_.is_null())
507cfb708c354e2f30ccc5cba9d644650f408a1ec3eJohn McCall    return get_local_change_processor_.Run(url.origin());
50851bd803fbdade51d674598ed45da3d54190a656cJohn McCall  DCHECK(local_change_processor_);
50951bd803fbdade51d674598ed45da3d54190a656cJohn McCall  return local_change_processor_;
51051bd803fbdade51d674598ed45da3d54190a656cJohn McCall}
511a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall
512ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt}  // namespace sync_file_system
513ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt