extension_sync_service.cc revision f2477e01787aa58f445919b809d89e252beef54f
11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file.
41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_sync_service.h"
61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <iterator>
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/basictypes.h"
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/app_sync_data.h"
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_error_ui.h"
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_prefs.h"
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_sync_data.h"
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_sync_service_factory.h"
181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_util.h"
191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/sync/glue/sync_start_util.h"
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/sync/sync_prefs.h"
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/common/extensions/sync_helper.h"
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/app_sorting.h"
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/feature_switch.h"
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/common/manifest_constants.h"
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/api/sync_change.h"
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/api/sync_error_factory.h"
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extensions::Extension;
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extensions::ExtensionPrefs;
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extensions::FeatureSwitch;
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ExtensionSyncService::ExtensionSyncService(Profile* profile,
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                           ExtensionPrefs* extension_prefs,
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                           ExtensionService* extension_service)
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : profile_(profile),
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_prefs_(extension_prefs),
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_(extension_service),
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_(this),
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_(this),
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      pending_app_enables_(
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          make_scoped_ptr(new browser_sync::SyncPrefs(
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              extension_prefs_->pref_service())),
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          &app_sync_bundle_,
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          syncer::APPS),
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      pending_extension_enables_(
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          make_scoped_ptr(new browser_sync::SyncPrefs(
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              extension_prefs_->pref_service())),
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          &extension_sync_bundle_,
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          syncer::EXTENSIONS) {
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SetSyncStartFlare(sync_start_util::GetFlareForSyncableService(
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      profile_->GetPath()));
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_service_->set_extension_sync_service(this);
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extension_prefs_->app_sorting()->SetExtensionSyncService(this);
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ExtensionSyncService::~ExtensionSyncService() {}
611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ExtensionSyncService* ExtensionSyncService::Get(Profile* profile) {
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return ExtensionSyncServiceFactory::GetForProfile(profile);
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)syncer::SyncChange ExtensionSyncService::PrepareToSyncUninstallExtension(
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::Extension* extension, bool extensions_ready) {
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Extract the data we need for sync now, but don't actually sync until we've
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // completed the uninstallation.
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // TODO(tim): If we get here and IsSyncing is false, this will cause
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // "back from the dead" style bugs, because sync will add-back the extension
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // that was uninstalled here when MergeDataAndStartSyncing is called.
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // See crbug.com/256795.
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extensions::sync_helper::IsSyncableApp(extension)) {
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (app_sync_bundle_.IsSyncing())
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return app_sync_bundle_.CreateSyncChangeToDelete(extension);
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else if (extensions_ready && !flare_.is_null())
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      flare_.Run(syncer::APPS);  // Tell sync to start ASAP.
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (extensions::sync_helper::IsSyncableExtension(extension)) {
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (extension_sync_bundle_.IsSyncing())
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return extension_sync_bundle_.CreateSyncChangeToDelete(extension);
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else if (extensions_ready && !flare_.is_null())
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      flare_.Run(syncer::EXTENSIONS);  // Tell sync to start ASAP.
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return syncer::SyncChange();
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::ProcessSyncUninstallExtension(
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::string& extension_id,
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const syncer::SyncChange& sync_change) {
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (app_sync_bundle_.HasExtensionId(extension_id) &&
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      sync_change.sync_data().GetDataType() == syncer::APPS) {
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    app_sync_bundle_.ProcessDeletion(extension_id, sync_change);
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (extension_sync_bundle_.HasExtensionId(extension_id) &&
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)             sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) {
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_sync_bundle_.ProcessDeletion(extension_id, sync_change);
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SyncEnableExtension(
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::Extension& extension) {
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Syncing may not have started yet, so handle pending enables.
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extensions::sync_helper::IsSyncableApp(&extension))
1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pending_app_enables_.OnExtensionEnabled(extension.id());
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extensions::sync_helper::IsSyncableExtension(&extension))
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pending_extension_enables_.OnExtensionEnabled(extension.id());
1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SyncExtensionChangeIfNeeded(extension);
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SyncDisableExtension(
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::Extension& extension) {
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Syncing may not have started yet, so handle pending enables.
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extensions::sync_helper::IsSyncableApp(&extension))
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pending_app_enables_.OnExtensionDisabled(extension.id());
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extensions::sync_helper::IsSyncableExtension(&extension))
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pending_extension_enables_.OnExtensionDisabled(extension.id());
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SyncExtensionChangeIfNeeded(extension);
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)syncer::SyncMergeResult ExtensionSyncService::MergeDataAndStartSyncing(
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    syncer::ModelType type,
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const syncer::SyncDataList& initial_sync_data,
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CHECK(sync_processor.get());
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CHECK(sync_error_factory.get());
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (type) {
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case syncer::EXTENSIONS:
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_.SetupSync(sync_processor.release(),
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                       sync_error_factory.release(),
1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                       initial_sync_data);
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      pending_extension_enables_.OnSyncStarted(extension_service_);
1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case syncer::APPS:
1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_.SetupSync(sync_processor.release(),
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 sync_error_factory.release(),
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 initial_sync_data);
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      pending_app_enables_.OnSyncStarted(extension_service_);
1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    default:
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LOG(FATAL) << "Got " << type << " ModelType";
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Process local extensions.
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // TODO(yoz): Determine whether pending extensions should be considered too.
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  //            See crbug.com/104399.
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  syncer::SyncDataList sync_data_list = GetAllSyncData(type);
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  syncer::SyncChangeList sync_change_list;
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (syncer::SyncDataList::const_iterator i = sync_data_list.begin();
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       i != sync_data_list.end();
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       ++i) {
1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    switch (type) {
1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        case syncer::EXTENSIONS:
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          sync_change_list.push_back(
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              extension_sync_bundle_.CreateSyncChange(*i));
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          break;
1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        case syncer::APPS:
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          sync_change_list.push_back(app_sync_bundle_.CreateSyncChange(*i));
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          break;
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      default:
1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        LOG(FATAL) << "Got " << type << " ModelType";
1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::EXTENSIONS) {
1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_sync_bundle_.ProcessSyncChangeList(sync_change_list);
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (type == syncer::APPS) {
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    app_sync_bundle_.ProcessSyncChangeList(sync_change_list);
1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return syncer::SyncMergeResult(type);
1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::StopSyncing(syncer::ModelType type) {
1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::APPS) {
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    app_sync_bundle_.Reset();
1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (type == syncer::EXTENSIONS) {
1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_sync_bundle_.Reset();
1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)syncer::SyncDataList ExtensionSyncService::GetAllSyncData(
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    syncer::ModelType type) const {
1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::EXTENSIONS)
1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return extension_sync_bundle_.GetAllSyncData();
1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::APPS)
1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return app_sync_bundle_.GetAllSyncData();
2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // We should only get sync data for extensions and apps.
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  NOTREACHED();
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return syncer::SyncDataList();
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)syncer::SyncError ExtensionSyncService::ProcessSyncChanges(
2081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const tracked_objects::Location& from_here,
2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const syncer::SyncChangeList& change_list) {
2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (syncer::SyncChangeList::const_iterator i = change_list.begin();
2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      i != change_list.end();
2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ++i) {
2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    syncer::ModelType type = i->sync_data().GetDataType();
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (type == syncer::EXTENSIONS) {
2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_.ProcessSyncChange(
2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          extensions::ExtensionSyncData(*i));
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else if (type == syncer::APPS) {
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_.ProcessSyncChange(extensions::AppSyncData(*i));
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extension_prefs_->app_sorting()->FixNTPOrdinalCollisions();
2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return syncer::SyncError();
2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)extensions::ExtensionSyncData ExtensionSyncService::GetExtensionSyncData(
2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Extension& extension) const {
2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return extensions::ExtensionSyncData(
2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension,
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->IsExtensionEnabled(extension.id()),
2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_util::IsIncognitoEnabled(extension.id(), extension_service_));
2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)extensions::AppSyncData ExtensionSyncService::GetAppSyncData(
2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Extension& extension) const {
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return extensions::AppSyncData(
2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension,
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->IsExtensionEnabled(extension.id()),
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_util::IsIncognitoEnabled(extension.id(), extension_service_),
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_prefs_->app_sorting()->GetAppLaunchOrdinal(extension.id()),
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_prefs_->app_sorting()->GetPageOrdinal(extension.id()));
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)std::vector<extensions::ExtensionSyncData>
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ExtensionSyncService::GetExtensionSyncDataList() const {
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<extensions::ExtensionSyncData> extension_sync_list;
2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_sync_bundle_.GetExtensionSyncDataListHelper(
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->extensions(), &extension_sync_list);
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_sync_bundle_.GetExtensionSyncDataListHelper(
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->disabled_extensions(), &extension_sync_list);
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_sync_bundle_.GetExtensionSyncDataListHelper(
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->terminated_extensions(), &extension_sync_list);
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<extensions::ExtensionSyncData> pending_extensions =
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_.GetPendingData();
2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_sync_list.insert(extension_sync_list.begin(),
2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                             pending_extensions.begin(),
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                             pending_extensions.end());
2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return extension_sync_list;
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)std::vector<extensions::AppSyncData> ExtensionSyncService::GetAppSyncDataList()
2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const {
2661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<extensions::AppSyncData> app_sync_list;
2671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  app_sync_bundle_.GetAppSyncDataListHelper(
2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->extensions(), &app_sync_list);
2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  app_sync_bundle_.GetAppSyncDataListHelper(
2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->disabled_extensions(), &app_sync_list);
2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  app_sync_bundle_.GetAppSyncDataListHelper(
2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->terminated_extensions(), &app_sync_list);
2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<extensions::AppSyncData> pending_apps =
2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_.GetPendingData();
2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  app_sync_list.insert(app_sync_list.begin(),
2771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                       pending_apps.begin(),
2781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                       pending_apps.end());
2791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return app_sync_list;
2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::ProcessExtensionSyncData(
2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::ExtensionSyncData& extension_sync_data) {
2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!ProcessExtensionSyncDataHelper(extension_sync_data,
2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      syncer::EXTENSIONS)) {
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_sync_bundle_.AddPendingExtension(extension_sync_data.id(),
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                               extension_sync_data);
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_service_->CheckForUpdatesSoon();
2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::ProcessAppSyncData(
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::AppSyncData& app_sync_data) {
2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const std::string& id = app_sync_data.id();
2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (app_sync_data.app_launch_ordinal().IsValid() &&
3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_data.page_ordinal().IsValid()) {
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extension_prefs_->app_sorting()->SetAppLaunchOrdinal(
3031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        id,
3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        app_sync_data.app_launch_ordinal());
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extension_prefs_->app_sorting()->SetPageOrdinal(
3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        id,
3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        app_sync_data.page_ordinal());
3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!ProcessExtensionSyncDataHelper(app_sync_data.extension_sync_data(),
3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      syncer::APPS)) {
3121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    app_sync_bundle_.AddPendingApp(id, app_sync_data);
3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_service_->CheckForUpdatesSoon();
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SyncOrderingChange(const std::string& extension_id) {
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const extensions::Extension* ext = extension_service_->GetInstalledExtension(
3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_id);
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (ext)
3251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    SyncExtensionChangeIfNeeded(*ext);
3261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SetSyncStartFlare(
3291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const syncer::SyncableService::StartSyncFlare& flare) {
3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  flare_ = flare;
3311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::IsCorrectSyncType(const Extension& extension,
3341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                         syncer::ModelType type) const {
3351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::EXTENSIONS &&
3361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions::sync_helper::IsSyncableExtension(&extension)) {
3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
3381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::APPS &&
3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions::sync_helper::IsSyncableApp(&extension)) {
3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return false;
3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::IsPendingEnable(
3491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::string& extension_id) const {
3501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return pending_app_enables_.Contains(extension_id) ||
3511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      pending_extension_enables_.Contains(extension_id);
3521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::ProcessExtensionSyncDataHelper(
3551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::ExtensionSyncData& extension_sync_data,
3561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    syncer::ModelType type) {
3571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const std::string& id = extension_sync_data.id();
3581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const Extension* extension = extension_service_->GetInstalledExtension(id);
3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // TODO(bolms): we should really handle this better.  The particularly bad
3611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // case is where an app becomes an extension or vice versa, and we end up with
3621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // a zombie extension that won't go away.
3631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extension && !IsCorrectSyncType(*extension, type))
3641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
3651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Handle uninstalls first.
3671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extension_sync_data.uninstalled()) {
3681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (!extension_service_->UninstallExtensionHelper(extension_service_, id)) {
3691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LOG(WARNING) << "Could not uninstall extension " << id
3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                   << " for sync";
3711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
3721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
3731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Extension from sync was uninstalled by the user as external extensions.
3761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Honor user choice and skip installation/enabling.
3771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extension_service_->IsExternalExtensionUninstalled(id)) {
3781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    LOG(WARNING) << "Extension with id " << id
3791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 << " from sync was uninstalled as external extension";
3801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
3811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Set user settings.
384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If the extension has been disabled from sync, it may not have
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // been installed yet, so we don't know if the disable reason was a
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // permissions increase.  That will be updated once CheckPermissionsIncrease
387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // is called for it.
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (extension_sync_data.enabled())
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extension_service_->EnableExtension(id);
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else if (!IsPendingEnable(id))
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extension_service_->DisableExtension(
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        id, Extension::DISABLE_UNKNOWN_FROM_SYNC);
3931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // We need to cache some version information here because setting the
3951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // incognito flag invalidates the |extension| pointer (it reloads the
3961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // extension).
3971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool extension_installed = (extension != NULL);
3981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int result = extension ?
3991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension->version()->CompareTo(extension_sync_data.version()) : 0;
4001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_util::SetIsIncognitoEnabled(
4011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      id, extension_service_, extension_sync_data.incognito_enabled());
4021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension = NULL;  // No longer safe to use.
4031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extension_installed) {
4051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // If the extension is already installed, check if it's outdated.
4061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (result < 0) {
4071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Extension is outdated.
4081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return false;
4091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
4101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else {
4111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // TODO(akalin): Replace silent update with a list of enabled
4121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // permissions.
4131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const bool kInstallSilently = true;
4141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CHECK(type == syncer::EXTENSIONS || type == syncer::APPS);
4161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extensions::PendingExtensionInfo::ShouldAllowInstallPredicate filter =
4171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        (type == syncer::APPS) ? extensions::sync_helper::IsSyncableApp :
4181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 extensions::sync_helper::IsSyncableExtension;
4191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (!extension_service_->pending_extension_manager()->AddFromSync(
4211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            id,
4221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            extension_sync_data.update_url(),
4231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            filter,
4241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            kInstallSilently)) {
4251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LOG(WARNING) << "Could not add pending extension for " << id;
4261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // This means that the extension is already pending installation, with a
4271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // non-INTERNAL location.  Add to pending_sync_data, even though it will
4281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // never be removed (we'll never install a syncable version of the
4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // extension), so that GetAllSyncData() continues to send it.
4301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
4311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Track pending extensions so that we can return them in GetAllSyncData().
4321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
4331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SyncExtensionChangeIfNeeded(
4391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Extension& extension) {
4401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extensions::sync_helper::IsSyncableApp(&extension)) {
4411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (app_sync_bundle_.IsSyncing())
4421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_.SyncChangeIfNeeded(extension);
4431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else if (extension_service_->is_ready() && !flare_.is_null())
4441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      flare_.Run(syncer::APPS);
4451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (extensions::sync_helper::IsSyncableExtension(&extension)) {
4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (extension_sync_bundle_.IsSyncing())
4471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_.SyncChangeIfNeeded(extension);
4481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else if (extension_service_->is_ready() && !flare_.is_null())
4491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      flare_.Run(syncer::EXTENSIONS);
4501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
452