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

Side by Side Diff: components/update_client/protocol_builder.cc

Issue 2888183003: Consolidate the update_client serialization code. (Closed)
Patch Set: . Created 3 years, 7 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
(Empty)
1 // Copyright 2017 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.
4
5 #include "components/update_client/protocol_builder.h"
6
7 #include <stdint.h>
8
9 #include "base/guid.h"
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/sys_info.h"
14 #include "build/build_config.h"
15 #include "components/update_client/component.h"
16 #include "components/update_client/configurator.h"
17 #include "components/update_client/persisted_data.h"
18 #include "components/update_client/protocol_parser.h"
19 #include "components/update_client/update_query_params.h"
20 #include "components/update_client/updater_state.h"
21 #include "components/update_client/utils.h"
22
23 #if defined(OS_WIN)
24 #include "base/win/windows_version.h"
25 #endif
26
27 namespace update_client {
28
29 namespace {
30
31 // Returns a sanitized version of the brand or an empty string otherwise.
32 std::string SanitizeBrand(const std::string& brand) {
33 return IsValidBrand(brand) ? brand : std::string("");
34 }
35
36 // Filters invalid attributes from |installer_attributes|.
37 InstallerAttributes SanitizeInstallerAttributes(
38 const InstallerAttributes& installer_attributes) {
39 InstallerAttributes sanitized_attrs;
40 for (const auto& attr : installer_attributes) {
41 if (IsValidInstallerAttribute(attr))
42 sanitized_attrs.insert(attr);
43 }
44 return sanitized_attrs;
45 }
46
47 // Returns the amount of physical memory in GB, rounded to the nearest GB.
48 int GetPhysicalMemoryGB() {
49 const double kOneGB = 1024 * 1024 * 1024;
50 const int64_t phys_mem = base::SysInfo::AmountOfPhysicalMemory();
51 return static_cast<int>(std::floor(0.5 + phys_mem / kOneGB));
52 }
53
54 std::string GetOSVersion() {
55 #if defined(OS_WIN)
56 const auto ver = base::win::OSInfo::GetInstance()->version_number();
57 return base::StringPrintf("%d.%d.%d.%d", ver.major, ver.minor, ver.build,
58 ver.patch);
59 #else
60 return base::SysInfo().OperatingSystemVersion();
61 #endif
62 }
63
64 std::string GetServicePack() {
65 #if defined(OS_WIN)
66 return base::win::OSInfo::GetInstance()->service_pack_str();
67 #else
68 return std::string();
69 #endif
70 }
71
72 // Returns a string literal corresponding to the value of the downloader |d|.
73 const char* DownloaderToString(CrxDownloader::DownloadMetrics::Downloader d) {
74 switch (d) {
75 case CrxDownloader::DownloadMetrics::kUrlFetcher:
76 return "direct";
77 case CrxDownloader::DownloadMetrics::kBits:
78 return "bits";
79 default:
80 return "unknown";
81 }
82 }
83
84 // Returns a string representing a sequence of download complete events
85 // corresponding to each download metrics in |item|.
86 std::string BuildDownloadCompleteEventElements(const Component& component) {
87 using base::StringAppendF;
88 std::string download_events;
89 for (const auto& metrics : component.download_metrics()) {
90 std::string event("<event eventtype=\"14\"");
91 StringAppendF(&event, " eventresult=\"%d\"", metrics.error == 0);
92 StringAppendF(&event, " downloader=\"%s\"",
93 DownloaderToString(metrics.downloader));
94 if (metrics.error) {
95 StringAppendF(&event, " errorcode=\"%d\"", metrics.error);
96 }
97 StringAppendF(&event, " url=\"%s\"", metrics.url.spec().c_str());
98
99 // -1 means that the byte counts are not known.
100 if (metrics.downloaded_bytes != -1) {
101 StringAppendF(&event, " downloaded=\"%s\"",
102 base::Int64ToString(metrics.downloaded_bytes).c_str());
103 }
104 if (metrics.total_bytes != -1) {
105 StringAppendF(&event, " total=\"%s\"",
106 base::Int64ToString(metrics.total_bytes).c_str());
107 }
108
109 if (metrics.download_time_ms) {
110 StringAppendF(&event, " download_time_ms=\"%s\"",
111 base::Uint64ToString(metrics.download_time_ms).c_str());
112 }
113 StringAppendF(&event, "/>");
114
115 download_events += event;
116 }
117 return download_events;
118 }
119
120 // Returns a string representing one ping event for the update of a component.
121 // The event type for this ping event is 3.
122 std::string BuildUpdateCompleteEventElement(const Component& component) {
123 DCHECK(component.state() == ComponentState::kUpdateError ||
124 component.state() == ComponentState::kUpdated);
125
126 using base::StringAppendF;
127
128 std::string ping_event("<event eventtype=\"3\"");
129 const int event_result = component.state() == ComponentState::kUpdated;
130 StringAppendF(&ping_event, " eventresult=\"%d\"", event_result);
131 if (component.error_category())
132 StringAppendF(&ping_event, " errorcat=\"%d\"", component.error_category());
133 if (component.error_code())
134 StringAppendF(&ping_event, " errorcode=\"%d\"", component.error_code());
135 if (component.extra_code1())
136 StringAppendF(&ping_event, " extracode1=\"%d\"", component.extra_code1());
137 if (HasDiffUpdate(component))
138 StringAppendF(&ping_event, " diffresult=\"%d\"",
139 !component.diff_update_failed());
140 if (component.diff_error_category()) {
141 StringAppendF(&ping_event, " differrorcat=\"%d\"",
142 component.diff_error_category());
143 }
144 if (component.diff_error_code())
145 StringAppendF(&ping_event, " differrorcode=\"%d\"",
146 component.diff_error_code());
147 if (component.diff_extra_code1()) {
148 StringAppendF(&ping_event, " diffextracode1=\"%d\"",
149 component.diff_extra_code1());
150 }
151 if (!component.previous_fp().empty())
152 StringAppendF(&ping_event, " previousfp=\"%s\"",
153 component.previous_fp().c_str());
154 if (!component.next_fp().empty())
155 StringAppendF(&ping_event, " nextfp=\"%s\"", component.next_fp().c_str());
156 StringAppendF(&ping_event, "/>");
157 return ping_event;
158 }
159
160 // Returns a string representing one ping event for the uninstall of a
161 // component. The event type for this ping event is 4.
162 std::string BuildUninstalledEventElement(const Component& component) {
163 DCHECK(component.state() == ComponentState::kUninstalled);
164
165 using base::StringAppendF;
166
167 std::string ping_event("<event eventtype=\"4\" eventresult=\"1\"");
168 if (component.extra_code1())
169 StringAppendF(&ping_event, " extracode1=\"%d\"", component.extra_code1());
170 StringAppendF(&ping_event, "/>");
171 return ping_event;
172 }
173
174 } // namespace
175
176 std::string BuildProtocolRequest(
177 const std::string& prod_id,
178 const std::string& browser_version,
179 const std::string& channel,
180 const std::string& lang,
181 const std::string& os_long_name,
182 const std::string& download_preference,
183 const std::string& request_body,
184 const std::string& additional_attributes,
185 const std::unique_ptr<UpdaterState::Attributes>& updater_state_attributes) {
186 std::string request = base::StringPrintf(
187 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
188 "<request protocol=\"%s\" ",
189 kProtocolVersion);
190
191 if (!additional_attributes.empty())
192 base::StringAppendF(&request, "%s ", additional_attributes.c_str());
193
194 // Chrome version and platform information.
195 base::StringAppendF(
196 &request,
197 "version=\"%s-%s\" prodversion=\"%s\" "
198 "requestid=\"{%s}\" lang=\"%s\" updaterchannel=\"%s\" prodchannel=\"%s\" "
199 "os=\"%s\" arch=\"%s\" nacl_arch=\"%s\"",
200 prod_id.c_str(), // "version" is prefixed by prod_id.
201 browser_version.c_str(),
202 browser_version.c_str(), // "prodversion"
203 base::GenerateGUID().c_str(), // "requestid"
204 lang.c_str(), // "lang"
205 channel.c_str(), // "updaterchannel"
206 channel.c_str(), // "prodchannel"
207 UpdateQueryParams::GetOS(), // "os"
208 UpdateQueryParams::GetArch(), // "arch"
209 UpdateQueryParams::GetNaclArch()); // "nacl_arch"
210 #if defined(OS_WIN)
211 const bool is_wow64(base::win::OSInfo::GetInstance()->wow64_status() ==
212 base::win::OSInfo::WOW64_ENABLED);
213 if (is_wow64)
214 base::StringAppendF(&request, " wow64=\"1\"");
215 #endif
216 if (!download_preference.empty())
217 base::StringAppendF(&request, " dlpref=\"%s\"",
218 download_preference.c_str());
219 if (updater_state_attributes &&
220 updater_state_attributes->count(UpdaterState::kIsEnterpriseManaged)) {
221 base::StringAppendF(
222 &request, " %s=\"%s\"", // domainjoined
223 UpdaterState::kIsEnterpriseManaged,
224 (*updater_state_attributes)[UpdaterState::kIsEnterpriseManaged]
225 .c_str());
226 }
227 base::StringAppendF(&request, ">");
228
229 // HW platform information.
230 base::StringAppendF(&request, "<hw physmemory=\"%d\"/>",
231 GetPhysicalMemoryGB()); // "physmem" in GB.
232
233 // OS version and platform information.
234 const std::string os_version = GetOSVersion();
235 const std::string os_sp = GetServicePack();
236 base::StringAppendF(
237 &request, "<os platform=\"%s\" arch=\"%s\"",
238 os_long_name.c_str(), // "platform"
239 base::SysInfo().OperatingSystemArchitecture().c_str()); // "arch"
240 if (!os_version.empty())
241 base::StringAppendF(&request, " version=\"%s\"", os_version.c_str());
242 if (!os_sp.empty())
243 base::StringAppendF(&request, " sp=\"%s\"", os_sp.c_str());
244 base::StringAppendF(&request, "/>");
245
246 #if defined(GOOGLE_CHROME_BUILD)
247 // Updater state.
248 if (updater_state_attributes) {
249 base::StringAppendF(&request, "<updater");
250 for (const auto& attr : *updater_state_attributes) {
251 if (attr.first != UpdaterState::kIsEnterpriseManaged) {
252 base::StringAppendF(&request, " %s=\"%s\"", attr.first.c_str(),
253 attr.second.c_str());
254 }
255 }
256 base::StringAppendF(&request, "/>");
257 }
258 #endif // GOOGLE_CHROME_BUILD
259
260 // The actual payload of the request.
261 base::StringAppendF(&request, "%s</request>", request_body.c_str());
262
263 return request;
264 }
265
266 std::string BuildUpdateCheckRequest(
267 const Configurator& config,
268 const std::vector<std::string>& ids_checked,
269 const IdToComponentPtrMap& components,
270 PersistedData* metadata,
271 const std::string& additional_attributes,
272 bool enabled_component_updates,
273 const std::unique_ptr<UpdaterState::Attributes>& updater_state_attributes) {
274 const std::string brand(SanitizeBrand(config.GetBrand()));
275 std::string app_elements;
276 for (const auto& id : ids_checked) {
277 DCHECK_EQ(1u, components.count(id));
278 const Component& component = *components.at(id);
279
280 const update_client::InstallerAttributes installer_attributes(
281 SanitizeInstallerAttributes(
282 component.crx_component().installer_attributes));
283 std::string app("<app ");
284 base::StringAppendF(&app, "appid=\"%s\" version=\"%s\"",
285 component.id().c_str(),
286 component.crx_component().version.GetString().c_str());
287 if (!brand.empty())
288 base::StringAppendF(&app, " brand=\"%s\"", brand.c_str());
289 if (component.on_demand())
290 base::StringAppendF(&app, " installsource=\"ondemand\"");
291 for (const auto& attr : installer_attributes) {
292 base::StringAppendF(&app, " %s=\"%s\"", attr.first.c_str(),
293 attr.second.c_str());
294 }
295 const std::string cohort = metadata->GetCohort(component.id());
296 const std::string cohort_name = metadata->GetCohortName(component.id());
297 const std::string cohort_hint = metadata->GetCohortHint(component.id());
298 if (!cohort.empty())
299 base::StringAppendF(&app, " cohort=\"%s\"", cohort.c_str());
300 if (!cohort_name.empty())
301 base::StringAppendF(&app, " cohortname=\"%s\"", cohort_name.c_str());
302 if (!cohort_hint.empty())
303 base::StringAppendF(&app, " cohorthint=\"%s\"", cohort_hint.c_str());
304 base::StringAppendF(&app, ">");
305
306 base::StringAppendF(&app, "<updatecheck");
307 if (component.crx_component()
308 .supports_group_policy_enable_component_updates &&
309 !enabled_component_updates) {
310 base::StringAppendF(&app, " updatedisabled=\"true\"");
311 }
312 base::StringAppendF(&app, "/>");
313
314 base::StringAppendF(&app, "<ping rd=\"%d\" ping_freshness=\"%s\"/>",
315 metadata->GetDateLastRollCall(component.id()),
316 metadata->GetPingFreshness(component.id()).c_str());
317 if (!component.crx_component().fingerprint.empty()) {
318 base::StringAppendF(&app,
319 "<packages>"
320 "<package fp=\"%s\"/>"
321 "</packages>",
322 component.crx_component().fingerprint.c_str());
323 }
324 base::StringAppendF(&app, "</app>");
325 app_elements.append(app);
326 VLOG(1) << "Appending to update request: " << app;
327 }
328
329 // Include the updater state in the update check request.
330 return BuildProtocolRequest(
331 config.GetProdId(), config.GetBrowserVersion().GetString(),
332 config.GetChannel(), config.GetLang(), config.GetOSLongName(),
333 config.GetDownloadPreference(), app_elements, additional_attributes,
334 updater_state_attributes);
335 }
336
337 std::string BuildPing(const Configurator& config, const Component& component) {
338 const char app_element_format[] =
339 "<app appid=\"%s\" version=\"%s\" nextversion=\"%s\">"
340 "%s"
341 "%s"
342 "</app>";
343
344 std::string ping_event;
345 switch (component.state()) {
346 case ComponentState::kUpdateError: // Fall through.
347 case ComponentState::kUpdated:
348 ping_event = BuildUpdateCompleteEventElement(component);
349 break;
350 case ComponentState::kUninstalled:
351 ping_event = BuildUninstalledEventElement(component);
352 break;
353 default:
354 NOTREACHED();
355 break;
356 }
357
358 const std::string app_element(base::StringPrintf(
359 app_element_format,
360 component.id().c_str(), // "appid"
361 component.previous_version().GetString().c_str(), // "version"
362 component.next_version().GetString().c_str(), // "nextversion"
363 ping_event.c_str(), // ping event
364 BuildDownloadCompleteEventElements(component)
365 .c_str())); // download events
366
367 // The ping request does not include any updater state.
368 return BuildProtocolRequest(
369 config.GetProdId(), config.GetBrowserVersion().GetString(),
370 config.GetChannel(), config.GetLang(), config.GetOSLongName(),
371 config.GetDownloadPreference(), app_element, "", nullptr);
372 }
373
374 } // namespace update_client
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698