blob: bd94b2dd21cefbc76a824f7eb99c2c955e81e6b9 [file] [log] [blame]
Darin Petkovf2065b42011-05-17 16:36:27 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Darin Petkova4a8a8c2010-07-15 22:21:12 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "update_engine/omaha_request_params.h"
6
7#include <errno.h>
8#include <fcntl.h>
9#include <sys/utsname.h>
10
11#include <map>
12#include <string>
Darin Petkova3df55b2010-11-15 13:33:55 -080013#include <vector>
Darin Petkova4a8a8c2010-07-15 22:21:12 -070014
Darin Petkov49d91322010-10-25 16:34:58 -070015#include <base/file_util.h>
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020016#include <policy/device_policy.h>
Darin Petkov49d91322010-10-25 16:34:58 -070017
Darin Petkova4a8a8c2010-07-15 22:21:12 -070018#include "update_engine/simple_key_value_store.h"
Jay Srinivasanae4697c2013-03-18 17:08:08 -070019#include "update_engine/system_state.h"
Darin Petkova4a8a8c2010-07-15 22:21:12 -070020#include "update_engine/utils.h"
21
Darin Petkov49d91322010-10-25 16:34:58 -070022#define CALL_MEMBER_FN(object, member) ((object).*(member))
23
Darin Petkova4a8a8c2010-07-15 22:21:12 -070024using std::map;
25using std::string;
Darin Petkova3df55b2010-11-15 13:33:55 -080026using std::vector;
Darin Petkova4a8a8c2010-07-15 22:21:12 -070027
Darin Petkova4a8a8c2010-07-15 22:21:12 -070028namespace chromeos_update_engine {
29
Darin Petkov5a7f5652010-07-22 21:40:09 -070030const char* const OmahaRequestParams::kAppId(
31 "{87efface-864d-49a5-9bb3-4b050a7c227a}");
32const char* const OmahaRequestParams::kOsPlatform("Chrome OS");
33const char* const OmahaRequestParams::kOsVersion("Indy");
Jay Srinivasan55f50c22013-01-10 19:24:35 -080034const char* const kProductionOmahaUrl(
Darin Petkov5a7f5652010-07-22 21:40:09 -070035 "https://tools.google.com/service/update2");
36
Jay Srinivasanae4697c2013-03-18 17:08:08 -070037const char* const OmahaRequestParams::kUpdateChannelKey(
38 "CHROMEOS_RELEASE_TRACK");
39const char* const OmahaRequestParams::kIsPowerwashAllowedKey(
40 "CHROMEOS_IS_POWERWASH_ALLOWED");
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020041
Jay Srinivasanae4697c2013-03-18 17:08:08 -070042const char* kChannelsByStability[] = {
43 // This list has to be sorted from least stable to most stable channel.
44 "canary-channel",
45 "dev-channel",
46 "beta-channel",
47 "stable-channel",
48};
Darin Petkov49d91322010-10-25 16:34:58 -070049
Jay Srinivasanae4697c2013-03-18 17:08:08 -070050bool OmahaRequestParams::Init(const std::string& in_app_version,
51 const std::string& in_update_url,
52 bool in_interactive) {
Jay Srinivasan1c0fe792013-03-28 16:45:25 -070053 LOG(INFO) << "Initializing parameters for this update attempt";
Jay Srinivasanae4697c2013-03-18 17:08:08 -070054 InitFromLsbValue();
Darin Petkov10d02dd2011-01-10 14:57:39 -080055 bool stateful_override = !ShouldLockDown();
Jay Srinivasanae4697c2013-03-18 17:08:08 -070056 os_platform_ = OmahaRequestParams::kOsPlatform;
57 os_version_ = OmahaRequestParams::kOsVersion;
58 app_version_ = in_app_version.empty() ?
Darin Petkov10d02dd2011-01-10 14:57:39 -080059 GetLsbValue("CHROMEOS_RELEASE_VERSION", "", NULL, stateful_override) :
60 in_app_version;
Jay Srinivasanae4697c2013-03-18 17:08:08 -070061 os_sp_ = app_version_ + "_" + GetMachineType();
62 os_board_ = GetLsbValue("CHROMEOS_RELEASE_BOARD",
63 "",
64 NULL,
65 stateful_override);
66 app_id_ = GetLsbValue("CHROMEOS_RELEASE_APPID",
67 OmahaRequestParams::kAppId,
68 NULL,
69 stateful_override);
70 board_app_id_ = GetLsbValue("CHROMEOS_BOARD_APPID",
71 app_id_,
72 NULL,
73 stateful_override);
74 app_lang_ = "en-US";
75 hwid_ = utils::GetHardwareClass();
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020076
Jay Srinivasanae4697c2013-03-18 17:08:08 -070077 if (current_channel_ == target_channel_) {
78 // deltas are only okay if the /.nodelta file does not exist. if we don't
79 // know (i.e. stat() returns some unexpected error), then err on the side of
80 // caution and say deltas are not okay.
81 struct stat stbuf;
82 delta_okay_ = (stat((root_ + "/.nodelta").c_str(), &stbuf) < 0) &&
83 (errno == ENOENT);
84
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020085 } else {
Jay Srinivasanae4697c2013-03-18 17:08:08 -070086 LOG(INFO) << "Disabling deltas as a channel change is pending";
87 // For now, disable delta updates if the current channel is different from
88 // the channel that we're sending to the update server because such updates
89 // are destined to fail -- the current rootfs hash will be different than
90 // the expected hash due to the different channel in /etc/lsb-release.
91 delta_okay_ = false;
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020092 }
93
Jay Srinivasanae4697c2013-03-18 17:08:08 -070094 if (in_update_url.empty())
95 update_url_ = GetLsbValue("CHROMEOS_AUSERVER", kProductionOmahaUrl, NULL,
96 stateful_override);
97 else
98 update_url_ = in_update_url;
Gilad Arnoldbbdd4902013-01-10 16:06:30 -080099
100 // Set the interactive flag accordingly.
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700101 interactive_ = in_interactive;
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700102 return true;
103}
104
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700105bool OmahaRequestParams::SetTargetChannel(const std::string& new_target_channel,
106 bool is_powerwash_allowed) {
107 LOG(INFO) << "SetTargetChannel called with " << new_target_channel
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700108 << ", Is Powerwash Allowed = "
109 << utils::ToString(is_powerwash_allowed)
110 << ". Current channel = " << current_channel_
111 << ", existing target channel = " << target_channel_
112 << ", download channel = " << download_channel_;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700113
114 if (current_channel_ == "canary-channel") {
115 // TODO(jaysri): chromium-os:39751: We don't have the UI warnings yet. So,
116 // enable the powerwash-on-changing-to-more-stable-channel behavior for now
117 // only on canary-channel devices.
118 is_powerwash_allowed = true;
119 LOG(INFO) << "Is Powerwash Allowed set to true as we are in canary-channel";
120 } else if (!utils::IsOfficialBuild() &&
121 current_channel_ == "testimage-channel") {
122 // Also, allow test builds to have the powerwash behavior so we can always
123 // test channel changing behavior on them, without having to first get them
124 // on an official channel.
125 is_powerwash_allowed = true;
126 LOG(INFO) << "Is Powerwash Allowed set to true as we are running an "
127 "unofficial build";
128 }
129
130 TEST_AND_RETURN_FALSE(IsValidChannel(new_target_channel));
Darin Petkov49d91322010-10-25 16:34:58 -0700131 FilePath kFile(root_ + utils::kStatefulPartition + "/etc/lsb-release");
132 string file_data;
133 map<string, string> data;
134 if (file_util::ReadFileToString(kFile, &file_data)) {
135 data = simple_key_value_store::ParseString(file_data);
136 }
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700137 data[kUpdateChannelKey] = new_target_channel;
138 data[kIsPowerwashAllowedKey] = is_powerwash_allowed ? "true" : "false";
Darin Petkov49d91322010-10-25 16:34:58 -0700139 file_data = simple_key_value_store::AssembleString(data);
140 TEST_AND_RETURN_FALSE(file_util::CreateDirectory(kFile.DirName()));
141 TEST_AND_RETURN_FALSE(
142 file_util::WriteFile(kFile, file_data.data(), file_data.size()) ==
143 static_cast<int>(file_data.size()));
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700144 target_channel_ = new_target_channel;
145 is_powerwash_allowed_ = is_powerwash_allowed;
Darin Petkov49d91322010-10-25 16:34:58 -0700146 return true;
147}
148
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700149void OmahaRequestParams::SetTargetChannelFromLsbValue() {
150 string target_channel_new_value = GetLsbValue(
151 kUpdateChannelKey,
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700152 current_channel_,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700153 &chromeos_update_engine::OmahaRequestParams::IsValidChannel,
154 true); // stateful_override
155
156 if (target_channel_ != target_channel_new_value) {
157 target_channel_ = target_channel_new_value;
158 LOG(INFO) << "Target Channel set to " << target_channel_
159 << " from LSB file";
160 }
Darin Petkov49d91322010-10-25 16:34:58 -0700161}
162
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700163void OmahaRequestParams::SetCurrentChannelFromLsbValue() {
164 string current_channel_new_value = GetLsbValue(
165 kUpdateChannelKey,
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700166 current_channel_,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700167 NULL, // No need to validate the read-only rootfs channel.
168 false); // stateful_override is false so we get the current channel.
169
170 if (current_channel_ != current_channel_new_value) {
171 current_channel_ = current_channel_new_value;
172 LOG(INFO) << "Current Channel set to " << current_channel_
173 << " from LSB file in rootfs";
174 }
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900175}
176
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700177void OmahaRequestParams::SetIsPowerwashAllowedFromLsbValue() {
178 string is_powerwash_allowed_str = GetLsbValue(
179 kIsPowerwashAllowedKey,
180 "false",
181 NULL, // no need to validate
182 true); // always get it from stateful, as that's the only place it'll be
183 bool is_powerwash_allowed_new_value = (is_powerwash_allowed_str == "true");
184 if (is_powerwash_allowed_ != is_powerwash_allowed_new_value) {
185 is_powerwash_allowed_ = is_powerwash_allowed_new_value;
186 LOG(INFO) << "Powerwash Allowed set to "
187 << utils::ToString(is_powerwash_allowed_)
188 << " from LSB file in stateful";
189 }
190}
191
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700192void OmahaRequestParams::UpdateDownloadChannel() {
193 if (download_channel_ != target_channel_) {
194 download_channel_ = target_channel_;
195 LOG(INFO) << "Download channel for this attempt = " << download_channel_;
196 }
197}
198
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700199void OmahaRequestParams::InitFromLsbValue() {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700200 SetCurrentChannelFromLsbValue();
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700201 SetTargetChannelFromLsbValue();
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700202 SetIsPowerwashAllowedFromLsbValue();
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700203 UpdateDownloadChannel();
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700204}
205
206string OmahaRequestParams::GetLsbValue(const string& key,
207 const string& default_value,
208 ValueValidator validator,
209 bool stateful_override) const {
Darin Petkova3df55b2010-11-15 13:33:55 -0800210 vector<string> files;
211 if (stateful_override) {
212 files.push_back(string(utils::kStatefulPartition) + "/etc/lsb-release");
213 }
214 files.push_back("/etc/lsb-release");
215 for (vector<string>::const_iterator it = files.begin();
216 it != files.end(); ++it) {
217 // TODO(adlr): make sure files checked are owned as root (and all their
218 // parents are recursively, too).
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700219 string file_data;
Gilad Arnold19a45f02012-07-19 12:36:10 -0700220 if (!utils::ReadFile(root_ + *it, &file_data))
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700221 continue;
222
223 map<string, string> data = simple_key_value_store::ParseString(file_data);
Darin Petkov49d91322010-10-25 16:34:58 -0700224 if (utils::MapContainsKey(data, key)) {
225 const string& value = data[key];
226 if (validator && !CALL_MEMBER_FN(*this, validator)(value)) {
227 continue;
228 }
229 return value;
230 }
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700231 }
232 // not found
233 return default_value;
234}
235
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700236string OmahaRequestParams::GetMachineType() const {
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700237 struct utsname buf;
238 string ret;
239 if (uname(&buf) == 0)
240 ret = buf.machine;
241 return ret;
242}
243
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700244bool OmahaRequestParams::ShouldLockDown() const {
Darin Petkov10d02dd2011-01-10 14:57:39 -0800245 if (force_lock_down_) {
246 return forced_lock_down_;
247 }
248 return utils::IsOfficialBuild() && utils::IsNormalBootMode();
Darin Petkov49d91322010-10-25 16:34:58 -0700249}
250
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700251bool OmahaRequestParams::IsValidChannel(const std::string& channel) const {
252 return GetChannelIndex(channel) >= 0;
Darin Petkov49d91322010-10-25 16:34:58 -0700253}
254
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700255void OmahaRequestParams::set_root(const std::string& root) {
256 root_ = root;
257 InitFromLsbValue();
258}
259
260void OmahaRequestParams::SetLockDown(bool lock) {
Darin Petkov10d02dd2011-01-10 14:57:39 -0800261 force_lock_down_ = true;
262 forced_lock_down_ = lock;
Darin Petkov49d91322010-10-25 16:34:58 -0700263}
264
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700265int OmahaRequestParams::GetChannelIndex(const std::string& channel) const {
266 for (size_t t = 0; t < arraysize(kChannelsByStability); ++t)
267 if (channel == kChannelsByStability[t])
268 return t;
269
270 return -1;
271}
272
273bool OmahaRequestParams::to_more_stable_channel() const {
274 int current_channel_index = GetChannelIndex(current_channel_);
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700275 int download_channel_index = GetChannelIndex(download_channel_);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700276
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700277 return download_channel_index > current_channel_index;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700278}
279
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700280} // namespace chromeos_update_engine