1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "update_engine/cros/omaha_request_action.h"
18 
19 #include <inttypes.h>
20 
21 #include <limits>
22 #include <map>
23 #include <sstream>
24 #include <string>
25 #include <utility>
26 #include <vector>
27 
28 #include <base/bind.h>
29 #include <base/files/file_util.h>
30 #include <base/logging.h>
31 #include <base/optional.h>
32 #include <base/rand_util.h>
33 #include <base/strings/string_number_conversions.h>
34 #include <base/strings/string_split.h>
35 #include <base/strings/string_util.h>
36 #include <base/strings/stringprintf.h>
37 #include <base/time/time.h>
38 #include <brillo/key_value_store.h>
39 #include <expat.h>
40 #include <metrics/metrics_library.h>
41 #include <policy/libpolicy.h>
42 
43 #include "update_engine/common/action_pipe.h"
44 #include "update_engine/common/constants.h"
45 #include "update_engine/common/hardware_interface.h"
46 #include "update_engine/common/hash_calculator.h"
47 #include "update_engine/common/metrics_reporter_interface.h"
48 #include "update_engine/common/platform_constants.h"
49 #include "update_engine/common/prefs.h"
50 #include "update_engine/common/prefs_interface.h"
51 #include "update_engine/common/system_state.h"
52 #include "update_engine/common/utils.h"
53 #include "update_engine/cros/connection_manager_interface.h"
54 #include "update_engine/cros/omaha_request_builder_xml.h"
55 #include "update_engine/cros/omaha_request_params.h"
56 #include "update_engine/cros/p2p_manager.h"
57 #include "update_engine/cros/payload_state_interface.h"
58 #include "update_engine/cros/update_attempter.h"
59 #include "update_engine/metrics_utils.h"
60 
61 using base::Optional;
62 using base::Time;
63 using base::TimeDelta;
64 using chromeos_update_manager::kRollforwardInfinity;
65 using std::map;
66 using std::string;
67 using std::vector;
68 
69 namespace chromeos_update_engine {
70 
71 // List of custom attributes that we interpret in the Omaha response:
72 constexpr char kAttrDeadline[] = "deadline";
73 constexpr char kAttrDisableP2PForDownloading[] = "DisableP2PForDownloading";
74 constexpr char kAttrDisableP2PForSharing[] = "DisableP2PForSharing";
75 constexpr char kAttrDisablePayloadBackoff[] = "DisablePayloadBackoff";
76 constexpr char kAttrVersion[] = "version";
77 // Deprecated: "IsDelta"
78 constexpr char kAttrIsDeltaPayload[] = "IsDeltaPayload";
79 constexpr char kAttrMaxFailureCountPerUrl[] = "MaxFailureCountPerUrl";
80 constexpr char kAttrMaxDaysToScatter[] = "MaxDaysToScatter";
81 // Deprecated: "ManifestSignatureRsa"
82 // Deprecated: "ManifestSize"
83 constexpr char kAttrMetadataSignatureRsa[] = "MetadataSignatureRsa";
84 constexpr char kAttrMetadataSize[] = "MetadataSize";
85 constexpr char kAttrMoreInfo[] = "MoreInfo";
86 constexpr char kAttrNoUpdate[] = "noupdate";
87 // Deprecated: "NeedsAdmin"
88 constexpr char kAttrPollInterval[] = "PollInterval";
89 constexpr char kAttrPowerwash[] = "Powerwash";
90 constexpr char kAttrPrompt[] = "Prompt";
91 constexpr char kAttrPublicKeyRsa[] = "PublicKeyRsa";
92 
93 // List of attributes that we interpret in the Omaha response:
94 constexpr char kAttrAppId[] = "appid";
95 constexpr char kAttrCodeBase[] = "codebase";
96 constexpr char kAttrCohort[] = "cohort";
97 constexpr char kAttrCohortHint[] = "cohorthint";
98 constexpr char kAttrCohortName[] = "cohortname";
99 constexpr char kAttrElapsedDays[] = "elapsed_days";
100 constexpr char kAttrElapsedSeconds[] = "elapsed_seconds";
101 constexpr char kAttrEvent[] = "event";
102 constexpr char kAttrFp[] = "fp";
103 constexpr char kAttrHashSha256[] = "hash_sha256";
104 // Deprecated: "hash"; Although we still need to pass it from the server for
105 // backward compatibility.
106 constexpr char kAttrName[] = "name";
107 // Deprecated: "sha256"; Although we still need to pass it from the server for
108 // backward compatibility.
109 constexpr char kAttrSize[] = "size";
110 constexpr char kAttrStatus[] = "status";
111 
112 // List of values that we interpret in the Omaha response:
113 constexpr char kValPostInstall[] = "postinstall";
114 constexpr char kValNoUpdate[] = "noupdate";
115 
116 // updatecheck attributes.
117 // Deprecated: "eol"
118 constexpr char kAttrEolDate[] = "_eol_date";
119 constexpr char kAttrRollback[] = "_rollback";
120 constexpr char kAttrFirmwareVersion[] = "_firmware_version";
121 constexpr char kAttrKernelVersion[] = "_kernel_version";
122 
123 // Struct used for holding data obtained when parsing the XML.
124 struct OmahaParserData {
125   OmahaParserData(XML_Parser _xml_parser, int _rollback_allowed_milestones)
126       : xml_parser(_xml_parser),
127         rollback_allowed_milestones(_rollback_allowed_milestones) {}
128 
129   // Pointer to the expat XML_Parser object.
130   XML_Parser xml_parser;
131 
132   // Some values that we need during parsing.
133   int rollback_allowed_milestones;
134 
135   // This is the state of the parser as it's processing the XML.
136   bool failed = false;
137   bool entity_decl = false;
138   string current_path;
139 
140   // These are the values extracted from the XML.
141   struct DayStart {
142     string elapsed_days;
143     string elapsed_seconds;
144   } daystart;
145 
146   struct App {
147     string id;
148     Optional<string> cohort;
149     Optional<string> cohorthint;
150     Optional<string> cohortname;
151 
152     struct Url {
153       string codebase;
154     };
155     vector<Url> urls;
156 
157     struct Manifest {
158       string version;
159     } manifest;
160 
161     struct UpdateCheck {
162       string status;
163       string poll_interval;
164       string eol_date;
165       string rollback;
166       string firmware_version;
167       string kernel_version;
168       string past_firmware_version;
169       string past_kernel_version;
170     } updatecheck;
171 
172     struct PostInstallAction {
173       vector<string> is_delta_payloads;
174       vector<string> metadata_signature_rsas;
175       vector<string> metadata_sizes;
176       string max_days_to_scatter;
177       string no_update;
178       string more_info_url;
179       string prompt;
180       string deadline;
181       string disable_p2p_for_downloading;
182       string disable_p2p_for_sharing;
183       string public_key_rsa;
184       string max_failure_count_per_url;
185       string disable_payload_backoff;
186       string powerwash_required;
187     };
188     Optional<PostInstallAction> postinstall_action;
189 
190     struct Package {
191       string name;
192       string size;
193       string hash;
194       string fp;
195     };
196     vector<Package> packages;
197   };
198   vector<App> apps;
199 };
200 
201 namespace {
202 
203 // Callback function invoked by expat.
204 void ParserHandlerStart(void* user_data,
205                         const XML_Char* element,
206                         const XML_Char** attr) {
207   OmahaParserData* data = reinterpret_cast<OmahaParserData*>(user_data);
208 
209   if (data->failed)
210     return;
211 
212   data->current_path += string("/") + element;
213 
214   map<string, string> attrs;
215   if (attr != nullptr) {
216     for (int n = 0; attr[n] != nullptr && attr[n + 1] != nullptr; n += 2) {
217       string key = attr[n];
218       string value = attr[n + 1];
219       attrs[key] = value;
220     }
221   }
222 
223   if (data->current_path == "/response/daystart") {
224     data->daystart = {
225         .elapsed_days = attrs[kAttrElapsedDays],
226         .elapsed_seconds = attrs[kAttrElapsedSeconds],
227     };
228   } else if (data->current_path == "/response/app") {
229     data->apps.push_back({.id = attrs[kAttrAppId]});
230     if (attrs.find(kAttrCohort) != attrs.end())
231       data->apps.back().cohort = attrs[kAttrCohort];
232     if (attrs.find(kAttrCohortHint) != attrs.end())
233       data->apps.back().cohorthint = attrs[kAttrCohortHint];
234     if (attrs.find(kAttrCohortName) != attrs.end())
235       data->apps.back().cohortname = attrs[kAttrCohortName];
236   } else if (data->current_path == "/response/app/updatecheck") {
237     data->apps.back().updatecheck = {
238         .status = attrs[kAttrStatus],
239         .poll_interval = attrs[kAttrPollInterval],
240         .eol_date = attrs[kAttrEolDate],
241         .rollback = attrs[kAttrRollback],
242         .firmware_version = attrs[kAttrFirmwareVersion],
243         .kernel_version = attrs[kAttrKernelVersion],
244         .past_firmware_version = attrs[base::StringPrintf(
245             "%s_%i", kAttrFirmwareVersion, data->rollback_allowed_milestones)],
246         .past_kernel_version = attrs[base::StringPrintf(
247             "%s_%i", kAttrKernelVersion, data->rollback_allowed_milestones)],
248     };
249   } else if (data->current_path == "/response/app/updatecheck/urls/url") {
250     data->apps.back().urls.push_back({.codebase = attrs[kAttrCodeBase]});
251   } else if (data->current_path ==
252              "/response/app/updatecheck/manifest/packages/package") {
253     data->apps.back().packages.push_back({
254         .name = attrs[kAttrName],
255         .size = attrs[kAttrSize],
256         .hash = attrs[kAttrHashSha256],
257         .fp = attrs[kAttrFp],
258     });
259   } else if (data->current_path == "/response/app/updatecheck/manifest") {
260     data->apps.back().manifest.version = attrs[kAttrVersion];
261   } else if (data->current_path ==
262              "/response/app/updatecheck/manifest/actions/action") {
263     // We only care about the postinstall action.
264     if (attrs[kAttrEvent] == kValPostInstall) {
265       OmahaParserData::App::PostInstallAction action = {
266           .is_delta_payloads = base::SplitString(attrs[kAttrIsDeltaPayload],
267                                                  ":",
268                                                  base::TRIM_WHITESPACE,
269                                                  base::SPLIT_WANT_ALL),
270           .metadata_signature_rsas =
271               base::SplitString(attrs[kAttrMetadataSignatureRsa],
272                                 ":",
273                                 base::TRIM_WHITESPACE,
274                                 base::SPLIT_WANT_ALL),
275           .metadata_sizes = base::SplitString(attrs[kAttrMetadataSize],
276                                               ":",
277                                               base::TRIM_WHITESPACE,
278                                               base::SPLIT_WANT_ALL),
279           .max_days_to_scatter = attrs[kAttrMaxDaysToScatter],
280           .no_update = attrs[kAttrNoUpdate],
281           .more_info_url = attrs[kAttrMoreInfo],
282           .prompt = attrs[kAttrPrompt],
283           .deadline = attrs[kAttrDeadline],
284           .disable_p2p_for_downloading = attrs[kAttrDisableP2PForDownloading],
285           .disable_p2p_for_sharing = attrs[kAttrDisableP2PForSharing],
286           .public_key_rsa = attrs[kAttrPublicKeyRsa],
287           .max_failure_count_per_url = attrs[kAttrMaxFailureCountPerUrl],
288           .disable_payload_backoff = attrs[kAttrDisablePayloadBackoff],
289           .powerwash_required = attrs[kAttrPowerwash],
290       };
291       data->apps.back().postinstall_action = std::move(action);
292     }
293   }
294 }
295 
296 // Callback function invoked by expat.
297 void ParserHandlerEnd(void* user_data, const XML_Char* element) {
298   OmahaParserData* data = reinterpret_cast<OmahaParserData*>(user_data);
299   if (data->failed)
300     return;
301 
302   const string path_suffix = string("/") + element;
303 
304   if (!base::EndsWith(
305           data->current_path, path_suffix, base::CompareCase::SENSITIVE)) {
306     LOG(ERROR) << "Unexpected end element '" << element
307                << "' with current_path='" << data->current_path << "'";
308     data->failed = true;
309     return;
310   }
311   data->current_path.resize(data->current_path.size() - path_suffix.size());
312 }
313 
314 // Callback function invoked by expat.
315 //
316 // This is called for entity declarations. Since Omaha is guaranteed
317 // to never return any XML with entities our course of action is to
318 // just stop parsing. This avoids potential resource exhaustion
319 // problems AKA the "billion laughs". CVE-2013-0340.
320 void ParserHandlerEntityDecl(void* user_data,
321                              const XML_Char* entity_name,
322                              int is_parameter_entity,
323                              const XML_Char* value,
324                              int value_length,
325                              const XML_Char* base,
326                              const XML_Char* system_id,
327                              const XML_Char* public_id,
328                              const XML_Char* notation_name) {
329   OmahaParserData* data = reinterpret_cast<OmahaParserData*>(user_data);
330 
331   LOG(ERROR) << "XML entities are not supported. Aborting parsing.";
332   data->failed = true;
333   data->entity_decl = true;
334   XML_StopParser(data->xml_parser, false);
335 }
336 
337 }  // namespace
338 
339 OmahaRequestAction::OmahaRequestAction(
340     OmahaEvent* event,
341     std::unique_ptr<HttpFetcher> http_fetcher,
342     bool ping_only,
343     const string& session_id)
344     : event_(event),
345       http_fetcher_(std::move(http_fetcher)),
346       policy_provider_(std::make_unique<policy::PolicyProvider>()),
347       ping_only_(ping_only),
348       ping_active_days_(0),
349       ping_roll_call_days_(0),
350       session_id_(session_id) {
351   policy_provider_->Reload();
352 }
353 
354 OmahaRequestAction::~OmahaRequestAction() {}
355 
356 // Calculates the value to use for the ping days parameter.
357 int OmahaRequestAction::CalculatePingDays(const string& key) {
358   int days = kPingNeverPinged;
359   int64_t last_ping = 0;
360   if (SystemState::Get()->prefs()->GetInt64(key, &last_ping) &&
361       last_ping >= 0) {
362     days = (Time::Now() - Time::FromInternalValue(last_ping)).InDays();
363     if (days < 0) {
364       // If |days| is negative, then the system clock must have jumped
365       // back in time since the ping was sent. Mark the value so that
366       // it doesn't get sent to the server but we still update the
367       // last ping daystart preference. This way the next ping time
368       // will be correct, hopefully.
369       days = kPingTimeJump;
370       LOG(WARNING)
371           << "System clock jumped back in time. Resetting ping daystarts.";
372     }
373   }
374   return days;
375 }
376 
377 void OmahaRequestAction::InitPingDays() {
378   // We send pings only along with update checks, not with events.
379   if (IsEvent()) {
380     return;
381   }
382   // TODO(petkov): Figure a way to distinguish active use pings
383   // vs. roll call pings. Currently, the two pings are identical. A
384   // fix needs to change this code as well as UpdateLastPingDays and ShouldPing.
385   ping_active_days_ = CalculatePingDays(kPrefsLastActivePingDay);
386   ping_roll_call_days_ = CalculatePingDays(kPrefsLastRollCallPingDay);
387 }
388 
389 bool OmahaRequestAction::ShouldPing() const {
390   if (ping_active_days_ == kPingNeverPinged &&
391       ping_roll_call_days_ == kPingNeverPinged) {
392     int powerwash_count = SystemState::Get()->hardware()->GetPowerwashCount();
393     if (powerwash_count > 0) {
394       LOG(INFO) << "Not sending ping with a=-1 r=-1 to omaha because "
395                 << "powerwash_count is " << powerwash_count;
396       return false;
397     }
398     if (SystemState::Get()->hardware()->GetFirstActiveOmahaPingSent()) {
399       LOG(INFO) << "Not sending ping with a=-1 r=-1 to omaha because "
400                 << "the first_active_omaha_ping_sent is true.";
401       return false;
402     }
403     return true;
404   }
405   return ping_active_days_ > 0 || ping_roll_call_days_ > 0;
406 }
407 
408 // static
409 int OmahaRequestAction::GetInstallDate() {
410   auto* prefs = SystemState::Get()->prefs();
411   // If we have the value stored on disk, just return it.
412   int64_t stored_value;
413   if (prefs->GetInt64(kPrefsInstallDateDays, &stored_value)) {
414     // Convert and validity-check.
415     int install_date_days = static_cast<int>(stored_value);
416     if (install_date_days >= 0)
417       return install_date_days;
418     LOG(ERROR) << "Dropping stored Omaha InstallData since its value num_days="
419                << install_date_days << " looks suspicious.";
420     prefs->Delete(kPrefsInstallDateDays);
421   }
422 
423   // Otherwise, if OOBE is not complete then do nothing and wait for
424   // ParseResponse() to call ParseInstallDate() and then
425   // PersistInstallDate() to set the kPrefsInstallDateDays state
426   // variable. Once that is done, we'll then report back in future
427   // Omaha requests.  This works exactly because OOBE triggers an
428   // update check.
429   //
430   // However, if OOBE is complete and the kPrefsInstallDateDays state
431   // variable is not set, there are two possibilities
432   //
433   //   1. The update check in OOBE failed so we never got a response
434   //      from Omaha (no network etc.); or
435   //
436   //   2. OOBE was done on an older version that didn't write to the
437   //      kPrefsInstallDateDays state variable.
438   //
439   // In both cases, we approximate the install date by simply
440   // inspecting the timestamp of when OOBE happened.
441 
442   Time time_of_oobe;
443   if (!SystemState::Get()->hardware()->IsOOBEEnabled() ||
444       !SystemState::Get()->hardware()->IsOOBEComplete(&time_of_oobe)) {
445     LOG(INFO) << "Not generating Omaha InstallData as we have "
446               << "no prefs file and OOBE is not complete or not enabled.";
447     return -1;
448   }
449 
450   int num_days;
451   if (!utils::ConvertToOmahaInstallDate(time_of_oobe, &num_days)) {
452     LOG(ERROR) << "Not generating Omaha InstallData from time of OOBE "
453                << "as its value '" << utils::ToString(time_of_oobe)
454                << "' looks suspicious.";
455     return -1;
456   }
457 
458   // Persist this to disk, for future use.
459   if (!OmahaRequestAction::PersistInstallDate(num_days,
460                                               kProvisionedFromOOBEMarker))
461     return -1;
462 
463   LOG(INFO) << "Set the Omaha InstallDate from OOBE time-stamp to " << num_days
464             << " days.";
465 
466   return num_days;
467 }
468 
469 void OmahaRequestAction::StorePingReply(
470     const OmahaParserData& parser_data) const {
471   const auto* params = SystemState::Get()->request_params();
472   for (const auto& app : parser_data.apps) {
473     auto it = params->dlc_apps_params().find(app.id);
474     if (it == params->dlc_apps_params().end())
475       continue;
476 
477     const OmahaRequestParams::AppParams& dlc_params = it->second;
478     const string& dlc_id = dlc_params.name;
479     // Skip if the ping for this DLC was not sent.
480     if (!dlc_params.send_ping)
481       continue;
482 
483     auto* prefs = SystemState::Get()->prefs();
484     // Reset the active metadata value to |kPingInactiveValue|.
485     auto active_key =
486         prefs->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsPingActive});
487     if (!prefs->SetInt64(active_key, kPingInactiveValue))
488       LOG(ERROR) << "Failed to set the value of ping metadata '" << active_key
489                  << "'.";
490 
491     auto last_rollcall_key =
492         prefs->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsPingLastRollcall});
493     if (!prefs->SetString(last_rollcall_key, parser_data.daystart.elapsed_days))
494       LOG(ERROR) << "Failed to set the value of ping metadata '"
495                  << last_rollcall_key << "'.";
496 
497     if (dlc_params.ping_active) {
498       // Write the value of elapsed_days into |kPrefsPingLastActive| only if
499       // the previous ping was an active one.
500       auto last_active_key =
501           prefs->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsPingLastActive});
502       if (!prefs->SetString(last_active_key, parser_data.daystart.elapsed_days))
503         LOG(ERROR) << "Failed to set the value of ping metadata '"
504                    << last_active_key << "'.";
505     }
506   }
507 }
508 
509 void OmahaRequestAction::PerformAction() {
510   http_fetcher_->set_delegate(this);
511   InitPingDays();
512   if (ping_only_ && !ShouldPing()) {
513     processor_->ActionComplete(this, ErrorCode::kSuccess);
514     return;
515   }
516 
517   OmahaRequestBuilderXml omaha_request(event_.get(),
518                                        ping_only_,
519                                        ShouldPing(),  // include_ping
520                                        ping_active_days_,
521                                        ping_roll_call_days_,
522                                        GetInstallDate(),
523                                        session_id_);
524   string request_post = omaha_request.GetRequest();
525 
526   // Set X-Goog-Update headers.
527   const auto* params = SystemState::Get()->request_params();
528   http_fetcher_->SetHeader(kXGoogleUpdateInteractivity,
529                            params->interactive() ? "fg" : "bg");
530   http_fetcher_->SetHeader(kXGoogleUpdateAppId, params->GetAppId());
531   http_fetcher_->SetHeader(
532       kXGoogleUpdateUpdater,
533       base::StringPrintf(
534           "%s-%s", constants::kOmahaUpdaterID, kOmahaUpdaterVersion));
535 
536   http_fetcher_->SetPostData(
537       request_post.data(), request_post.size(), kHttpContentTypeTextXml);
538   LOG(INFO) << "Posting an Omaha request to " << params->update_url();
539   LOG(INFO) << "Request: " << request_post;
540   http_fetcher_->BeginTransfer(params->update_url());
541 }
542 
543 void OmahaRequestAction::TerminateProcessing() {
544   http_fetcher_->TerminateTransfer();
545 }
546 
547 // We just store the response in the buffer. Once we've received all bytes,
548 // we'll look in the buffer and decide what to do.
549 bool OmahaRequestAction::ReceivedBytes(HttpFetcher* fetcher,
550                                        const void* bytes,
551                                        size_t length) {
552   const uint8_t* byte_ptr = reinterpret_cast<const uint8_t*>(bytes);
553   response_buffer_.insert(response_buffer_.end(), byte_ptr, byte_ptr + length);
554   return true;
555 }
556 
557 namespace {
558 
559 // Parses a 64 bit base-10 int from a string and returns it. Returns 0
560 // on error. If the string contains "0", that's indistinguishable from
561 // error.
562 off_t ParseInt(const string& str) {
563   off_t ret = 0;
564   int rc = sscanf(str.c_str(), "%" PRIi64, &ret);  // NOLINT(runtime/printf)
565   if (rc < 1) {
566     // failure
567     return 0;
568   }
569   return ret;
570 }
571 
572 // Parses |str| and returns |true| if, and only if, its value is "true".
573 bool ParseBool(const string& str) {
574   return str == "true";
575 }
576 
577 // Update the last ping day preferences based on the server daystart
578 // response. Returns true on success, false otherwise.
579 bool UpdateLastPingDays(OmahaParserData* parser_data) {
580   int64_t elapsed_seconds = 0;
581   TEST_AND_RETURN_FALSE(base::StringToInt64(
582       parser_data->daystart.elapsed_seconds, &elapsed_seconds));
583   TEST_AND_RETURN_FALSE(elapsed_seconds >= 0);
584 
585   // Remember the local time that matches the server's last midnight
586   // time.
587   auto* prefs = SystemState::Get()->prefs();
588   Time daystart = Time::Now() - TimeDelta::FromSeconds(elapsed_seconds);
589   prefs->SetInt64(kPrefsLastActivePingDay, daystart.ToInternalValue());
590   prefs->SetInt64(kPrefsLastRollCallPingDay, daystart.ToInternalValue());
591   return true;
592 }
593 
594 // Parses the package node in the given XML document and populates
595 // |output_object| if valid. Returns true if we should continue the parsing.
596 // False otherwise, in which case it sets any error code using |completer|.
597 bool ParsePackage(OmahaParserData::App* app,
598                   OmahaResponse* output_object,
599                   bool can_exclude,
600                   ScopedActionCompleter* completer) {
601   if (app->updatecheck.status.empty() ||
602       app->updatecheck.status == kValNoUpdate) {
603     if (!app->packages.empty()) {
604       LOG(ERROR) << "No update in this <app> but <package> is not empty.";
605       completer->set_code(ErrorCode::kOmahaResponseInvalid);
606       return false;
607     }
608     return true;
609   }
610   if (app->packages.empty()) {
611     LOG(ERROR) << "Omaha Response has no packages.";
612     completer->set_code(ErrorCode::kOmahaResponseInvalid);
613     return false;
614   }
615   if (app->urls.empty()) {
616     LOG(ERROR) << "No Omaha Response URLs.";
617     completer->set_code(ErrorCode::kOmahaResponseInvalid);
618     return false;
619   }
620   for (size_t i = 0; i < app->packages.size(); i++) {
621     const auto& package = app->packages[i];
622     if (package.name.empty()) {
623       LOG(ERROR) << "Omaha Response has empty package name.";
624       completer->set_code(ErrorCode::kOmahaResponseInvalid);
625       return false;
626     }
627 
628     OmahaResponse::Package out_package;
629     out_package.app_id = app->id;
630     out_package.can_exclude = can_exclude;
631     for (const auto& url : app->urls) {
632       if (url.codebase.empty()) {
633         LOG(ERROR) << "Omaha Response URL has empty codebase.";
634         completer->set_code(ErrorCode::kOmahaResponseInvalid);
635         return false;
636       }
637       out_package.payload_urls.push_back(url.codebase + package.name);
638     }
639 
640     base::StringToUint64(package.size, &out_package.size);
641     if (out_package.size <= 0) {
642       LOG(ERROR) << "Omaha Response has invalid payload size: " << package.size;
643       completer->set_code(ErrorCode::kOmahaResponseInvalid);
644       return false;
645     }
646 
647     if (i < app->postinstall_action->metadata_sizes.size())
648       base::StringToUint64(app->postinstall_action->metadata_sizes[i],
649                            &out_package.metadata_size);
650 
651     if (i < app->postinstall_action->metadata_signature_rsas.size())
652       out_package.metadata_signature =
653           app->postinstall_action->metadata_signature_rsas[i];
654 
655     out_package.hash = package.hash;
656     if (out_package.hash.empty()) {
657       LOG(ERROR) << "Omaha Response has empty hash_sha256 value.";
658       completer->set_code(ErrorCode::kOmahaResponseInvalid);
659       return false;
660     }
661 
662     out_package.fp = package.fp;
663 
664     if (i < app->postinstall_action->is_delta_payloads.size())
665       out_package.is_delta =
666           ParseBool(app->postinstall_action->is_delta_payloads[i]);
667 
668     output_object->packages.push_back(std::move(out_package));
669   }
670 
671   return true;
672 }
673 
674 // Removes the candidate URLs which are excluded within packages, if all the
675 // candidate URLs are excluded within a package, the package will be excluded.
676 void ProcessExclusions(OmahaResponse* output_object,
677                        OmahaRequestParams* params,
678                        ExcluderInterface* excluder) {
679   for (auto package_it = output_object->packages.begin();
680        package_it != output_object->packages.end();
681        /* Increment logic in loop */) {
682     // If package cannot be excluded, quickly continue.
683     if (!package_it->can_exclude) {
684       ++package_it;
685       continue;
686     }
687     // Remove the excluded payload URLs.
688     for (auto payload_url_it = package_it->payload_urls.begin();
689          payload_url_it != package_it->payload_urls.end();
690          /* Increment logic in loop */) {
691       auto exclusion_name = utils::GetExclusionName(*payload_url_it);
692       // If payload URL is not excluded, quickly continue.
693       if (!excluder->IsExcluded(exclusion_name)) {
694         ++payload_url_it;
695         continue;
696       }
697       LOG(INFO) << "Excluding payload URL=" << *payload_url_it
698                 << " for payload hash=" << package_it->hash;
699       payload_url_it = package_it->payload_urls.erase(payload_url_it);
700     }
701     // If there are no candidate payload URLs, remove the package.
702     if (package_it->payload_urls.empty()) {
703       LOG(INFO) << "Excluding payload hash=" << package_it->hash;
704       // Need to set DLC as not updated so correct metrics can be sent when an
705       // update is completed.
706       params->SetDlcNoUpdate(package_it->app_id);
707       package_it = output_object->packages.erase(package_it);
708       continue;
709     }
710     ++package_it;
711   }
712 }
713 
714 // Parses the 2 key version strings kernel_version and firmware_version. If the
715 // field is not present, or cannot be parsed the values default to 0xffff.
716 void ParseRollbackVersions(const OmahaParserData::App& platform_app,
717                            int allowed_milestones,
718                            OmahaResponse* output_object) {
719   // Defaults to false if attribute is not present.
720   output_object->is_rollback = ParseBool(platform_app.updatecheck.rollback);
721 
722   utils::ParseRollbackKeyVersion(
723       platform_app.updatecheck.firmware_version,
724       &output_object->rollback_key_version.firmware_key,
725       &output_object->rollback_key_version.firmware);
726   utils::ParseRollbackKeyVersion(
727       platform_app.updatecheck.kernel_version,
728       &output_object->rollback_key_version.kernel_key,
729       &output_object->rollback_key_version.kernel);
730 
731   string firmware_version = platform_app.updatecheck.past_firmware_version;
732   string kernel_version = platform_app.updatecheck.past_kernel_version;
733 
734   LOG(INFO) << "For milestone N-" << allowed_milestones
735             << " firmware_key_version=" << firmware_version
736             << " kernel_key_version=" << kernel_version;
737 
738   OmahaResponse::RollbackKeyVersion version;
739   utils::ParseRollbackKeyVersion(
740       firmware_version, &version.firmware_key, &version.firmware);
741   utils::ParseRollbackKeyVersion(
742       kernel_version, &version.kernel_key, &version.kernel);
743 
744   output_object->past_rollback_key_version = std::move(version);
745 }
746 
747 void PersistEolInfo(const OmahaParserData::App& platform_app) {
748   // If EOL date attribute is not sent, don't delete the old persisted EOL
749   // date information.
750   if (!platform_app.updatecheck.eol_date.empty() &&
751       !SystemState::Get()->prefs()->SetString(
752           kPrefsOmahaEolDate, platform_app.updatecheck.eol_date)) {
753     LOG(ERROR) << "Setting EOL date failed.";
754   }
755 }
756 
757 }  // namespace
758 
759 bool OmahaRequestAction::ParseResponse(OmahaParserData* parser_data,
760                                        OmahaResponse* output_object,
761                                        ScopedActionCompleter* completer) {
762   if (parser_data->apps.empty()) {
763     completer->set_code(ErrorCode::kOmahaResponseInvalid);
764     return false;
765   }
766 
767   // Locate the platform App since it's an important one that has specific
768   // information attached to it that may not be available from other Apps.
769   const auto* params = SystemState::Get()->request_params();
770   auto platform_app = std::find_if(parser_data->apps.begin(),
771                                    parser_data->apps.end(),
772                                    [&params](const OmahaParserData::App& app) {
773                                      return app.id == params->GetAppId();
774                                    });
775   if (platform_app == parser_data->apps.end()) {
776     LOG(WARNING) << "Platform App is missing.";
777   } else {
778     // chromium-os:37289: The PollInterval is not supported by Omaha server
779     // currently.  But still keeping this existing code in case we ever decide
780     // to slow down the request rate from the server-side. Note that the
781     // PollInterval is not persisted, so it has to be sent by the server on
782     // every response to guarantee that the scheduler uses this value
783     // (otherwise, if the device got rebooted after the last server-indicated
784     // value, it'll revert to the default value). Also kDefaultMaxUpdateChecks
785     // value for the scattering logic is based on the assumption that we perform
786     // an update check every hour so that the max value of 8 will roughly be
787     // equivalent to one work day. If we decide to use PollInterval permanently,
788     // we should update the max_update_checks_allowed to take PollInterval into
789     // account.  Note: The parsing for PollInterval happens even before parsing
790     // of the status because we may want to specify the PollInterval even when
791     // there's no update.
792     base::StringToInt(platform_app->updatecheck.poll_interval,
793                       &output_object->poll_interval);
794 
795     PersistEolInfo(*platform_app);
796 
797     // Parses the rollback versions of the current image. If the fields do not
798     // exist they default to 0xffff for the 4 key versions.
799     ParseRollbackVersions(
800         *platform_app, params->rollback_allowed_milestones(), output_object);
801   }
802 
803   // Check for the "elapsed_days" attribute in the "daystart"
804   // element. This is the number of days since Jan 1 2007, 0:00
805   // PST. If we don't have a persisted value of the Omaha InstallDate,
806   // we'll use it to calculate it and then persist it.
807   if (ParseInstallDate(parser_data, output_object) && !HasInstallDate()) {
808     // Since output_object->install_date_days is never negative, the
809     // elapsed_days -> install-date calculation is reduced to simply
810     // rounding down to the nearest number divisible by 7.
811     int remainder = output_object->install_date_days % 7;
812     int install_date_days_rounded =
813         output_object->install_date_days - remainder;
814     if (PersistInstallDate(install_date_days_rounded,
815                            kProvisionedFromOmahaResponse)) {
816       LOG(INFO) << "Set the Omaha InstallDate from Omaha Response to "
817                 << install_date_days_rounded << " days.";
818     }
819   }
820 
821   // We persist the cohorts sent by omaha even if the status is "noupdate".
822   PersistCohorts(*parser_data);
823 
824   if (!ParseStatus(parser_data, output_object, completer))
825     return false;
826 
827   if (!ParseParams(parser_data, output_object, completer))
828     return false;
829 
830   // Package has to be parsed after Params now because ParseParams need to make
831   // sure that postinstall action exists.
832   for (auto& app : parser_data->apps) {
833     // Only allow exclusions for a non-critical package during an update. For
834     // non-critical package installations, let the errors propagate instead
835     // of being handled inside update_engine as installations are a dlcservice
836     // specific feature.
837     bool can_exclude = !params->is_install() && params->IsDlcAppId(app.id);
838     if (!ParsePackage(&app, output_object, can_exclude, completer))
839       return false;
840   }
841 
842   return true;
843 }
844 
845 bool OmahaRequestAction::ParseStatus(OmahaParserData* parser_data,
846                                      OmahaResponse* output_object,
847                                      ScopedActionCompleter* completer) {
848   output_object->update_exists = false;
849   auto* params = SystemState::Get()->request_params();
850   for (const auto& app : parser_data->apps) {
851     const string& status = app.updatecheck.status;
852     if (status == kValNoUpdate) {
853       // If the app is a DLC, allow status "noupdate" to support DLC
854       // deprecations.
855       if (params->IsDlcAppId(app.id)) {
856         LOG(INFO) << "No update for App " << app.id
857                   << " but update continuing since a DLC.";
858         params->SetDlcNoUpdate(app.id);
859         continue;
860       }
861       // Don't update if any app has status="noupdate".
862       LOG(INFO) << "No update for App " << app.id;
863       output_object->update_exists = false;
864       break;
865     } else if (status == "ok") {
866       if (ParseBool(app.postinstall_action->no_update)) {
867         // noupdate="true" in postinstall attributes means it's an update to
868         // self, only update if there's at least one app really have update.
869         LOG(INFO) << "Update to self for App " << app.id;
870       } else {
871         output_object->update_exists = true;
872       }
873     } else if (status.empty() && params->is_install() &&
874                params->GetAppId() == app.id) {
875       // Skips the platform app for install operation.
876       LOG(INFO) << "No payload (and ignore) for App " << app.id;
877     } else {
878       LOG(ERROR) << "Unknown Omaha response status: " << status;
879       completer->set_code(ErrorCode::kOmahaResponseInvalid);
880       return false;
881     }
882   }
883   if (!output_object->update_exists) {
884     SetOutputObject(*output_object);
885     completer->set_code(ErrorCode::kSuccess);
886   }
887 
888   return output_object->update_exists;
889 }
890 
891 bool OmahaRequestAction::ParseParams(OmahaParserData* parser_data,
892                                      OmahaResponse* output_object,
893                                      ScopedActionCompleter* completer) {
894   const auto* params = SystemState::Get()->request_params();
895   const OmahaParserData::App* main_app = nullptr;
896   for (const auto& app : parser_data->apps) {
897     if (app.id == params->GetAppId() && app.postinstall_action) {
898       main_app = &app;
899     } else if (params->is_install()) {
900       if (app.manifest.version != params->app_version()) {
901         LOG(WARNING) << "An app has a version: " << app.manifest.version
902                      << " that is different than platform app version: "
903                      << params->app_version();
904       }
905     }
906     if (app.postinstall_action && main_app == nullptr) {
907       main_app = &app;
908     }
909   }
910 
911   if (main_app == nullptr) {
912     LOG(ERROR) << "Omaha Response has no postinstall event action.";
913     completer->set_code(ErrorCode::kOmahaResponseInvalid);
914     return false;
915   }
916 
917   const OmahaParserData::App& app = *main_app;
918   // Get the optional properties one by one.
919   output_object->version = app.manifest.version;
920   output_object->more_info_url = app.postinstall_action->more_info_url;
921   output_object->prompt = ParseBool(app.postinstall_action->prompt);
922   output_object->deadline = app.postinstall_action->deadline;
923   output_object->max_days_to_scatter =
924       ParseInt(app.postinstall_action->max_days_to_scatter);
925   output_object->disable_p2p_for_downloading =
926       ParseBool(app.postinstall_action->disable_p2p_for_downloading);
927   output_object->disable_p2p_for_sharing =
928       ParseBool(app.postinstall_action->disable_p2p_for_sharing);
929   output_object->public_key_rsa = app.postinstall_action->public_key_rsa;
930 
931   if (!base::StringToUint(app.postinstall_action->max_failure_count_per_url,
932                           &output_object->max_failure_count_per_url))
933     output_object->max_failure_count_per_url = kDefaultMaxFailureCountPerUrl;
934 
935   output_object->disable_payload_backoff =
936       ParseBool(app.postinstall_action->disable_payload_backoff);
937   output_object->powerwash_required =
938       ParseBool(app.postinstall_action->powerwash_required);
939 
940   if (output_object->version.empty()) {
941     LOG(ERROR) << "Omaha Response does not have version in manifest!";
942     completer->set_code(ErrorCode::kOmahaResponseInvalid);
943     return false;
944   }
945 
946   return true;
947 }
948 
949 // If the transfer was successful, this uses expat to parse the response
950 // and fill in the appropriate fields of the output object. Also, notifies
951 // the processor that we're done.
952 void OmahaRequestAction::TransferComplete(HttpFetcher* fetcher,
953                                           bool successful) {
954   ScopedActionCompleter completer(processor_, this);
955   string current_response(response_buffer_.begin(), response_buffer_.end());
956   LOG(INFO) << "Omaha request response: " << current_response;
957 
958   PayloadStateInterface* const payload_state =
959       SystemState::Get()->payload_state();
960 
961   // Set the max kernel key version based on whether rollback is allowed.
962   SetMaxKernelKeyVersionForRollback();
963 
964   // Events are best effort transactions -- assume they always succeed.
965   if (IsEvent()) {
966     CHECK(!HasOutputPipe()) << "No output pipe allowed for event requests.";
967     completer.set_code(ErrorCode::kSuccess);
968     return;
969   }
970 
971   ErrorCode aux_error_code = fetcher->GetAuxiliaryErrorCode();
972   if (aux_error_code != ErrorCode::kSuccess) {
973     metrics::DownloadErrorCode download_error_code =
974         metrics_utils::GetDownloadErrorCode(aux_error_code);
975     SystemState::Get()->metrics_reporter()->ReportUpdateCheckMetrics(
976         metrics::CheckResult::kUnset,
977         metrics::CheckReaction::kUnset,
978         download_error_code);
979   }
980 
981   if (!successful) {
982     int code = GetHTTPResponseCode();
983     LOG(ERROR) << "Omaha request network transfer failed with HTTPResponseCode="
984                << code;
985     // Makes sure we send proper error values.
986     if (code < 0 || code >= 1000) {
987       code = 999;
988       LOG(WARNING) << "Converting to proper HTTPResponseCode=" << code;
989     }
990     completer.set_code(static_cast<ErrorCode>(
991         static_cast<int>(ErrorCode::kOmahaRequestHTTPResponseBase) + code));
992     return;
993   }
994 
995   XML_Parser parser = XML_ParserCreate(nullptr);
996   OmahaParserData parser_data(
997       parser,
998       SystemState::Get()->request_params()->rollback_allowed_milestones());
999   XML_SetUserData(parser, &parser_data);
1000   XML_SetElementHandler(parser, ParserHandlerStart, ParserHandlerEnd);
1001   XML_SetEntityDeclHandler(parser, ParserHandlerEntityDecl);
1002   XML_Status res =
1003       XML_Parse(parser,
1004                 reinterpret_cast<const char*>(response_buffer_.data()),
1005                 response_buffer_.size(),
1006                 XML_TRUE);
1007 
1008   if (res != XML_STATUS_OK || parser_data.failed) {
1009     LOG(ERROR) << "Omaha response not valid XML: "
1010                << XML_ErrorString(XML_GetErrorCode(parser)) << " at line "
1011                << XML_GetCurrentLineNumber(parser) << " col "
1012                << XML_GetCurrentColumnNumber(parser);
1013     XML_ParserFree(parser);
1014     ErrorCode error_code = ErrorCode::kOmahaRequestXMLParseError;
1015     if (response_buffer_.empty()) {
1016       error_code = ErrorCode::kOmahaRequestEmptyResponseError;
1017     } else if (parser_data.entity_decl) {
1018       error_code = ErrorCode::kOmahaRequestXMLHasEntityDecl;
1019     }
1020     completer.set_code(error_code);
1021     return;
1022   }
1023   XML_ParserFree(parser);
1024 
1025   // Update the last ping day preferences based on the server daystart response
1026   // even if we didn't send a ping. Omaha always includes the daystart in the
1027   // response, but log the error if it didn't.
1028   LOG_IF(ERROR, !UpdateLastPingDays(&parser_data))
1029       << "Failed to update the last ping day preferences!";
1030 
1031   // Sets first_active_omaha_ping_sent to true (vpd in CrOS). We only do this if
1032   // we have got a response from omaha and if its value has never been set to
1033   // true before. Failure of this function should be ignored. There should be no
1034   // need to check if a=-1 has been sent because older devices have already sent
1035   // their a=-1 in the past and we have to set first_active_omaha_ping_sent for
1036   // future checks.
1037   if (!SystemState::Get()->hardware()->GetFirstActiveOmahaPingSent()) {
1038     if (!SystemState::Get()->hardware()->SetFirstActiveOmahaPingSent()) {
1039       SystemState::Get()->metrics_reporter()->ReportInternalErrorCode(
1040           ErrorCode::kFirstActiveOmahaPingSentPersistenceError);
1041     }
1042   }
1043 
1044   // Create/update the metadata files for each DLC app received.
1045   StorePingReply(parser_data);
1046 
1047   if (!HasOutputPipe()) {
1048     // Just set success to whether or not the http transfer succeeded,
1049     // which must be true at this point in the code.
1050     completer.set_code(ErrorCode::kSuccess);
1051     return;
1052   }
1053 
1054   OmahaResponse output_object;
1055   if (!ParseResponse(&parser_data, &output_object, &completer))
1056     return;
1057   ProcessExclusions(&output_object,
1058                     SystemState::Get()->request_params(),
1059                     SystemState::Get()->update_attempter()->GetExcluder());
1060   output_object.update_exists = true;
1061   SetOutputObject(output_object);
1062 
1063   LoadOrPersistUpdateFirstSeenAtPref();
1064 
1065   ErrorCode error = ErrorCode::kSuccess;
1066   if (ShouldIgnoreUpdate(output_object, &error)) {
1067     // No need to change output_object.update_exists here, since the value
1068     // has been output to the pipe.
1069     completer.set_code(error);
1070     return;
1071   }
1072 
1073   // If Omaha says to disable p2p, respect that
1074   if (output_object.disable_p2p_for_downloading) {
1075     LOG(INFO) << "Forcibly disabling use of p2p for downloading as "
1076               << "requested by Omaha.";
1077     payload_state->SetUsingP2PForDownloading(false);
1078   }
1079   if (output_object.disable_p2p_for_sharing) {
1080     LOG(INFO) << "Forcibly disabling use of p2p for sharing as "
1081               << "requested by Omaha.";
1082     payload_state->SetUsingP2PForSharing(false);
1083   }
1084 
1085   // Update the payload state with the current response. The payload state
1086   // will automatically reset all stale state if this response is different
1087   // from what's stored already. We are updating the payload state as late
1088   // as possible in this method so that if a new release gets pushed and then
1089   // got pulled back due to some issues, we don't want to clear our internal
1090   // state unnecessarily.
1091   payload_state->SetResponse(output_object);
1092 
1093   // It could be we've already exceeded the deadline for when p2p is
1094   // allowed or that we've tried too many times with p2p. Check that.
1095   if (payload_state->GetUsingP2PForDownloading()) {
1096     payload_state->P2PNewAttempt();
1097     if (!payload_state->P2PAttemptAllowed()) {
1098       LOG(INFO) << "Forcibly disabling use of p2p for downloading because "
1099                 << "of previous failures when using p2p.";
1100       payload_state->SetUsingP2PForDownloading(false);
1101     }
1102   }
1103 
1104   // From here on, we'll complete stuff in CompleteProcessing() so
1105   // disable |completer| since we'll create a new one in that
1106   // function.
1107   completer.set_should_complete(false);
1108 
1109   // If we're allowed to use p2p for downloading we do not pay
1110   // attention to wall-clock-based waiting if the URL is indeed
1111   // available via p2p. Therefore, check if the file is available via
1112   // p2p before deferring...
1113   if (payload_state->GetUsingP2PForDownloading()) {
1114     LookupPayloadViaP2P(output_object);
1115   } else {
1116     CompleteProcessing();
1117   }
1118 }
1119 
1120 void OmahaRequestAction::CompleteProcessing() {
1121   ScopedActionCompleter completer(processor_, this);
1122   OmahaResponse& output_object = const_cast<OmahaResponse&>(GetOutputObject());
1123   PayloadStateInterface* payload_state = SystemState::Get()->payload_state();
1124 
1125   if (ShouldDeferDownload(&output_object)) {
1126     output_object.update_exists = false;
1127     LOG(INFO) << "Ignoring Omaha updates as updates are deferred by policy.";
1128     completer.set_code(ErrorCode::kOmahaUpdateDeferredPerPolicy);
1129     return;
1130   }
1131 
1132   if (payload_state->ShouldBackoffDownload()) {
1133     output_object.update_exists = false;
1134     LOG(INFO) << "Ignoring Omaha updates in order to backoff our retry "
1135               << "attempts.";
1136     completer.set_code(ErrorCode::kOmahaUpdateDeferredForBackoff);
1137     return;
1138   }
1139   completer.set_code(ErrorCode::kSuccess);
1140 }
1141 
1142 void OmahaRequestAction::OnLookupPayloadViaP2PCompleted(const string& url) {
1143   LOG(INFO) << "Lookup complete, p2p-client returned URL '" << url << "'";
1144   if (!url.empty()) {
1145     SystemState::Get()->payload_state()->SetP2PUrl(url);
1146   } else {
1147     LOG(INFO) << "Forcibly disabling use of p2p for downloading "
1148               << "because no suitable peer could be found.";
1149     SystemState::Get()->payload_state()->SetUsingP2PForDownloading(false);
1150   }
1151   CompleteProcessing();
1152 }
1153 
1154 void OmahaRequestAction::LookupPayloadViaP2P(const OmahaResponse& response) {
1155   // If the device is in the middle of an update, the state variables
1156   // kPrefsUpdateStateNextDataOffset, kPrefsUpdateStateNextDataLength
1157   // tracks the offset and length of the operation currently in
1158   // progress. The offset is based from the end of the manifest which
1159   // is kPrefsManifestMetadataSize bytes long.
1160   //
1161   // To make forward progress and avoid deadlocks, we need to find a
1162   // peer that has at least the entire operation we're currently
1163   // working on. Otherwise we may end up in a situation where two
1164   // devices bounce back and forth downloading from each other,
1165   // neither making any forward progress until one of them decides to
1166   // stop using p2p (via kMaxP2PAttempts and kMaxP2PAttemptTimeSeconds
1167   // safe-guards). See http://crbug.com/297170 for an example)
1168   size_t minimum_size = 0;
1169   int64_t manifest_metadata_size = 0;
1170   int64_t manifest_signature_size = 0;
1171   int64_t next_data_offset = 0;
1172   int64_t next_data_length = 0;
1173   if (SystemState::Get()->prefs()->GetInt64(kPrefsManifestMetadataSize,
1174                                             &manifest_metadata_size) &&
1175       manifest_metadata_size != -1 &&
1176       SystemState::Get()->prefs()->GetInt64(kPrefsManifestSignatureSize,
1177                                             &manifest_signature_size) &&
1178       manifest_signature_size != -1 &&
1179       SystemState::Get()->prefs()->GetInt64(kPrefsUpdateStateNextDataOffset,
1180                                             &next_data_offset) &&
1181       next_data_offset != -1 &&
1182       SystemState::Get()->prefs()->GetInt64(kPrefsUpdateStateNextDataLength,
1183                                             &next_data_length)) {
1184     minimum_size = manifest_metadata_size + manifest_signature_size +
1185                    next_data_offset + next_data_length;
1186   }
1187 
1188   // TODO(senj): Fix P2P for multiple package.
1189   brillo::Blob raw_hash;
1190   if (!base::HexStringToBytes(response.packages[0].hash, &raw_hash))
1191     return;
1192   string file_id =
1193       utils::CalculateP2PFileId(raw_hash, response.packages[0].size);
1194   if (SystemState::Get()->p2p_manager()) {
1195     LOG(INFO) << "Checking if payload is available via p2p, file_id=" << file_id
1196               << " minimum_size=" << minimum_size;
1197     SystemState::Get()->p2p_manager()->LookupUrlForFile(
1198         file_id,
1199         minimum_size,
1200         TimeDelta::FromSeconds(kMaxP2PNetworkWaitTimeSeconds),
1201         base::Bind(&OmahaRequestAction::OnLookupPayloadViaP2PCompleted,
1202                    base::Unretained(this)));
1203   }
1204 }
1205 
1206 bool OmahaRequestAction::ShouldDeferDownload(OmahaResponse* output_object) {
1207   const auto* params = SystemState::Get()->request_params();
1208   if (params->interactive()) {
1209     LOG(INFO) << "Not deferring download because update is interactive.";
1210     return false;
1211   }
1212 
1213   // If we're using p2p to download _and_ we have a p2p URL, we never
1214   // defer the download. This is because the download will always
1215   // happen from a peer on the LAN and we've been waiting in line for
1216   // our turn.
1217   const PayloadStateInterface* payload_state =
1218       SystemState::Get()->payload_state();
1219   if (payload_state->GetUsingP2PForDownloading() &&
1220       !payload_state->GetP2PUrl().empty()) {
1221     LOG(INFO) << "Download not deferred because download "
1222               << "will happen from a local peer (via p2p).";
1223     return false;
1224   }
1225 
1226   // We should defer the downloads only if we've first satisfied the
1227   // wall-clock-based-waiting period and then the update-check-based waiting
1228   // period, if required.
1229   if (!params->wall_clock_based_wait_enabled()) {
1230     LOG(INFO) << "Wall-clock-based waiting period is not enabled,"
1231               << " so no deferring needed.";
1232     return false;
1233   }
1234 
1235   switch (IsWallClockBasedWaitingSatisfied(output_object)) {
1236     case kWallClockWaitNotSatisfied:
1237       // We haven't even satisfied the first condition, passing the
1238       // wall-clock-based waiting period, so we should defer the downloads
1239       // until that happens.
1240       LOG(INFO) << "wall-clock-based-wait not satisfied.";
1241       return true;
1242 
1243     case kWallClockWaitDoneButUpdateCheckWaitRequired:
1244       LOG(INFO) << "wall-clock-based-wait satisfied and "
1245                 << "update-check-based-wait required.";
1246       return !IsUpdateCheckCountBasedWaitingSatisfied();
1247 
1248     case kWallClockWaitDoneAndUpdateCheckWaitNotRequired:
1249       // Wall-clock-based waiting period is satisfied, and it's determined
1250       // that we do not need the update-check-based wait. so no need to
1251       // defer downloads.
1252       LOG(INFO) << "wall-clock-based-wait satisfied and "
1253                 << "update-check-based-wait is not required.";
1254       return false;
1255 
1256     default:
1257       // Returning false for this default case so we err on the
1258       // side of downloading updates than deferring in case of any bugs.
1259       NOTREACHED();
1260       return false;
1261   }
1262 }
1263 
1264 OmahaRequestAction::WallClockWaitResult
1265 OmahaRequestAction::IsWallClockBasedWaitingSatisfied(
1266     OmahaResponse* output_object) {
1267   Time update_first_seen_at = LoadOrPersistUpdateFirstSeenAtPref();
1268   if (update_first_seen_at == base::Time()) {
1269     LOG(INFO) << "Not scattering as UpdateFirstSeenAt value cannot be read or "
1270                  "persisted.";
1271     return kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
1272   }
1273 
1274   TimeDelta elapsed_time =
1275       SystemState::Get()->clock()->GetWallclockTime() - update_first_seen_at;
1276   TimeDelta max_scatter_period =
1277       TimeDelta::FromDays(output_object->max_days_to_scatter);
1278   int64_t staging_wait_time_in_days = 0;
1279   // Use staging and its default max value if staging is on.
1280   if (SystemState::Get()->prefs()->GetInt64(kPrefsWallClockStagingWaitPeriod,
1281                                             &staging_wait_time_in_days) &&
1282       staging_wait_time_in_days > 0)
1283     max_scatter_period = TimeDelta::FromDays(kMaxWaitTimeStagingInDays);
1284 
1285   const auto* params = SystemState::Get()->request_params();
1286   LOG(INFO) << "Waiting Period = "
1287             << utils::FormatSecs(params->waiting_period().InSeconds())
1288             << ", Time Elapsed = "
1289             << utils::FormatSecs(elapsed_time.InSeconds())
1290             << ", MaxDaysToScatter = " << max_scatter_period.InDays();
1291 
1292   if (!output_object->deadline.empty()) {
1293     // The deadline is set for all rules which serve a delta update from a
1294     // previous FSI, which means this update will be applied mostly in OOBE
1295     // cases. For these cases, we shouldn't scatter so as to finish the OOBE
1296     // quickly.
1297     LOG(INFO) << "Not scattering as deadline flag is set.";
1298     return kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
1299   }
1300 
1301   if (max_scatter_period.InDays() == 0) {
1302     // This means the Omaha rule creator decides that this rule
1303     // should not be scattered irrespective of the policy.
1304     LOG(INFO) << "Not scattering as MaxDaysToScatter in rule is 0.";
1305     return kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
1306   }
1307 
1308   if (elapsed_time > max_scatter_period) {
1309     // This means we've waited more than the upperbound wait in the rule
1310     // from the time we first saw a valid update available to us.
1311     // This will prevent update starvation.
1312     LOG(INFO) << "Not scattering as we're past the MaxDaysToScatter limit.";
1313     return kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
1314   }
1315 
1316   // This means we are required to participate in scattering.
1317   // See if our turn has arrived now.
1318   TimeDelta remaining_wait_time = params->waiting_period() - elapsed_time;
1319   if (remaining_wait_time.InSeconds() <= 0) {
1320     // Yes, it's our turn now.
1321     LOG(INFO) << "Successfully passed the wall-clock-based-wait.";
1322 
1323     // But we can't download until the update-check-count-based wait is also
1324     // satisfied, so mark it as required now if update checks are enabled.
1325     return params->update_check_count_wait_enabled()
1326                ? kWallClockWaitDoneButUpdateCheckWaitRequired
1327                : kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
1328   }
1329 
1330   // Not our turn yet, so we have to wait until our turn to
1331   // help scatter the downloads across all clients of the enterprise.
1332   LOG(INFO) << "Update deferred for another "
1333             << utils::FormatSecs(remaining_wait_time.InSeconds())
1334             << " per policy.";
1335   return kWallClockWaitNotSatisfied;
1336 }
1337 
1338 bool OmahaRequestAction::IsUpdateCheckCountBasedWaitingSatisfied() {
1339   int64_t update_check_count_value;
1340   const auto* params = SystemState::Get()->request_params();
1341 
1342   if (SystemState::Get()->prefs()->Exists(kPrefsUpdateCheckCount)) {
1343     if (!SystemState::Get()->prefs()->GetInt64(kPrefsUpdateCheckCount,
1344                                                &update_check_count_value)) {
1345       // We are unable to read the update check count from file for some reason.
1346       // So let's proceed anyway so as to not stall the update.
1347       LOG(ERROR) << "Unable to read update check count. "
1348                  << "Skipping update-check-count-based-wait.";
1349       return true;
1350     }
1351   } else {
1352     // This file does not exist. This means we haven't started our update
1353     // check count down yet, so this is the right time to start the count down.
1354     update_check_count_value =
1355         base::RandInt(params->min_update_checks_needed(),
1356                       params->max_update_checks_allowed());
1357 
1358     LOG(INFO) << "Randomly picked update check count value = "
1359               << update_check_count_value;
1360 
1361     // Write out the initial value of update_check_count_value.
1362     if (!SystemState::Get()->prefs()->SetInt64(kPrefsUpdateCheckCount,
1363                                                update_check_count_value)) {
1364       // We weren't able to write the update check count file for some reason.
1365       // So let's proceed anyway so as to not stall the update.
1366       LOG(ERROR) << "Unable to write update check count. "
1367                  << "Skipping update-check-count-based-wait.";
1368       return true;
1369     }
1370   }
1371 
1372   if (update_check_count_value == 0) {
1373     LOG(INFO) << "Successfully passed the update-check-based-wait.";
1374     return true;
1375   }
1376 
1377   if (update_check_count_value < 0 ||
1378       update_check_count_value > params->max_update_checks_allowed()) {
1379     // We err on the side of skipping scattering logic instead of stalling
1380     // a machine from receiving any updates in case of any unexpected state.
1381     LOG(ERROR) << "Invalid value for update check count detected. "
1382                << "Skipping update-check-count-based-wait.";
1383     return true;
1384   }
1385 
1386   // Legal value, we need to wait for more update checks to happen
1387   // until this becomes 0.
1388   LOG(INFO) << "Deferring Omaha updates for another "
1389             << update_check_count_value << " update checks per policy";
1390   return false;
1391 }
1392 
1393 // static
1394 bool OmahaRequestAction::ParseInstallDate(OmahaParserData* parser_data,
1395                                           OmahaResponse* output_object) {
1396   int64_t elapsed_days = 0;
1397   if (!base::StringToInt64(parser_data->daystart.elapsed_days, &elapsed_days))
1398     return false;
1399 
1400   if (elapsed_days < 0)
1401     return false;
1402 
1403   output_object->install_date_days = elapsed_days;
1404   return true;
1405 }
1406 
1407 // static
1408 bool OmahaRequestAction::HasInstallDate() {
1409   return SystemState::Get()->prefs()->Exists(kPrefsInstallDateDays);
1410 }
1411 
1412 // static
1413 bool OmahaRequestAction::PersistInstallDate(
1414     int install_date_days,
1415     InstallDateProvisioningSource source) {
1416   TEST_AND_RETURN_FALSE(install_date_days >= 0);
1417 
1418   auto* prefs = SystemState::Get()->prefs();
1419   if (!prefs->SetInt64(kPrefsInstallDateDays, install_date_days))
1420     return false;
1421 
1422   SystemState::Get()->metrics_reporter()->ReportInstallDateProvisioningSource(
1423       static_cast<int>(source),  // Sample.
1424       kProvisionedMax);          // Maximum.
1425   return true;
1426 }
1427 
1428 void OmahaRequestAction::PersistCohortData(const string& prefs_key,
1429                                            const Optional<string>& new_value) {
1430   if (!new_value)
1431     return;
1432   const string& value = new_value.value();
1433   if (value.empty() && SystemState::Get()->prefs()->Exists(prefs_key)) {
1434     if (!SystemState::Get()->prefs()->Delete(prefs_key))
1435       LOG(ERROR) << "Failed to remove stored " << prefs_key << "value.";
1436     else
1437       LOG(INFO) << "Removed stored " << prefs_key << " value.";
1438   } else if (!value.empty()) {
1439     if (!SystemState::Get()->prefs()->SetString(prefs_key, value))
1440       LOG(INFO) << "Failed to store new setting " << prefs_key << " as "
1441                 << value;
1442     else
1443       LOG(INFO) << "Stored cohort setting " << prefs_key << " as " << value;
1444   }
1445 }
1446 
1447 void OmahaRequestAction::PersistCohorts(const OmahaParserData& parser_data) {
1448   const auto* params = SystemState::Get()->request_params();
1449   for (const auto& app : parser_data.apps) {
1450     // For platform App ID.
1451     if (app.id == params->GetAppId()) {
1452       PersistCohortData(kPrefsOmahaCohort, app.cohort);
1453       PersistCohortData(kPrefsOmahaCohortName, app.cohortname);
1454       PersistCohortData(kPrefsOmahaCohortHint, app.cohorthint);
1455     } else if (params->IsDlcAppId(app.id)) {
1456       string dlc_id;
1457       if (!params->GetDlcId(app.id, &dlc_id)) {
1458         LOG(WARNING) << "Skip persisting cohorts for DLC App ID=" << app.id
1459                      << " as it is not in the request params.";
1460         continue;
1461       }
1462       auto* prefs = SystemState::Get()->prefs();
1463       PersistCohortData(
1464           prefs->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohort}),
1465           app.cohort);
1466       PersistCohortData(
1467           prefs->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohortName}),
1468           app.cohortname);
1469       PersistCohortData(
1470           prefs->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohortHint}),
1471           app.cohorthint);
1472     } else {
1473       LOG(WARNING) << "Skip persisting cohorts for unknown App ID=" << app.id;
1474     }
1475   }
1476 }
1477 
1478 void OmahaRequestAction::ActionCompleted(ErrorCode code) {
1479   // We only want to report this on "update check".
1480   if (ping_only_ || event_ != nullptr)
1481     return;
1482 
1483   metrics::CheckResult result = metrics::CheckResult::kUnset;
1484   metrics::CheckReaction reaction = metrics::CheckReaction::kUnset;
1485   metrics::DownloadErrorCode download_error_code =
1486       metrics::DownloadErrorCode::kUnset;
1487 
1488   // Regular update attempt.
1489   switch (code) {
1490     case ErrorCode::kSuccess:
1491       // OK, we parsed the response successfully but that does
1492       // necessarily mean that an update is available.
1493       if (HasOutputPipe()) {
1494         const OmahaResponse& response = GetOutputObject();
1495         if (response.update_exists) {
1496           result = metrics::CheckResult::kUpdateAvailable;
1497           reaction = metrics::CheckReaction::kUpdating;
1498         } else {
1499           result = metrics::CheckResult::kNoUpdateAvailable;
1500         }
1501       } else {
1502         result = metrics::CheckResult::kNoUpdateAvailable;
1503       }
1504       break;
1505 
1506     case ErrorCode::kOmahaUpdateIgnoredPerPolicy:
1507     case ErrorCode::kOmahaUpdateIgnoredOverCellular:
1508       result = metrics::CheckResult::kUpdateAvailable;
1509       reaction = metrics::CheckReaction::kIgnored;
1510       break;
1511 
1512     case ErrorCode::kOmahaUpdateDeferredPerPolicy:
1513       result = metrics::CheckResult::kUpdateAvailable;
1514       reaction = metrics::CheckReaction::kDeferring;
1515       break;
1516 
1517     case ErrorCode::kOmahaUpdateDeferredForBackoff:
1518       result = metrics::CheckResult::kUpdateAvailable;
1519       reaction = metrics::CheckReaction::kBackingOff;
1520       break;
1521 
1522     default:
1523       // We report two flavors of errors, "Download errors" and "Parsing
1524       // error". Try to convert to the former and if that doesn't work
1525       // we know it's the latter.
1526       metrics::DownloadErrorCode tmp_error =
1527           metrics_utils::GetDownloadErrorCode(code);
1528       if (tmp_error != metrics::DownloadErrorCode::kInputMalformed) {
1529         result = metrics::CheckResult::kDownloadError;
1530         download_error_code = tmp_error;
1531       } else {
1532         result = metrics::CheckResult::kParsingError;
1533       }
1534       break;
1535   }
1536 
1537   SystemState::Get()->metrics_reporter()->ReportUpdateCheckMetrics(
1538       result, reaction, download_error_code);
1539 }
1540 
1541 bool OmahaRequestAction::ShouldIgnoreUpdate(const OmahaResponse& response,
1542                                             ErrorCode* error) const {
1543   // Note: policy decision to not update to a version we rolled back from.
1544   string rollback_version =
1545       SystemState::Get()->payload_state()->GetRollbackVersion();
1546   const auto* params = SystemState::Get()->request_params();
1547   if (!rollback_version.empty()) {
1548     LOG(INFO) << "Detected previous rollback from version " << rollback_version;
1549     if (rollback_version == response.version) {
1550       LOG(INFO) << "Received version that we rolled back from. Ignoring.";
1551       *error = ErrorCode::kOmahaUpdateIgnoredPerPolicy;
1552       return true;
1553     }
1554   }
1555 
1556   if (SystemState::Get()->hardware()->IsOOBEEnabled() &&
1557       !SystemState::Get()->hardware()->IsOOBEComplete(nullptr) &&
1558       (response.deadline.empty() ||
1559        SystemState::Get()->payload_state()->GetRollbackHappened()) &&
1560       params->app_version() != "ForcedUpdate") {
1561     LOG(INFO) << "Ignoring a non-critical Omaha update before OOBE completion.";
1562     *error = ErrorCode::kNonCriticalUpdateInOOBE;
1563     return true;
1564   }
1565 
1566   if (!IsUpdateAllowedOverCurrentConnection(error, response)) {
1567     LOG(INFO) << "Update is not allowed over current connection.";
1568     return true;
1569   }
1570 
1571   // Currently non-critical updates always update alongside the platform update
1572   // (a critical update) so this case should never actually be hit if the
1573   // request to Omaha for updates are correct. In other words, stop the update
1574   // from happening as there are no packages in the response to process.
1575   if (response.packages.empty()) {
1576     LOG(ERROR) << "All packages were excluded.";
1577   }
1578 
1579   // Note: We could technically delete the UpdateFirstSeenAt state when we
1580   // return true. If we do, it'll mean a device has to restart the
1581   // UpdateFirstSeenAt and thus help scattering take effect when the AU is
1582   // turned on again. On the other hand, it also increases the chance of update
1583   // starvation if an admin turns AU on/off more frequently. We choose to err on
1584   // the side of preventing starvation at the cost of not applying scattering in
1585   // those cases.
1586   return false;
1587 }
1588 
1589 bool OmahaRequestAction::IsUpdateAllowedOverCellularByPrefs(
1590     const OmahaResponse& response) const {
1591   auto* prefs = SystemState::Get()->prefs();
1592   bool is_allowed;
1593   if (prefs->Exists(kPrefsUpdateOverCellularPermission) &&
1594       prefs->GetBoolean(kPrefsUpdateOverCellularPermission, &is_allowed) &&
1595       is_allowed) {
1596     LOG(INFO) << "Allowing updates over cellular as permission preference is "
1597                  "set to true.";
1598     return true;
1599   }
1600 
1601   if (!prefs->Exists(kPrefsUpdateOverCellularTargetVersion) ||
1602       !prefs->Exists(kPrefsUpdateOverCellularTargetSize)) {
1603     LOG(INFO) << "Disabling updates over cellular as permission preference is "
1604                  "set to false or does not exist while target does not exist.";
1605     return false;
1606   }
1607 
1608   std::string target_version;
1609   int64_t target_size;
1610 
1611   if (!prefs->GetString(kPrefsUpdateOverCellularTargetVersion,
1612                         &target_version) ||
1613       !prefs->GetInt64(kPrefsUpdateOverCellularTargetSize, &target_size)) {
1614     LOG(INFO) << "Disabling updates over cellular as the target version or "
1615                  "size is not accessible.";
1616     return false;
1617   }
1618 
1619   uint64_t total_packages_size = 0;
1620   for (const auto& package : response.packages) {
1621     total_packages_size += package.size;
1622   }
1623   if (target_version == response.version &&
1624       static_cast<uint64_t>(target_size) == total_packages_size) {
1625     LOG(INFO) << "Allowing updates over cellular as the target matches the"
1626                  "omaha response.";
1627     return true;
1628   } else {
1629     LOG(INFO) << "Disabling updates over cellular as the target does not"
1630                  "match the omaha response.";
1631     return false;
1632   }
1633 }
1634 
1635 bool OmahaRequestAction::IsUpdateAllowedOverCurrentConnection(
1636     ErrorCode* error, const OmahaResponse& response) const {
1637   ConnectionType type;
1638   ConnectionTethering tethering;
1639   ConnectionManagerInterface* connection_manager =
1640       SystemState::Get()->connection_manager();
1641   if (!connection_manager->GetConnectionProperties(&type, &tethering)) {
1642     LOG(INFO) << "We could not determine our connection type. "
1643               << "Defaulting to allow updates.";
1644     return true;
1645   }
1646 
1647   bool is_allowed = connection_manager->IsUpdateAllowedOver(type, tethering);
1648   bool is_device_policy_set =
1649       connection_manager->IsAllowedConnectionTypesForUpdateSet();
1650   // Treats tethered connection as if it is cellular connection.
1651   bool is_over_cellular = type == ConnectionType::kCellular ||
1652                           tethering == ConnectionTethering::kConfirmed;
1653 
1654   if (!is_over_cellular) {
1655     // There's no need to further check user preferences as we are not over
1656     // cellular connection.
1657     if (!is_allowed)
1658       *error = ErrorCode::kOmahaUpdateIgnoredPerPolicy;
1659   } else if (is_device_policy_set) {
1660     // There's no need to further check user preferences as the device policy
1661     // is set regarding updates over cellular.
1662     if (!is_allowed)
1663       *error = ErrorCode::kOmahaUpdateIgnoredPerPolicy;
1664   } else {
1665     // Deivce policy is not set, so user preferences overwrite whether to
1666     // allow updates over cellular.
1667     is_allowed = IsUpdateAllowedOverCellularByPrefs(response);
1668     if (!is_allowed)
1669       *error = ErrorCode::kOmahaUpdateIgnoredOverCellular;
1670   }
1671 
1672   LOG(INFO) << "We are connected via "
1673             << connection_utils::StringForConnectionType(type)
1674             << ", Updates allowed: " << (is_allowed ? "Yes" : "No");
1675   return is_allowed;
1676 }
1677 
1678 bool OmahaRequestAction::IsRollbackEnabled() const {
1679   if (policy_provider_->IsConsumerDevice()) {
1680     LOG(INFO) << "Rollback is not enabled for consumer devices.";
1681     return false;
1682   }
1683 
1684   if (!policy_provider_->device_policy_is_loaded()) {
1685     LOG(INFO) << "No device policy is loaded. Assuming rollback enabled.";
1686     return true;
1687   }
1688 
1689   int allowed_milestones;
1690   if (!policy_provider_->GetDevicePolicy().GetRollbackAllowedMilestones(
1691           &allowed_milestones)) {
1692     LOG(INFO) << "RollbackAllowedMilestones policy can't be read. "
1693                  "Defaulting to rollback enabled.";
1694     return true;
1695   }
1696 
1697   LOG(INFO) << "Rollback allows " << allowed_milestones << " milestones.";
1698   return allowed_milestones > 0;
1699 }
1700 
1701 void OmahaRequestAction::SetMaxKernelKeyVersionForRollback() const {
1702   int max_kernel_rollforward;
1703   int min_kernel_version =
1704       SystemState::Get()->hardware()->GetMinKernelKeyVersion();
1705   if (IsRollbackEnabled()) {
1706     // If rollback is enabled, set the max kernel key version to the current
1707     // kernel key version. This has the effect of freezing kernel key roll
1708     // forwards.
1709     //
1710     // TODO(zentaro): This behavior is temporary, and ensures that no kernel
1711     // key roll forward happens until the server side components of rollback
1712     // are implemented. Future changes will allow the Omaha server to return
1713     // the kernel key version from max_rollback_versions in the past. At that
1714     // point the max kernel key version will be set to that value, creating a
1715     // sliding window of versions that can be rolled back to.
1716     LOG(INFO) << "Rollback is enabled. Setting kernel_max_rollforward to "
1717               << min_kernel_version;
1718     max_kernel_rollforward = min_kernel_version;
1719   } else {
1720     // For devices that are not rollback enabled (ie. consumer devices), the
1721     // max kernel key version is set to 0xfffffffe, which is logically
1722     // infinity. This maintains the previous behavior that that kernel key
1723     // versions roll forward each time they are incremented.
1724     LOG(INFO) << "Rollback is disabled. Setting kernel_max_rollforward to "
1725               << kRollforwardInfinity;
1726     max_kernel_rollforward = kRollforwardInfinity;
1727   }
1728 
1729   bool max_rollforward_set =
1730       SystemState::Get()->hardware()->SetMaxKernelKeyRollforward(
1731           max_kernel_rollforward);
1732   if (!max_rollforward_set) {
1733     LOG(ERROR) << "Failed to set kernel_max_rollforward";
1734   }
1735   // Report metrics
1736   SystemState::Get()->metrics_reporter()->ReportKeyVersionMetrics(
1737       min_kernel_version, max_kernel_rollforward, max_rollforward_set);
1738 }
1739 
1740 base::Time OmahaRequestAction::LoadOrPersistUpdateFirstSeenAtPref() const {
1741   Time update_first_seen_at;
1742   int64_t update_first_seen_at_int;
1743   if (SystemState::Get()->prefs()->Exists(kPrefsUpdateFirstSeenAt)) {
1744     if (SystemState::Get()->prefs()->GetInt64(kPrefsUpdateFirstSeenAt,
1745                                               &update_first_seen_at_int)) {
1746       // Note: This timestamp could be that of ANY update we saw in the past
1747       // (not necessarily this particular update we're considering to apply)
1748       // but never got to apply because of some reason (e.g. stop AU policy,
1749       // updates being pulled out from Omaha, changes in target version prefix,
1750       // new update being rolled out, etc.). But for the purposes of scattering
1751       // it doesn't matter which update the timestamp corresponds to. i.e.
1752       // the clock starts ticking the first time we see an update and we're
1753       // ready to apply when the random wait period is satisfied relative to
1754       // that first seen timestamp.
1755       update_first_seen_at = Time::FromInternalValue(update_first_seen_at_int);
1756       LOG(INFO) << "Using persisted value of UpdateFirstSeenAt: "
1757                 << utils::ToString(update_first_seen_at);
1758     } else {
1759       // This seems like an unexpected error where the persisted value exists
1760       // but it's not readable for some reason.
1761       LOG(INFO) << "UpdateFirstSeenAt value cannot be read";
1762       return base::Time();
1763     }
1764   } else {
1765     update_first_seen_at = SystemState::Get()->clock()->GetWallclockTime();
1766     update_first_seen_at_int = update_first_seen_at.ToInternalValue();
1767     if (SystemState::Get()->prefs()->SetInt64(kPrefsUpdateFirstSeenAt,
1768                                               update_first_seen_at_int)) {
1769       LOG(INFO) << "Persisted the new value for UpdateFirstSeenAt: "
1770                 << utils::ToString(update_first_seen_at);
1771     } else {
1772       // This seems like an unexpected error where the value cannot be
1773       // persisted for some reason.
1774       LOG(INFO) << "UpdateFirstSeenAt value "
1775                 << utils::ToString(update_first_seen_at)
1776                 << " cannot be persisted";
1777       return base::Time();
1778     }
1779   }
1780   return update_first_seen_at;
1781 }
1782 
1783 }  // namespace chromeos_update_engine
1784