summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortreib <treib@chromium.org>2015-05-20 05:56:07 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-20 12:56:03 +0000
commitc11923254ee7e930b2cd3431d94a6937982906f9 (patch)
tree8f36f6fc40434cbdb109cf78a53a41d3638eeacb
parentef99191240af78a81c19f34cf39c5097208246b7 (diff)
downloadchromium_src-c11923254ee7e930b2cd3431d94a6937982906f9.zip
chromium_src-c11923254ee7e930b2cd3431d94a6937982906f9.tar.gz
chromium_src-c11923254ee7e930b2cd3431d94a6937982906f9.tar.bz2
Extensions: Store disable reasons in Sync
This will allow us (in a follow-up CL) to *not* grant permissions to extensions that come in via Sync disabled due to a permission increase. BUG=484214 Review URL: https://codereview.chromium.org/1136543003 Cr-Commit-Position: refs/heads/master@{#330727}
-rw-r--r--chrome/browser/apps/ephemeral_app_browsertest.cc2
-rw-r--r--chrome/browser/extensions/app_sync_data.cc2
-rw-r--r--chrome/browser/extensions/app_sync_data.h1
-rw-r--r--chrome/browser/extensions/app_sync_data_unittest.cc1
-rw-r--r--chrome/browser/extensions/extension_service.cc13
-rw-r--r--chrome/browser/extensions/extension_service.h11
-rw-r--r--chrome/browser/extensions/extension_service_unittest.cc112
-rw-r--r--chrome/browser/extensions/extension_sync_data.cc5
-rw-r--r--chrome/browser/extensions/extension_sync_data.h5
-rw-r--r--chrome/browser/extensions/extension_sync_service.cc21
-rw-r--r--chrome/browser/sync/test/integration/sync_extension_helper.cc38
-rw-r--r--chrome/browser/sync/test/integration/sync_extension_helper.h1
-rw-r--r--chrome/browser/sync/test/integration/two_client_apps_sync_test.cc1
-rw-r--r--extensions/browser/extension_prefs.cc56
-rw-r--r--extensions/browser/extension_prefs.h53
-rw-r--r--sync/protocol/extension_specifics.proto5
-rw-r--r--sync/protocol/proto_value_conversions.cc3
17 files changed, 241 insertions, 89 deletions
diff --git a/chrome/browser/apps/ephemeral_app_browsertest.cc b/chrome/browser/apps/ephemeral_app_browsertest.cc
index 2804632..07e01b5 100644
--- a/chrome/browser/apps/ephemeral_app_browsertest.cc
+++ b/chrome/browser/apps/ephemeral_app_browsertest.cc
@@ -483,10 +483,12 @@ class EphemeralAppBrowserTest : public EphemeralAppTestBase {
ASSERT_TRUE(app);
// Simulate an install from sync.
+ int disable_reasons = enable_from_sync ? 0 : Extension::DISABLE_USER_ACTION;
const syncer::StringOrdinal kAppLaunchOrdinal("x");
const syncer::StringOrdinal kPageOrdinal("y");
AppSyncData app_sync_data(*app,
enable_from_sync,
+ disable_reasons,
false /* incognito enabled */,
false /* remote install */,
extensions::ExtensionSyncData::BOOLEAN_UNSET,
diff --git a/chrome/browser/extensions/app_sync_data.cc b/chrome/browser/extensions/app_sync_data.cc
index d49eb4e..6f231ba 100644
--- a/chrome/browser/extensions/app_sync_data.cc
+++ b/chrome/browser/extensions/app_sync_data.cc
@@ -24,6 +24,7 @@ AppSyncData::AppSyncData() {}
AppSyncData::AppSyncData(const Extension& extension,
bool enabled,
+ int disable_reasons,
bool incognito_enabled,
bool remote_install,
ExtensionSyncData::OptionalBoolean all_urls_enabled,
@@ -32,6 +33,7 @@ AppSyncData::AppSyncData(const Extension& extension,
extensions::LaunchType launch_type)
: extension_sync_data_(extension,
enabled,
+ disable_reasons,
incognito_enabled,
remote_install,
all_urls_enabled),
diff --git a/chrome/browser/extensions/app_sync_data.h b/chrome/browser/extensions/app_sync_data.h
index bbb8123..4d19060 100644
--- a/chrome/browser/extensions/app_sync_data.h
+++ b/chrome/browser/extensions/app_sync_data.h
@@ -39,6 +39,7 @@ class AppSyncData {
AppSyncData();
AppSyncData(const Extension& extension,
bool enabled,
+ int disable_reasons,
bool incognito_enabled,
bool remote_install,
ExtensionSyncData::OptionalBoolean all_urls_enabled,
diff --git a/chrome/browser/extensions/app_sync_data_unittest.cc b/chrome/browser/extensions/app_sync_data_unittest.cc
index 5b90621..ca4e7ef 100644
--- a/chrome/browser/extensions/app_sync_data_unittest.cc
+++ b/chrome/browser/extensions/app_sync_data_unittest.cc
@@ -27,6 +27,7 @@ class AppSyncDataTest : public testing::Test {
extension_specifics->set_update_url(kValidUpdateUrl);
extension_specifics->set_version(kValidVersion);
extension_specifics->set_enabled(false);
+ extension_specifics->set_disable_reasons(0);
extension_specifics->set_incognito_enabled(true);
extension_specifics->set_remote_install(false);
extension_specifics->set_all_urls_enabled(true);
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index c18d612..c066fd0 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -867,14 +867,13 @@ void ExtensionService::EnableExtension(const std::string& extension_id) {
extension_sync_service_->SyncEnableExtension(*extension);
}
-void ExtensionService::DisableExtension(
- const std::string& extension_id,
- Extension::DisableReason disable_reason) {
+void ExtensionService::DisableExtension(const std::string& extension_id,
+ int disable_reasons) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// The extension may have been disabled already. Just add a disable reason.
if (!IsExtensionEnabled(extension_id)) {
- extension_prefs_->AddDisableReason(extension_id, disable_reason);
+ extension_prefs_->AddDisableReasons(extension_id, disable_reasons);
return;
}
@@ -885,15 +884,15 @@ void ExtensionService::DisableExtension(
// can be uninstalled by the browser if the user sets extension-specific
// preferences.
if (extension &&
- disable_reason != Extension::DISABLE_RELOAD &&
- disable_reason != Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY &&
+ !(disable_reasons & Extension::DISABLE_RELOAD) &&
+ !(disable_reasons & Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY) &&
!system_->management_policy()->UserMayModifySettings(extension, NULL) &&
extension->location() != Manifest::EXTERNAL_COMPONENT) {
return;
}
extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED);
- extension_prefs_->AddDisableReason(extension_id, disable_reason);
+ extension_prefs_->AddDisableReasons(extension_id, disable_reasons);
int include_mask =
ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::DISABLED;
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 04d0f4e..0b97b1a 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -279,11 +279,12 @@ class ExtensionService
// nothing.
virtual void EnableExtension(const std::string& extension_id);
- // Disables the extension. If the extension is already disabled, or
- // cannot be disabled, does nothing.
- virtual void DisableExtension(
- const std::string& extension_id,
- extensions::Extension::DisableReason disable_reason);
+ // Disables the extension. If the extension is already disabled, just adds
+ // the |disable_reasons| (a bitmask of Extension::DisableReason - there can
+ // be multiple DisableReasons e.g. when an extension comes in disabled from
+ // Sync). If the extension cannot be disabled (due to policy), does nothing.
+ virtual void DisableExtension(const std::string& extension_id,
+ int disable_reasons);
// Disable non-default and non-managed extensions with ids not in
// |except_ids|. Default extensions are those from the Web Store with
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 308af80..7d8042d 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -924,12 +924,17 @@ class ExtensionServiceTest : public extensions::ExtensionServiceTestBase,
}
void UninstallExtension(const std::string& id, bool use_helper) {
+ UninstallExtension(id, use_helper, Extension::ENABLED);
+ }
+
+ void UninstallExtension(const std::string& id, bool use_helper,
+ Extension::State expected_state) {
// Verify that the extension is installed.
base::FilePath extension_path = extensions_install_dir().AppendASCII(id);
EXPECT_TRUE(base::PathExists(extension_path));
size_t pref_key_count = GetPrefKeyCount();
EXPECT_GT(pref_key_count, 0u);
- ValidateIntegerPref(id, "state", Extension::ENABLED);
+ ValidateIntegerPref(id, "state", expected_state);
// Uninstall it.
if (use_helper) {
@@ -5909,10 +5914,11 @@ TEST_F(ExtensionServiceTest, DisableExtensionFromSync) {
const Extension* extension = service()->GetExtensionById(good0, true);
ASSERT_TRUE(extension);
ASSERT_TRUE(service()->IsExtensionEnabled(good0));
- ExtensionSyncData disable_good_crx(*extension, false, false, false,
- ExtensionSyncData::BOOLEAN_UNSET);
// Then sync data arrives telling us to disable |good0|.
+ ExtensionSyncData disable_good_crx(*extension, false,
+ Extension::DISABLE_USER_ACTION, false,
+ false, ExtensionSyncData::BOOLEAN_UNSET);
syncer::SyncDataList sync_data;
sync_data.push_back(disable_good_crx.GetSyncData());
extension_sync_service()->MergeDataAndStartSyncing(
@@ -5956,8 +5962,9 @@ TEST_F(ExtensionServiceTest, DontDisableExtensionWithPendingEnableFromSync) {
// Now sync data comes in that says to disable good0. This should be
// ignored.
- ExtensionSyncData disable_good_crx(*extension, false, false, false,
- ExtensionSyncData::BOOLEAN_FALSE);
+ ExtensionSyncData disable_good_crx(*extension, false,
+ Extension::DISABLE_USER_ACTION, false,
+ false, ExtensionSyncData::BOOLEAN_UNSET);
syncer::SyncDataList sync_data;
sync_data.push_back(disable_good_crx.GetSyncData());
extension_sync_service()->MergeDataAndStartSyncing(
@@ -6514,6 +6521,101 @@ TEST_F(ExtensionServiceTest, ProcessSyncDataSettings) {
EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
}
+TEST_F(ExtensionServiceTest, ProcessSyncDataNewExtension) {
+ InitializeEmptyExtensionService();
+ InitializeExtensionSyncService();
+ syncer::FakeSyncChangeProcessor processor;
+ extension_sync_service()->MergeDataAndStartSyncing(
+ syncer::EXTENSIONS,
+ syncer::SyncDataList(),
+ scoped_ptr<syncer::SyncChangeProcessor>(
+ new syncer::FakeSyncChangeProcessor),
+ scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
+ ext_specifics->set_id(good_crx);
+ ext_specifics->set_version(base::Version("1").GetString());
+
+ const base::FilePath path = data_dir().AppendASCII("good.crx");
+ const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+
+ {
+ ext_specifics->set_enabled(true);
+ ext_specifics->set_disable_reasons(0);
+
+ syncer::SyncData sync_data =
+ syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
+ syncer::SyncChange sync_change(FROM_HERE,
+ syncer::SyncChange::ACTION_UPDATE,
+ sync_data);
+ syncer::SyncChangeList list(1);
+ list[0] = sync_change;
+ extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
+
+ ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
+ UpdateExtension(good_crx, path, ENABLED);
+ EXPECT_EQ(0, prefs->GetDisableReasons(good_crx));
+ // Permissions should have been granted during installation.
+ scoped_refptr<PermissionSet> permissions(
+ prefs->GetGrantedPermissions(good_crx));
+ EXPECT_FALSE(permissions->IsEmpty());
+ ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
+ }
+ UninstallExtension(good_crx, false);
+ {
+ ext_specifics->set_enabled(false);
+ ext_specifics->set_disable_reasons(Extension::DISABLE_USER_ACTION);
+
+ syncer::SyncData sync_data =
+ syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
+ syncer::SyncChange sync_change(FROM_HERE,
+ syncer::SyncChange::ACTION_UPDATE,
+ sync_data);
+ syncer::SyncChangeList list(1);
+ list[0] = sync_change;
+ extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
+
+ ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
+ UpdateExtension(good_crx, path, DISABLED);
+ EXPECT_EQ(Extension::DISABLE_USER_ACTION,
+ prefs->GetDisableReasons(good_crx));
+ // Even if the extension came in disabled, its permissions should have been
+ // granted (the user already approved them on another machine).
+ scoped_refptr<PermissionSet> permissions(
+ prefs->GetGrantedPermissions(good_crx));
+ EXPECT_FALSE(permissions->IsEmpty());
+ ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
+ }
+ UninstallExtension(good_crx, false, Extension::DISABLED);
+ {
+ ext_specifics->set_enabled(false);
+ // Legacy case (<M45): No disable reasons come in from Sync (see
+ // crbug.com/484214). After installation, the reason should be set to
+ // DISABLE_UNKNOWN_FROM_SYNC.
+ ext_specifics->set_disable_reasons(0);
+
+ syncer::SyncData sync_data =
+ syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
+ syncer::SyncChange sync_change(FROM_HERE,
+ syncer::SyncChange::ACTION_UPDATE,
+ sync_data);
+ syncer::SyncChangeList list(1);
+ list[0] = sync_change;
+ extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
+
+ ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
+ UpdateExtension(good_crx, path, DISABLED);
+ EXPECT_EQ(Extension::DISABLE_UNKNOWN_FROM_SYNC,
+ prefs->GetDisableReasons(good_crx));
+ scoped_refptr<PermissionSet> permissions(
+ prefs->GetGrantedPermissions(good_crx));
+ EXPECT_FALSE(permissions->IsEmpty());
+ ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
+ }
+ UninstallExtension(good_crx, false, Extension::DISABLED);
+}
+
TEST_F(ExtensionServiceTest, ProcessSyncDataTerminatedExtension) {
InitializeExtensionServiceWithUpdater();
InitializeExtensionSyncService();
diff --git a/chrome/browser/extensions/extension_sync_data.cc b/chrome/browser/extensions/extension_sync_data.cc
index aa56051..6914bc1 100644
--- a/chrome/browser/extensions/extension_sync_data.cc
+++ b/chrome/browser/extensions/extension_sync_data.cc
@@ -55,6 +55,7 @@ void RecordBadSyncData(BadSyncDataReason reason) {
ExtensionSyncData::ExtensionSyncData()
: uninstalled_(false),
enabled_(false),
+ disable_reasons_(Extension::DISABLE_NONE),
incognito_enabled_(false),
remote_install_(false),
all_urls_enabled_(BOOLEAN_UNSET),
@@ -63,12 +64,14 @@ ExtensionSyncData::ExtensionSyncData()
ExtensionSyncData::ExtensionSyncData(const Extension& extension,
bool enabled,
+ int disable_reasons,
bool incognito_enabled,
bool remote_install,
OptionalBoolean all_urls_enabled)
: id_(extension.id()),
uninstalled_(false),
enabled_(enabled),
+ disable_reasons_(disable_reasons),
incognito_enabled_(incognito_enabled),
remote_install_(remote_install),
all_urls_enabled_(all_urls_enabled),
@@ -122,6 +125,7 @@ void ExtensionSyncData::PopulateExtensionSpecifics(
specifics->set_update_url(update_url_.spec());
specifics->set_version(version_.GetString());
specifics->set_enabled(enabled_);
+ specifics->set_disable_reasons(disable_reasons_);
specifics->set_incognito_enabled(incognito_enabled_);
specifics->set_remote_install(remote_install_);
if (all_urls_enabled_ != BOOLEAN_UNSET)
@@ -160,6 +164,7 @@ bool ExtensionSyncData::PopulateFromExtensionSpecifics(
update_url_ = specifics_update_url;
version_ = specifics_version;
enabled_ = specifics.enabled();
+ disable_reasons_ = specifics.disable_reasons();
incognito_enabled_ = specifics.incognito_enabled();
if (specifics.has_all_urls_enabled()) {
all_urls_enabled_ =
diff --git a/chrome/browser/extensions/extension_sync_data.h b/chrome/browser/extensions/extension_sync_data.h
index 5808b6b..5a94eab 100644
--- a/chrome/browser/extensions/extension_sync_data.h
+++ b/chrome/browser/extensions/extension_sync_data.h
@@ -36,6 +36,7 @@ class ExtensionSyncData {
ExtensionSyncData();
ExtensionSyncData(const Extension& extension,
bool enabled,
+ int disable_reasons,
bool incognito_enabled,
bool remote_install,
OptionalBoolean all_urls_enabled);
@@ -69,13 +70,14 @@ class ExtensionSyncData {
// |version|).
bool uninstalled() const { return uninstalled_; }
bool enabled() const { return enabled_; }
+ int disable_reasons() const { return disable_reasons_; }
bool incognito_enabled() const { return incognito_enabled_; }
bool remote_install() const { return remote_install_; }
OptionalBoolean all_urls_enabled() const { return all_urls_enabled_; }
bool installed_by_custodian() const { return installed_by_custodian_; }
// Version-dependent properties (i.e., should be used only when the
- // version of the currenty-installed extension matches |version|).
+ // version of the currently-installed extension matches |version|).
const Version& version() const { return version_; }
const GURL& update_url() const { return update_url_; }
// Used only for debugging.
@@ -88,6 +90,7 @@ class ExtensionSyncData {
std::string id_;
bool uninstalled_;
bool enabled_;
+ int disable_reasons_;
bool incognito_enabled_;
bool remote_install_;
OptionalBoolean all_urls_enabled_;
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc
index 9a8fddb..12769c6 100644
--- a/chrome/browser/extensions/extension_sync_service.cc
+++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -283,6 +283,7 @@ ExtensionSyncData ExtensionSyncService::GetExtensionSyncData(
return ExtensionSyncData(
extension,
extension_service_->IsExtensionEnabled(extension.id()),
+ extension_prefs_->GetDisableReasons(extension.id()),
extensions::util::IsIncognitoEnabled(extension.id(), profile_),
extension_prefs_->HasDisableReason(extension.id(),
Extension::DISABLE_REMOTE_INSTALL),
@@ -293,6 +294,7 @@ AppSyncData ExtensionSyncService::GetAppSyncData(
const Extension& extension) const {
return AppSyncData(
extension, extension_service_->IsExtensionEnabled(extension.id()),
+ extension_prefs_->GetDisableReasons(extension.id()),
extensions::util::IsIncognitoEnabled(extension.id(), profile_),
extension_prefs_->HasDisableReason(extension.id(),
Extension::DISABLE_REMOTE_INSTALL),
@@ -516,13 +518,22 @@ bool ExtensionSyncService::ProcessExtensionSyncDataHelper(
if (extension_sync_data.enabled()) {
extension_service_->EnableExtension(id);
} else if (!IsPendingEnable(id)) {
+ int disable_reasons = extension_sync_data.disable_reasons();
if (extension_sync_data.remote_install()) {
- extension_service_->DisableExtension(id,
- Extension::DISABLE_REMOTE_INSTALL);
- } else {
- extension_service_->DisableExtension(
- id, Extension::DISABLE_UNKNOWN_FROM_SYNC);
+ // In the non-legacy case (>=M45) where disable reasons are synced at all,
+ // DISABLE_REMOTE_INSTALL should be among them already.
+ DCHECK(!disable_reasons ||
+ (disable_reasons & Extension::DISABLE_REMOTE_INSTALL));
+ disable_reasons |= Extension::DISABLE_REMOTE_INSTALL;
}
+ if (!disable_reasons) {
+ // Legacy case (<M45), from before we synced disable reasons (see
+ // crbug.com/484214).
+ disable_reasons = Extension::DISABLE_UNKNOWN_FROM_SYNC;
+ }
+
+ extension_service_->DisableExtension(
+ id, Extension::DisableReason(disable_reasons));
}
// We need to cache some version information here because setting the
diff --git a/chrome/browser/sync/test/integration/sync_extension_helper.cc b/chrome/browser/sync/test/integration/sync_extension_helper.cc
index a041671..d51c5a9 100644
--- a/chrome/browser/sync/test/integration/sync_extension_helper.cc
+++ b/chrome/browser/sync/test/integration/sync_extension_helper.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "components/crx_file/id_util.h"
+#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/install_flag.h"
@@ -27,17 +28,19 @@
#include "testing/gtest/include/gtest/gtest.h"
using extensions::Extension;
+using extensions::ExtensionPrefs;
using extensions::ExtensionRegistry;
using extensions::Manifest;
SyncExtensionHelper::ExtensionState::ExtensionState()
- : enabled_state(ENABLED), incognito_enabled(false) {}
+ : enabled_state(ENABLED), disable_reasons(0), incognito_enabled(false) {}
SyncExtensionHelper::ExtensionState::~ExtensionState() {}
bool SyncExtensionHelper::ExtensionState::Equals(
const SyncExtensionHelper::ExtensionState &other) const {
return ((enabled_state == other.enabled_state) &&
+ (disable_reasons == other.disable_reasons) &&
(incognito_enabled == other.incognito_enabled));
}
@@ -205,20 +208,21 @@ SyncExtensionHelper::ExtensionStateMap
ExtensionService* extension_service =
extensions::ExtensionSystem::Get(profile)->extension_service();
- for (extensions::ExtensionSet::const_iterator it = extensions->begin();
- it != extensions->end(); ++it) {
- const std::string& id = (*it)->id();
- extension_state_map[id].enabled_state =
+ for (const scoped_refptr<const Extension>& extension : *extensions) {
+ const std::string& id = extension->id();
+ ExtensionState& extension_state = extension_state_map[id];
+ extension_state.enabled_state =
extension_service->IsExtensionEnabled(id) ?
ExtensionState::ENABLED :
ExtensionState::DISABLED;
- extension_state_map[id].incognito_enabled =
+ extension_state.disable_reasons =
+ ExtensionPrefs::Get(profile)->GetDisableReasons(id);
+ extension_state.incognito_enabled =
extensions::util::IsIncognitoEnabled(id, profile);
- DVLOG(2) << "Extension " << (*it)->id() << " in profile "
- << profile_debug_name << " is "
- << (extension_service->IsExtensionEnabled(id) ?
- "enabled" : "disabled");
+ DVLOG(2) << "Extension " << id << " in profile " << profile_debug_name
+ << " is " << (extension_service->IsExtensionEnabled(id) ?
+ "enabled" : "disabled");
}
const extensions::PendingExtensionManager* pending_extension_manager =
@@ -227,12 +231,14 @@ SyncExtensionHelper::ExtensionStateMap
std::list<std::string> pending_crx_ids;
pending_extension_manager->GetPendingIdsForUpdateCheck(&pending_crx_ids);
- std::list<std::string>::const_iterator id;
- for (id = pending_crx_ids.begin(); id != pending_crx_ids.end(); ++id) {
- extension_state_map[*id].enabled_state = ExtensionState::PENDING;
- extension_state_map[*id].incognito_enabled =
- extensions::util::IsIncognitoEnabled(*id, profile);
- DVLOG(2) << "Extension " << *id << " in profile "
+ for (const std::string& id : pending_crx_ids) {
+ ExtensionState& extension_state = extension_state_map[id];
+ extension_state.enabled_state = ExtensionState::PENDING;
+ extension_state.disable_reasons =
+ ExtensionPrefs::Get(profile)->GetDisableReasons(id);
+ extension_state.incognito_enabled =
+ extensions::util::IsIncognitoEnabled(id, profile);
+ DVLOG(2) << "Extension " << id << " in profile "
<< profile_debug_name << " is pending";
}
diff --git a/chrome/browser/sync/test/integration/sync_extension_helper.h b/chrome/browser/sync/test/integration/sync_extension_helper.h
index 06bf60a..c81977d 100644
--- a/chrome/browser/sync/test/integration/sync_extension_helper.h
+++ b/chrome/browser/sync/test/integration/sync_extension_helper.h
@@ -83,6 +83,7 @@ class SyncExtensionHelper {
bool Equals(const ExtensionState &other) const;
EnabledState enabled_state;
+ int disable_reasons;
bool incognito_enabled;
};
diff --git a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
index 19f360d..4989ae2 100644
--- a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
@@ -409,6 +409,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, UnexpectedLaunchType) {
extensions::AppSyncData invalid_launch_type_data(
*extension,
original_data.extension_sync_data().enabled(),
+ original_data.extension_sync_data().disable_reasons(),
original_data.extension_sync_data().incognito_enabled(),
original_data.extension_sync_data().remote_install(),
original_data.extension_sync_data().all_urls_enabled(),
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index 99955f4..460e0de 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -539,7 +539,7 @@ bool ExtensionPrefs::HasPrefForExtension(
bool ExtensionPrefs::ReadPrefAsURLPatternSet(const std::string& extension_id,
const std::string& pref_key,
URLPatternSet* result,
- int valid_schemes) {
+ int valid_schemes) const {
const base::ListValue* value = NULL;
if (!ReadPrefAsList(extension_id, pref_key, &value))
return false;
@@ -572,7 +572,7 @@ bool ExtensionPrefs::ReadPrefAsBooleanAndReturn(
PermissionSet* ExtensionPrefs::ReadPrefAsPermissionSet(
const std::string& extension_id,
- const std::string& pref_key) {
+ const std::string& pref_key) const {
if (!GetExtensionPref(extension_id))
return NULL;
@@ -682,7 +682,7 @@ int ExtensionPrefs::IncrementAcknowledgePromptCount(
}
bool ExtensionPrefs::IsExternalExtensionAcknowledged(
- const std::string& extension_id) {
+ const std::string& extension_id) const {
return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalAcknowledged);
}
@@ -695,7 +695,7 @@ void ExtensionPrefs::AcknowledgeExternalExtension(
}
bool ExtensionPrefs::IsBlacklistedExtensionAcknowledged(
- const std::string& extension_id) {
+ const std::string& extension_id) const {
return ReadPrefAsBooleanAndReturn(extension_id, kPrefBlacklistAcknowledged);
}
@@ -708,7 +708,7 @@ void ExtensionPrefs::AcknowledgeBlacklistedExtension(
}
bool ExtensionPrefs::IsExternalInstallFirstRun(
- const std::string& extension_id) {
+ const std::string& extension_id) const {
return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalInstallFirstRun);
}
@@ -728,7 +728,7 @@ bool ExtensionPrefs::SetAlertSystemFirstRun() {
}
bool ExtensionPrefs::DidExtensionEscalatePermissions(
- const std::string& extension_id) {
+ const std::string& extension_id) const {
return ReadPrefAsBooleanAndReturn(extension_id,
kExtensionDidEscalatePermissions);
}
@@ -759,6 +759,11 @@ void ExtensionPrefs::AddDisableReason(const std::string& extension_id,
ModifyDisableReasons(extension_id, disable_reason, DISABLE_REASON_ADD);
}
+void ExtensionPrefs::AddDisableReasons(const std::string& extension_id,
+ int disable_reasons) {
+ ModifyDisableReasons(extension_id, disable_reasons, DISABLE_REASON_ADD);
+}
+
void ExtensionPrefs::RemoveDisableReason(
const std::string& extension_id,
Extension::DisableReason disable_reason) {
@@ -803,7 +808,7 @@ void ExtensionPrefs::ModifyDisableReasons(const std::string& extension_id,
OnExtensionDisableReasonsChanged(extension_id, new_value));
}
-std::set<std::string> ExtensionPrefs::GetBlacklistedExtensions() {
+std::set<std::string> ExtensionPrefs::GetBlacklistedExtensions() const {
std::set<std::string> ids;
const base::DictionaryValue* extensions =
@@ -921,7 +926,8 @@ void ExtensionPrefs::SetBlacklistLastPingDay(const base::Time& time) {
SaveTime(update.Get(), kLastPingDay, time);
}
-base::Time ExtensionPrefs::LastActivePingDay(const std::string& extension_id) {
+base::Time ExtensionPrefs::LastActivePingDay(
+ const std::string& extension_id) const {
DCHECK(crx_file::id_util::IdIsValid(extension_id));
return ReadTime(GetExtensionPref(extension_id), kLastActivePingDay);
}
@@ -933,7 +939,7 @@ void ExtensionPrefs::SetLastActivePingDay(const std::string& extension_id,
SaveTime(update.Get(), kLastActivePingDay, time);
}
-bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) {
+bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) const {
const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
bool result = false;
if (dictionary && dictionary->GetBoolean(kActiveBit, &result))
@@ -1026,7 +1032,7 @@ void ExtensionPrefs::MigrateDisableReasons(
}
PermissionSet* ExtensionPrefs::GetGrantedPermissions(
- const std::string& extension_id) {
+ const std::string& extension_id) const {
CHECK(crx_file::id_util::IdIsValid(extension_id));
return ReadPrefAsPermissionSet(extension_id, kPrefGrantedPermissions);
}
@@ -1068,7 +1074,7 @@ void ExtensionPrefs::RemoveGrantedPermissions(
}
PermissionSet* ExtensionPrefs::GetActivePermissions(
- const std::string& extension_id) {
+ const std::string& extension_id) const {
CHECK(crx_file::id_util::IdIsValid(extension_id));
return ReadPrefAsPermissionSet(extension_id, kPrefActivePermissions);
}
@@ -1086,7 +1092,7 @@ void ExtensionPrefs::SetExtensionRunning(const std::string& extension_id,
UpdateExtensionPref(extension_id, kPrefRunning, value);
}
-bool ExtensionPrefs::IsExtensionRunning(const std::string& extension_id) {
+bool ExtensionPrefs::IsExtensionRunning(const std::string& extension_id) const {
const base::DictionaryValue* extension = GetExtensionPref(extension_id);
if (!extension)
return false;
@@ -1101,7 +1107,7 @@ void ExtensionPrefs::SetIsActive(const std::string& extension_id,
UpdateExtensionPref(extension_id, kIsActive, value);
}
-bool ExtensionPrefs::IsActive(const std::string& extension_id) {
+bool ExtensionPrefs::IsActive(const std::string& extension_id) const {
const base::DictionaryValue* extension = GetExtensionPref(extension_id);
if (!extension)
return false;
@@ -1162,7 +1168,7 @@ bool ExtensionPrefs::IsExtensionDisabled(
return DoesExtensionHaveState(id, Extension::DISABLED);
}
-ExtensionIdList ExtensionPrefs::GetToolbarOrder() {
+ExtensionIdList ExtensionPrefs::GetToolbarOrder() const {
ExtensionIdList id_list_out;
GetUserExtensionPrefIntoContainer(pref_names::kToolbar, &id_list_out);
return id_list_out;
@@ -1238,7 +1244,7 @@ void ExtensionPrefs::SetExtensionBlacklistState(const std::string& extension_id,
}
BlacklistState ExtensionPrefs::GetExtensionBlacklistState(
- const std::string& extension_id) {
+ const std::string& extension_id) const {
if (IsExtensionBlacklisted(extension_id))
return BLACKLISTED_MALWARE;
const base::DictionaryValue* ext_prefs = GetExtensionPref(extension_id);
@@ -1249,7 +1255,8 @@ BlacklistState ExtensionPrefs::GetExtensionBlacklistState(
return NOT_BLACKLISTED;
}
-std::string ExtensionPrefs::GetVersionString(const std::string& extension_id) {
+std::string ExtensionPrefs::GetVersionString(
+ const std::string& extension_id) const {
const base::DictionaryValue* extension = GetExtensionPref(extension_id);
if (!extension)
return std::string();
@@ -1546,7 +1553,8 @@ void ExtensionPrefs::OnEphemeralAppPromoted(const std::string& extension_id) {
}
}
-bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) {
+bool ExtensionPrefs::WasAppDraggedByUser(
+ const std::string& extension_id) const {
return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp);
}
@@ -1684,7 +1692,7 @@ void ExtensionPrefs::ClearLastLaunchTimes() {
}
}
-void ExtensionPrefs::GetExtensions(ExtensionIdList* out) {
+void ExtensionPrefs::GetExtensions(ExtensionIdList* out) const {
CHECK(out);
scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo());
@@ -1783,7 +1791,7 @@ void ExtensionPrefs::InitPrefStore() {
extension_pref_value_map_->NotifyInitializationCompleted();
}
-bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) {
+bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) const {
bool has_incognito_pref_value = false;
extension_pref_value_map_->GetEffectivePrefValue(pref_key,
true,
@@ -1810,7 +1818,7 @@ void ExtensionPrefs::SetGeometryCache(
UpdateExtensionPref(extension_id, kPrefGeometryCache, cache.release());
}
-const base::DictionaryValue* ExtensionPrefs::GetInstallSignature() {
+const base::DictionaryValue* ExtensionPrefs::GetInstallSignature() const {
return prefs_->GetDictionary(kInstallSignature);
}
@@ -1843,7 +1851,7 @@ void ExtensionPrefs::SetInstallParam(const std::string& extension_id,
new base::StringValue(install_parameter));
}
-int ExtensionPrefs::GetCorruptedDisableCount() {
+int ExtensionPrefs::GetCorruptedDisableCount() const {
return prefs_->GetInteger(kCorruptedDisableCount);
}
@@ -1888,7 +1896,7 @@ void ExtensionPrefs::SetNeedsStorageGarbageCollection(bool value) {
prefs_->SetBoolean(pref_names::kStorageGarbageCollect, value);
}
-bool ExtensionPrefs::NeedsStorageGarbageCollection() {
+bool ExtensionPrefs::NeedsStorageGarbageCollection() const {
return prefs_->GetBoolean(pref_names::kStorageGarbageCollect);
}
@@ -1925,7 +1933,7 @@ void ExtensionPrefs::RegisterProfilePrefs(
template <class ExtensionIdContainer>
bool ExtensionPrefs::GetUserExtensionPrefIntoContainer(
const char* pref,
- ExtensionIdContainer* id_container_out) {
+ ExtensionIdContainer* id_container_out) const {
DCHECK(id_container_out->empty());
const base::Value* user_pref_value = prefs_->GetUserPrefValue(pref);
@@ -1966,7 +1974,7 @@ void ExtensionPrefs::PopulateExtensionInfoPrefs(
Extension::State initial_state,
int install_flags,
const std::string& install_parameter,
- base::DictionaryValue* extension_dict) {
+ base::DictionaryValue* extension_dict) const {
extension_dict->Set(kPrefState, new base::FundamentalValue(initial_state));
extension_dict->Set(kPrefLocation,
new base::FundamentalValue(extension->location()));
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h
index e946901..88ff025 100644
--- a/extensions/browser/extension_prefs.h
+++ b/extensions/browser/extension_prefs.h
@@ -173,7 +173,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
bool IsExtensionDisabled(const std::string& id) const;
// Get/Set the order that the browser actions appear in the toolbar.
- ExtensionIdList GetToolbarOrder();
+ ExtensionIdList GetToolbarOrder() const;
void SetToolbarOrder(const ExtensionIdList& extension_ids);
// Called when an extension is installed, so that prefs get created.
@@ -212,10 +212,11 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Checks whether |extension_id| is marked as greylisted.
// TODO(oleg): Replace IsExtensionBlacklisted by this method.
- BlacklistState GetExtensionBlacklistState(const std::string& extension_id);
+ BlacklistState GetExtensionBlacklistState(
+ const std::string& extension_id) const;
// Populates |out| with the ids of all installed extensions.
- void GetExtensions(ExtensionIdList* out);
+ void GetExtensions(ExtensionIdList* out) const;
// ExtensionScopedPrefs methods:
void UpdateExtensionPref(const std::string& id,
@@ -248,7 +249,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
bool HasPrefForExtension(const std::string& extension_id) const override;
// Did the extension ask to escalate its permission during an upgrade?
- bool DidExtensionEscalatePermissions(const std::string& id);
+ bool DidExtensionEscalatePermissions(const std::string& id) const;
// If |did_escalate| is true, the preferences for |extension| will be set to
// require the install warning when the user tries to enable.
@@ -262,6 +263,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
Extension::DisableReason disable_reason) const;
void AddDisableReason(const std::string& extension_id,
Extension::DisableReason disable_reason);
+ void AddDisableReasons(const std::string& extension_id, int disable_reasons);
void RemoveDisableReason(const std::string& extension_id,
Extension::DisableReason disable_reason);
void ClearDisableReasons(const std::string& extension_id);
@@ -270,7 +272,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// return only the blocked extensions, not the "greylist" extensions.
// TODO(oleg): Make method names consistent here, in extension service and in
// blacklist.
- std::set<std::string> GetBlacklistedExtensions();
+ std::set<std::string> GetBlacklistedExtensions() const;
// Sets whether the extension with |id| is blacklisted.
void SetExtensionBlacklisted(const std::string& extension_id,
@@ -278,7 +280,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Returns the version string for the currently installed extension, or
// the empty string if not found.
- std::string GetVersionString(const std::string& extension_id);
+ std::string GetVersionString(const std::string& extension_id) const;
// Re-writes the extension manifest into the prefs.
// Called to change the extension's manifest when it's re-localized.
@@ -300,16 +302,17 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
int IncrementAcknowledgePromptCount(const std::string& extension_id);
// Whether the user has acknowledged an external extension.
- bool IsExternalExtensionAcknowledged(const std::string& extension_id);
+ bool IsExternalExtensionAcknowledged(const std::string& extension_id) const;
void AcknowledgeExternalExtension(const std::string& extension_id);
// Whether the user has acknowledged a blacklisted extension.
- bool IsBlacklistedExtensionAcknowledged(const std::string& extension_id);
+ bool IsBlacklistedExtensionAcknowledged(
+ const std::string& extension_id) const;
void AcknowledgeBlacklistedExtension(const std::string& extension_id);
// Whether the external extension was installed during the first run
// of this profile.
- bool IsExternalInstallFirstRun(const std::string& extension_id);
+ bool IsExternalInstallFirstRun(const std::string& extension_id) const;
void SetExternalInstallFirstRun(const std::string& extension_id);
// Returns true if the extension notification code has already run for the
@@ -334,20 +337,20 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Similar to LastPingDay/SetLastPingDay, but for sending "days since active"
// ping.
- base::Time LastActivePingDay(const std::string& extension_id);
+ base::Time LastActivePingDay(const std::string& extension_id) const;
void SetLastActivePingDay(const std::string& extension_id,
const base::Time& time);
// A bit we use for determining if we should send the "days since active"
// ping. A value of true means the item has been active (launched) since the
// last update check.
- bool GetActiveBit(const std::string& extension_id);
+ bool GetActiveBit(const std::string& extension_id) const;
void SetActiveBit(const std::string& extension_id, bool active);
// Returns the granted permission set for the extension with |extension_id|,
// and NULL if no preferences were found for |extension_id|.
// This passes ownership of the returned set to the caller.
- PermissionSet* GetGrantedPermissions(const std::string& extension_id);
+ PermissionSet* GetGrantedPermissions(const std::string& extension_id) const;
// Adds |permissions| to the granted permissions set for the extension with
// |extension_id|. The new granted permissions set will be the union of
@@ -362,7 +365,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Gets the active permission set for the specified extension. This may
// differ from the permissions in the manifest due to the optional
// permissions API. This passes ownership of the set to the caller.
- PermissionSet* GetActivePermissions(const std::string& extension_id);
+ PermissionSet* GetActivePermissions(const std::string& extension_id) const;
// Sets the active |permissions| for the extension with |extension_id|.
void SetActivePermissions(const std::string& extension_id,
@@ -373,13 +376,13 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Returns whether or not this extension is marked as running. This is used to
// restart apps across browser restarts.
- bool IsExtensionRunning(const std::string& extension_id);
+ bool IsExtensionRunning(const std::string& extension_id) const;
// Set/Get whether or not the app is active. Used to force a launch of apps
// that don't handle onRestarted() on a restart. We can only safely do that if
// the app was active when it was last running.
void SetIsActive(const std::string& extension_id, bool is_active);
- bool IsActive(const std::string& extension_id);
+ bool IsActive(const std::string& extension_id) const;
// Returns true if the user enabled this extension to be loaded in incognito
// mode.
@@ -450,7 +453,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Returns true if the user repositioned the app on the app launcher via drag
// and drop.
- bool WasAppDraggedByUser(const std::string& extension_id);
+ bool WasAppDraggedByUser(const std::string& extension_id) const;
// Sets a flag indicating that the user repositioned the app on the app
// launcher by drag and dropping it.
@@ -458,7 +461,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Returns true if there is an extension which controls the preference value
// for |pref_key| *and* it is specific to incognito mode.
- bool HasIncognitoPrefValue(const std::string& pref_key);
+ bool HasIncognitoPrefValue(const std::string& pref_key) const;
// Returns the creation flags mask for the extension.
int GetCreationFlags(const std::string& extension_id) const;
@@ -510,7 +513,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// start of this ExtensionService. Applies only to extensions with isolated
// storage.
void SetNeedsStorageGarbageCollection(bool value);
- bool NeedsStorageGarbageCollection();
+ bool NeedsStorageGarbageCollection() const;
// Used by AppWindowGeometryCache to persist its cache. These methods
// should not be called directly.
@@ -521,7 +524,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Used for verification of installed extension ids. For the Set method, pass
// null to remove the preference.
- const base::DictionaryValue* GetInstallSignature();
+ const base::DictionaryValue* GetInstallSignature() const;
void SetInstallSignature(const base::DictionaryValue* signature);
// The installation parameter associated with the extension.
@@ -531,7 +534,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// The total number of times we've disabled an extension due to corrupted
// contents.
- int GetCorruptedDisableCount();
+ int GetCorruptedDisableCount() const;
void IncrementCorruptedDisableCount();
private:
@@ -574,7 +577,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
bool ReadPrefAsURLPatternSet(const std::string& extension_id,
const std::string& pref_key,
URLPatternSet* result,
- int valid_schemes);
+ int valid_schemes) const;
// Converts |new_value| to a list of strings and sets the |pref_key| pref
// belonging to |extension_id|.
@@ -590,7 +593,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Interprets |pref_key| in |extension_id|'s preferences as an
// PermissionSet, and passes ownership of the set to the caller.
PermissionSet* ReadPrefAsPermissionSet(const std::string& extension_id,
- const std::string& pref_key);
+ const std::string& pref_key) const;
// Converts the |new_value| to its value and sets the |pref_key| pref
// belonging to |extension_id|.
@@ -635,7 +638,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
template <class ExtensionIdContainer>
bool GetUserExtensionPrefIntoContainer(
const char* pref,
- ExtensionIdContainer* id_container_out);
+ ExtensionIdContainer* id_container_out) const;
// Writes the list of strings contained in |strings| to |pref| in prefs.
template <class ExtensionIdContainer>
@@ -644,7 +647,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
// Helper function to populate |extension_dict| with the values needed
// by a newly installed extension. Work is broken up between this
- // function and FinishExtensionInfoPrefs() to accomodate delayed
+ // function and FinishExtensionInfoPrefs() to accommodate delayed
// installations.
//
// |install_flags| are a bitmask of extension::InstallFlags.
@@ -653,7 +656,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, public KeyedService {
Extension::State initial_state,
int install_flags,
const std::string& install_parameter,
- base::DictionaryValue* extension_dict);
+ base::DictionaryValue* extension_dict) const;
void InitExtensionControlledPrefs(ExtensionPrefValueMap* value_map);
diff --git a/sync/protocol/extension_specifics.proto b/sync/protocol/extension_specifics.proto
index 8e724a3..a854e01 100644
--- a/sync/protocol/extension_specifics.proto
+++ b/sync/protocol/extension_specifics.proto
@@ -48,5 +48,10 @@ message ExtensionSpecifics {
// optional and may be absent. We need this for the time being because we need
// to know if a user has not set an explicit preference.
optional bool all_urls_enabled = 9;
+
+ // Bitmask of the set of reasons why the extension is disabled (see
+ // Extension::DisableReason). Only relevant when enabled == false. Note that
+ // old clients (<M45) won't set this, even when enabled is false.
+ optional int32 disable_reasons = 10;
}
diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc
index 3ce9528..758729b 100644
--- a/sync/protocol/proto_value_conversions.cc
+++ b/sync/protocol/proto_value_conversions.cc
@@ -456,10 +456,11 @@ scoped_ptr<base::DictionaryValue> ExtensionSpecificsToValue(
SET_STR(update_url);
SET_BOOL(enabled);
SET_BOOL(incognito_enabled);
+ SET_STR(name);
SET_BOOL(remote_install);
SET_BOOL(installed_by_custodian);
SET_BOOL(all_urls_enabled);
- SET_STR(name);
+ SET_INT32(disable_reasons);
return value;
}