blob: 3e88aa626cac1adc8034ff8ba9abebe5c5a27568 [file] [log] [blame]
[email protected]4557d222012-03-04 23:33:361// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]90310d92011-04-17 07:35:042// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_sync_data.h"
6
[email protected]418e953e2011-04-27 21:30:227#include "base/logging.h"
yoz870444532015-03-12 18:42:538#include "base/metrics/histogram_macros.h"
yoz768503cd2015-02-24 03:40:319#include "base/strings/stringprintf.h"
[email protected]3bdba0d2011-08-23 07:17:3010#include "chrome/browser/extensions/extension_service.h"
treib0c714f7c2015-07-08 10:04:5811#include "chrome/common/extensions/manifest_handlers/app_icon_color_info.h"
12#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
13#include "chrome/common/extensions/manifest_handlers/linked_app_icons.h"
[email protected]fdd28372014-08-21 02:27:2614#include "components/crx_file/id_util.h"
[email protected]e4452d32013-11-15 23:07:4115#include "extensions/common/extension.h"
rockotd5546142014-10-15 00:29:0816#include "extensions/common/manifest_url_handlers.h"
[email protected]895a1e52012-05-15 02:50:1217#include "sync/api/sync_data.h"
treib0c714f7c2015-07-08 10:04:5818#include "sync/protocol/app_specifics.pb.h"
[email protected]1bcf30e2012-03-10 01:06:4119#include "sync/protocol/extension_specifics.pb.h"
20#include "sync/protocol/sync.pb.h"
[email protected]418e953e2011-04-27 21:30:2221
treib0c714f7c2015-07-08 10:04:5822using syncer::StringOrdinal;
23
[email protected]5db9ada2012-04-11 13:48:2024namespace extensions {
25
yoz768503cd2015-02-24 03:40:3126namespace {
27
28std::string GetExtensionSpecificsLogMessage(
29 const sync_pb::ExtensionSpecifics& specifics) {
treib231f2bb2015-06-09 12:46:2430 return base::StringPrintf(
31 "id: %s\nversion: %s\nupdate_url: %s\nenabled: %i\ndisable_reasons: %i",
32 specifics.id().c_str(),
33 specifics.version().c_str(),
34 specifics.update_url().c_str(),
35 specifics.enabled(),
36 specifics.disable_reasons());
yoz768503cd2015-02-24 03:40:3137}
38
yoz870444532015-03-12 18:42:5339enum BadSyncDataReason {
40 // Invalid extension ID.
41 BAD_EXTENSION_ID,
42
43 // Invalid version.
44 BAD_VERSION,
45
46 // Invalid update URL.
47 BAD_UPDATE_URL,
48
49 // No ExtensionSpecifics in the EntitySpecifics.
50 NO_EXTENSION_SPECIFICS,
51
treib29e1b9b12015-11-11 08:50:5652 // Not used anymore; still here because of UMA.
53 DEPRECATED_BAD_DISABLE_REASONS,
treib231f2bb2015-06-09 12:46:2454
yoz870444532015-03-12 18:42:5355 // Must be at the end.
56 NUM_BAD_SYNC_DATA_REASONS
57};
58
59void RecordBadSyncData(BadSyncDataReason reason) {
60 UMA_HISTOGRAM_ENUMERATION("Extensions.BadSyncDataReason", reason,
61 NUM_BAD_SYNC_DATA_REASONS);
62}
63
yoz768503cd2015-02-24 03:40:3164} // namespace
65
treib0c714f7c2015-07-08 10:04:5866ExtensionSyncData::LinkedAppIconInfo::LinkedAppIconInfo() {
67}
68
69ExtensionSyncData::LinkedAppIconInfo::~LinkedAppIconInfo() {
70}
71
[email protected]90310d92011-04-17 07:35:0472ExtensionSyncData::ExtensionSyncData()
treib0c714f7c2015-07-08 10:04:5873 : is_app_(false),
74 uninstalled_(false),
[email protected]3bdba0d2011-08-23 07:17:3075 enabled_(false),
treib231f2bb2015-06-09 12:46:2476 supports_disable_reasons_(false),
treibc1192322015-05-20 12:56:0777 disable_reasons_(Extension::DISABLE_NONE),
[email protected]075b3922014-05-03 06:14:1778 incognito_enabled_(false),
[email protected]6338fa32014-07-16 21:41:5979 remote_install_(false),
rdevlin.cronind1aa8522015-02-13 00:25:5780 all_urls_enabled_(BOOLEAN_UNSET),
treib0c714f7c2015-07-08 10:04:5881 installed_by_custodian_(false),
82 launch_type_(LAUNCH_TYPE_INVALID) {
[email protected]3bdba0d2011-08-23 07:17:3083}
84
[email protected]3bdba0d2011-08-23 07:17:3085ExtensionSyncData::ExtensionSyncData(const Extension& extension,
86 bool enabled,
treibc1192322015-05-20 12:56:0787 int disable_reasons,
[email protected]21db9ef2014-05-16 02:06:2788 bool incognito_enabled,
rdevlin.cronind1aa8522015-02-13 00:25:5789 bool remote_install,
90 OptionalBoolean all_urls_enabled)
treib0c714f7c2015-07-08 10:04:5891 : ExtensionSyncData(extension, enabled, disable_reasons, incognito_enabled,
92 remote_install, all_urls_enabled, StringOrdinal(),
93 StringOrdinal(), LAUNCH_TYPE_INVALID) {
94}
95
96ExtensionSyncData::ExtensionSyncData(const Extension& extension,
97 bool enabled,
98 int disable_reasons,
99 bool incognito_enabled,
100 bool remote_install,
101 OptionalBoolean all_urls_enabled,
102 const StringOrdinal& app_launch_ordinal,
103 const StringOrdinal& page_ordinal,
104 extensions::LaunchType launch_type)
105 : is_app_(extension.is_app()),
106 id_(extension.id()),
[email protected]5db9ada2012-04-11 13:48:20107 uninstalled_(false),
108 enabled_(enabled),
treib231f2bb2015-06-09 12:46:24109 supports_disable_reasons_(true),
treibc1192322015-05-20 12:56:07110 disable_reasons_(disable_reasons),
[email protected]5db9ada2012-04-11 13:48:20111 incognito_enabled_(incognito_enabled),
[email protected]21db9ef2014-05-16 02:06:27112 remote_install_(remote_install),
rdevlin.cronind1aa8522015-02-13 00:25:57113 all_urls_enabled_(all_urls_enabled),
[email protected]6338fa32014-07-16 21:41:59114 installed_by_custodian_(extension.was_installed_by_custodian()),
[email protected]f4263c52014-04-09 12:40:51115 version_(extension.from_bookmark() ? base::Version("0")
116 : *extension.version()),
[email protected]65348062013-01-15 07:27:22117 update_url_(ManifestURL::GetUpdateURL(&extension)),
treib0c714f7c2015-07-08 10:04:58118 name_(extension.non_localized_name()),
119 app_launch_ordinal_(app_launch_ordinal),
120 page_ordinal_(page_ordinal),
121 launch_type_(launch_type) {
122 if (is_app_ && extension.from_bookmark()) {
123 bookmark_app_description_ = extension.description();
124 bookmark_app_url_ = AppLaunchInfo::GetLaunchWebURL(&extension).spec();
125 bookmark_app_icon_color_ = AppIconColorInfo::GetIconColorString(&extension);
126 extensions::LinkedAppIcons icons =
127 LinkedAppIcons::GetLinkedAppIcons(&extension);
128 for (const auto& icon : icons.icons) {
129 LinkedAppIconInfo linked_icon;
130 linked_icon.url = icon.url;
131 linked_icon.size = icon.size;
132 linked_icons_.push_back(linked_icon);
133 }
134 }
[email protected]3bdba0d2011-08-23 07:17:30135}
[email protected]90310d92011-04-17 07:35:04136
vmpstrb8aacbe2016-02-26 02:00:48137ExtensionSyncData::ExtensionSyncData(const ExtensionSyncData& other) = default;
138
[email protected]90310d92011-04-17 07:35:04139ExtensionSyncData::~ExtensionSyncData() {}
[email protected]418e953e2011-04-27 21:30:22140
yoz870444532015-03-12 18:42:53141// static
142scoped_ptr<ExtensionSyncData> ExtensionSyncData::CreateFromSyncData(
143 const syncer::SyncData& sync_data) {
144 scoped_ptr<ExtensionSyncData> data(new ExtensionSyncData);
145 if (data->PopulateFromSyncData(sync_data))
dcheng1fc00f12015-12-26 22:18:03146 return data;
treib0c714f7c2015-07-08 10:04:58147 return nullptr;
yoz870444532015-03-12 18:42:53148}
149
150// static
151scoped_ptr<ExtensionSyncData> ExtensionSyncData::CreateFromSyncChange(
152 const syncer::SyncChange& sync_change) {
153 scoped_ptr<ExtensionSyncData> data(
154 CreateFromSyncData(sync_change.sync_data()));
155 if (!data.get())
treib0c714f7c2015-07-08 10:04:58156 return nullptr;
yoz870444532015-03-12 18:42:53157
treibecc63c8d2015-09-07 16:34:47158 if (sync_change.change_type() == syncer::SyncChange::ACTION_DELETE)
159 data->uninstalled_ = true;
dcheng1fc00f12015-12-26 22:18:03160 return data;
yoz870444532015-03-12 18:42:53161}
162
[email protected]65f173552012-06-28 22:43:58163syncer::SyncData ExtensionSyncData::GetSyncData() const {
[email protected]5db9ada2012-04-11 13:48:20164 sync_pb::EntitySpecifics specifics;
treib0c714f7c2015-07-08 10:04:58165 if (is_app_)
166 ToAppSpecifics(specifics.mutable_app());
167 else
168 ToExtensionSpecifics(specifics.mutable_extension());
[email protected]168389f2011-12-20 17:12:48169
[email protected]65f173552012-06-28 22:43:58170 return syncer::SyncData::CreateLocalData(id_, name_, specifics);
[email protected]5db9ada2012-04-11 13:48:20171}
[email protected]168389f2011-12-20 17:12:48172
[email protected]65f173552012-06-28 22:43:58173syncer::SyncChange ExtensionSyncData::GetSyncChange(
174 syncer::SyncChange::SyncChangeType change_type) const {
[email protected]b78170f2012-07-11 03:34:26175 return syncer::SyncChange(FROM_HERE, change_type, GetSyncData());
[email protected]aa7599d2011-10-28 07:24:32176}
177
treib0c714f7c2015-07-08 10:04:58178void ExtensionSyncData::ToExtensionSpecifics(
[email protected]3bdba0d2011-08-23 07:17:30179 sync_pb::ExtensionSpecifics* specifics) const {
[email protected]fdd28372014-08-21 02:27:26180 DCHECK(crx_file::id_util::IdIsValid(id_));
[email protected]3bdba0d2011-08-23 07:17:30181 specifics->set_id(id_);
182 specifics->set_update_url(update_url_.spec());
183 specifics->set_version(version_.GetString());
184 specifics->set_enabled(enabled_);
treib231f2bb2015-06-09 12:46:24185 if (supports_disable_reasons_)
186 specifics->set_disable_reasons(disable_reasons_);
[email protected]3bdba0d2011-08-23 07:17:30187 specifics->set_incognito_enabled(incognito_enabled_);
[email protected]075b3922014-05-03 06:14:17188 specifics->set_remote_install(remote_install_);
rdevlin.cronind1aa8522015-02-13 00:25:57189 if (all_urls_enabled_ != BOOLEAN_UNSET)
190 specifics->set_all_urls_enabled(all_urls_enabled_ == BOOLEAN_TRUE);
[email protected]6338fa32014-07-16 21:41:59191 specifics->set_installed_by_custodian(installed_by_custodian_);
[email protected]3bdba0d2011-08-23 07:17:30192 specifics->set_name(name_);
[email protected]0fac519c2011-08-19 18:05:57193}
[email protected]3bdba0d2011-08-23 07:17:30194
treib0c714f7c2015-07-08 10:04:58195void ExtensionSyncData::ToAppSpecifics(sync_pb::AppSpecifics* specifics) const {
196 DCHECK(specifics);
197 // Only sync the ordinal values and launch type if they are valid.
198 if (app_launch_ordinal_.IsValid())
199 specifics->set_app_launch_ordinal(app_launch_ordinal_.ToInternalValue());
200 if (page_ordinal_.IsValid())
201 specifics->set_page_ordinal(page_ordinal_.ToInternalValue());
202
203 sync_pb::AppSpecifics::LaunchType sync_launch_type =
204 static_cast<sync_pb::AppSpecifics::LaunchType>(launch_type_);
205
206 // The corresponding validation of this value during processing of an
treibc3494532015-07-21 14:51:45207 // ExtensionSyncData is in ExtensionSyncService::ApplySyncData.
treib0c714f7c2015-07-08 10:04:58208 if (launch_type_ >= LAUNCH_TYPE_FIRST && launch_type_ < NUM_LAUNCH_TYPES &&
209 sync_pb::AppSpecifics_LaunchType_IsValid(sync_launch_type)) {
210 specifics->set_launch_type(sync_launch_type);
211 }
212
213 if (!bookmark_app_url_.empty())
214 specifics->set_bookmark_app_url(bookmark_app_url_);
215
216 if (!bookmark_app_description_.empty())
217 specifics->set_bookmark_app_description(bookmark_app_description_);
218
219 if (!bookmark_app_icon_color_.empty())
220 specifics->set_bookmark_app_icon_color(bookmark_app_icon_color_);
221
222 for (const auto& linked_icon : linked_icons_) {
223 sync_pb::LinkedAppIconInfo* linked_app_icon_info =
224 specifics->add_linked_app_icons();
225 linked_app_icon_info->set_url(linked_icon.url.spec());
226 linked_app_icon_info->set_size(linked_icon.size);
227 }
228
229 ToExtensionSpecifics(specifics->mutable_extension());
230}
231
yoz870444532015-03-12 18:42:53232bool ExtensionSyncData::PopulateFromExtensionSpecifics(
[email protected]3bdba0d2011-08-23 07:17:30233 const sync_pb::ExtensionSpecifics& specifics) {
[email protected]fdd28372014-08-21 02:27:26234 if (!crx_file::id_util::IdIsValid(specifics.id())) {
yoz870444532015-03-12 18:42:53235 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad ID):\n"
yoz768503cd2015-02-24 03:40:31236 << GetExtensionSpecificsLogMessage(specifics);
yoz870444532015-03-12 18:42:53237 RecordBadSyncData(BAD_EXTENSION_ID);
238 return false;
[email protected]3bdba0d2011-08-23 07:17:30239 }
240
thakis37be69c2015-08-19 03:26:57241 Version specifics_version(specifics.version());
yoz768503cd2015-02-24 03:40:31242 if (!specifics_version.IsValid()) {
yoz870444532015-03-12 18:42:53243 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad version):\n"
yoz768503cd2015-02-24 03:40:31244 << GetExtensionSpecificsLogMessage(specifics);
yoz870444532015-03-12 18:42:53245 RecordBadSyncData(BAD_VERSION);
246 return false;
yoz768503cd2015-02-24 03:40:31247 }
[email protected]3bdba0d2011-08-23 07:17:30248
249 // The update URL must be either empty or valid.
250 GURL specifics_update_url(specifics.update_url());
251 if (!specifics_update_url.is_empty() && !specifics_update_url.is_valid()) {
yoz870444532015-03-12 18:42:53252 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad update URL):\n"
yoz768503cd2015-02-24 03:40:31253 << GetExtensionSpecificsLogMessage(specifics);
yoz870444532015-03-12 18:42:53254 RecordBadSyncData(BAD_UPDATE_URL);
255 return false;
[email protected]3bdba0d2011-08-23 07:17:30256 }
257
[email protected]3bdba0d2011-08-23 07:17:30258 id_ = specifics.id();
259 update_url_ = specifics_update_url;
[email protected]e1adb9a2011-09-09 17:42:52260 version_ = specifics_version;
[email protected]3bdba0d2011-08-23 07:17:30261 enabled_ = specifics.enabled();
treib231f2bb2015-06-09 12:46:24262 supports_disable_reasons_ = specifics.has_disable_reasons();
treibc1192322015-05-20 12:56:07263 disable_reasons_ = specifics.disable_reasons();
[email protected]3bdba0d2011-08-23 07:17:30264 incognito_enabled_ = specifics.incognito_enabled();
rdevlin.cronind1aa8522015-02-13 00:25:57265 if (specifics.has_all_urls_enabled()) {
266 all_urls_enabled_ =
267 specifics.all_urls_enabled() ? BOOLEAN_TRUE : BOOLEAN_FALSE;
268 } else {
269 // Set this explicitly (even though it's the default) on the offchance
270 // that someone is re-using an ExtensionSyncData object.
271 all_urls_enabled_ = BOOLEAN_UNSET;
272 }
[email protected]075b3922014-05-03 06:14:17273 remote_install_ = specifics.remote_install();
[email protected]6338fa32014-07-16 21:41:59274 installed_by_custodian_ = specifics.installed_by_custodian();
[email protected]3bdba0d2011-08-23 07:17:30275 name_ = specifics.name();
yoz870444532015-03-12 18:42:53276 return true;
[email protected]3bdba0d2011-08-23 07:17:30277}
278
treib0c714f7c2015-07-08 10:04:58279bool ExtensionSyncData::PopulateFromAppSpecifics(
280 const sync_pb::AppSpecifics& specifics) {
281 if (!PopulateFromExtensionSpecifics(specifics.extension()))
282 return false;
283
284 is_app_ = true;
285
286 app_launch_ordinal_ = syncer::StringOrdinal(specifics.app_launch_ordinal());
287 page_ordinal_ = syncer::StringOrdinal(specifics.page_ordinal());
288
289 launch_type_ = specifics.has_launch_type()
290 ? static_cast<extensions::LaunchType>(specifics.launch_type())
291 : LAUNCH_TYPE_INVALID;
292
293 bookmark_app_url_ = specifics.bookmark_app_url();
294 bookmark_app_description_ = specifics.bookmark_app_description();
295 bookmark_app_icon_color_ = specifics.bookmark_app_icon_color();
296
297 for (int i = 0; i < specifics.linked_app_icons_size(); ++i) {
298 const sync_pb::LinkedAppIconInfo& linked_app_icon_info =
299 specifics.linked_app_icons(i);
300 if (linked_app_icon_info.has_url() && linked_app_icon_info.has_size()) {
301 LinkedAppIconInfo linked_icon;
302 linked_icon.url = GURL(linked_app_icon_info.url());
303 linked_icon.size = linked_app_icon_info.size();
304 linked_icons_.push_back(linked_icon);
305 }
306 }
307
308 return true;
309}
310
yoz870444532015-03-12 18:42:53311bool ExtensionSyncData::PopulateFromSyncData(
[email protected]65f173552012-06-28 22:43:58312 const syncer::SyncData& sync_data) {
[email protected]3bdba0d2011-08-23 07:17:30313 const sync_pb::EntitySpecifics& entity_specifics = sync_data.GetSpecifics();
[email protected]168389f2011-12-20 17:12:48314
treib0c714f7c2015-07-08 10:04:58315 if (entity_specifics.has_app())
316 return PopulateFromAppSpecifics(entity_specifics.app());
317
yoz870444532015-03-12 18:42:53318 if (entity_specifics.has_extension())
319 return PopulateFromExtensionSpecifics(entity_specifics.extension());
320
321 LOG(ERROR) << "Attempt to sync bad EntitySpecifics: no extension data.";
322 RecordBadSyncData(NO_EXTENSION_SPECIFICS);
323 return false;
[email protected]3bdba0d2011-08-23 07:17:30324}
[email protected]5db9ada2012-04-11 13:48:20325
326} // namespace extensions