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 <iterator> | 7 #include <iterator> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 21 matching lines...) Expand all Loading... | |
32 #include "extensions/common/extension.h" | 32 #include "extensions/common/extension.h" |
33 #include "extensions/common/extension_icon_set.h" | 33 #include "extensions/common/extension_icon_set.h" |
34 #include "extensions/common/feature_switch.h" | 34 #include "extensions/common/feature_switch.h" |
35 #include "extensions/common/image_util.h" | 35 #include "extensions/common/image_util.h" |
36 #include "extensions/common/manifest_constants.h" | 36 #include "extensions/common/manifest_constants.h" |
37 #include "extensions/common/manifest_handlers/icons_handler.h" | 37 #include "extensions/common/manifest_handlers/icons_handler.h" |
38 #include "sync/api/sync_change.h" | 38 #include "sync/api/sync_change.h" |
39 #include "sync/api/sync_error_factory.h" | 39 #include "sync/api/sync_error_factory.h" |
40 #include "ui/gfx/image/image_family.h" | 40 #include "ui/gfx/image/image_family.h" |
41 | 41 |
42 #if defined(ENABLE_SUPERVISED_USERS) | |
43 #include "chrome/browser/supervised_user/supervised_user_service.h" | |
44 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" | |
45 #endif | |
46 | |
42 using extensions::AppSyncData; | 47 using extensions::AppSyncData; |
43 using extensions::Extension; | 48 using extensions::Extension; |
44 using extensions::ExtensionPrefs; | 49 using extensions::ExtensionPrefs; |
45 using extensions::ExtensionRegistry; | 50 using extensions::ExtensionRegistry; |
46 using extensions::ExtensionSyncData; | 51 using extensions::ExtensionSyncData; |
47 using extensions::FeatureSwitch; | 52 using extensions::FeatureSwitch; |
48 | 53 |
49 namespace { | 54 namespace { |
50 | 55 |
51 void OnWebApplicationInfoLoaded( | 56 void OnWebApplicationInfoLoaded( |
(...skipping 22 matching lines...) Expand all Loading... | |
74 return ExtensionSyncData::BOOLEAN_FALSE; | 79 return ExtensionSyncData::BOOLEAN_FALSE; |
75 | 80 |
76 // If the user has explicitly set a value, then we sync it. | 81 // If the user has explicitly set a value, then we sync it. |
77 if (extensions::util::HasSetAllowedScriptingOnAllUrls(extension_id, context)) | 82 if (extensions::util::HasSetAllowedScriptingOnAllUrls(extension_id, context)) |
78 return ExtensionSyncData::BOOLEAN_TRUE; | 83 return ExtensionSyncData::BOOLEAN_TRUE; |
79 | 84 |
80 // Otherwise, unset. | 85 // Otherwise, unset. |
81 return ExtensionSyncData::BOOLEAN_UNSET; | 86 return ExtensionSyncData::BOOLEAN_UNSET; |
82 } | 87 } |
83 | 88 |
89 #if defined(ENABLE_SUPERVISED_USERS) | |
90 // Callback for SupervisedUserService::AddExtensionUpdateRequest. | |
91 void ExtensionUpdateRequestSent(const std::string& id, bool success) { | |
92 LOG_IF(WARNING, !success) << "Failed sending update request for " << id; | |
93 } | |
94 #endif | |
95 | |
84 } // namespace | 96 } // namespace |
85 | 97 |
86 ExtensionSyncService::ExtensionSyncService(Profile* profile, | 98 ExtensionSyncService::ExtensionSyncService(Profile* profile, |
87 ExtensionPrefs* extension_prefs, | 99 ExtensionPrefs* extension_prefs, |
88 ExtensionService* extension_service) | 100 ExtensionService* extension_service) |
89 : profile_(profile), | 101 : profile_(profile), |
90 extension_prefs_(extension_prefs), | 102 extension_prefs_(extension_prefs), |
91 extension_service_(extension_service), | 103 extension_service_(extension_service), |
92 app_sync_bundle_(this), | 104 app_sync_bundle_(this), |
93 extension_sync_bundle_(this), | 105 extension_sync_bundle_(this), |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
472 bool ExtensionSyncService::IsPendingEnable( | 484 bool ExtensionSyncService::IsPendingEnable( |
473 const std::string& extension_id) const { | 485 const std::string& extension_id) const { |
474 return pending_app_enables_.Contains(extension_id) || | 486 return pending_app_enables_.Contains(extension_id) || |
475 pending_extension_enables_.Contains(extension_id); | 487 pending_extension_enables_.Contains(extension_id); |
476 } | 488 } |
477 | 489 |
478 bool ExtensionSyncService::ProcessExtensionSyncDataHelper( | 490 bool ExtensionSyncService::ProcessExtensionSyncDataHelper( |
479 const ExtensionSyncData& extension_sync_data, | 491 const ExtensionSyncData& extension_sync_data, |
480 syncer::ModelType type) { | 492 syncer::ModelType type) { |
481 const std::string& id = extension_sync_data.id(); | 493 const std::string& id = extension_sync_data.id(); |
482 const Extension* extension = extension_service_->GetInstalledExtension(id); | 494 const Extension* extension = extension_service_->GetInstalledExtension(id); |
not at google - send to devlin
2015/06/22 21:03:10
Can we save a reference to ExtensionRegistry (say
Marc Treib
2015/06/23 10:22:25
Sure, done.
| |
483 | 495 |
484 // TODO(bolms): we should really handle this better. The particularly bad | 496 // TODO(bolms): we should really handle this better. The particularly bad |
485 // case is where an app becomes an extension or vice versa, and we end up with | 497 // case is where an app becomes an extension or vice versa, and we end up with |
486 // a zombie extension that won't go away. | 498 // a zombie extension that won't go away. |
487 if (extension && !IsCorrectSyncType(*extension, type)) | 499 if (extension && !IsCorrectSyncType(*extension, type)) |
488 return true; | 500 return true; |
489 | 501 |
490 // Handle uninstalls first. | 502 // Handle uninstalls first. |
491 if (extension_sync_data.uninstalled()) { | 503 if (extension_sync_data.uninstalled()) { |
492 if (!extension_service_->UninstallExtensionHelper( | 504 if (!extension_service_->UninstallExtensionHelper( |
493 extension_service_, id, extensions::UNINSTALL_REASON_SYNC)) { | 505 extension_service_, id, extensions::UNINSTALL_REASON_SYNC)) { |
494 LOG(WARNING) << "Could not uninstall extension " << id << " for sync"; | 506 LOG(WARNING) << "Could not uninstall extension " << id << " for sync"; |
495 } | 507 } |
496 return true; | 508 return true; |
497 } | 509 } |
498 | 510 |
499 // Extension from sync was uninstalled by the user as external extensions. | 511 // Extension from sync was uninstalled by the user as external extensions. |
500 // Honor user choice and skip installation/enabling. | 512 // Honor user choice and skip installation/enabling. |
501 if (extensions::ExtensionPrefs::Get(profile_) | 513 if (extensions::ExtensionPrefs::Get(profile_) |
502 ->IsExternalExtensionUninstalled(id)) { | 514 ->IsExternalExtensionUninstalled(id)) { |
503 LOG(WARNING) << "Extension with id " << id | 515 LOG(WARNING) << "Extension with id " << id |
504 << " from sync was uninstalled as external extension"; | 516 << " from sync was uninstalled as external extension"; |
505 return true; | 517 return true; |
506 } | 518 } |
507 | 519 |
520 int version_compare_result = extension ? | |
521 extension->version()->CompareTo(extension_sync_data.version()) : 0; | |
522 | |
508 // Set user settings. | 523 // Set user settings. |
509 if (extension_sync_data.enabled()) { | 524 if (extension_sync_data.enabled()) { |
525 DCHECK(!extension_sync_data.disable_reasons()); | |
526 | |
527 #if defined(ENABLE_SUPERVISED_USERS) | |
528 if (extension && | |
529 extensions::util::IsExtensionSupervised(extension, profile_) && | |
530 !ExtensionRegistry::Get(profile_)->enabled_extensions().Contains(id)) { | |
531 if (version_compare_result < 0) { | |
532 // The installed version is outdated. Defer applying the change until | |
533 // it's up-to-date. | |
534 return false; | |
Marc Treib
2015/06/22 15:35:18
Actually, I think the same behavior should apply t
not at google - send to devlin
2015/06/22 21:03:10
I agree this isn't necessarily supervised-user spe
Marc Treib
2015/06/23 10:22:25
But the extension update could have arrived first,
not at google - send to devlin
2015/06/24 00:25:11
Ok, right. I think it only makes sense for supervi
Marc Treib
2015/06/24 11:50:57
I still think the same thing can happen for regula
not at google - send to devlin
2015/06/24 20:47:38
Nit: it's omaha not the webstore.
Also the situat
| |
535 } | |
536 if (version_compare_result > 0) { | |
537 // The installed version is newer than what Sync tells us to re-enable. | |
538 // This means another update has happened since the custodian approved | |
539 // the re-enable. We can't be sure if there are new permissions that the | |
540 // custodian hasn't seen, so ignore the re-enable. Instead send another | |
541 // re-enable request to the custodian. | |
not at google - send to devlin
2015/06/24 00:25:10
Is this actually necessary? I would have expected
Marc Treib
2015/06/24 11:50:57
Hm, I'd need to remove the "don't send duplicate p
not at google - send to devlin
2015/06/24 20:47:38
Mm I don't understand why you'd need to remove tha
Marc Treib
2015/06/29 09:52:49
Wait, rolling back extensions isn't possible anywa
not at google - send to devlin
2015/06/29 22:59:04
Yes, I just meant the case when an update from syn
Marc Treib
2015/06/30 08:32:37
I'm totally happy to do this for all users, and ha
| |
542 SupervisedUserService* supervised_user_service = | |
543 SupervisedUserServiceFactory::GetForProfile(profile_); | |
544 supervised_user_service->AddExtensionUpdateRequest( | |
545 id, *extension->version(), | |
546 base::Bind(ExtensionUpdateRequestSent, id)); | |
547 return true; | |
548 } | |
549 } | |
550 #endif | |
510 // Only grant permissions if the sync data explicitly sets the disable | 551 // Only grant permissions if the sync data explicitly sets the disable |
511 // reasons to Extension::DISABLE_NONE (as opposed to the legacy (<M45) case | 552 // reasons to Extension::DISABLE_NONE (as opposed to the legacy (<M45) case |
512 // where they're not set at all), and if the version from sync matches our | 553 // where they're not set at all), and if the version from sync matches our |
513 // local one. Otherwise we just enable it without granting permissions. If | 554 // local one. Otherwise we just enable it without granting permissions. If |
514 // any permissions are missing, CheckPermissionsIncrease will soon disable | 555 // any permissions are missing, CheckPermissionsIncrease will soon disable |
515 // it again. | 556 // it again. |
516 DCHECK(!extension_sync_data.disable_reasons()); | |
517 bool grant_permissions = | 557 bool grant_permissions = |
518 extension_sync_data.supports_disable_reasons() && | 558 extension_sync_data.supports_disable_reasons() && |
519 extension && | 559 extension && (version_compare_result == 0); |
520 extension->version()->Equals(extension_sync_data.version()); | |
521 if (grant_permissions) | 560 if (grant_permissions) |
522 extension_service_->GrantPermissionsAndEnableExtension(extension); | 561 extension_service_->GrantPermissionsAndEnableExtension(extension); |
523 else | 562 else |
524 extension_service_->EnableExtension(id); | 563 extension_service_->EnableExtension(id); |
525 } else if (!IsPendingEnable(id)) { | 564 } else if (!IsPendingEnable(id)) { |
526 int disable_reasons = extension_sync_data.disable_reasons(); | 565 int disable_reasons = extension_sync_data.disable_reasons(); |
527 if (extension_sync_data.remote_install()) { | 566 if (extension_sync_data.remote_install()) { |
528 if (!(disable_reasons & Extension::DISABLE_REMOTE_INSTALL)) { | 567 if (!(disable_reasons & Extension::DISABLE_REMOTE_INSTALL)) { |
529 // In the non-legacy case (>=M45) where disable reasons are synced at | 568 // In the non-legacy case (>=M45) where disable reasons are synced at |
530 // all, DISABLE_REMOTE_INSTALL should be among them already. | 569 // all, DISABLE_REMOTE_INSTALL should be among them already. |
531 DCHECK(!extension_sync_data.supports_disable_reasons()); | 570 DCHECK(!extension_sync_data.supports_disable_reasons()); |
532 disable_reasons |= Extension::DISABLE_REMOTE_INSTALL; | 571 disable_reasons |= Extension::DISABLE_REMOTE_INSTALL; |
533 } | 572 } |
534 } else if (!extension_sync_data.supports_disable_reasons()) { | 573 } else if (!extension_sync_data.supports_disable_reasons()) { |
535 // Legacy case (<M45), from before we synced disable reasons (see | 574 // Legacy case (<M45), from before we synced disable reasons (see |
536 // crbug.com/484214). | 575 // crbug.com/484214). |
537 disable_reasons = Extension::DISABLE_UNKNOWN_FROM_SYNC; | 576 disable_reasons = Extension::DISABLE_UNKNOWN_FROM_SYNC; |
538 } | 577 } |
539 | 578 |
540 // In the non-legacy case (>=M45), clear any existing disable reasons first. | 579 // In the non-legacy case (>=M45), clear any existing disable reasons first. |
541 // Otherwise sync can't remove just some of them. | 580 // Otherwise sync can't remove just some of them. |
542 if (extension_sync_data.supports_disable_reasons()) | 581 if (extension_sync_data.supports_disable_reasons()) |
543 extensions::ExtensionPrefs::Get(profile_)->ClearDisableReasons(id); | 582 extensions::ExtensionPrefs::Get(profile_)->ClearDisableReasons(id); |
544 | 583 |
545 extension_service_->DisableExtension(id, disable_reasons); | 584 extension_service_->DisableExtension(id, disable_reasons); |
546 } | 585 } |
547 | 586 |
548 // We need to cache some version information here because setting the | 587 // We need to cache some information here because setting the incognito flag |
549 // incognito flag invalidates the |extension| pointer (it reloads the | 588 // invalidates the |extension| pointer (it reloads the extension). |
550 // extension). | |
551 bool extension_installed = (extension != NULL); | 589 bool extension_installed = (extension != NULL); |
552 int version_compare_result = extension ? | |
553 extension->version()->CompareTo(extension_sync_data.version()) : 0; | |
554 | 590 |
555 // If the target extension has already been installed ephemerally, it can | 591 // If the target extension has already been installed ephemerally, it can |
556 // be promoted to a regular installed extension and downloading from the Web | 592 // be promoted to a regular installed extension and downloading from the Web |
557 // Store is not necessary. | 593 // Store is not necessary. |
558 if (extension && extensions::util::IsEphemeralApp(id, profile_)) | 594 if (extension && extensions::util::IsEphemeralApp(id, profile_)) |
559 extension_service_->PromoteEphemeralApp(extension, true); | 595 extension_service_->PromoteEphemeralApp(extension, true); |
560 | 596 |
561 // Update the incognito flag. | 597 // Update the incognito flag. |
562 extensions::util::SetIsIncognitoEnabled( | 598 extensions::util::SetIsIncognitoEnabled( |
563 id, profile_, extension_sync_data.incognito_enabled()); | 599 id, profile_, extension_sync_data.incognito_enabled()); |
564 extension = NULL; // No longer safe to use. | 600 extension = NULL; // No longer safe to use. |
565 | 601 |
566 // Update the all urls flag. | 602 // Update the all urls flag. |
567 if (extension_sync_data.all_urls_enabled() != | 603 if (extension_sync_data.all_urls_enabled() != |
568 ExtensionSyncData::BOOLEAN_UNSET) { | 604 ExtensionSyncData::BOOLEAN_UNSET) { |
569 bool allowed = extension_sync_data.all_urls_enabled() == | 605 bool allowed = extension_sync_data.all_urls_enabled() == |
570 ExtensionSyncData::BOOLEAN_TRUE; | 606 ExtensionSyncData::BOOLEAN_TRUE; |
571 extensions::util::SetAllowedScriptingOnAllUrls(id, profile_, allowed); | 607 extensions::util::SetAllowedScriptingOnAllUrls(id, profile_, allowed); |
572 } | 608 } |
573 | 609 |
574 if (extension_installed) { | 610 if (extension_installed) { |
575 // If the extension is already installed, check if it's outdated. | 611 // If the extension is already installed, check if it's outdated. |
576 if (version_compare_result < 0) { | 612 if (version_compare_result < 0) { |
577 // Extension is outdated. | 613 // Extension is outdated. |
578 return false; | 614 return false; |
Marc Treib
2015/06/22 15:35:18
This is a bit weird: Returning "false" here causes
not at google - send to devlin
2015/06/22 21:03:10
Bleh. This is too complicated.
Marc Treib
2015/06/23 10:22:25
No argument here...
| |
579 } | 615 } |
580 } else { | 616 } else { |
581 CHECK(type == syncer::EXTENSIONS || type == syncer::APPS); | 617 CHECK(type == syncer::EXTENSIONS || type == syncer::APPS); |
582 extensions::PendingExtensionInfo::ShouldAllowInstallPredicate filter = | 618 extensions::PendingExtensionInfo::ShouldAllowInstallPredicate filter = |
583 (type == syncer::APPS) ? extensions::sync_helper::IsSyncableApp : | 619 (type == syncer::APPS) ? extensions::sync_helper::IsSyncableApp : |
584 extensions::sync_helper::IsSyncableExtension; | 620 extensions::sync_helper::IsSyncableExtension; |
585 | 621 |
586 if (!extension_service_->pending_extension_manager()->AddFromSync( | 622 if (!extension_service_->pending_extension_manager()->AddFromSync( |
587 id, | 623 id, |
588 extension_sync_data.update_url(), | 624 extension_sync_data.update_url(), |
(...skipping 20 matching lines...) Expand all Loading... | |
609 app_sync_bundle_.SyncChangeIfNeeded(extension); | 645 app_sync_bundle_.SyncChangeIfNeeded(extension); |
610 else if (extension_service_->is_ready() && !flare_.is_null()) | 646 else if (extension_service_->is_ready() && !flare_.is_null()) |
611 flare_.Run(syncer::APPS); | 647 flare_.Run(syncer::APPS); |
612 } else if (extensions::util::ShouldSyncExtension(&extension, profile_)) { | 648 } else if (extensions::util::ShouldSyncExtension(&extension, profile_)) { |
613 if (extension_sync_bundle_.IsSyncing()) | 649 if (extension_sync_bundle_.IsSyncing()) |
614 extension_sync_bundle_.SyncChangeIfNeeded(extension); | 650 extension_sync_bundle_.SyncChangeIfNeeded(extension); |
615 else if (extension_service_->is_ready() && !flare_.is_null()) | 651 else if (extension_service_->is_ready() && !flare_.is_null()) |
616 flare_.Run(syncer::EXTENSIONS); | 652 flare_.Run(syncer::EXTENSIONS); |
617 } | 653 } |
618 } | 654 } |
OLD | NEW |