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"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/utf_string_conversions.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/app_sync_data.h"
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/extensions/bookmark_app_helper.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"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/extensions/launch_util.h"
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/sync/glue/sync_start_util.h"
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/common/extensions/extension_constants.h"
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/common/extensions/sync_helper.h"
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/common/web_application_info.h"
2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "components/sync_driver/sync_prefs.h"
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/app_sorting.h"
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_util.h"
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/common/extension_icon_set.h"
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/feature_switch.h"
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/common/manifest_constants.h"
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/common/manifest_handlers/icons_handler.h"
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/api/sync_change.h"
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "sync/api/sync_error_factory.h"
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/gfx/image/image_family.h"
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extensions::Extension;
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extensions::ExtensionPrefs;
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using extensions::ExtensionRegistry;
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extensions::FeatureSwitch;
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace {
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid OnWebApplicationInfoLoaded(
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebApplicationInfo synced_info,
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::WeakPtr<ExtensionService> extension_service,
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const WebApplicationInfo& loaded_info) {
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_EQ(synced_info.app_url, loaded_info.app_url);
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!extension_service)
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Use the old icons if they exist.
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  synced_info.icons = loaded_info.icons;
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CreateOrUpdateBookmarkApp(extension_service.get(), synced_info);
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ExtensionSyncService::ExtensionSyncService(Profile* profile,
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                           ExtensionPrefs* extension_prefs,
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                           ExtensionService* extension_service)
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : profile_(profile),
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_prefs_(extension_prefs),
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_(extension_service),
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_(this),
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_(this),
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      pending_app_enables_(make_scoped_ptr(new sync_driver::SyncPrefs(
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                               extension_prefs_->pref_service())),
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           &app_sync_bundle_,
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           syncer::APPS),
7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      pending_extension_enables_(make_scoped_ptr(new sync_driver::SyncPrefs(
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                     extension_prefs_->pref_service())),
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                 &extension_sync_bundle_,
78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                 syncer::EXTENSIONS) {
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SetSyncStartFlare(sync_start_util::GetFlareForSyncableService(
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      profile_->GetPath()));
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_service_->set_extension_sync_service(this);
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extension_prefs_->app_sorting()->SetExtensionSyncService(this);
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ExtensionSyncService::~ExtensionSyncService() {}
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ExtensionSyncService* ExtensionSyncService::Get(Profile* profile) {
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return ExtensionSyncServiceFactory::GetForProfile(profile);
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)syncer::SyncChange ExtensionSyncService::PrepareToSyncUninstallExtension(
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::Extension* extension, bool extensions_ready) {
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Extract the data we need for sync now, but don't actually sync until we've
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // completed the uninstallation.
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // TODO(tim): If we get here and IsSyncing is false, this will cause
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // "back from the dead" style bugs, because sync will add-back the extension
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // that was uninstalled here when MergeDataAndStartSyncing is called.
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // See crbug.com/256795.
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (extensions::util::ShouldSyncApp(extension, profile_)) {
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (app_sync_bundle_.IsSyncing())
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return app_sync_bundle_.CreateSyncChangeToDelete(extension);
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else if (extensions_ready && !flare_.is_null())
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      flare_.Run(syncer::APPS);  // Tell sync to start ASAP.
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (extensions::sync_helper::IsSyncableExtension(extension)) {
1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (extension_sync_bundle_.IsSyncing())
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return extension_sync_bundle_.CreateSyncChangeToDelete(extension);
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else if (extensions_ready && !flare_.is_null())
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      flare_.Run(syncer::EXTENSIONS);  // Tell sync to start ASAP.
1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return syncer::SyncChange();
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::ProcessSyncUninstallExtension(
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::string& extension_id,
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const syncer::SyncChange& sync_change) {
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (app_sync_bundle_.HasExtensionId(extension_id) &&
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      sync_change.sync_data().GetDataType() == syncer::APPS) {
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    app_sync_bundle_.ProcessDeletion(extension_id, sync_change);
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (extension_sync_bundle_.HasExtensionId(extension_id) &&
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)             sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) {
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_sync_bundle_.ProcessDeletion(extension_id, sync_change);
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SyncEnableExtension(
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::Extension& extension) {
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Syncing may not have started yet, so handle pending enables.
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (extensions::util::ShouldSyncApp(&extension, profile_))
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pending_app_enables_.OnExtensionEnabled(extension.id());
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (extensions::util::ShouldSyncExtension(&extension, profile_))
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pending_extension_enables_.OnExtensionEnabled(extension.id());
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SyncExtensionChangeIfNeeded(extension);
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SyncDisableExtension(
1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::Extension& extension) {
1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Syncing may not have started yet, so handle pending enables.
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (extensions::util::ShouldSyncApp(&extension, profile_))
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pending_app_enables_.OnExtensionDisabled(extension.id());
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (extensions::util::ShouldSyncExtension(&extension, profile_))
1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    pending_extension_enables_.OnExtensionDisabled(extension.id());
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SyncExtensionChangeIfNeeded(extension);
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)syncer::SyncMergeResult ExtensionSyncService::MergeDataAndStartSyncing(
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    syncer::ModelType type,
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const syncer::SyncDataList& initial_sync_data,
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CHECK(sync_processor.get());
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CHECK(sync_error_factory.get());
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (type) {
1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case syncer::EXTENSIONS:
1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_.SetupSync(sync_processor.release(),
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                       sync_error_factory.release(),
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                       initial_sync_data);
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      pending_extension_enables_.OnSyncStarted(extension_service_);
1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case syncer::APPS:
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_.SetupSync(sync_processor.release(),
1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 sync_error_factory.release(),
1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 initial_sync_data);
1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      pending_app_enables_.OnSyncStarted(extension_service_);
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    default:
1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LOG(FATAL) << "Got " << type << " ModelType";
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Process local extensions.
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // TODO(yoz): Determine whether pending extensions should be considered too.
1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  //            See crbug.com/104399.
1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  syncer::SyncDataList sync_data_list = GetAllSyncData(type);
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  syncer::SyncChangeList sync_change_list;
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (syncer::SyncDataList::const_iterator i = sync_data_list.begin();
1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       i != sync_data_list.end();
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       ++i) {
1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    switch (type) {
1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        case syncer::EXTENSIONS:
1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          sync_change_list.push_back(
1921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              extension_sync_bundle_.CreateSyncChange(*i));
1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          break;
1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        case syncer::APPS:
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          sync_change_list.push_back(app_sync_bundle_.CreateSyncChange(*i));
1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          break;
1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      default:
1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        LOG(FATAL) << "Got " << type << " ModelType";
1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::EXTENSIONS) {
2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_sync_bundle_.ProcessSyncChangeList(sync_change_list);
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (type == syncer::APPS) {
2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    app_sync_bundle_.ProcessSyncChangeList(sync_change_list);
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return syncer::SyncMergeResult(type);
2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::StopSyncing(syncer::ModelType type) {
2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::APPS) {
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    app_sync_bundle_.Reset();
2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else if (type == syncer::EXTENSIONS) {
2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_sync_bundle_.Reset();
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)syncer::SyncDataList ExtensionSyncService::GetAllSyncData(
2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    syncer::ModelType type) const {
2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::EXTENSIONS)
2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return extension_sync_bundle_.GetAllSyncData();
2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::APPS)
2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return app_sync_bundle_.GetAllSyncData();
2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // We should only get sync data for extensions and apps.
2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  NOTREACHED();
2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return syncer::SyncDataList();
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)syncer::SyncError ExtensionSyncService::ProcessSyncChanges(
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const tracked_objects::Location& from_here,
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const syncer::SyncChangeList& change_list) {
2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (syncer::SyncChangeList::const_iterator i = change_list.begin();
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      i != change_list.end();
2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ++i) {
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    syncer::ModelType type = i->sync_data().GetDataType();
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (type == syncer::EXTENSIONS) {
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_.ProcessSyncChange(
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          extensions::ExtensionSyncData(*i));
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else if (type == syncer::APPS) {
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_.ProcessSyncChange(extensions::AppSyncData(*i));
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extension_prefs_->app_sorting()->FixNTPOrdinalCollisions();
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return syncer::SyncError();
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)extensions::ExtensionSyncData ExtensionSyncService::GetExtensionSyncData(
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Extension& extension) const {
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return extensions::ExtensionSyncData(
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension,
2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->IsExtensionEnabled(extension.id()),
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      extensions::util::IsIncognitoEnabled(extension.id(), profile_),
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      extension_prefs_->HasDisableReason(extension.id(),
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         Extension::DISABLE_REMOTE_INSTALL));
2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)extensions::AppSyncData ExtensionSyncService::GetAppSyncData(
2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Extension& extension) const {
2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return extensions::AppSyncData(
2661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension,
2671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_service_->IsExtensionEnabled(extension.id()),
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extensions::util::IsIncognitoEnabled(extension.id(), profile_),
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      extension_prefs_->HasDisableReason(extension.id(),
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         Extension::DISABLE_REMOTE_INSTALL),
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_prefs_->app_sorting()->GetAppLaunchOrdinal(extension.id()),
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extension_prefs_->app_sorting()->GetPageOrdinal(extension.id()),
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extensions::GetLaunchTypePrefValue(extension_prefs_, extension.id()));
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)std::vector<extensions::ExtensionSyncData>
2771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ExtensionSyncService::GetExtensionSyncDataList() const {
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
2791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<extensions::ExtensionSyncData> extension_sync_list;
2801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_sync_bundle_.GetExtensionSyncDataListHelper(
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      registry->enabled_extensions(), &extension_sync_list);
2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_sync_bundle_.GetExtensionSyncDataListHelper(
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      registry->disabled_extensions(), &extension_sync_list);
2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_sync_bundle_.GetExtensionSyncDataListHelper(
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      registry->terminated_extensions(), &extension_sync_list);
2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<extensions::ExtensionSyncData> pending_extensions =
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_.GetPendingData();
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension_sync_list.insert(extension_sync_list.begin(),
2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                             pending_extensions.begin(),
2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                             pending_extensions.end());
2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return extension_sync_list;
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)std::vector<extensions::AppSyncData> ExtensionSyncService::GetAppSyncDataList()
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const {
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<extensions::AppSyncData> app_sync_list;
3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  app_sync_bundle_.GetAppSyncDataListHelper(
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      registry->enabled_extensions(), &app_sync_list);
3021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  app_sync_bundle_.GetAppSyncDataListHelper(
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      registry->disabled_extensions(), &app_sync_list);
3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  app_sync_bundle_.GetAppSyncDataListHelper(
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      registry->terminated_extensions(), &app_sync_list);
3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<extensions::AppSyncData> pending_apps =
3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_.GetPendingData();
3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  app_sync_list.insert(app_sync_list.begin(),
3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                       pending_apps.begin(),
3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                       pending_apps.end());
3121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return app_sync_list;
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::ProcessExtensionSyncData(
3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::ExtensionSyncData& extension_sync_data) {
3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!ProcessExtensionSyncDataHelper(extension_sync_data,
3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      syncer::EXTENSIONS)) {
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_sync_bundle_.AddPendingExtension(extension_sync_data.id(),
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                               extension_sync_data);
3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_service_->CheckForUpdatesSoon();
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
3241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
3271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::ProcessAppSyncData(
3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::AppSyncData& app_sync_data) {
3311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const std::string& id = app_sync_data.id();
3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (app_sync_data.app_launch_ordinal().IsValid() &&
3341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_data.page_ordinal().IsValid()) {
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extension_prefs_->app_sorting()->SetAppLaunchOrdinal(
3361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        id,
3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        app_sync_data.app_launch_ordinal());
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extension_prefs_->app_sorting()->SetPageOrdinal(
3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        id,
3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        app_sync_data.page_ordinal());
3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The corresponding validation of this value during AppSyncData population
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is in AppSyncData::PopulateAppSpecifics.
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (app_sync_data.launch_type() >= extensions::LAUNCH_TYPE_FIRST &&
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      app_sync_data.launch_type() < extensions::NUM_LAUNCH_TYPES) {
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    extensions::SetLaunchType(extension_service_, id,
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              app_sync_data.launch_type());
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!app_sync_data.bookmark_app_url().empty())
3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ProcessBookmarkAppSyncData(app_sync_data);
3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!ProcessExtensionSyncDataHelper(app_sync_data.extension_sync_data(),
3551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      syncer::APPS)) {
3561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    app_sync_bundle_.AddPendingApp(id, app_sync_data);
3571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extension_service_->CheckForUpdatesSoon();
3581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
3621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid ExtensionSyncService::ProcessBookmarkAppSyncData(
3655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const extensions::AppSyncData& app_sync_data) {
3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Process bookmark app sync if necessary.
3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  GURL bookmark_app_url(app_sync_data.bookmark_app_url());
3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!bookmark_app_url.is_valid() ||
3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      app_sync_data.extension_sync_data().uninstalled()) {
3705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
3715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const extensions::Extension* extension =
3745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      extension_service_->GetInstalledExtension(
3755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          app_sync_data.extension_sync_data().id());
3765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Return if there are no bookmark app details that need updating.
3785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (extension && extension->non_localized_name() ==
3795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       app_sync_data.extension_sync_data().name() &&
3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      extension->description() == app_sync_data.bookmark_app_description()) {
3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
3825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WebApplicationInfo web_app_info;
3855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  web_app_info.app_url = bookmark_app_url;
3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  web_app_info.title =
3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::UTF8ToUTF16(app_sync_data.extension_sync_data().name());
3885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  web_app_info.description =
3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::UTF8ToUTF16(app_sync_data.bookmark_app_description());
3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // If the bookmark app already exists, keep the old icons.
3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!extension) {
3935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CreateOrUpdateBookmarkApp(extension_service_, web_app_info);
3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
3955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    app_sync_data.extension_sync_data().name();
3965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    GetWebApplicationInfoFromApp(profile_,
3975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 extension,
3985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 base::Bind(&OnWebApplicationInfoLoaded,
3995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                            web_app_info,
4005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                            extension_service_->AsWeakPtr()));
4015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SyncOrderingChange(const std::string& extension_id) {
4051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const extensions::Extension* ext = extension_service_->GetInstalledExtension(
4061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_id);
4071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (ext)
4091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    SyncExtensionChangeIfNeeded(*ext);
4101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SetSyncStartFlare(
4131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const syncer::SyncableService::StartSyncFlare& flare) {
4141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  flare_ = flare;
4151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::IsCorrectSyncType(const Extension& extension,
4181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                         syncer::ModelType type) const {
4191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::EXTENSIONS &&
4201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions::sync_helper::IsSyncableExtension(&extension)) {
4211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
4221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (type == syncer::APPS &&
4251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions::sync_helper::IsSyncableApp(&extension)) {
4261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
4271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return false;
4301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::IsPendingEnable(
4331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::string& extension_id) const {
4341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return pending_app_enables_.Contains(extension_id) ||
4351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      pending_extension_enables_.Contains(extension_id);
4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ExtensionSyncService::ProcessExtensionSyncDataHelper(
4391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const extensions::ExtensionSyncData& extension_sync_data,
4401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    syncer::ModelType type) {
4411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const std::string& id = extension_sync_data.id();
4421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const Extension* extension = extension_service_->GetInstalledExtension(id);
4431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // TODO(bolms): we should really handle this better.  The particularly bad
4451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // case is where an app becomes an extension or vice versa, and we end up with
4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // a zombie extension that won't go away.
4471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extension && !IsCorrectSyncType(*extension, type))
4481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
4491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Handle uninstalls first.
4511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extension_sync_data.uninstalled()) {
4521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (!extension_service_->UninstallExtensionHelper(extension_service_, id)) {
4531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LOG(WARNING) << "Could not uninstall extension " << id
4541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                   << " for sync";
4551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
4561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
4571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Extension from sync was uninstalled by the user as external extensions.
4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Honor user choice and skip installation/enabling.
461effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (extensions::ExtensionPrefs::Get(profile_)
462effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          ->IsExternalExtensionUninstalled(id)) {
4631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    LOG(WARNING) << "Extension with id " << id
4641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 << " from sync was uninstalled as external extension";
4651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
4661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Set user settings.
469f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If the extension has been disabled from sync, it may not have
470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // been installed yet, so we don't know if the disable reason was a
471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // permissions increase.  That will be updated once CheckPermissionsIncrease
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // is called for it.
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // However if the extension is marked as a remote install in sync, we know
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // what the disable reason is, so set it to that directly. Note that when
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // CheckPermissionsIncrease runs, it might still add permissions increase
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // as a disable reason for the extension.
477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (extension_sync_data.enabled()) {
478f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extension_service_->EnableExtension(id);
479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else if (!IsPendingEnable(id)) {
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (extension_sync_data.remote_install()) {
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      extension_service_->DisableExtension(id,
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                           Extension::DISABLE_REMOTE_INSTALL);
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      extension_service_->DisableExtension(
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          id, Extension::DISABLE_UNKNOWN_FROM_SYNC);
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
4881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // We need to cache some version information here because setting the
4901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // incognito flag invalidates the |extension| pointer (it reloads the
4911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // extension).
4921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool extension_installed = (extension != NULL);
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int version_compare_result = extension ?
4941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension->version()->CompareTo(extension_sync_data.version()) : 0;
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // If the target extension has already been installed ephemerally, it can
497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // be promoted to a regular installed extension and downloading from the Web
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Store is not necessary.
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (extension && extensions::util::IsEphemeralApp(id, profile_))
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    extension_service_->PromoteEphemeralApp(extension, true);
501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Update the incognito flag.
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  extensions::util::SetIsIncognitoEnabled(
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      id, profile_, extension_sync_data.incognito_enabled());
5051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extension = NULL;  // No longer safe to use.
5061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (extension_installed) {
5081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // If the extension is already installed, check if it's outdated.
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (version_compare_result < 0) {
5101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Extension is outdated.
5111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return false;
5121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
5131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else {
5141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // TODO(akalin): Replace silent update with a list of enabled
5151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // permissions.
5161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const bool kInstallSilently = true;
5171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CHECK(type == syncer::EXTENSIONS || type == syncer::APPS);
5191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    extensions::PendingExtensionInfo::ShouldAllowInstallPredicate filter =
5201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        (type == syncer::APPS) ? extensions::sync_helper::IsSyncableApp :
5211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 extensions::sync_helper::IsSyncableExtension;
5221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (!extension_service_->pending_extension_manager()->AddFromSync(
5241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            id,
5251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            extension_sync_data.update_url(),
5261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            filter,
527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            kInstallSilently,
528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            extension_sync_data.remote_install())) {
5291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LOG(WARNING) << "Could not add pending extension for " << id;
5301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // This means that the extension is already pending installation, with a
5311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // non-INTERNAL location.  Add to pending_sync_data, even though it will
5321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // never be removed (we'll never install a syncable version of the
5331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // extension), so that GetAllSyncData() continues to send it.
5341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
5351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Track pending extensions so that we can return them in GetAllSyncData().
5361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
5371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
5381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
5401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ExtensionSyncService::SyncExtensionChangeIfNeeded(
5431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Extension& extension) {
544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (extensions::util::ShouldSyncApp(&extension, profile_)) {
5451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (app_sync_bundle_.IsSyncing())
5461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      app_sync_bundle_.SyncChangeIfNeeded(extension);
5471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else if (extension_service_->is_ready() && !flare_.is_null())
5481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      flare_.Run(syncer::APPS);
549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else if (extensions::util::ShouldSyncExtension(&extension, profile_)) {
5501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (extension_sync_bundle_.IsSyncing())
5511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extension_sync_bundle_.SyncChangeIfNeeded(extension);
5521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else if (extension_service_->is_ready() && !flare_.is_null())
5531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      flare_.Run(syncer::EXTENSIONS);
5541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
5551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
556