• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef UPDATE_ENGINE_CROS_OMAHA_REQUEST_ACTION_H_
18 #define UPDATE_ENGINE_CROS_OMAHA_REQUEST_ACTION_H_
19 
20 #include <fcntl.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 
24 #include <map>
25 #include <memory>
26 #include <string>
27 #include <vector>
28 
29 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
30 
31 #include <base/optional.h>
32 #include <brillo/secure_blob.h>
33 #include <curl/curl.h>
34 
35 #include "update_engine/common/action.h"
36 #include "update_engine/common/http_fetcher.h"
37 #include "update_engine/cros/omaha_request_builder_xml.h"
38 #include "update_engine/cros/omaha_response.h"
39 
40 // The Omaha Request action makes a request to Omaha and can output
41 // the response on the output ActionPipe.
42 
43 namespace policy {
44 class PolicyProvider;
45 }
46 
47 namespace chromeos_update_engine {
48 
49 class NoneType;
50 class OmahaRequestAction;
51 class OmahaRequestParams;
52 
53 // This struct is declared in the .cc file.
54 struct OmahaParserData;
55 
56 template <>
57 class ActionTraits<OmahaRequestAction> {
58  public:
59   // Takes parameters on the input pipe.
60   typedef NoneType InputObjectType;
61   // On UpdateCheck success, puts the Omaha response on output. Event
62   // requests do not have an output pipe.
63   typedef OmahaResponse OutputObjectType;
64 };
65 
66 class OmahaRequestAction : public Action<OmahaRequestAction>,
67                            public HttpFetcherDelegate {
68  public:
69   static const int kPingTimeJump = -2;
70   // We choose this value of 3 as a heuristic for a work day in trying
71   // each URL, assuming we check roughly every 45 mins. This is a good time to
72   // wait so we don't give up the preferred URLs, but allow using the URL that
73   // appears earlier in list for every payload before resorting to the fallback
74   // URLs in the candiate URL list.
75   static const int kDefaultMaxFailureCountPerUrl = 3;
76 
77   // If staging is enabled, set the maximum wait time to 28 days, since that is
78   // the predetermined wait time for staging.
79   static const int kMaxWaitTimeStagingInDays = 28;
80 
81   // These are the possible outcome upon checking whether we satisfied
82   // the wall-clock-based-wait.
83   enum WallClockWaitResult {
84     kWallClockWaitNotSatisfied,
85     kWallClockWaitDoneButUpdateCheckWaitRequired,
86     kWallClockWaitDoneAndUpdateCheckWaitNotRequired,
87   };
88 
89   // The ctor takes in all the parameters that will be used for making
90   // the request to Omaha. For some of them we have constants that
91   // should be used.
92   //
93   // Takes ownership of the passed in HttpFetcher. Useful for testing.
94   //
95   // Takes ownership of the passed in OmahaEvent. If |event| is null,
96   // this is an UpdateCheck request, otherwise it's an Event request.
97   // Event requests always succeed.
98   //
99   // A good calling pattern is:
100   // OmahaRequestAction(..., new OmahaEvent(...), new WhateverHttpFetcher);
101   // or
102   // OmahaRequestAction(..., nullptr, new WhateverHttpFetcher);
103   OmahaRequestAction(OmahaEvent* event,
104                      std::unique_ptr<HttpFetcher> http_fetcher,
105                      bool ping_only,
106                      const std::string& session_id);
107   ~OmahaRequestAction() override;
108   typedef ActionTraits<OmahaRequestAction>::InputObjectType InputObjectType;
109   typedef ActionTraits<OmahaRequestAction>::OutputObjectType OutputObjectType;
110   void PerformAction() override;
111   void TerminateProcessing() override;
112   void ActionCompleted(ErrorCode code) override;
113 
GetHTTPResponseCode()114   int GetHTTPResponseCode() { return http_fetcher_->http_response_code(); }
115 
116   // Debugging/logging
StaticType()117   static std::string StaticType() { return "OmahaRequestAction"; }
Type()118   std::string Type() const override { return StaticType(); }
119 
120   // Delegate methods (see http_fetcher.h)
121   bool ReceivedBytes(HttpFetcher* fetcher,
122                      const void* bytes,
123                      size_t length) override;
124 
125   void TransferComplete(HttpFetcher* fetcher, bool successful) override;
126 
127   // Returns true if this is an Event request, false if it's an UpdateCheck.
IsEvent()128   bool IsEvent() const { return event_.get() != nullptr; }
129 
130  private:
131   friend class OmahaRequestActionTest;
132   friend class OmahaRequestActionTestProcessorDelegate;
133   FRIEND_TEST(OmahaRequestActionTest, GetInstallDateWhenNoPrefsNorOOBE);
134   FRIEND_TEST(OmahaRequestActionTest,
135               GetInstallDateWhenOOBECompletedWithInvalidDate);
136   FRIEND_TEST(OmahaRequestActionTest,
137               GetInstallDateWhenOOBECompletedWithValidDate);
138   FRIEND_TEST(OmahaRequestActionTest,
139               GetInstallDateWhenOOBECompletedDateChanges);
140   friend class UpdateAttempterTest;
141   FRIEND_TEST(UpdateAttempterTest, SessionIdTestEnforceEmptyStrPingOmaha);
142   FRIEND_TEST(UpdateAttempterTest, SessionIdTestConsistencyInUpdateFlow);
143 
144   // Enumeration used in PersistInstallDate().
145   enum InstallDateProvisioningSource {
146     kProvisionedFromOmahaResponse,
147     kProvisionedFromOOBEMarker,
148 
149     // kProvisionedMax is the count of the number of enums above. Add
150     // any new enums above this line only.
151     kProvisionedMax
152   };
153 
154   // Gets the install date, expressed as the number of PST8PDT
155   // calendar weeks since January 1st 2007, times seven. Returns -1 if
156   // unknown. See http://crbug.com/336838 for details about this value.
157   static int GetInstallDate();
158 
159   // Parses the Omaha Response in |doc| and sets the
160   // |install_date_days| field of |output_object| to the value of the
161   // elapsed_days attribute of the daystart element. Returns True if
162   // the value was set, False if it wasn't found.
163   static bool ParseInstallDate(OmahaParserData* parser_data,
164                                OmahaResponse* output_object);
165 
166   // Returns True if the kPrefsInstallDateDays state variable is set,
167   // False otherwise.
168   static bool HasInstallDate();
169 
170   // Writes |install_date_days| into the kPrefsInstallDateDays state
171   // variable and emits an UMA stat for the |source| used. Returns
172   // True if the value was written, False if an error occurred.
173   static bool PersistInstallDate(int install_date_days,
174                                  InstallDateProvisioningSource source);
175 
176   // Persist the new cohort value received in the XML file in the |prefs_key|
177   // preference file. If the |new_value| is empty, do nothing. If the
178   // |new_value| stores and empty value, the currently stored value will be
179   // deleted. Don't call this function with an empty |new_value| if the value
180   // was not set in the XML, since that would delete the stored value.
181   void PersistCohortData(const std::string& prefs_key,
182                          const base::Optional<std::string>& new_value);
183 
184   // Parses and persists the cohorts sent back in the updatecheck tag
185   // attributes.
186   void PersistCohorts(const OmahaParserData& parser_data);
187 
188   // If this is an update check request, initializes
189   // |ping_active_days_| and |ping_roll_call_days_| to values that may
190   // be sent as pings to Omaha.
191   void InitPingDays();
192 
193   // Based on the persistent preference store values, calculates the
194   // number of days since the last ping sent for |key|.
195   int CalculatePingDays(const std::string& key);
196 
197   // Returns whether we have "active_days" or "roll_call_days" ping values to
198   // send to Omaha and thus we should include them in the response.
199   bool ShouldPing() const;
200 
201   // Process Omaha's response to a ping request and store the results in the DLC
202   // metadata directory.
203   void StorePingReply(const OmahaParserData& parser_data) const;
204 
205   // Returns true if the download of a new update should be deferred.
206   // False if the update can be downloaded.
207   bool ShouldDeferDownload(OmahaResponse* output_object);
208 
209   // Returns true if the basic wall-clock-based waiting period has been
210   // satisfied based on the scattering policy setting. False otherwise.
211   // If true, it also indicates whether the additional update-check-count-based
212   // waiting period also needs to be satisfied before the download can begin.
213   WallClockWaitResult IsWallClockBasedWaitingSatisfied(
214       OmahaResponse* output_object);
215 
216   // Returns true if the update-check-count-based waiting period has been
217   // satisfied. False otherwise.
218   bool IsUpdateCheckCountBasedWaitingSatisfied();
219 
220   // Parses the response from Omaha that's available in |doc| using the other
221   // helper methods below and populates the |output_object| with the relevant
222   // values. Returns true if we should continue the parsing.  False otherwise,
223   // in which case it sets any error code using |completer|.
224   bool ParseResponse(OmahaParserData* parser_data,
225                      OmahaResponse* output_object,
226                      ScopedActionCompleter* completer);
227 
228   // Parses the status property in the given update_check_node and populates
229   // |output_object| if valid. Returns true if we should continue the parsing.
230   // False otherwise, in which case it sets any error code using |completer|.
231   bool ParseStatus(OmahaParserData* parser_data,
232                    OmahaResponse* output_object,
233                    ScopedActionCompleter* completer);
234 
235   // Parses the URL nodes in the given XML document and populates
236   // |output_object| if valid. Returns true if we should continue the parsing.
237   // False otherwise, in which case it sets any error code using |completer|.
238   bool ParseUrls(OmahaParserData* parser_data,
239                  OmahaResponse* output_object,
240                  ScopedActionCompleter* completer);
241 
242   // Parses the other parameters in the given XML document and populates
243   // |output_object| if valid. Returns true if we should continue the parsing.
244   // False otherwise, in which case it sets any error code using |completer|.
245   bool ParseParams(OmahaParserData* parser_data,
246                    OmahaResponse* output_object,
247                    ScopedActionCompleter* completer);
248 
249   // Called by TransferComplete() to complete processing, either
250   // asynchronously after looking up resources via p2p or directly.
251   void CompleteProcessing();
252 
253   // Helper to asynchronously look up payload on the LAN.
254   void LookupPayloadViaP2P(const OmahaResponse& response);
255 
256   // Callback used by LookupPayloadViaP2P().
257   void OnLookupPayloadViaP2PCompleted(const std::string& url);
258 
259   // Returns true if the current update should be ignored.
260   bool ShouldIgnoreUpdate(const OmahaResponse& response,
261                           ErrorCode* error) const;
262 
263   // Return true if updates are allowed by user preferences.
264   bool IsUpdateAllowedOverCellularByPrefs(const OmahaResponse& response) const;
265 
266   // Returns true if updates are allowed over the current type of connection.
267   // False otherwise.
268   bool IsUpdateAllowedOverCurrentConnection(
269       ErrorCode* error, const OmahaResponse& response) const;
270 
271   // Returns true if rollback is enabled. Always returns false for consumer
272   // devices.
273   bool IsRollbackEnabled() const;
274 
275   // Sets the appropriate max kernel key version based on whether rollback is
276   // enabled.
277   void SetMaxKernelKeyVersionForRollback() const;
278 
279   // Reads and returns the kPrefsUpdateFirstSeenAt pref if the pref currently
280   // exists. Otherwise saves the current wallclock time to the
281   // kPrefsUpdateFirstSeenAt pref and returns it as a base::Time object.
282   base::Time LoadOrPersistUpdateFirstSeenAtPref() const;
283 
284   // Pointer to the OmahaEvent info. This is an UpdateCheck request if null.
285   std::unique_ptr<OmahaEvent> event_;
286 
287   // pointer to the HttpFetcher that does the http work
288   std::unique_ptr<HttpFetcher> http_fetcher_;
289 
290   // Used for fetching information about the device policy.
291   std::unique_ptr<policy::PolicyProvider> policy_provider_;
292 
293   // If true, only include the <ping> element in the request.
294   bool ping_only_;
295 
296   // Stores the response from the omaha server
297   brillo::Blob response_buffer_;
298 
299   // Initialized by InitPingDays to values that may be sent to Omaha
300   // as part of a ping message. Note that only positive values and -1
301   // are sent to Omaha.
302   int ping_active_days_;
303   int ping_roll_call_days_;
304 
305   std::string session_id_;
306 
307   DISALLOW_COPY_AND_ASSIGN(OmahaRequestAction);
308 };
309 
310 }  // namespace chromeos_update_engine
311 
312 #endif  // UPDATE_ENGINE_CROS_OMAHA_REQUEST_ACTION_H_
313