Add a webstorePrivate API to show a permission prompt for delegated bundle installs
[chromium-blink-merge.git] / chrome / browser / extensions / extension_sync_data.cc
blob17bb21730e9adfa6d68a9a59a77c0e04110a1431
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/extension_sync_data.h"
7 #include "base/logging.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/extensions/app_sync_data.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "components/crx_file/id_util.h"
13 #include "extensions/common/extension.h"
14 #include "extensions/common/manifest_url_handlers.h"
15 #include "sync/api/sync_data.h"
16 #include "sync/protocol/extension_specifics.pb.h"
17 #include "sync/protocol/sync.pb.h"
19 namespace extensions {
21 namespace {
23 std::string GetExtensionSpecificsLogMessage(
24 const sync_pb::ExtensionSpecifics& specifics) {
25 return base::StringPrintf(
26 "id: %s\nversion: %s\nupdate_url: %s\nenabled: %i\ndisable_reasons: %i",
27 specifics.id().c_str(),
28 specifics.version().c_str(),
29 specifics.update_url().c_str(),
30 specifics.enabled(),
31 specifics.disable_reasons());
34 enum BadSyncDataReason {
35 // Invalid extension ID.
36 BAD_EXTENSION_ID,
38 // Invalid version.
39 BAD_VERSION,
41 // Invalid update URL.
42 BAD_UPDATE_URL,
44 // No ExtensionSpecifics in the EntitySpecifics.
45 NO_EXTENSION_SPECIFICS,
47 // Enabled extensions can't have disable reasons.
48 BAD_DISABLE_REASONS,
50 // Must be at the end.
51 NUM_BAD_SYNC_DATA_REASONS
54 void RecordBadSyncData(BadSyncDataReason reason) {
55 UMA_HISTOGRAM_ENUMERATION("Extensions.BadSyncDataReason", reason,
56 NUM_BAD_SYNC_DATA_REASONS);
59 } // namespace
61 ExtensionSyncData::ExtensionSyncData()
62 : uninstalled_(false),
63 enabled_(false),
64 supports_disable_reasons_(false),
65 disable_reasons_(Extension::DISABLE_NONE),
66 incognito_enabled_(false),
67 remote_install_(false),
68 all_urls_enabled_(BOOLEAN_UNSET),
69 installed_by_custodian_(false) {
72 ExtensionSyncData::ExtensionSyncData(const Extension& extension,
73 bool enabled,
74 int disable_reasons,
75 bool incognito_enabled,
76 bool remote_install,
77 OptionalBoolean all_urls_enabled)
78 : id_(extension.id()),
79 uninstalled_(false),
80 enabled_(enabled),
81 supports_disable_reasons_(true),
82 disable_reasons_(disable_reasons),
83 incognito_enabled_(incognito_enabled),
84 remote_install_(remote_install),
85 all_urls_enabled_(all_urls_enabled),
86 installed_by_custodian_(extension.was_installed_by_custodian()),
87 version_(extension.from_bookmark() ? base::Version("0")
88 : *extension.version()),
89 update_url_(ManifestURL::GetUpdateURL(&extension)),
90 name_(extension.non_localized_name()) {
93 ExtensionSyncData::~ExtensionSyncData() {}
95 // static
96 scoped_ptr<ExtensionSyncData> ExtensionSyncData::CreateFromSyncData(
97 const syncer::SyncData& sync_data) {
98 scoped_ptr<ExtensionSyncData> data(new ExtensionSyncData);
99 if (data->PopulateFromSyncData(sync_data))
100 return data.Pass();
101 return scoped_ptr<ExtensionSyncData>();
104 // static
105 scoped_ptr<ExtensionSyncData> ExtensionSyncData::CreateFromSyncChange(
106 const syncer::SyncChange& sync_change) {
107 scoped_ptr<ExtensionSyncData> data(
108 CreateFromSyncData(sync_change.sync_data()));
109 if (!data.get())
110 return scoped_ptr<ExtensionSyncData>();
112 data->set_uninstalled(sync_change.change_type() ==
113 syncer::SyncChange::ACTION_DELETE);
114 return data.Pass();
117 syncer::SyncData ExtensionSyncData::GetSyncData() const {
118 sync_pb::EntitySpecifics specifics;
119 PopulateExtensionSpecifics(specifics.mutable_extension());
121 return syncer::SyncData::CreateLocalData(id_, name_, specifics);
124 syncer::SyncChange ExtensionSyncData::GetSyncChange(
125 syncer::SyncChange::SyncChangeType change_type) const {
126 return syncer::SyncChange(FROM_HERE, change_type, GetSyncData());
129 void ExtensionSyncData::PopulateExtensionSpecifics(
130 sync_pb::ExtensionSpecifics* specifics) const {
131 DCHECK(crx_file::id_util::IdIsValid(id_));
132 specifics->set_id(id_);
133 specifics->set_update_url(update_url_.spec());
134 specifics->set_version(version_.GetString());
135 specifics->set_enabled(enabled_);
136 if (supports_disable_reasons_)
137 specifics->set_disable_reasons(disable_reasons_);
138 specifics->set_incognito_enabled(incognito_enabled_);
139 specifics->set_remote_install(remote_install_);
140 if (all_urls_enabled_ != BOOLEAN_UNSET)
141 specifics->set_all_urls_enabled(all_urls_enabled_ == BOOLEAN_TRUE);
142 specifics->set_installed_by_custodian(installed_by_custodian_);
143 specifics->set_name(name_);
146 bool ExtensionSyncData::PopulateFromExtensionSpecifics(
147 const sync_pb::ExtensionSpecifics& specifics) {
148 if (!crx_file::id_util::IdIsValid(specifics.id())) {
149 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad ID):\n"
150 << GetExtensionSpecificsLogMessage(specifics);
151 RecordBadSyncData(BAD_EXTENSION_ID);
152 return false;
155 Version specifics_version(specifics.version());
156 if (!specifics_version.IsValid()) {
157 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad version):\n"
158 << GetExtensionSpecificsLogMessage(specifics);
159 RecordBadSyncData(BAD_VERSION);
160 return false;
163 // The update URL must be either empty or valid.
164 GURL specifics_update_url(specifics.update_url());
165 if (!specifics_update_url.is_empty() && !specifics_update_url.is_valid()) {
166 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad update URL):\n"
167 << GetExtensionSpecificsLogMessage(specifics);
168 RecordBadSyncData(BAD_UPDATE_URL);
169 return false;
172 // Enabled extensions can't have disable reasons. (The proto field may be
173 // unset, in which case it defaults to DISABLE_NONE.)
174 if (specifics.enabled() &&
175 specifics.disable_reasons() != Extension::DISABLE_NONE) {
176 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics "
177 << "(enabled extension can't have disable reasons):\n"
178 << GetExtensionSpecificsLogMessage(specifics);
179 RecordBadSyncData(BAD_DISABLE_REASONS);
180 return false;
183 id_ = specifics.id();
184 update_url_ = specifics_update_url;
185 version_ = specifics_version;
186 enabled_ = specifics.enabled();
187 supports_disable_reasons_ = specifics.has_disable_reasons();
188 disable_reasons_ = specifics.disable_reasons();
189 incognito_enabled_ = specifics.incognito_enabled();
190 if (specifics.has_all_urls_enabled()) {
191 all_urls_enabled_ =
192 specifics.all_urls_enabled() ? BOOLEAN_TRUE : BOOLEAN_FALSE;
193 } else {
194 // Set this explicitly (even though it's the default) on the offchance
195 // that someone is re-using an ExtensionSyncData object.
196 all_urls_enabled_ = BOOLEAN_UNSET;
198 remote_install_ = specifics.remote_install();
199 installed_by_custodian_ = specifics.installed_by_custodian();
200 name_ = specifics.name();
201 return true;
204 void ExtensionSyncData::set_uninstalled(bool uninstalled) {
205 uninstalled_ = uninstalled;
208 bool ExtensionSyncData::PopulateFromSyncData(
209 const syncer::SyncData& sync_data) {
210 const sync_pb::EntitySpecifics& entity_specifics = sync_data.GetSpecifics();
212 if (entity_specifics.has_extension())
213 return PopulateFromExtensionSpecifics(entity_specifics.extension());
215 LOG(ERROR) << "Attempt to sync bad EntitySpecifics: no extension data.";
216 RecordBadSyncData(NO_EXTENSION_SPECIFICS);
217 return false;
220 } // namespace extensions