sync_file_system_service.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.h"
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h"
212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/sync_file_system/logger.h"
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/sync_file_system/sync_direction.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_event_observer.h"
252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_file_metadata.h"
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/sync_process_runner.h"
272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_status_code.h"
282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/keyed_service/content/browser_context_dependency_manager.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_details.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_service.h"
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/browser/storage_partition.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "extensions/common/manifest_constants.h"
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_context.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using extensions::Extension;
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using extensions::ExtensionPrefs;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using fileapi::FileSystemURL;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using fileapi::FileSystemURLSet;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sync_file_system {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kLocalSyncName[] = "Local sync";
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kRemoteSyncName[] = "Remote sync";
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kRemoteSyncNameV2[] = "Remote sync (v2)";
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;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case REMOTE_SERVICE_DISABLED:
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SYNC_SERVICE_DISABLED;
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case REMOTE_SERVICE_STATE_MAX:
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NOTREACHED();
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NOTREACHED() << "Unknown remote service state: " << state;
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SYNC_SERVICE_DISABLED;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DidHandleOriginForExtensionUnloadedEvent(
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& origin,
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode code) {
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(chrome::NOTIFICATION_EXTENSION_UNLOADED == type ||
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)         chrome::NOTIFICATION_EXTENSION_UNINSTALLED == type);
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (code != SYNC_STATUS_OK &&
79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      code != SYNC_STATUS_UNKNOWN_ORIGIN) {
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    switch (type) {
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      case chrome::NOTIFICATION_EXTENSION_UNLOADED:
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        util::Log(logging::LOG_WARNING,
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  FROM_HERE,
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  "Disabling origin for UNLOADED(DISABLE) failed: %s",
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  origin.spec().c_str());
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        util::Log(logging::LOG_WARNING,
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  FROM_HERE,
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  "Uninstall origin for UNINSTALLED failed: %s",
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  origin.spec().c_str());
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default:
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DidHandleOriginForExtensionEnabledEvent(
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& origin,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode code) {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(chrome::NOTIFICATION_EXTENSION_ENABLED == type);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (code != SYNC_STATUS_OK)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    util::Log(logging::LOG_WARNING,
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              FROM_HERE,
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              "Enabling origin for ENABLED failed: %s",
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              origin.spec().c_str());
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstd::string SyncFileStatusToString(SyncFileStatus sync_file_status) {
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return extensions::api::sync_file_system::ToString(
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      extensions::SyncFileStatusToExtensionEnum(sync_file_status));
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Gets called repeatedly until every SyncFileStatus has been mapped.
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DidGetFileSyncStatusForDump(
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::ListValue* files,
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    size_t* num_results,
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const SyncFileSystemService::DumpFilesCallback& callback,
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::DictionaryValue* file,
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SyncStatusCode sync_status_code,
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SyncFileStatus sync_file_status) {
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(files);
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(num_results);
1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (file)
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    file->SetString("status", SyncFileStatusToString(sync_file_status));
1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Once all results have been received, run the callback to signal end.
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_LE(*num_results, files->GetSize());
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (++*num_results < files->GetSize())
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  callback.Run(files);
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// We need this indirection because WeakPtr can only be bound to methods
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// without a return value.
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)LocalChangeProcessor* GetLocalChangeProcessorAdapter(
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::WeakPtr<SyncFileSystemService> service,
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GURL& origin) {
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!service)
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return NULL;
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return service->GetLocalChangeProcessor(origin);
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace
149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)//---------------------------------------------------------------------------
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// SyncProcessRunner's.
152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// SyncProcessRunner implementation for LocalSync.
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class LocalSyncRunner : public SyncProcessRunner,
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        public LocalFileSyncService::Observer {
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LocalSyncRunner(const std::string& name,
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  SyncFileSystemService* sync_service)
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : SyncProcessRunner(name, sync_service),
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        factory_(this) {}
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void StartSync(const SyncStatusCallback& callback) OVERRIDE {
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sync_service()->local_service_->ProcessLocalChange(
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&LocalSyncRunner::DidProcessLocalChange,
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   factory_.GetWeakPtr(), callback));
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // LocalFileSyncService::Observer overrides.
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnLocalChangeAvailable(int64 pending_changes) OVERRIDE {
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    OnChangesUpdated(pending_changes);
173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Kick other sync runners just in case they're not running.
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sync_service()->RunForEachSyncRunners(
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        &SyncProcessRunner::ScheduleIfNotRunning);
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void DidProcessLocalChange(
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const SyncStatusCallback& callback,
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      SyncStatusCode status,
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const FileSystemURL& url) {
184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    util::Log(logging::LOG_VERBOSE, FROM_HERE,
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              "ProcessLocalChange finished with status=%d (%s) for url=%s",
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              status, SyncStatusCodeToString(status),
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              url.DebugString().c_str());
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    callback.Run(status);
189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::WeakPtrFactory<LocalSyncRunner> factory_;
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LocalSyncRunner);
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// SyncProcessRunner implementation for RemoteSync.
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class RemoteSyncRunner : public SyncProcessRunner,
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         public RemoteFileSyncService::Observer {
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RemoteSyncRunner(const std::string& name,
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   SyncFileSystemService* sync_service,
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   RemoteFileSyncService* remote_service)
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : SyncProcessRunner(name, sync_service),
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        remote_service_(remote_service),
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        last_state_(REMOTE_SERVICE_OK),
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        factory_(this) {}
206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void StartSync(const SyncStatusCallback& callback) OVERRIDE {
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    remote_service_->ProcessRemoteChange(
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&RemoteSyncRunner::DidProcessRemoteChange,
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   factory_.GetWeakPtr(), callback));
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual SyncServiceState GetServiceState() OVERRIDE {
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return RemoteStateToSyncServiceState(last_state_);
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // RemoteFileSyncService::Observer overrides.
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnRemoteChangeQueueUpdated(int64 pending_changes) OVERRIDE {
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    OnChangesUpdated(pending_changes);
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Kick other sync runners just in case they're not running.
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sync_service()->RunForEachSyncRunners(
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        &SyncProcessRunner::ScheduleIfNotRunning);
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnRemoteServiceStateUpdated(
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      RemoteServiceState state,
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const std::string& description) OVERRIDE {
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Just forward to SyncFileSystemService.
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sync_service()->OnRemoteServiceStateUpdated(state, description);
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    last_state_ = state;
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void DidProcessRemoteChange(
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const SyncStatusCallback& callback,
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      SyncStatusCode status,
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const FileSystemURL& url) {
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    util::Log(logging::LOG_VERBOSE, FROM_HERE,
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              "ProcessRemoteChange finished with status=%d (%s) for url=%s",
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              status, SyncStatusCodeToString(status),
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              url.DebugString().c_str());
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (status == SYNC_STATUS_FILE_BUSY) {
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      sync_service()->local_service_->RegisterURLForWaitingSync(
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          url, base::Bind(&RemoteSyncRunner::Schedule,
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          factory_.GetWeakPtr()));
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    callback.Run(status);
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  RemoteFileSyncService* remote_service_;
255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RemoteServiceState last_state_;
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::WeakPtrFactory<RemoteSyncRunner> factory_;
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(RemoteSyncRunner);
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//-----------------------------------------------------------------------------
261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// SyncFileSystemService
262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncFileSystemService::Shutdown() {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->Shutdown();
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_.reset();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_.reset();
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  v2_remote_service_.reset();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileSyncServiceBase* profile_sync_service =
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileSyncServiceFactory::GetForProfile(profile_);
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_sync_service)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    profile_sync_service->RemoveObserver(this);
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_ = NULL;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncFileSystemService::~SyncFileSystemService() {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!profile_);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncFileSystemService::InitializeForApp(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fileapi::FileSystemContext* file_system_context,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& app_origin,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SyncStatusCallback& callback) {
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(local_service_);
290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(remote_service_);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(app_origin == app_origin.GetOrigin());
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  util::Log(logging::LOG_VERBOSE, FROM_HERE,
2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            "Initializing for App: %s", app_origin.spec().c_str());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->MaybeInitializeFileSystemContext(
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      app_origin, file_system_context,
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidInitializeFileSystem,
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr(), app_origin, callback));
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SyncServiceState SyncFileSystemService::GetSyncServiceState() {
303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // For now we always query the state from the main RemoteFileSyncService.
304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return RemoteStateToSyncServiceState(remote_service_->GetCurrentState());
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SyncFileSystemService::GetExtensionStatusMap(
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::map<GURL, std::string>* status_map) {
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(status_map);
310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  status_map->clear();
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->GetOriginStatusMap(status_map);
312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (v2_remote_service_)
313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v2_remote_service_->GetOriginStatusMap(status_map);
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SyncFileSystemService::DumpFiles(const GURL& origin,
3177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                      const DumpFilesCallback& callback) {
318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!origin.is_empty());
3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  content::StoragePartition* storage_partition =
3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      content::BrowserContext::GetStoragePartitionForSite(profile_, origin);
3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  fileapi::FileSystemContext* file_system_context =
3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      storage_partition->GetFileSystemContext();
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->MaybeInitializeFileSystemContext(
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      origin, file_system_context,
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      base::Bind(&SyncFileSystemService::DidInitializeFileSystemForDump,
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                 AsWeakPtr(), origin, callback));
3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)scoped_ptr<base::ListValue> SyncFileSystemService::DumpDatabase() {
331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<base::ListValue> list = remote_service_->DumpDatabase();
332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!list)
333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    list.reset(new base::ListValue);
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (v2_remote_service_) {
335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<base::ListValue> v2list = v2_remote_service_->DumpDatabase();
336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!v2list)
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return list.Pass();
338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for (base::ListValue::iterator itr = v2list->begin();
339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         itr != v2list->end(); ) {
340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      scoped_ptr<base::Value> item;
341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      itr = v2list->Erase(itr, &item);
342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      list->Append(item.release());
343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return list.Pass();
346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::GetFileSyncStatus(
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url, const SyncFileStatusCallback& callback) {
350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(local_service_);
351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(GetRemoteService(url.origin()));
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // It's possible to get an invalid FileEntry.
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!url.is_valid()) {
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::MessageLoopProxy::current()->PostTask(
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(callback,
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_FILE_ERROR_INVALID_URL,
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_FILE_STATUS_UNKNOWN));
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (GetRemoteService(url.origin())->IsConflicting(url)) {
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::MessageLoopProxy::current()->PostTask(
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(callback,
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_STATUS_OK,
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_FILE_STATUS_CONFLICTING));
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->HasPendingLocalChanges(
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url,
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidGetLocalChangeStatus,
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr(), callback));
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::AddSyncEventObserver(SyncEventObserver* observer) {
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.AddObserver(observer);
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::RemoveSyncEventObserver(
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncEventObserver* observer) {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.RemoveObserver(observer);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ConflictResolutionPolicy SyncFileSystemService::GetConflictResolutionPolicy(
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const GURL& origin) {
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetRemoteService(origin)->GetConflictResolutionPolicy(origin);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyncStatusCode SyncFileSystemService::SetConflictResolutionPolicy(
393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const GURL& origin,
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ConflictResolutionPolicy policy) {
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("SyncFileSystem.ConflictResolutionPolicy",
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            policy, CONFLICT_RESOLUTION_POLICY_MAX);
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetRemoteService(origin)->SetConflictResolutionPolicy(origin, policy);
398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)LocalChangeProcessor* SyncFileSystemService::GetLocalChangeProcessor(
401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GURL& origin) {
402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return GetRemoteService(origin)->GetLocalChangeProcessor();
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncFileSystemService::SyncFileSystemService(Profile* profile)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile),
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sync_enabled_(true) {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncFileSystemService::Initialize(
411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<LocalFileSyncService> local_service,
412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<RemoteFileSyncService> remote_service) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(local_service);
415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(remote_service);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile_);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_ = local_service.Pass();
419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_ = remote_service.Pass();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<LocalSyncRunner> local_syncer(
422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new LocalSyncRunner(kLocalSyncName, this));
423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<RemoteSyncRunner> remote_syncer(
424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new RemoteSyncRunner(kRemoteSyncName, this, remote_service_.get()));
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->AddChangeObserver(local_syncer.get());
427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetLocalChangeProcessorCallback(
428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&GetLocalChangeProcessorAdapter, AsWeakPtr()));
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->AddServiceObserver(remote_syncer.get());
431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->AddFileStatusObserver(this);
432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->SetRemoteChangeProcessor(local_service_.get());
433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  local_sync_runners_.push_back(local_syncer.release());
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  remote_sync_runners_.push_back(remote_syncer.release());
436d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileSyncServiceBase* profile_sync_service =
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileSyncServiceFactory::GetForProfile(profile_);
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_sync_service) {
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateSyncEnabledStatus(profile_sync_service);
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    profile_sync_service->AddObserver(this);
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 content::Source<Profile>(profile_));
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 content::Source<Profile>(profile_));
448a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 content::Source<Profile>(profile_));
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED,
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 content::Source<Profile>(profile_));
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidInitializeFileSystem(
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& app_origin,
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncStatusCallback& callback,
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status) {
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "DidInitializeFileSystem: "
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << app_origin.spec() << " " << status;
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status != SYNC_STATUS_OK) {
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(status);
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Local side of initialization for the app is done.
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Continue on initializing the remote side.
468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GetRemoteService(app_origin)->RegisterOrigin(
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      app_origin,
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyncFileSystemService::DidRegisterOrigin,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr(), app_origin, callback));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidRegisterOrigin(
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& app_origin,
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncStatusCallback& callback,
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status) {
47858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  util::Log(logging::LOG_VERBOSE, FROM_HERE,
47958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            "DidInitializeForApp (registered the origin): %s: %s",
48058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            app_origin.spec().c_str(),
48158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            SyncStatusCodeToString(status));
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("SyncFileSystem.RegisterOriginResult",
484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            GetRemoteService(app_origin)->GetCurrentState(),
485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            REMOTE_SERVICE_STATE_MAX);
486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (status == SYNC_STATUS_FAILED) {
488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // If we got generic error return the service status information.
489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    switch (GetRemoteService(app_origin)->GetCurrentState()) {
490a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case REMOTE_SERVICE_AUTHENTICATION_REQUIRED:
491a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        callback.Run(SYNC_STATUS_AUTHENTICATION_FAILED);
492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return;
493a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case REMOTE_SERVICE_TEMPORARY_UNAVAILABLE:
494a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        callback.Run(SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE);
495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return;
496a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      default:
497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
498a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(status);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SyncFileSystemService::DidInitializeFileSystemForDump(
5057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const GURL& origin,
5067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const DumpFilesCallback& callback,
5077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SyncStatusCode status) {
5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!origin.is_empty());
5097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (status != SYNC_STATUS_OK) {
5117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::ListValue empty_result;
5127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    callback.Run(&empty_result);
5137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
5147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::ListValue* files =
517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      GetRemoteService(origin)->DumpFiles(origin).release();
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!files) {
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(new base::ListValue);
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!files->GetSize()) {
5247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    callback.Run(files);
5257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::Callback<void(base::DictionaryValue* file,
5297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                      SyncStatusCode sync_status,
5307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                      SyncFileStatus sync_file_status)> completion_callback =
5317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      base::Bind(&DidGetFileSyncStatusForDump, base::Owned(files),
5327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                 base::Owned(new size_t(0)), callback);
5337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // After all metadata loaded, sync status can be added to each entry.
5357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (size_t i = 0; i < files->GetSize(); ++i) {
5367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::DictionaryValue* file = NULL;
5377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string path_string;
5387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!files->GetDictionary(i, &file) ||
5397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        !file->GetString("path", &path_string)) {
5407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      NOTREACHED();
5417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      completion_callback.Run(
5427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          NULL, SYNC_FILE_ERROR_FAILED, SYNC_FILE_STATUS_UNKNOWN);
5437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      continue;
5447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
5457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::FilePath file_path = base::FilePath::FromUTF8Unsafe(path_string);
5477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    FileSystemURL url = CreateSyncableFileSystemURL(origin, file_path);
5487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    GetFileSyncStatus(url, base::Bind(completion_callback, file));
5497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
5517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::SetSyncEnabledForTesting(bool enabled) {
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sync_enabled_ = enabled;
554a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->SetSyncEnabled(sync_enabled_);
555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (v2_remote_service_)
556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v2_remote_service_->SetSyncEnabled(sync_enabled_);
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::DidGetLocalChangeStatus(
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncFileStatusCallback& callback,
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status,
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool has_pending_local_changes) {
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      status,
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      has_pending_local_changes ?
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SYNC_FILE_STATUS_HAS_PENDING_CHANGES : SYNC_FILE_STATUS_SYNCED);
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SyncFileSystemService::OnSyncIdle() {
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 remote_changes = 0;
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (ScopedVector<SyncProcessRunner>::iterator iter =
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           remote_sync_runners_.begin();
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       iter != remote_sync_runners_.end(); ++iter)
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    remote_changes += (*iter)->pending_changes();
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (remote_changes == 0)
5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    local_service_->PromoteDemotedChanges();
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64 local_changes = 0;
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (ScopedVector<SyncProcessRunner>::iterator iter =
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           local_sync_runners_.begin();
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       iter != local_sync_runners_.end(); ++iter)
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    local_changes += (*iter)->pending_changes();
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (local_changes == 0 && v2_remote_service_)
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    v2_remote_service_->PromoteDemotedChanges();
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnRemoteServiceStateUpdated(
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoteServiceState state,
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& description) {
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  util::Log(logging::LOG_VERBOSE, FROM_HERE,
5927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            "OnRemoteServiceStateChanged: %d %s", state, description.c_str());
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyncEventObserver, observers_,
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OnSyncStateUpdated(GURL(),
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         RemoteStateToSyncServiceState(state),
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         description));
599a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
600a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RunForEachSyncRunners(&SyncProcessRunner::Schedule);
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::Observe(
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::NotificationSource& source,
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::NotificationDetails& details) {
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Event notification sequence.
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // (User action)    (Notification type)
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Install:         INSTALLED.
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Update:          INSTALLED.
612a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Uninstall:       UNINSTALLED.
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Launch, Close:   No notification.
614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Enable:          ENABLED.
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Disable:         UNLOADED(DISABLE).
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Reload, Restart: UNLOADED(DISABLE) -> INSTALLED -> ENABLED.
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_INSTALLED:
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      HandleExtensionInstalled(details);
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_UNLOADED:
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      HandleExtensionUnloaded(type, details);
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
625a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
626a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      HandleExtensionUninstalled(type, details);
627a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_ENABLED:
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      HandleExtensionEnabled(type, details);
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "Unknown notification.";
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SyncFileSystemService::HandleExtensionInstalled(
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const content::NotificationDetails& details) {
639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const Extension* extension =
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::Details<const extensions::InstalledExtensionInfo>(details)->
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          extension;
642d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  GURL app_origin = Extension::GetBaseURLFromExtensionId(extension->id());
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DVLOG(1) << "Handle extension notification for INSTALLED: " << app_origin;
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // NOTE: When an app is uninstalled and re-installed in a sequence,
645a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // |local_service_| may still keeps |app_origin| as disabled origin.
646a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetOriginEnabled(app_origin, true);
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::HandleExtensionUnloaded(
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::NotificationDetails& details) {
652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content::Details<const extensions::UnloadedExtensionInfo> info(details);
6531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (info->reason != extensions::UnloadedExtensionInfo::REASON_DISABLE)
654a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
655d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::string extension_id = info->extension->id();
657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  GURL app_origin = Extension::GetBaseURLFromExtensionId(extension_id);
658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
659d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int reasons = ExtensionPrefs::Get(profile_)->GetDisableReasons(extension_id);
660d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (reasons & Extension::DISABLE_RELOAD) {
661d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Bypass disabling the origin since the app will be re-enabled soon.
662d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // NOTE: If re-enabling the app fails, the app is disabled while it is
663d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // handled as enabled origin in the SyncFS. This should be safe and will be
664d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // recovered when the user re-enables the app manually or the sync service
665d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // restarts.
666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE_RELOAD): "
667d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)             << app_origin;
668d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
669d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
670d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
671a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DVLOG(1) << "Handle extension notification for UNLOAD(DISABLE): "
672a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           << app_origin;
673a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GetRemoteService(app_origin)->DisableOrigin(
674a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      app_origin,
675a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&DidHandleOriginForExtensionUnloadedEvent,
676a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 type, app_origin));
677a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetOriginEnabled(app_origin, false);
678a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
680a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void SyncFileSystemService::HandleExtensionUninstalled(
681a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    int type,
682a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const content::NotificationDetails& details) {
68368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const Extension* extension = content::Details<const Extension>(details).ptr();
68468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(extension);
68568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
68668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RemoteFileSyncService::UninstallFlag flag =
68768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE;
68868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If it's loaded from an unpacked package and with key: field,
68968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // the uninstall will not be sync'ed and the user might be using the
69068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // same app key in other installs, so avoid purging the remote folder.
69168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (extensions::Manifest::IsUnpackedLocation(extension->location()) &&
69268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      extension->manifest()->HasKey(extensions::manifest_keys::kKey)) {
69368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    flag = RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE;
69468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
69568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
69668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  GURL app_origin = Extension::GetBaseURLFromExtensionId(extension->id());
697a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DVLOG(1) << "Handle extension notification for UNINSTALLED: "
698a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           << app_origin;
699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GetRemoteService(app_origin)->UninstallOrigin(
70068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      app_origin, flag,
701a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&DidHandleOriginForExtensionUnloadedEvent,
702a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 type, app_origin));
703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetOriginEnabled(app_origin, false);
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::HandleExtensionEnabled(
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int type,
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::NotificationDetails& details) {
709d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::string extension_id = content::Details<const Extension>(details)->id();
710d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  GURL app_origin = Extension::GetBaseURLFromExtensionId(extension_id);
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Handle extension notification for ENABLED: " << app_origin;
712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GetRemoteService(app_origin)->EnableOrigin(
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      app_origin,
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&DidHandleOriginForExtensionEnabledEvent, type, app_origin));
715a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  local_service_->SetOriginEnabled(app_origin, true);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnStateChanged() {
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileSyncServiceBase* profile_sync_service =
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileSyncServiceFactory::GetForProfile(profile_);
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_sync_service)
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateSyncEnabledStatus(profile_sync_service);
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::OnFileStatusChanged(
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncFileStatus sync_status,
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncAction action_taken,
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncDirection direction) {
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyncEventObserver, observers_,
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OnFileSynced(url, sync_status, action_taken, direction));
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncFileSystemService::UpdateSyncEnabledStatus(
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProfileSyncServiceBase* profile_sync_service) {
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!profile_sync_service->HasSyncSetupCompleted())
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
739d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool old_sync_enabled = sync_enabled_;
740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  sync_enabled_ = profile_sync_service->GetActiveDataTypes().Has(
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::APPS);
742a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  remote_service_->SetSyncEnabled(sync_enabled_);
743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (v2_remote_service_)
744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v2_remote_service_->SetSyncEnabled(sync_enabled_);
745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!old_sync_enabled && sync_enabled_)
746a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    RunForEachSyncRunners(&SyncProcessRunner::Schedule);
747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
748a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SyncFileSystemService::RunForEachSyncRunners(
750a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    void(SyncProcessRunner::*method)()) {
7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (ScopedVector<SyncProcessRunner>::iterator iter =
7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           local_sync_runners_.begin();
7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       iter != local_sync_runners_.end(); ++iter)
7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ((*iter)->*method)();
7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (ScopedVector<SyncProcessRunner>::iterator iter =
7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           remote_sync_runners_.begin();
7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       iter != remote_sync_runners_.end(); ++iter)
758a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ((*iter)->*method)();
759a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
760a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
761a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)RemoteFileSyncService* SyncFileSystemService::GetRemoteService(
762a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GURL& origin) {
763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IsV2Enabled())
764a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return remote_service_.get();
765a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!IsV2EnabledForOrigin(origin))
766a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return remote_service_.get();
767a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
768a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!v2_remote_service_) {
769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v2_remote_service_ = RemoteFileSyncService::CreateForBrowserContext(
770a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        RemoteFileSyncService::V2, profile_);
771a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<RemoteSyncRunner> v2_remote_syncer(
772a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        new RemoteSyncRunner(kRemoteSyncNameV2, this,
773a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             v2_remote_service_.get()));
774a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v2_remote_service_->AddServiceObserver(v2_remote_syncer.get());
775a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v2_remote_service_->AddFileStatusObserver(this);
776a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v2_remote_service_->SetRemoteChangeProcessor(local_service_.get());
777a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    v2_remote_service_->SetSyncEnabled(sync_enabled_);
778a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    v2_remote_service_->SetDefaultConflictResolutionPolicy(
779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        remote_service_->GetDefaultConflictResolutionPolicy());
7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    remote_sync_runners_.push_back(v2_remote_syncer.release());
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
782a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return v2_remote_service_.get();
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sync_file_system
786