Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Side by Side Diff: chrome/browser/extensions/extension_sync_service.cc

Issue 1200833004: Apps&Extensions for Supervised Users: send permission request on outdated re-enables (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698