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

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

Issue 996213005: Don't crash when trying to create an ExtensionSyncData from invalid SyncData. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: kalmanize Created 5 years, 9 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 (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
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_sync_data.h ('k') | chrome/browser/extensions/extension_sync_data_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698