blob: d649a1484eebf1be3b798ea8ade9d7418a752a89 [file] [log] [blame]
Sorin Jianu039032b2018-10-12 21:48:131// Copyright 2018 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_serializer.h"
6
7#include <utility>
8
Hans Wennborgdf87046c2020-04-28 11:06:249#include "base/check.h"
Sorin Jianu039032b2018-10-12 21:48:1310#include "base/containers/flat_map.h"
11#include "base/guid.h"
Sorin Jianu039032b2018-10-12 21:48:1312#include "base/strings/strcat.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/strings/string_util.h"
15#include "base/strings/stringprintf.h"
Sebastien Marchand75a7cdf2018-11-13 23:47:0316#include "base/system/sys_info.h"
Sorin Jianu039032b2018-10-12 21:48:1317#include "base/version.h"
18#include "build/build_config.h"
19#include "components/update_client/activity_data_service.h"
20#include "components/update_client/persisted_data.h"
Sorin Jianu039032b2018-10-12 21:48:1321#include "components/update_client/update_query_params.h"
22#include "components/update_client/updater_state.h"
23
24#if defined(OS_WIN)
25#include "base/win/windows_version.h"
26#endif
27
28namespace update_client {
29
30namespace {
31
32// Returns the amount of physical memory in GB, rounded to the nearest GB.
33int GetPhysicalMemoryGB() {
34 const double kOneGB = 1024 * 1024 * 1024;
35 const int64_t phys_mem = base::SysInfo::AmountOfPhysicalMemory();
36 return static_cast<int>(std::floor(0.5 + phys_mem / kOneGB));
37}
38
39std::string GetOSVersion() {
40#if defined(OS_WIN)
41 const auto ver = base::win::OSInfo::GetInstance()->version_number();
42 return base::StringPrintf("%d.%d.%d.%d", ver.major, ver.minor, ver.build,
43 ver.patch);
44#else
45 return base::SysInfo().OperatingSystemVersion();
46#endif
47}
48
49std::string GetServicePack() {
50#if defined(OS_WIN)
51 return base::win::OSInfo::GetInstance()->service_pack_str();
52#else
53 return {};
54#endif
55}
56
57} // namespace
58
Sorin Jianu039032b2018-10-12 21:48:1359base::flat_map<std::string, std::string> BuildUpdateCheckExtraRequestHeaders(
60 const std::string& prod_id,
61 const base::Version& browser_version,
62 const std::vector<std::string>& ids,
63 bool is_foreground) {
64 // This number of extension ids results in an HTTP header length of about 1KB.
65 constexpr size_t maxIdsCount = 30;
66 const std::vector<std::string>& app_ids =
67 ids.size() <= maxIdsCount
68 ? ids
69 : std::vector<std::string>(ids.cbegin(), ids.cbegin() + maxIdsCount);
70 return {
71 {"X-Goog-Update-Updater",
72 base::StrCat({prod_id, "-", browser_version.GetString()})},
73 {"X-Goog-Update-Interactivity", is_foreground ? "fg" : "bg"},
74 {"X-Goog-Update-AppId", base::JoinString(app_ids, ",")},
75 };
76}
77
78protocol_request::Request MakeProtocolRequest(
79 const std::string& session_id,
80 const std::string& prod_id,
81 const std::string& browser_version,
82 const std::string& lang,
83 const std::string& channel,
84 const std::string& os_long_name,
85 const std::string& download_preference,
86 const base::flat_map<std::string, std::string>& additional_attributes,
87 const std::map<std::string, std::string>* updater_state_attributes,
88 std::vector<protocol_request::App> apps) {
89 protocol_request::Request request;
90 request.protocol_version = kProtocolVersion;
91
92 // Session id and request id.
93 DCHECK(!session_id.empty());
Sorin Jianuc9d642e2018-12-18 19:38:3694 DCHECK(base::StartsWith(session_id, "{", base::CompareCase::SENSITIVE));
95 DCHECK(base::EndsWith(session_id, "}", base::CompareCase::SENSITIVE));
96 request.session_id = session_id;
Sorin Jianu039032b2018-10-12 21:48:1397 request.request_id = base::StrCat({"{", base::GenerateGUID(), "}"});
98
99 request.updatername = prod_id;
100 request.updaterversion = browser_version;
101 request.prodversion = browser_version;
102 request.lang = lang;
103 request.updaterchannel = channel;
104 request.prodchannel = channel;
105 request.operating_system = UpdateQueryParams::GetOS();
106 request.arch = UpdateQueryParams::GetArch();
107 request.nacl_arch = UpdateQueryParams::GetNaclArch();
108 request.dlpref = download_preference;
109 request.additional_attributes = additional_attributes;
110
111#if defined(OS_WIN)
112 if (base::win::OSInfo::GetInstance()->wow64_status() ==
113 base::win::OSInfo::WOW64_ENABLED)
114 request.is_wow64 = true;
115#endif
116
117 if (updater_state_attributes &&
118 updater_state_attributes->count(UpdaterState::kIsEnterpriseManaged)) {
119 request.domain_joined =
120 updater_state_attributes->at(UpdaterState::kIsEnterpriseManaged) == "1";
121 }
122
123 // HW platform information.
124 request.hw.physmemory = GetPhysicalMemoryGB();
125
126 // OS version and platform information.
127 request.os.platform = os_long_name;
128 request.os.version = GetOSVersion();
129 request.os.service_pack = GetServicePack();
130 request.os.arch = base::SysInfo().OperatingSystemArchitecture();
131
132 if (updater_state_attributes) {
Anton Bikineev1156b5f2021-05-15 22:35:36133 request.updater = absl::make_optional<protocol_request::Updater>();
Sorin Jianu039032b2018-10-12 21:48:13134 auto it = updater_state_attributes->find("name");
135 if (it != updater_state_attributes->end())
136 request.updater->name = it->second;
137 it = updater_state_attributes->find("version");
138 if (it != updater_state_attributes->end())
139 request.updater->version = it->second;
140 it = updater_state_attributes->find("ismachine");
141 if (it != updater_state_attributes->end()) {
142 DCHECK(it->second == "0" || it->second == "1");
143 request.updater->is_machine = it->second != "0";
144 }
145 it = updater_state_attributes->find("autoupdatecheckenabled");
146 if (it != updater_state_attributes->end()) {
147 DCHECK(it->second == "0" || it->second == "1");
148 request.updater->autoupdate_check_enabled = it->second != "0";
149 }
150 it = updater_state_attributes->find("laststarted");
151 if (it != updater_state_attributes->end()) {
152 int last_started = 0;
153 if (base::StringToInt(it->second, &last_started))
154 request.updater->last_started = last_started;
155 }
156 it = updater_state_attributes->find("lastchecked");
157 if (it != updater_state_attributes->end()) {
158 int last_checked = 0;
159 if (base::StringToInt(it->second, &last_checked))
160 request.updater->last_checked = last_checked;
161 }
162 it = updater_state_attributes->find("updatepolicy");
163 if (it != updater_state_attributes->end()) {
164 int update_policy = 0;
165 if (base::StringToInt(it->second, &update_policy))
166 request.updater->update_policy = update_policy;
167 }
168 }
169
170 request.apps = std::move(apps);
171 return request;
172}
173
174protocol_request::App MakeProtocolApp(
175 const std::string& app_id,
176 const base::Version& version,
Anton Bikineev1156b5f2021-05-15 22:35:36177 absl::optional<std::vector<base::Value>> events) {
Sorin Jianu039032b2018-10-12 21:48:13178 protocol_request::App app;
179 app.app_id = app_id;
180 app.version = version.GetString();
181 app.events = std::move(events);
182 return app;
183}
184
185protocol_request::App MakeProtocolApp(
186 const std::string& app_id,
187 const base::Version& version,
188 const std::string& brand_code,
189 const std::string& install_source,
190 const std::string& install_location,
191 const std::string& fingerprint,
192 const base::flat_map<std::string, std::string>& installer_attributes,
193 const std::string& cohort,
194 const std::string& cohort_hint,
195 const std::string& cohort_name,
Yann Dago84505252020-08-27 22:20:51196 const std::string& release_channel,
Sorin Jianu039032b2018-10-12 21:48:13197 const std::vector<int>& disabled_reasons,
Anton Bikineev1156b5f2021-05-15 22:35:36198 absl::optional<protocol_request::UpdateCheck> update_check,
199 absl::optional<protocol_request::Ping> ping) {
200 auto app = MakeProtocolApp(app_id, version, absl::nullopt);
Sorin Jianu039032b2018-10-12 21:48:13201 app.brand_code = brand_code;
202 app.install_source = install_source;
203 app.install_location = install_location;
204 app.fingerprint = fingerprint;
205 app.installer_attributes = installer_attributes;
206 app.cohort = cohort;
207 app.cohort_hint = cohort_hint;
208 app.cohort_name = cohort_name;
Yann Dago84505252020-08-27 22:20:51209 app.release_channel = release_channel;
Sorin Jianu039032b2018-10-12 21:48:13210 app.enabled = disabled_reasons.empty();
211 app.disabled_reasons = disabled_reasons;
212 app.update_check = std::move(update_check);
213 app.ping = std::move(ping);
214 return app;
215}
216
217protocol_request::UpdateCheck MakeProtocolUpdateCheck(bool is_update_disabled) {
218 protocol_request::UpdateCheck update_check;
219 update_check.is_update_disabled = is_update_disabled;
220 return update_check;
221}
222
223protocol_request::Ping MakeProtocolPing(const std::string& app_id,
Joshua Pawlicki44bef9522020-12-09 17:07:23224 const PersistedData* metadata,
225 bool active) {
Sorin Jianu039032b2018-10-12 21:48:13226 DCHECK(metadata);
227 protocol_request::Ping ping;
228
Joshua Pawlicki44bef9522020-12-09 17:07:23229 if (active) {
Sorin Jianu039032b2018-10-12 21:48:13230 const int date_last_active = metadata->GetDateLastActive(app_id);
231 if (date_last_active != kDateUnknown) {
232 ping.date_last_active = date_last_active;
233 } else {
234 ping.days_since_last_active_ping =
235 metadata->GetDaysSinceLastActive(app_id);
236 }
237 }
238 const int date_last_roll_call = metadata->GetDateLastRollCall(app_id);
239 if (date_last_roll_call != kDateUnknown) {
240 ping.date_last_roll_call = date_last_roll_call;
241 } else {
242 ping.days_since_last_roll_call = metadata->GetDaysSinceLastRollCall(app_id);
243 }
244 ping.ping_freshness = metadata->GetPingFreshness(app_id);
245
246 return ping;
247}
248
249} // namespace update_client