OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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_data.h" | 5 #include "chrome/browser/extensions/extension_sync_data.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/metrics/histogram_macros.h" |
8 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
9 #include "chrome/browser/extensions/app_sync_data.h" | 10 #include "chrome/browser/extensions/app_sync_data.h" |
10 #include "chrome/browser/extensions/extension_service.h" | 11 #include "chrome/browser/extensions/extension_service.h" |
11 #include "components/crx_file/id_util.h" | 12 #include "components/crx_file/id_util.h" |
12 #include "extensions/common/extension.h" | 13 #include "extensions/common/extension.h" |
13 #include "extensions/common/manifest_url_handlers.h" | 14 #include "extensions/common/manifest_url_handlers.h" |
14 #include "sync/api/sync_data.h" | 15 #include "sync/api/sync_data.h" |
15 #include "sync/protocol/extension_specifics.pb.h" | 16 #include "sync/protocol/extension_specifics.pb.h" |
16 #include "sync/protocol/sync.pb.h" | 17 #include "sync/protocol/sync.pb.h" |
17 | 18 |
18 namespace extensions { | 19 namespace extensions { |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 std::string GetExtensionSpecificsLogMessage( | 23 std::string GetExtensionSpecificsLogMessage( |
23 const sync_pb::ExtensionSpecifics& specifics) { | 24 const sync_pb::ExtensionSpecifics& specifics) { |
24 return base::StringPrintf("id: %s\nversion: %s\nupdate_url: %s", | 25 return base::StringPrintf("id: %s\nversion: %s\nupdate_url: %s", |
25 specifics.id().c_str(), | 26 specifics.id().c_str(), |
26 specifics.version().c_str(), | 27 specifics.version().c_str(), |
27 specifics.update_url().c_str()); | 28 specifics.update_url().c_str()); |
28 } | 29 } |
29 | 30 |
| 31 enum BadSyncDataReason { |
| 32 // Invalid extension ID. |
| 33 BAD_EXTENSION_ID, |
| 34 |
| 35 // Invalid version. |
| 36 BAD_VERSION, |
| 37 |
| 38 // Invalid update URL. |
| 39 BAD_UPDATE_URL, |
| 40 |
| 41 // No ExtensionSpecifics in the EntitySpecifics. |
| 42 NO_EXTENSION_SPECIFICS, |
| 43 |
| 44 // Must be at the end. |
| 45 NUM_BAD_SYNC_DATA_REASONS |
| 46 }; |
| 47 |
| 48 void RecordBadSyncData(BadSyncDataReason reason) { |
| 49 UMA_HISTOGRAM_ENUMERATION("Extensions.BadSyncDataReason", reason, |
| 50 NUM_BAD_SYNC_DATA_REASONS); |
| 51 } |
| 52 |
30 } // namespace | 53 } // namespace |
31 | 54 |
32 ExtensionSyncData::ExtensionSyncData() | 55 ExtensionSyncData::ExtensionSyncData() |
33 : uninstalled_(false), | 56 : uninstalled_(false), |
34 enabled_(false), | 57 enabled_(false), |
35 incognito_enabled_(false), | 58 incognito_enabled_(false), |
36 remote_install_(false), | 59 remote_install_(false), |
37 all_urls_enabled_(BOOLEAN_UNSET), | 60 all_urls_enabled_(BOOLEAN_UNSET), |
38 installed_by_custodian_(false) { | 61 installed_by_custodian_(false) { |
39 } | 62 } |
40 | 63 |
41 ExtensionSyncData::ExtensionSyncData(const syncer::SyncData& sync_data) | |
42 : uninstalled_(false), | |
43 enabled_(false), | |
44 incognito_enabled_(false), | |
45 remote_install_(false), | |
46 all_urls_enabled_(BOOLEAN_UNSET), | |
47 installed_by_custodian_(false) { | |
48 PopulateFromSyncData(sync_data); | |
49 } | |
50 | |
51 ExtensionSyncData::ExtensionSyncData(const syncer::SyncChange& sync_change) | |
52 : uninstalled_(sync_change.change_type() == | |
53 syncer::SyncChange::ACTION_DELETE), | |
54 enabled_(false), | |
55 incognito_enabled_(false), | |
56 remote_install_(false), | |
57 all_urls_enabled_(BOOLEAN_UNSET), | |
58 installed_by_custodian_(false) { | |
59 PopulateFromSyncData(sync_change.sync_data()); | |
60 } | |
61 | |
62 ExtensionSyncData::ExtensionSyncData(const Extension& extension, | 64 ExtensionSyncData::ExtensionSyncData(const Extension& extension, |
63 bool enabled, | 65 bool enabled, |
64 bool incognito_enabled, | 66 bool incognito_enabled, |
65 bool remote_install, | 67 bool remote_install, |
66 OptionalBoolean all_urls_enabled) | 68 OptionalBoolean all_urls_enabled) |
67 : id_(extension.id()), | 69 : id_(extension.id()), |
68 uninstalled_(false), | 70 uninstalled_(false), |
69 enabled_(enabled), | 71 enabled_(enabled), |
70 incognito_enabled_(incognito_enabled), | 72 incognito_enabled_(incognito_enabled), |
71 remote_install_(remote_install), | 73 remote_install_(remote_install), |
72 all_urls_enabled_(all_urls_enabled), | 74 all_urls_enabled_(all_urls_enabled), |
73 installed_by_custodian_(extension.was_installed_by_custodian()), | 75 installed_by_custodian_(extension.was_installed_by_custodian()), |
74 version_(extension.from_bookmark() ? base::Version("0") | 76 version_(extension.from_bookmark() ? base::Version("0") |
75 : *extension.version()), | 77 : *extension.version()), |
76 update_url_(ManifestURL::GetUpdateURL(&extension)), | 78 update_url_(ManifestURL::GetUpdateURL(&extension)), |
77 name_(extension.non_localized_name()) { | 79 name_(extension.non_localized_name()) { |
78 } | 80 } |
79 | 81 |
80 ExtensionSyncData::~ExtensionSyncData() {} | 82 ExtensionSyncData::~ExtensionSyncData() {} |
81 | 83 |
| 84 // static |
| 85 scoped_ptr<ExtensionSyncData> ExtensionSyncData::CreateFromSyncData( |
| 86 const syncer::SyncData& sync_data) { |
| 87 scoped_ptr<ExtensionSyncData> data(new ExtensionSyncData); |
| 88 if (data->PopulateFromSyncData(sync_data)) |
| 89 return data.Pass(); |
| 90 return scoped_ptr<ExtensionSyncData>(); |
| 91 } |
| 92 |
| 93 // static |
| 94 scoped_ptr<ExtensionSyncData> ExtensionSyncData::CreateFromSyncChange( |
| 95 const syncer::SyncChange& sync_change) { |
| 96 scoped_ptr<ExtensionSyncData> data( |
| 97 CreateFromSyncData(sync_change.sync_data())); |
| 98 if (!data.get()) |
| 99 return scoped_ptr<ExtensionSyncData>(); |
| 100 |
| 101 data->set_uninstalled(sync_change.change_type() == |
| 102 syncer::SyncChange::ACTION_DELETE); |
| 103 return data.Pass(); |
| 104 } |
| 105 |
82 syncer::SyncData ExtensionSyncData::GetSyncData() const { | 106 syncer::SyncData ExtensionSyncData::GetSyncData() const { |
83 sync_pb::EntitySpecifics specifics; | 107 sync_pb::EntitySpecifics specifics; |
84 PopulateExtensionSpecifics(specifics.mutable_extension()); | 108 PopulateExtensionSpecifics(specifics.mutable_extension()); |
85 | 109 |
86 return syncer::SyncData::CreateLocalData(id_, name_, specifics); | 110 return syncer::SyncData::CreateLocalData(id_, name_, specifics); |
87 } | 111 } |
88 | 112 |
89 syncer::SyncChange ExtensionSyncData::GetSyncChange( | 113 syncer::SyncChange ExtensionSyncData::GetSyncChange( |
90 syncer::SyncChange::SyncChangeType change_type) const { | 114 syncer::SyncChange::SyncChangeType change_type) const { |
91 return syncer::SyncChange(FROM_HERE, change_type, GetSyncData()); | 115 return syncer::SyncChange(FROM_HERE, change_type, GetSyncData()); |
92 } | 116 } |
93 | 117 |
94 void ExtensionSyncData::PopulateExtensionSpecifics( | 118 void ExtensionSyncData::PopulateExtensionSpecifics( |
95 sync_pb::ExtensionSpecifics* specifics) const { | 119 sync_pb::ExtensionSpecifics* specifics) const { |
96 DCHECK(crx_file::id_util::IdIsValid(id_)); | 120 DCHECK(crx_file::id_util::IdIsValid(id_)); |
97 specifics->set_id(id_); | 121 specifics->set_id(id_); |
98 specifics->set_update_url(update_url_.spec()); | 122 specifics->set_update_url(update_url_.spec()); |
99 specifics->set_version(version_.GetString()); | 123 specifics->set_version(version_.GetString()); |
100 specifics->set_enabled(enabled_); | 124 specifics->set_enabled(enabled_); |
101 specifics->set_incognito_enabled(incognito_enabled_); | 125 specifics->set_incognito_enabled(incognito_enabled_); |
102 specifics->set_remote_install(remote_install_); | 126 specifics->set_remote_install(remote_install_); |
103 if (all_urls_enabled_ != BOOLEAN_UNSET) | 127 if (all_urls_enabled_ != BOOLEAN_UNSET) |
104 specifics->set_all_urls_enabled(all_urls_enabled_ == BOOLEAN_TRUE); | 128 specifics->set_all_urls_enabled(all_urls_enabled_ == BOOLEAN_TRUE); |
105 specifics->set_installed_by_custodian(installed_by_custodian_); | 129 specifics->set_installed_by_custodian(installed_by_custodian_); |
106 specifics->set_name(name_); | 130 specifics->set_name(name_); |
107 } | 131 } |
108 | 132 |
109 void ExtensionSyncData::PopulateFromExtensionSpecifics( | 133 bool ExtensionSyncData::PopulateFromExtensionSpecifics( |
110 const sync_pb::ExtensionSpecifics& specifics) { | 134 const sync_pb::ExtensionSpecifics& specifics) { |
111 if (!crx_file::id_util::IdIsValid(specifics.id())) { | 135 if (!crx_file::id_util::IdIsValid(specifics.id())) { |
112 LOG(FATAL) << "Attempt to sync bad ExtensionSpecifics (bad ID):\n" | 136 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad ID):\n" |
113 << GetExtensionSpecificsLogMessage(specifics); | 137 << GetExtensionSpecificsLogMessage(specifics); |
| 138 RecordBadSyncData(BAD_EXTENSION_ID); |
| 139 return false; |
114 } | 140 } |
115 | 141 |
116 Version specifics_version(specifics.version()); | 142 Version specifics_version(specifics.version()); |
117 if (!specifics_version.IsValid()) { | 143 if (!specifics_version.IsValid()) { |
118 LOG(FATAL) << "Attempt to sync bad ExtensionSpecifics (bad version):\n" | 144 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad version):\n" |
119 << GetExtensionSpecificsLogMessage(specifics); | 145 << GetExtensionSpecificsLogMessage(specifics); |
| 146 RecordBadSyncData(BAD_VERSION); |
| 147 return false; |
120 } | 148 } |
121 | 149 |
122 // The update URL must be either empty or valid. | 150 // The update URL must be either empty or valid. |
123 GURL specifics_update_url(specifics.update_url()); | 151 GURL specifics_update_url(specifics.update_url()); |
124 if (!specifics_update_url.is_empty() && !specifics_update_url.is_valid()) { | 152 if (!specifics_update_url.is_empty() && !specifics_update_url.is_valid()) { |
125 LOG(FATAL) << "Attempt to sync bad ExtensionSpecifics (bad update URL):\n" | 153 LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad update URL):\n" |
126 << GetExtensionSpecificsLogMessage(specifics); | 154 << GetExtensionSpecificsLogMessage(specifics); |
| 155 RecordBadSyncData(BAD_UPDATE_URL); |
| 156 return false; |
127 } | 157 } |
128 | 158 |
129 id_ = specifics.id(); | 159 id_ = specifics.id(); |
130 update_url_ = specifics_update_url; | 160 update_url_ = specifics_update_url; |
131 version_ = specifics_version; | 161 version_ = specifics_version; |
132 enabled_ = specifics.enabled(); | 162 enabled_ = specifics.enabled(); |
133 incognito_enabled_ = specifics.incognito_enabled(); | 163 incognito_enabled_ = specifics.incognito_enabled(); |
134 if (specifics.has_all_urls_enabled()) { | 164 if (specifics.has_all_urls_enabled()) { |
135 all_urls_enabled_ = | 165 all_urls_enabled_ = |
136 specifics.all_urls_enabled() ? BOOLEAN_TRUE : BOOLEAN_FALSE; | 166 specifics.all_urls_enabled() ? BOOLEAN_TRUE : BOOLEAN_FALSE; |
137 } else { | 167 } else { |
138 // Set this explicitly (even though it's the default) on the offchance | 168 // Set this explicitly (even though it's the default) on the offchance |
139 // that someone is re-using an ExtensionSyncData object. | 169 // that someone is re-using an ExtensionSyncData object. |
140 all_urls_enabled_ = BOOLEAN_UNSET; | 170 all_urls_enabled_ = BOOLEAN_UNSET; |
141 } | 171 } |
142 remote_install_ = specifics.remote_install(); | 172 remote_install_ = specifics.remote_install(); |
143 installed_by_custodian_ = specifics.installed_by_custodian(); | 173 installed_by_custodian_ = specifics.installed_by_custodian(); |
144 name_ = specifics.name(); | 174 name_ = specifics.name(); |
| 175 return true; |
145 } | 176 } |
146 | 177 |
147 void ExtensionSyncData::set_uninstalled(bool uninstalled) { | 178 void ExtensionSyncData::set_uninstalled(bool uninstalled) { |
148 uninstalled_ = uninstalled; | 179 uninstalled_ = uninstalled; |
149 } | 180 } |
150 | 181 |
151 void ExtensionSyncData::PopulateFromSyncData( | 182 bool ExtensionSyncData::PopulateFromSyncData( |
152 const syncer::SyncData& sync_data) { | 183 const syncer::SyncData& sync_data) { |
153 const sync_pb::EntitySpecifics& entity_specifics = sync_data.GetSpecifics(); | 184 const sync_pb::EntitySpecifics& entity_specifics = sync_data.GetSpecifics(); |
154 | 185 |
155 if (entity_specifics.has_extension()) { | 186 if (entity_specifics.has_extension()) |
156 PopulateFromExtensionSpecifics(entity_specifics.extension()); | 187 return PopulateFromExtensionSpecifics(entity_specifics.extension()); |
157 } else { | 188 |
158 LOG(FATAL) << "Attempt to sync bad EntitySpecifics."; | 189 LOG(ERROR) << "Attempt to sync bad EntitySpecifics: no extension data."; |
159 } | 190 RecordBadSyncData(NO_EXTENSION_SPECIFICS); |
| 191 return false; |
160 } | 192 } |
161 | 193 |
162 } // namespace extensions | 194 } // namespace extensions |
OLD | NEW |