15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/format_macros.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/metrics/histogram.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/single_thread_task_runner.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/thread_task_runner_handle.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.h"
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h"
222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/sync_file_system/logger.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/sync_file_system/sync_direction.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_event_observer.h"
262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_file_metadata.h"
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/sync_process_runner.h"
282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_status_code.h"
292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/keyed_service/content/browser_context_dependency_manager.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/browser/storage_partition.h"
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/extension_registry.h"
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "extensions/common/manifest_constants.h"
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using extensions::Extension;
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using extensions::ExtensionPrefs;
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing extensions::ExtensionRegistry;
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURL;
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURLSet;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sync_file_system {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kLocalSyncName[] = "Local sync";
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kRemoteSyncName[] = "Remote sync";
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SyncServiceState RemoteStateToSyncServiceState(
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoteServiceState state) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (state) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case REMOTE_SERVICE_OK:
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SYNC_SERVICE_RUNNING;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE:
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SYNC_SERVICE_TEMPORARY_UNAVAILABLE;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case REMOTE_SERVICE_AUTHENTICATION_REQUIRED:
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SYNC_SERVICE_AUTHENTICATION_REQUIRED;
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case REMOTE_SERVICE_ACCESS_FORBIDDEN:
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return SYNC_SERVICE_TEMPORARY_UNAVAILABLE;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case REMOTE_SERVICE_DISABLED:
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SYNC_SERVICE_DISABLED;
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case REMOTE_SERVICE_STATE_MAX:
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NOTREACHED();
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NOTREACHED() << "Unknown remote service state: " << state;
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SYNC_SERVICE_DISABLED;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid DidHandleUninstalledEvent(const GURL& origin, SyncStatusCode code) {
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (code != SYNC_STATUS_OK && code != SYNC_STATUS_UNKNOWN_ORIGIN) {
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    util::Log(logging::LOG_WARNING, FROM_HERE,
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              "Failed to uninstall origin for uninstall event: %s",
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              origin.spec().c_str());
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid DidHandleUnloadedEvent(const GURL& origin, SyncStatusCode code) {
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (code != SYNC_STATUS_OK && code != SYNC_STATUS_UNKNOWN_ORIGIN) {
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    util::Log(logging::LOG_WARNING, FROM_HERE,
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              "Failed to disable origin for unload event: %s",
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              origin.spec().c_str());
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid DidHandleLoadEvent(
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& origin,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode code) {
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (code != SYNC_STATUS_OK) {
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    util::Log(logging::LOG_WARNING, FROM_HERE,
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              "Failed to enable origin for load event: %s",
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              origin.spec().c_str());
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstd::string SyncFileStatusToString(SyncFileStatus sync_file_status) {
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return extensions::api::sync_file_system::ToString(
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      extensions::SyncFileStatusToExtensionEnum(sync_file_status));
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Gets called repeatedly until every SyncFileStatus has been mapped.
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DidGetFileSyncStatusForDump(
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::ListValue* files,
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    size_t* num_results,
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const SyncFileSystemService::DumpFilesCallback& callback,
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::DictionaryValue* file,
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SyncStatusCode sync_status_code,
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SyncFileStatus sync_file_status) {
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(files);
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(num_results);
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (file)
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    file->SetString("status", SyncFileStatusToString(sync_file_status));
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Once all results have been received, run the callback to signal end.
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_LE(*num_results, files->GetSize());
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (++*num_results < files->GetSize())
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(*files);
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// We need this indirection because WeakPtr can only be bound to methods
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// without a return value.
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)LocalChangeProcessor* GetLocalChangeProcessorAdapter(
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::WeakPtr<SyncFileSystemService> service,
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GURL& origin) {
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!service)
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return NULL;
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return service->GetLocalChangeProcessor(origin);
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)//---------------------------------------------------------------------------
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// SyncProcessRunner's.
141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// SyncProcessRunner implementation for LocalSync.
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class LocalSyncRunner : public SyncProcessRunner,
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        public LocalFileSyncService::Observer {
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LocalSyncRunner(const std::string& name,
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  SyncFileSystemService* sync_service)
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      : SyncProcessRunner(name, sync_service,
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          scoped_ptr<SyncProcessRunner::TimerHelper>(), 1),
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        factory_(this) {}
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void StartSync(const SyncStatusCallback& callback) OVERRIDE {
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetSyncService()->local_service_->ProcessLocalChange(
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&LocalSyncRunner::DidProcessLocalChange,
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   factory_.GetWeakPtr(), callback));
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // LocalFileSyncService::Observer overrides.
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnLocalChangeAvailable(int64 pending_changes) OVERRIDE {
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    OnChangesUpdated(pending_changes);
163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Kick other sync runners just in case they're not running.
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetSyncService()->RunForEachSyncRunners(&SyncProcessRunner::Schedule);
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void DidProcessLocalChange(
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const SyncStatusCallback& callback,
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      SyncStatusCode status,
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const FileSystemURL& url) {
173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    util::Log(logging::LOG_VERBOSE, FROM_HERE,
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              "ProcessLocalChange finished with status=%d (%s) for url=%s",
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              status, SyncStatusCodeToString(status),
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              url.DebugString().c_str());
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    callback.Run(status);
178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::WeakPtrFactory<LocalSyncRunner> factory_;
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LocalSyncRunner);
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// SyncProcessRunner implementation for RemoteSync.
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class RemoteSyncRunner : public SyncProcessRunner,
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         public RemoteFileSyncService::Observer {
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RemoteSyncRunner(const std::string& name,
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   SyncFileSystemService* sync_service,
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   RemoteFileSyncService* remote_service)
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      : SyncProcessRunner(name, sync_service,
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          scoped_ptr<SyncProcessRunner::TimerHelper>(), 1),
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        remote_service_(remote_service),
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        last_state_(REMOTE_SERVICE_OK),
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        factory_(this) {}
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void StartSync(const SyncStatusCallback& callback) OVERRIDE {
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    remote_service_->ProcessRemoteChange(
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&RemoteSyncRunner::DidProcessRemoteChange,
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   factory_.GetWeakPtr(), callback));
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual SyncServiceState GetServiceState() OVERRIDE {
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return RemoteStateToSyncServiceState(last_state_);
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // RemoteFileSyncService::Observer overrides.
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnRemoteChangeQueueUpdated(int64 pending_changes) OVERRIDE {
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    OnChangesUpdated(pending_changes);
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Kick other sync runners just in case they're not running.
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetSyncService()->RunForEachSyncRunners(&SyncProcessRunner::Schedule);
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnRemoteServiceStateUpdated(
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      RemoteServiceState state,
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const std::string& description) OVERRIDE {
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Just forward to SyncFileSystemService.
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetSyncService()->OnRemoteServiceStateUpdated(state, description);
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    last_state_ = state;
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void DidProcessRemoteChange(
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const SyncStatusCallback& callback,
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      SyncStatusCode status,
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const FileSystemURL& url) {
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    util::Log(logging::LOG_VERBOSE, FROM_HERE,
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              "ProcessRemoteChange finished with status=%d (%s) for url=%s",
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              status, SyncStatusCodeToString(status),
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              url.DebugString().c_str());
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (status == SYNC_STATUS_FILE_BUSY) {
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GetSyncService()->local_service_->RegisterURLForWaitingSync(
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          url, base::Bind(&RemoteSyncRunner::Schedule,
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          factory_.GetWeakPtr()));
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    callback.Run(status);
241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  RemoteFileSyncService* remote_service_;
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RemoteServiceState last_state_;
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::WeakPtrFactory<RemoteSyncRunner> factory_;
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(RemoteSyncRunner);
247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//-----------------------------------------------------------------------------
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// SyncFileSystemService
251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncFileSystemService::Shutdown() {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  local_sync_runners_.clear();
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  remote_sync_runners_.clear();
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->Shutdown();
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_.reset();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_.reset();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileSyncServiceBase* profile_sync_service =
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileSyncServiceFactory::GetForProfile(profile_);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_sync_service)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    profile_sync_service->RemoveObserver(this);
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ExtensionRegistry::Get(profile_)->RemoveObserver(this);
269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_ = NULL;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncFileSystemService::~SyncFileSystemService() {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!profile_);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncFileSystemService::InitializeForApp(
27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::FileSystemContext* file_system_context,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& app_origin,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SyncStatusCallback& callback) {
282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(local_service_);
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(remote_service_);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(app_origin == app_origin.GetOrigin());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  util::Log(logging::LOG_VERBOSE, FROM_HERE,
2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            "Initializing for App: %s", app_origin.spec().c_str());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->MaybeInitializeFileSystemContext(
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      app_origin, file_system_context,
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidInitializeFileSystem,
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr(), app_origin, callback));
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SyncFileSystemService::GetExtensionStatusMap(
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ExtensionStatusMapCallback& callback) {
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  remote_service_->GetOriginStatusMap(
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&SyncFileSystemService::DidGetExtensionStatusMap,
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 AsWeakPtr(), callback));
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SyncFileSystemService::DumpFiles(const GURL& origin,
3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                      const DumpFilesCallback& callback) {
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!origin.is_empty());
3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  content::StoragePartition* storage_partition =
3077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      content::BrowserContext::GetStoragePartitionForSite(profile_, origin);
30803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::FileSystemContext* file_system_context =
3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      storage_partition->GetFileSystemContext();
310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->MaybeInitializeFileSystemContext(
3117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      origin, file_system_context,
3127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      base::Bind(&SyncFileSystemService::DidInitializeFileSystemForDump,
3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                 AsWeakPtr(), origin, callback));
3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SyncFileSystemService::DumpDatabase(const DumpFilesCallback& callback) {
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  remote_service_->DumpDatabase(
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&SyncFileSystemService::DidDumpDatabase,
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 AsWeakPtr(), callback));
320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::GetFileSyncStatus(
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url, const SyncFileStatusCallback& callback) {
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(local_service_);
325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(GetRemoteService(url.origin()));
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // It's possible to get an invalid FileEntry.
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!url.is_valid()) {
329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::ThreadTaskRunnerHandle::Get()->PostTask(
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(callback,
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_FILE_ERROR_INVALID_URL,
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_FILE_STATUS_UNKNOWN));
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->HasPendingLocalChanges(
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url,
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidGetLocalChangeStatus,
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr(), callback));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::AddSyncEventObserver(SyncEventObserver* observer) {
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.AddObserver(observer);
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::RemoveSyncEventObserver(
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncEventObserver* observer) {
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.RemoveObserver(observer);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)LocalChangeProcessor* SyncFileSystemService::GetLocalChangeProcessor(
353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GURL& origin) {
354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return GetRemoteService(origin)->GetLocalChangeProcessor();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
357116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SyncFileSystemService::OnSyncIdle() {
35803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (promoting_demoted_changes_)
35903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
36003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  promoting_demoted_changes_ = true;
36103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
36203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int* job_count = new int(1);
36303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::Closure promote_completion_callback =
36403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&SyncFileSystemService::OnPromotionCompleted,
36503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 AsWeakPtr(), base::Owned(job_count));
36603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int64 remote_changes = 0;
36803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < remote_sync_runners_.size(); ++i)
36903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    remote_changes += remote_sync_runners_[i]->pending_changes();
37003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (remote_changes == 0) {
37103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ++*job_count;
37203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    local_service_->PromoteDemotedChanges(promote_completion_callback);
37303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int64 local_changes = 0;
37603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < local_sync_runners_.size(); ++i)
37703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    local_changes += local_sync_runners_[i]->pending_changes();
3786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (local_changes == 0) {
37903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ++*job_count;
38003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    remote_service_->PromoteDemotedChanges(promote_completion_callback);
38103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
38203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
38303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  promote_completion_callback.Run();
38403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
38503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
38603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SyncFileSystemService::OnPromotionCompleted(int* count) {
38703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (--*count != 0)
38803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
38903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  promoting_demoted_changes_ = false;
39003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckIfIdle();
39103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
39203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
39303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SyncFileSystemService::CheckIfIdle() {
39403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (promoting_demoted_changes_)
39503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
39603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
39703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < remote_sync_runners_.size(); ++i) {
39803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    SyncServiceState service_state = remote_sync_runners_[i]->GetServiceState();
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (service_state != SYNC_SERVICE_RUNNING)
40003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      continue;
40103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
40203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (remote_sync_runners_[i]->pending_changes())
40303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
40403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
40503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
40603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < local_sync_runners_.size(); ++i) {
40703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    SyncServiceState service_state = local_sync_runners_[i]->GetServiceState();
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (service_state != SYNC_SERVICE_RUNNING)
40903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      continue;
41003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
41103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (local_sync_runners_[i]->pending_changes())
41203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
4136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
41403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
41503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (idle_callback_.is_null())
41603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
41703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
41803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::Closure callback = idle_callback_;
41903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  idle_callback_.Reset();
42003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  callback.Run();
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
423116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSyncServiceState SyncFileSystemService::GetSyncServiceState() {
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // For now we always query the state from the main RemoteFileSyncService.
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return RemoteStateToSyncServiceState(remote_service_->GetCurrentState());
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
428116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSyncFileSystemService* SyncFileSystemService::GetSyncService() {
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return this;
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
43203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SyncFileSystemService::CallOnIdleForTesting(
43303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const base::Closure& callback) {
43403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(idle_callback_.is_null());
43503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  idle_callback_ = callback;
43603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckIfIdle();
43703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
43803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncFileSystemService::SyncFileSystemService(Profile* profile)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile),
44103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      sync_enabled_(true),
44203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      promoting_demoted_changes_(false) {
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncFileSystemService::Initialize(
446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<LocalFileSyncService> local_service,
447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<RemoteFileSyncService> remote_service) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(local_service);
450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(remote_service);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile_);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_ = local_service.Pass();
454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_ = remote_service.Pass();
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<LocalSyncRunner> local_syncer(
457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new LocalSyncRunner(kLocalSyncName, this));
458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<RemoteSyncRunner> remote_syncer(
459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new RemoteSyncRunner(kRemoteSyncName, this, remote_service_.get()));
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->AddChangeObserver(local_syncer.get());
462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetLocalChangeProcessorCallback(
463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&GetLocalChangeProcessorAdapter, AsWeakPtr()));
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->AddServiceObserver(remote_syncer.get());
466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->AddFileStatusObserver(this);
467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->SetRemoteChangeProcessor(local_service_.get());
468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  local_sync_runners_.push_back(local_syncer.release());
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  remote_sync_runners_.push_back(remote_syncer.release());
471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileSyncServiceBase* profile_sync_service =
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileSyncServiceFactory::GetForProfile(profile_);
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_sync_service) {
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateSyncEnabledStatus(profile_sync_service);
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    profile_sync_service->AddObserver(this);
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ExtensionRegistry::Get(profile_)->AddObserver(this);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidInitializeFileSystem(
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& app_origin,
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncStatusCallback& callback,
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status) {
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "DidInitializeFileSystem: "
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << app_origin.spec() << " " << status;
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status != SYNC_STATUS_OK) {
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(status);
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Local side of initialization for the app is done.
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Continue on initializing the remote side.
496a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GetRemoteService(app_origin)->RegisterOrigin(
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      app_origin,
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidRegisterOrigin,
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr(), app_origin, callback));
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidRegisterOrigin(
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& app_origin,
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncStatusCallback& callback,
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status) {
50658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  util::Log(logging::LOG_VERBOSE, FROM_HERE,
50758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            "DidInitializeForApp (registered the origin): %s: %s",
50858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            app_origin.spec().c_str(),
50958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            SyncStatusCodeToString(status));
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("SyncFileSystem.RegisterOriginResult",
512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            GetRemoteService(app_origin)->GetCurrentState(),
513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            REMOTE_SERVICE_STATE_MAX);
514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (status == SYNC_STATUS_FAILED) {
516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // If we got generic error return the service status information.
517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    switch (GetRemoteService(app_origin)->GetCurrentState()) {
518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case REMOTE_SERVICE_AUTHENTICATION_REQUIRED:
519a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        callback.Run(SYNC_STATUS_AUTHENTICATION_FAILED);
520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return;
521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE:
522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        callback.Run(SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE);
523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return;
524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      default:
525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
528a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(status);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SyncFileSystemService::DidInitializeFileSystemForDump(
5337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const GURL& origin,
5347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const DumpFilesCallback& callback,
5357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SyncStatusCode status) {
5367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!origin.is_empty());
5377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (status != SYNC_STATUS_OK) {
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(base::ListValue());
5407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
5417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetRemoteService(origin)->DumpFiles(
544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      origin,
545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(
546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          &SyncFileSystemService::DidDumpFiles,
547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          AsWeakPtr(),
548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          origin,
549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          callback));
550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SyncFileSystemService::DidDumpFiles(
553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& origin,
554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const DumpFilesCallback& callback,
555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<base::ListValue> dump_files) {
556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!dump_files || !dump_files->GetSize()) {
557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(base::ListValue());
5587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
5597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::ListValue* files = dump_files.get();
562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::Callback<void(base::DictionaryValue*,
563cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      SyncStatusCode,
564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      SyncFileStatus)> completion_callback =
565cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&DidGetFileSyncStatusForDump,
566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Owned(dump_files.release()),
567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Owned(new size_t(0)),
568cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 callback);
5697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // After all metadata loaded, sync status can be added to each entry.
5717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (size_t i = 0; i < files->GetSize(); ++i) {
5727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::DictionaryValue* file = NULL;
5737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string path_string;
5747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!files->GetDictionary(i, &file) ||
5757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        !file->GetString("path", &path_string)) {
5767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      NOTREACHED();
5777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      completion_callback.Run(
5787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          NULL, SYNC_FILE_ERROR_FAILED, SYNC_FILE_STATUS_UNKNOWN);
5797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      continue;
5807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
5817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::FilePath file_path = base::FilePath::FromUTF8Unsafe(path_string);
5837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    FileSystemURL url = CreateSyncableFileSystemURL(origin, file_path);
5847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    GetFileSyncStatus(url, base::Bind(completion_callback, file));
5857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
5877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
58803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SyncFileSystemService::DidDumpDatabase(const DumpFilesCallback& callback,
58903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                            scoped_ptr<base::ListValue> list) {
590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!list)
591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    list = make_scoped_ptr(new base::ListValue);
59203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  callback.Run(*list);
593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SyncFileSystemService::DidGetExtensionStatusMap(
596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ExtensionStatusMapCallback& callback,
597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<RemoteFileSyncService::OriginStatusMap> status_map) {
5986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!status_map)
5996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    status_map = make_scoped_ptr(new RemoteFileSyncService::OriginStatusMap);
60003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  callback.Run(*status_map);
601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::SetSyncEnabledForTesting(bool enabled) {
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sync_enabled_ = enabled;
605a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->SetSyncEnabled(sync_enabled_);
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidGetLocalChangeStatus(
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncFileStatusCallback& callback,
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status,
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool has_pending_local_changes) {
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      status,
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      has_pending_local_changes ?
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SYNC_FILE_STATUS_HAS_PENDING_CHANGES : SYNC_FILE_STATUS_SYNCED);
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnRemoteServiceStateUpdated(
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoteServiceState state,
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& description) {
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  util::Log(logging::LOG_VERBOSE, FROM_HERE,
6237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            "OnRemoteServiceStateChanged: %d %s", state, description.c_str());
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyncEventObserver, observers_,
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OnSyncStateUpdated(GURL(),
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         RemoteStateToSyncServiceState(state),
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         description));
630a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
631a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RunForEachSyncRunners(&SyncProcessRunner::Schedule);
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
634116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SyncFileSystemService::OnExtensionInstalled(
635116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::BrowserContext* browser_context,
636116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Extension* extension,
637116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool is_update) {
638d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  GURL app_origin = Extension::GetBaseURLFromExtensionId(extension->id());
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DVLOG(1) << "Handle extension notification for INSTALLED: " << app_origin;
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // NOTE: When an app is uninstalled and re-installed in a sequence,
641a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // |local_service_| may still keeps |app_origin| as disabled origin.
642a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetOriginEnabled(app_origin, true);
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
645116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SyncFileSystemService::OnExtensionUnloaded(
646116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::BrowserContext* browser_context,
647116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Extension* extension,
648116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    extensions::UnloadedExtensionInfo::Reason reason) {
649116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (reason != extensions::UnloadedExtensionInfo::REASON_DISABLE)
650a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
651d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
652116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GURL app_origin = Extension::GetBaseURLFromExtensionId(extension->id());
653116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int disable_reasons =
654116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ExtensionPrefs::Get(profile_)->GetDisableReasons(extension->id());
655116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (disable_reasons & Extension::DISABLE_RELOAD) {
656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Bypass disabling the origin since the app will be re-enabled soon.
657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // NOTE: If re-enabling the app fails, the app is disabled while it is
658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // handled as enabled origin in the SyncFS. This should be safe and will be
659d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // recovered when the user re-enables the app manually or the sync service
660d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // restarts.
661d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE_RELOAD): "
662d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)             << app_origin;
663d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
664d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
665d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
666a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE): "
667a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           << app_origin;
668a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GetRemoteService(app_origin)->DisableOrigin(
669a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      app_origin,
670116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&DidHandleUnloadedEvent, app_origin));
671a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetOriginEnabled(app_origin, false);
672a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
674116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SyncFileSystemService::OnExtensionUninstalled(
675116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::BrowserContext* browser_context,
6765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Extension* extension,
6775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    extensions::UninstallReason reason) {
67868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RemoteFileSyncService::UninstallFlag flag =
67968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE;
68068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If it's loaded from an unpacked package and with key: field,
68168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // the uninstall will not be sync'ed and the user might be using the
68268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // same app key in other installs, so avoid purging the remote folder.
68368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (extensions::Manifest::IsUnpackedLocation(extension->location()) &&
68468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      extension->manifest()->HasKey(extensions::manifest_keys::kKey)) {
68568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    flag = RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE;
68668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
68768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
68868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  GURL app_origin = Extension::GetBaseURLFromExtensionId(extension->id());
689a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DVLOG(1) << "Handle extension notification for UNINSTALLED: "
690a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           << app_origin;
691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GetRemoteService(app_origin)->UninstallOrigin(
69268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      app_origin, flag,
693116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&DidHandleUninstalledEvent, app_origin));
694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetOriginEnabled(app_origin, false);
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
697116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SyncFileSystemService::OnExtensionLoaded(
698116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::BrowserContext* browser_context,
699116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Extension* extension) {
700116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GURL app_origin = Extension::GetBaseURLFromExtensionId(extension->id());
701116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DVLOG(1) << "Handle extension notification for LOADED: " << app_origin;
702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GetRemoteService(app_origin)->EnableOrigin(
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      app_origin,
704116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&DidHandleLoadEvent, app_origin));
705a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetOriginEnabled(app_origin, true);
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnStateChanged() {
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileSyncServiceBase* profile_sync_service =
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileSyncServiceFactory::GetForProfile(profile_);
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_sync_service)
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateSyncEnabledStatus(profile_sync_service);
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnFileStatusChanged(
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncFileStatus sync_status,
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncAction action_taken,
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncDirection direction) {
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyncEventObserver, observers_,
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OnFileSynced(url, sync_status, action_taken, direction));
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::UpdateSyncEnabledStatus(
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProfileSyncServiceBase* profile_sync_service) {
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!profile_sync_service->HasSyncSetupCompleted())
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
729d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool old_sync_enabled = sync_enabled_;
730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  sync_enabled_ = profile_sync_service->GetActiveDataTypes().Has(
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::APPS);
732a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->SetSyncEnabled(sync_enabled_);
733a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!old_sync_enabled && sync_enabled_)
734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    RunForEachSyncRunners(&SyncProcessRunner::Schedule);
735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
736a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
737a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SyncFileSystemService::RunForEachSyncRunners(
738a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    void(SyncProcessRunner::*method)()) {
7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (ScopedVector<SyncProcessRunner>::iterator iter =
7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           local_sync_runners_.begin();
7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       iter != local_sync_runners_.end(); ++iter)
7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ((*iter)->*method)();
7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (ScopedVector<SyncProcessRunner>::iterator iter =
7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           remote_sync_runners_.begin();
7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       iter != remote_sync_runners_.end(); ++iter)
746a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ((*iter)->*method)();
747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
748a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)RemoteFileSyncService* SyncFileSystemService::GetRemoteService(
750a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GURL& origin) {
75103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return remote_service_.get();
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sync_file_system
755