| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_sync_service.h" | 5 #include "chrome/browser/extensions/extension_sync_service.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "base/threading/thread_restrictions.h" | 9 #include "base/threading/thread_restrictions.h" |
| 10 #include "chrome/browser/extensions/bookmark_app_helper.h" | 10 #include "chrome/browser/extensions/bookmark_app_helper.h" |
| 11 #include "chrome/browser/extensions/extension_service.h" | 11 #include "chrome/browser/extensions/extension_service.h" |
| 12 #include "chrome/browser/extensions/extension_sync_data.h" | 12 #include "chrome/browser/extensions/extension_sync_data.h" |
| 13 #include "chrome/browser/extensions/extension_sync_service_factory.h" | 13 #include "chrome/browser/extensions/extension_sync_service_factory.h" |
| 14 #include "chrome/browser/extensions/extension_util.h" | 14 #include "chrome/browser/extensions/extension_util.h" |
| 15 #include "chrome/browser/extensions/launch_util.h" | 15 #include "chrome/browser/extensions/launch_util.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/sync/glue/sync_start_util.h" | 17 #include "chrome/browser/sync/glue/sync_start_util.h" |
| 18 #include "chrome/common/extensions/extension_constants.h" | 18 #include "chrome/common/extensions/extension_constants.h" |
| 19 #include "chrome/common/extensions/sync_helper.h" | 19 #include "chrome/common/extensions/sync_helper.h" |
| 20 #include "chrome/common/web_application_info.h" | 20 #include "chrome/common/web_application_info.h" |
| 21 #include "components/sync_driver/sync_prefs.h" | 21 #include "components/sync_driver/sync_prefs.h" |
| 22 #include "extensions/browser/app_sorting.h" | 22 #include "extensions/browser/app_sorting.h" |
| 23 #include "extensions/browser/extension_prefs.h" | 23 #include "extensions/browser/extension_prefs.h" |
| 24 #include "extensions/browser/extension_registry.h" | 24 #include "extensions/browser/extension_registry.h" |
| 25 #include "extensions/browser/extension_system.h" |
| 25 #include "extensions/browser/extension_util.h" | 26 #include "extensions/browser/extension_util.h" |
| 26 #include "extensions/browser/uninstall_reason.h" | 27 #include "extensions/browser/uninstall_reason.h" |
| 27 #include "extensions/common/extension.h" | 28 #include "extensions/common/extension.h" |
| 28 #include "extensions/common/extension_set.h" | 29 #include "extensions/common/extension_set.h" |
| 29 #include "extensions/common/image_util.h" | 30 #include "extensions/common/image_util.h" |
| 30 #include "sync/api/sync_change.h" | 31 #include "sync/api/sync_change.h" |
| 31 #include "sync/api/sync_error_factory.h" | 32 #include "sync/api/sync_error_factory.h" |
| 32 | 33 |
| 34 using extensions::AppSorting; |
| 33 using extensions::Extension; | 35 using extensions::Extension; |
| 34 using extensions::ExtensionPrefs; | 36 using extensions::ExtensionPrefs; |
| 35 using extensions::ExtensionRegistry; | 37 using extensions::ExtensionRegistry; |
| 36 using extensions::ExtensionSet; | 38 using extensions::ExtensionSet; |
| 37 using extensions::ExtensionSyncData; | 39 using extensions::ExtensionSyncData; |
| 40 using extensions::ExtensionSystem; |
| 38 using extensions::SyncBundle; | 41 using extensions::SyncBundle; |
| 39 | 42 |
| 40 namespace { | 43 namespace { |
| 41 | 44 |
| 42 void OnWebApplicationInfoLoaded( | 45 void OnWebApplicationInfoLoaded( |
| 43 WebApplicationInfo synced_info, | 46 WebApplicationInfo synced_info, |
| 44 base::WeakPtr<ExtensionService> extension_service, | 47 base::WeakPtr<ExtensionService> extension_service, |
| 45 const WebApplicationInfo& loaded_info) { | 48 const WebApplicationInfo& loaded_info) { |
| 46 DCHECK_EQ(synced_info.app_url, loaded_info.app_url); | 49 DCHECK_EQ(synced_info.app_url, loaded_info.app_url); |
| 47 | 50 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 | 104 |
| 102 ExtensionSyncService::~ExtensionSyncService() {} | 105 ExtensionSyncService::~ExtensionSyncService() {} |
| 103 | 106 |
| 104 // static | 107 // static |
| 105 ExtensionSyncService* ExtensionSyncService::Get( | 108 ExtensionSyncService* ExtensionSyncService::Get( |
| 106 content::BrowserContext* context) { | 109 content::BrowserContext* context) { |
| 107 return ExtensionSyncServiceFactory::GetForBrowserContext(context); | 110 return ExtensionSyncServiceFactory::GetForBrowserContext(context); |
| 108 } | 111 } |
| 109 | 112 |
| 110 void ExtensionSyncService::SyncUninstallExtension( | 113 void ExtensionSyncService::SyncUninstallExtension( |
| 111 const extensions::Extension& extension) { | 114 const Extension& extension) { |
| 112 if (!extensions::util::ShouldSync(&extension, profile_)) | 115 if (!extensions::util::ShouldSync(&extension, profile_)) |
| 113 return; | 116 return; |
| 114 | 117 |
| 115 // TODO(tim): If we get here and IsSyncing is false, this will cause | 118 // TODO(tim): If we get here and IsSyncing is false, this will cause |
| 116 // "back from the dead" style bugs, because sync will add-back the extension | 119 // "back from the dead" style bugs, because sync will add-back the extension |
| 117 // that was uninstalled here when MergeDataAndStartSyncing is called. | 120 // that was uninstalled here when MergeDataAndStartSyncing is called. |
| 118 // See crbug.com/256795. | 121 // See crbug.com/256795. |
| 119 syncer::ModelType type = | 122 syncer::ModelType type = |
| 120 extension.is_app() ? syncer::APPS : syncer::EXTENSIONS; | 123 extension.is_app() ? syncer::APPS : syncer::EXTENSIONS; |
| 121 SyncBundle* bundle = GetSyncBundle(type); | 124 SyncBundle* bundle = GetSyncBundle(type); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 // Now push those local changes to sync. | 177 // Now push those local changes to sync. |
| 175 // TODO(treib,kalman): We should only have to send out changes for extensions | 178 // TODO(treib,kalman): We should only have to send out changes for extensions |
| 176 // which have NeedsSync set (i.e. |GetLocalSyncDataList(type, false)|). That | 179 // which have NeedsSync set (i.e. |GetLocalSyncDataList(type, false)|). That |
| 177 // makes some sync_integration_tests fail though - figure out why and fix it! | 180 // makes some sync_integration_tests fail though - figure out why and fix it! |
| 178 std::vector<ExtensionSyncData> data_list = GetLocalSyncDataList(type, true); | 181 std::vector<ExtensionSyncData> data_list = GetLocalSyncDataList(type, true); |
| 179 bundle->PushSyncDataList(ToSyncerSyncDataList(data_list)); | 182 bundle->PushSyncDataList(ToSyncerSyncDataList(data_list)); |
| 180 for (const ExtensionSyncData& data : data_list) | 183 for (const ExtensionSyncData& data : data_list) |
| 181 ExtensionPrefs::Get(profile_)->SetNeedsSync(data.id(), false); | 184 ExtensionPrefs::Get(profile_)->SetNeedsSync(data.id(), false); |
| 182 | 185 |
| 183 if (type == syncer::APPS) | 186 if (type == syncer::APPS) |
| 184 extension_prefs_->app_sorting()->FixNTPOrdinalCollisions(); | 187 ExtensionSystem::Get(profile_)->app_sorting()->FixNTPOrdinalCollisions(); |
| 185 | 188 |
| 186 return syncer::SyncMergeResult(type); | 189 return syncer::SyncMergeResult(type); |
| 187 } | 190 } |
| 188 | 191 |
| 189 void ExtensionSyncService::StopSyncing(syncer::ModelType type) { | 192 void ExtensionSyncService::StopSyncing(syncer::ModelType type) { |
| 190 GetSyncBundle(type)->Reset(); | 193 GetSyncBundle(type)->Reset(); |
| 191 } | 194 } |
| 192 | 195 |
| 193 syncer::SyncDataList ExtensionSyncService::GetAllSyncData( | 196 syncer::SyncDataList ExtensionSyncService::GetAllSyncData( |
| 194 syncer::ModelType type) const { | 197 syncer::ModelType type) const { |
| 195 const SyncBundle* bundle = GetSyncBundle(type); | 198 const SyncBundle* bundle = GetSyncBundle(type); |
| 196 if (!bundle->IsSyncing()) | 199 if (!bundle->IsSyncing()) |
| 197 return syncer::SyncDataList(); | 200 return syncer::SyncDataList(); |
| 198 | 201 |
| 199 std::vector<extensions::ExtensionSyncData> sync_data_list = | 202 std::vector<ExtensionSyncData> sync_data_list = |
| 200 GetLocalSyncDataList(type, true); | 203 GetLocalSyncDataList(type, true); |
| 201 | 204 |
| 202 // Add pending data (where the local extension is either not installed yet or | 205 // Add pending data (where the local extension is either not installed yet or |
| 203 // outdated). | 206 // outdated). |
| 204 std::vector<ExtensionSyncData> pending_extensions = bundle->GetPendingData(); | 207 std::vector<ExtensionSyncData> pending_extensions = bundle->GetPendingData(); |
| 205 sync_data_list.insert(sync_data_list.begin(), | 208 sync_data_list.insert(sync_data_list.begin(), |
| 206 pending_extensions.begin(), | 209 pending_extensions.begin(), |
| 207 pending_extensions.end()); | 210 pending_extensions.end()); |
| 208 | 211 |
| 209 return ToSyncerSyncDataList(sync_data_list); | 212 return ToSyncerSyncDataList(sync_data_list); |
| 210 } | 213 } |
| 211 | 214 |
| 212 syncer::SyncError ExtensionSyncService::ProcessSyncChanges( | 215 syncer::SyncError ExtensionSyncService::ProcessSyncChanges( |
| 213 const tracked_objects::Location& from_here, | 216 const tracked_objects::Location& from_here, |
| 214 const syncer::SyncChangeList& change_list) { | 217 const syncer::SyncChangeList& change_list) { |
| 215 for (const syncer::SyncChange& sync_change : change_list) { | 218 for (const syncer::SyncChange& sync_change : change_list) { |
| 216 scoped_ptr<ExtensionSyncData> extension_sync_data( | 219 scoped_ptr<ExtensionSyncData> extension_sync_data( |
| 217 ExtensionSyncData::CreateFromSyncChange(sync_change)); | 220 ExtensionSyncData::CreateFromSyncChange(sync_change)); |
| 218 if (extension_sync_data) | 221 if (extension_sync_data) |
| 219 ApplySyncData(*extension_sync_data); | 222 ApplySyncData(*extension_sync_data); |
| 220 } | 223 } |
| 221 | 224 |
| 222 extension_prefs_->app_sorting()->FixNTPOrdinalCollisions(); | 225 ExtensionSystem::Get(profile_)->app_sorting()->FixNTPOrdinalCollisions(); |
| 223 | 226 |
| 224 return syncer::SyncError(); | 227 return syncer::SyncError(); |
| 225 } | 228 } |
| 226 | 229 |
| 227 ExtensionSyncData ExtensionSyncService::CreateSyncData( | 230 ExtensionSyncData ExtensionSyncService::CreateSyncData( |
| 228 const extensions::Extension& extension) const { | 231 const Extension& extension) const { |
| 229 bool enabled = extension_service_->IsExtensionEnabled(extension.id()); | 232 bool enabled = extension_service_->IsExtensionEnabled(extension.id()); |
| 230 int disable_reasons = extension_prefs_->GetDisableReasons(extension.id()); | 233 int disable_reasons = extension_prefs_->GetDisableReasons(extension.id()); |
| 231 bool incognito_enabled = extensions::util::IsIncognitoEnabled(extension.id(), | 234 bool incognito_enabled = extensions::util::IsIncognitoEnabled(extension.id(), |
| 232 profile_); | 235 profile_); |
| 233 bool remote_install = | 236 bool remote_install = |
| 234 extension_prefs_->HasDisableReason(extension.id(), | 237 extension_prefs_->HasDisableReason(extension.id(), |
| 235 Extension::DISABLE_REMOTE_INSTALL); | 238 Extension::DISABLE_REMOTE_INSTALL); |
| 236 ExtensionSyncData::OptionalBoolean allowed_on_all_url = | 239 ExtensionSyncData::OptionalBoolean allowed_on_all_url = |
| 237 GetAllowedOnAllUrlsOptionalBoolean(extension.id(), profile_); | 240 GetAllowedOnAllUrlsOptionalBoolean(extension.id(), profile_); |
| 238 if (extension.is_app()) { | 241 if (extension.is_app()) { |
| 242 AppSorting* app_sorting = ExtensionSystem::Get(profile_)->app_sorting(); |
| 239 return ExtensionSyncData( | 243 return ExtensionSyncData( |
| 240 extension, enabled, disable_reasons, incognito_enabled, remote_install, | 244 extension, enabled, disable_reasons, incognito_enabled, remote_install, |
| 241 allowed_on_all_url, | 245 allowed_on_all_url, |
| 242 extension_prefs_->app_sorting()->GetAppLaunchOrdinal(extension.id()), | 246 app_sorting->GetAppLaunchOrdinal(extension.id()), |
| 243 extension_prefs_->app_sorting()->GetPageOrdinal(extension.id()), | 247 app_sorting->GetPageOrdinal(extension.id()), |
| 244 extensions::GetLaunchTypePrefValue(extension_prefs_, extension.id())); | 248 extensions::GetLaunchTypePrefValue(extension_prefs_, extension.id())); |
| 245 } | 249 } |
| 246 return ExtensionSyncData( | 250 return ExtensionSyncData( |
| 247 extension, enabled, disable_reasons, incognito_enabled, remote_install, | 251 extension, enabled, disable_reasons, incognito_enabled, remote_install, |
| 248 allowed_on_all_url); | 252 allowed_on_all_url); |
| 249 } | 253 } |
| 250 | 254 |
| 251 bool ExtensionSyncService::ApplySyncData( | 255 bool ExtensionSyncService::ApplySyncData( |
| 252 const ExtensionSyncData& extension_sync_data) { | 256 const ExtensionSyncData& extension_sync_data) { |
| 253 syncer::ModelType type = extension_sync_data.is_app() ? syncer::APPS | 257 syncer::ModelType type = extension_sync_data.is_app() ? syncer::APPS |
| 254 : syncer::EXTENSIONS; | 258 : syncer::EXTENSIONS; |
| 255 SyncBundle* bundle = GetSyncBundle(type); | 259 SyncBundle* bundle = GetSyncBundle(type); |
| 256 bundle->ApplySyncData(extension_sync_data); | 260 bundle->ApplySyncData(extension_sync_data); |
| 257 | 261 |
| 258 const std::string& id = extension_sync_data.id(); | 262 const std::string& id = extension_sync_data.id(); |
| 259 | 263 |
| 260 if (extension_sync_data.is_app()) { | 264 if (extension_sync_data.is_app()) { |
| 261 if (extension_sync_data.app_launch_ordinal().IsValid() && | 265 if (extension_sync_data.app_launch_ordinal().IsValid() && |
| 262 extension_sync_data.page_ordinal().IsValid()) { | 266 extension_sync_data.page_ordinal().IsValid()) { |
| 263 extension_prefs_->app_sorting()->SetAppLaunchOrdinal( | 267 AppSorting* app_sorting = ExtensionSystem::Get(profile_)->app_sorting(); |
| 268 app_sorting->SetAppLaunchOrdinal( |
| 264 id, | 269 id, |
| 265 extension_sync_data.app_launch_ordinal()); | 270 extension_sync_data.app_launch_ordinal()); |
| 266 extension_prefs_->app_sorting()->SetPageOrdinal( | 271 app_sorting->SetPageOrdinal(id, extension_sync_data.page_ordinal()); |
| 267 id, | |
| 268 extension_sync_data.page_ordinal()); | |
| 269 } | 272 } |
| 270 | 273 |
| 271 // The corresponding validation of this value during ExtensionSyncData | 274 // The corresponding validation of this value during ExtensionSyncData |
| 272 // population is in ExtensionSyncData::ToAppSpecifics. | 275 // population is in ExtensionSyncData::ToAppSpecifics. |
| 273 if (extension_sync_data.launch_type() >= extensions::LAUNCH_TYPE_FIRST && | 276 if (extension_sync_data.launch_type() >= extensions::LAUNCH_TYPE_FIRST && |
| 274 extension_sync_data.launch_type() < extensions::NUM_LAUNCH_TYPES) { | 277 extension_sync_data.launch_type() < extensions::NUM_LAUNCH_TYPES) { |
| 275 extensions::SetLaunchType( | 278 extensions::SetLaunchType( |
| 276 profile_, id, extension_sync_data.launch_type()); | 279 profile_, id, extension_sync_data.launch_type()); |
| 277 } | 280 } |
| 278 | 281 |
| 279 if (!extension_sync_data.bookmark_app_url().empty()) | 282 if (!extension_sync_data.bookmark_app_url().empty()) |
| 280 ApplyBookmarkAppSyncData(extension_sync_data); | 283 ApplyBookmarkAppSyncData(extension_sync_data); |
| 281 } | 284 } |
| 282 | 285 |
| 283 if (!ApplyExtensionSyncDataHelper(extension_sync_data, type)) { | 286 if (!ApplyExtensionSyncDataHelper(extension_sync_data, type)) { |
| 284 bundle->AddPendingExtension(id, extension_sync_data); | 287 bundle->AddPendingExtension(id, extension_sync_data); |
| 285 extension_service_->CheckForUpdatesSoon(); | 288 extension_service_->CheckForUpdatesSoon(); |
| 286 return false; | 289 return false; |
| 287 } | 290 } |
| 288 | 291 |
| 289 return true; | 292 return true; |
| 290 } | 293 } |
| 291 | 294 |
| 292 void ExtensionSyncService::ApplyBookmarkAppSyncData( | 295 void ExtensionSyncService::ApplyBookmarkAppSyncData( |
| 293 const extensions::ExtensionSyncData& extension_sync_data) { | 296 const ExtensionSyncData& extension_sync_data) { |
| 294 DCHECK(extension_sync_data.is_app()); | 297 DCHECK(extension_sync_data.is_app()); |
| 295 | 298 |
| 296 // Process bookmark app sync if necessary. | 299 // Process bookmark app sync if necessary. |
| 297 GURL bookmark_app_url(extension_sync_data.bookmark_app_url()); | 300 GURL bookmark_app_url(extension_sync_data.bookmark_app_url()); |
| 298 if (!bookmark_app_url.is_valid() || | 301 if (!bookmark_app_url.is_valid() || |
| 299 extension_sync_data.uninstalled()) { | 302 extension_sync_data.uninstalled()) { |
| 300 return; | 303 return; |
| 301 } | 304 } |
| 302 | 305 |
| 303 const Extension* extension = | 306 const Extension* extension = |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 // non-INTERNAL location. Add to pending_sync_data, even though it will | 513 // non-INTERNAL location. Add to pending_sync_data, even though it will |
| 511 // never be removed (we'll never install a syncable version of the | 514 // never be removed (we'll never install a syncable version of the |
| 512 // extension), so that GetAllSyncData() continues to send it. | 515 // extension), so that GetAllSyncData() continues to send it. |
| 513 } | 516 } |
| 514 // Track pending extensions so that we can return them in GetAllSyncData(). | 517 // Track pending extensions so that we can return them in GetAllSyncData(). |
| 515 return false; | 518 return false; |
| 516 } | 519 } |
| 517 | 520 |
| 518 return true; | 521 return true; |
| 519 } | 522 } |
| OLD | NEW |