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

Side by Side Diff: omaha_request_action.cc

Issue 2856070: Don't send machine and user ID to Omaha anymore. Send a/r pings instead. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/update_engine.git
Patch Set: Address review comments. Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "update_engine/omaha_request_action.h" 5 #include "update_engine/omaha_request_action.h"
6 #include <inttypes.h> 6 #include <inttypes.h>
7 #include <sstream> 7 #include <sstream>
8 8
9 #include <libxml/parser.h> 9 #include <libxml/parser.h>
10 #include <libxml/xpath.h> 10 #include <libxml/xpath.h>
11 #include <libxml/xpathInternals.h> 11 #include <libxml/xpathInternals.h>
12 12
13 #include "base/string_util.h" 13 #include "base/string_util.h"
14 #include "base/time.h"
14 #include "chromeos/obsolete_logging.h" 15 #include "chromeos/obsolete_logging.h"
15 #include "update_engine/action_pipe.h" 16 #include "update_engine/action_pipe.h"
16 #include "update_engine/omaha_request_params.h" 17 #include "update_engine/omaha_request_params.h"
18 #include "update_engine/prefs_interface.h"
17 #include "update_engine/utils.h" 19 #include "update_engine/utils.h"
18 20
21 using base::Time;
22 using base::TimeDelta;
19 using std::string; 23 using std::string;
20 24
21 namespace chromeos_update_engine { 25 namespace chromeos_update_engine {
22 26
23 namespace { 27 namespace {
24 28
25 const string kGupdateVersion("ChromeOSUpdateEngine-0.1.0.0"); 29 const string kGupdateVersion("ChromeOSUpdateEngine-0.1.0.0");
26 30
27 // This is handy for passing strings into libxml2 31 // This is handy for passing strings into libxml2
28 #define ConstXMLStr(x) (reinterpret_cast<const xmlChar*>(x)) 32 #define ConstXMLStr(x) (reinterpret_cast<const xmlChar*>(x))
(...skipping 18 matching lines...) Expand all
47 xmlXPathFreeObject(reinterpret_cast<xmlXPathObject*>(x)); 51 xmlXPathFreeObject(reinterpret_cast<xmlXPathObject*>(x));
48 } 52 }
49 }; 53 };
50 class ScopedPtrXmlXPathContextFree { 54 class ScopedPtrXmlXPathContextFree {
51 public: 55 public:
52 inline void operator()(void* x) const { 56 inline void operator()(void* x) const {
53 xmlXPathFreeContext(reinterpret_cast<xmlXPathContext*>(x)); 57 xmlXPathFreeContext(reinterpret_cast<xmlXPathContext*>(x));
54 } 58 }
55 }; 59 };
56 60
61 // Returns true if |ping_days| has a value that needs to be sent,
62 // false otherwise.
63 bool ShouldPing(int ping_days) {
64 return ping_days > 0 || ping_days == OmahaRequestAction::kNeverPinged;
65 }
66
67 // Returns an XML ping element attribute assignment with attribute
68 // |name| and value |ping_days| if |ping_days| has a value that needs
69 // to be sent, or an empty string otherwise.
70 string GetPingAttribute(const string& name, int ping_days) {
71 if (ShouldPing(ping_days)) {
72 return StringPrintf(" %s=\"%d\"", name.c_str(), ping_days);
73 }
74 return "";
75 }
76
77 // Returns an XML ping element if any of the elapsed days need to be
78 // sent, or an empty string otherwise.
79 string GetPingBody(int ping_active_days, int ping_roll_call_days) {
80 string ping_active = GetPingAttribute("a", ping_active_days);
81 string ping_roll_call = GetPingAttribute("r", ping_roll_call_days);
82 if (!ping_active.empty() || !ping_roll_call.empty()) {
83 return StringPrintf(" <o:ping%s%s></o:ping>\n",
84 ping_active.c_str(),
85 ping_roll_call.c_str());
86 }
87 return "";
88 }
89
57 string FormatRequest(const OmahaEvent* event, 90 string FormatRequest(const OmahaEvent* event,
58 const OmahaRequestParams& params) { 91 const OmahaRequestParams& params,
92 int ping_active_days,
93 int ping_roll_call_days) {
59 string body; 94 string body;
60 if (event == NULL) { 95 if (event == NULL) {
61 body = string( 96 body = GetPingBody(ping_active_days, ping_roll_call_days) +
62 " <o:ping active=\"0\"></o:ping>\n" 97 " <o:updatecheck></o:updatecheck>\n";
63 " <o:updatecheck></o:updatecheck>\n");
64 } else { 98 } else {
65 // The error code is an optional attribute so append it only if 99 // The error code is an optional attribute so append it only if
66 // the result is not success. 100 // the result is not success.
67 string error_code; 101 string error_code;
68 if (event->result != OmahaEvent::kResultSuccess) { 102 if (event->result != OmahaEvent::kResultSuccess) {
69 error_code = StringPrintf(" errorcode=\"%d\"", event->error_code); 103 error_code = StringPrintf(" errorcode=\"%d\"", event->error_code);
70 } 104 }
71 body = StringPrintf( 105 body = StringPrintf(
72 " <o:event eventtype=\"%d\" eventresult=\"%d\"%s></o:event>\n", 106 " <o:event eventtype=\"%d\" eventresult=\"%d\"%s></o:event>\n",
73 event->type, event->result, error_code.c_str()); 107 event->type, event->result, error_code.c_str());
74 } 108 }
75 return string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 109 return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
76 "<o:gupdate xmlns:o=\"http://www.google.com/update2/request\" " 110 "<o:gupdate xmlns:o=\"http://www.google.com/update2/request\" "
77 "version=\"" + XmlEncode(kGupdateVersion) + "\" " 111 "version=\"" + XmlEncode(kGupdateVersion) + "\" "
78 "updaterversion=\"" + XmlEncode(kGupdateVersion) + "\" " 112 "updaterversion=\"" + XmlEncode(kGupdateVersion) + "\" "
79 "protocol=\"2.0\" " 113 "protocol=\"2.0\" ismachine=\"1\">\n"
80 "machineid=\"") + XmlEncode(params.machine_id) +
81 "\" ismachine=\"1\" userid=\"" + XmlEncode(params.user_id) + "\">\n"
82 " <o:os version=\"" + XmlEncode(params.os_version) + "\" platform=\"" + 114 " <o:os version=\"" + XmlEncode(params.os_version) + "\" platform=\"" +
83 XmlEncode(params.os_platform) + "\" sp=\"" + 115 XmlEncode(params.os_platform) + "\" sp=\"" +
84 XmlEncode(params.os_sp) + "\"></o:os>\n" 116 XmlEncode(params.os_sp) + "\"></o:os>\n"
85 " <o:app appid=\"" + XmlEncode(params.app_id) + "\" version=\"" + 117 " <o:app appid=\"" + XmlEncode(params.app_id) + "\" version=\"" +
86 XmlEncode(params.app_version) + "\" " 118 XmlEncode(params.app_version) + "\" "
87 "lang=\"" + XmlEncode(params.app_lang) + "\" track=\"" + 119 "lang=\"" + XmlEncode(params.app_lang) + "\" track=\"" +
88 XmlEncode(params.app_track) + "\" board=\"" + 120 XmlEncode(params.app_track) + "\" board=\"" +
89 XmlEncode(params.os_board) + "\" delta_okay=\"" + 121 XmlEncode(params.os_board) + "\" delta_okay=\"" +
90 (params.delta_okay ? "true" : "false") + "\">\n" + body + 122 (params.delta_okay ? "true" : "false") + "\">\n" + body +
91 " </o:app>\n" 123 " </o:app>\n"
92 "</o:gupdate>\n"; 124 "</o:gupdate>\n";
93 } 125 }
126
94 } // namespace {} 127 } // namespace {}
95 128
96 // Encodes XML entities in a given string with libxml2. input must be 129 // Encodes XML entities in a given string with libxml2. input must be
97 // UTF-8 formatted. Output will be UTF-8 formatted. 130 // UTF-8 formatted. Output will be UTF-8 formatted.
98 string XmlEncode(const string& input) { 131 string XmlEncode(const string& input) {
99 // // TODO(adlr): if allocating a new xmlDoc each time is taking up too much 132 // // TODO(adlr): if allocating a new xmlDoc each time is taking up too much
100 // // cpu, considering creating one and caching it. 133 // // cpu, considering creating one and caching it.
101 // scoped_ptr_malloc<xmlDoc, ScopedPtrXmlDocFree> xml_doc( 134 // scoped_ptr_malloc<xmlDoc, ScopedPtrXmlDocFree> xml_doc(
102 // xmlNewDoc(ConstXMLStr("1.0"))); 135 // xmlNewDoc(ConstXMLStr("1.0")));
103 // if (!xml_doc.get()) { 136 // if (!xml_doc.get()) {
104 // LOG(ERROR) << "Unable to create xmlDoc"; 137 // LOG(ERROR) << "Unable to create xmlDoc";
105 // return ""; 138 // return "";
106 // } 139 // }
107 scoped_ptr_malloc<xmlChar, ScopedPtrXmlFree> str( 140 scoped_ptr_malloc<xmlChar, ScopedPtrXmlFree> str(
108 xmlEncodeEntitiesReentrant(NULL, ConstXMLStr(input.c_str()))); 141 xmlEncodeEntitiesReentrant(NULL, ConstXMLStr(input.c_str())));
109 return string(reinterpret_cast<const char *>(str.get())); 142 return string(reinterpret_cast<const char *>(str.get()));
110 } 143 }
111 144
112 OmahaRequestAction::OmahaRequestAction(const OmahaRequestParams& params, 145 OmahaRequestAction::OmahaRequestAction(PrefsInterface* prefs,
146 const OmahaRequestParams& params,
113 OmahaEvent* event, 147 OmahaEvent* event,
114 HttpFetcher* http_fetcher) 148 HttpFetcher* http_fetcher)
115 : params_(params), 149 : prefs_(prefs),
150 params_(params),
116 event_(event), 151 event_(event),
117 http_fetcher_(http_fetcher) {} 152 http_fetcher_(http_fetcher),
153 ping_active_days_(0),
154 ping_roll_call_days_(0) {}
118 155
119 OmahaRequestAction::~OmahaRequestAction() {} 156 OmahaRequestAction::~OmahaRequestAction() {}
120 157
158 // Calculates the value to use for the ping days parameter.
159 int OmahaRequestAction::CalculatePingDays(const string& key) {
160 int days = kNeverPinged;
161 int64_t last_ping = 0;
162 if (prefs_->GetInt64(key, &last_ping) && last_ping >= 0) {
163 days = (Time::Now() - Time::FromInternalValue(last_ping)).InDays();
164 if (days < 0) {
165 // If |days| is negative, then the system clock must have jumped
166 // back in time since the ping was sent. Mark the value so that
167 // it doesn't get sent to the server but we still update the
168 // last ping daystart preference. This way the next ping time
169 // will be correct, hopefully.
170 days = kPingTimeJump;
171 LOG(WARNING) <<
172 "System clock jumped back in time. Resetting ping daystarts.";
173 }
174 }
175 return days;
176 }
177
178 void OmahaRequestAction::InitPingDays() {
179 // We send pings only along with update checks, not with events.
180 if (IsEvent()) {
181 return;
182 }
183 // TODO(petkov): Figure a way to distinguish active use pings
184 // vs. roll call pings. Currently, the two pings are identical. A
185 // fix needs to change this code as well as UpdateLastPingDays.
186 ping_active_days_ = CalculatePingDays(kPrefsLastActivePingDay);
187 ping_roll_call_days_ = CalculatePingDays(kPrefsLastRollCallPingDay);
188 }
189
121 void OmahaRequestAction::PerformAction() { 190 void OmahaRequestAction::PerformAction() {
122 http_fetcher_->set_delegate(this); 191 http_fetcher_->set_delegate(this);
123 string request_post(FormatRequest(event_.get(), params_)); 192 InitPingDays();
193 string request_post(FormatRequest(event_.get(),
194 params_,
195 ping_active_days_,
196 ping_roll_call_days_));
124 http_fetcher_->SetPostData(request_post.data(), request_post.size()); 197 http_fetcher_->SetPostData(request_post.data(), request_post.size());
125 LOG(INFO) << "Posting an Omaha request to " << params_.update_url; 198 LOG(INFO) << "Posting an Omaha request to " << params_.update_url;
126 LOG(INFO) << "Request: " << request_post; 199 LOG(INFO) << "Request: " << request_post;
127 http_fetcher_->BeginTransfer(params_.update_url); 200 http_fetcher_->BeginTransfer(params_.update_url);
128 } 201 }
129 202
130 void OmahaRequestAction::TerminateProcessing() { 203 void OmahaRequestAction::TerminateProcessing() {
131 http_fetcher_->TerminateTransfer(); 204 http_fetcher_->TerminateTransfer();
132 } 205 }
133 206
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 // error. 265 // error.
193 off_t ParseInt(const string& str) { 266 off_t ParseInt(const string& str) {
194 off_t ret = 0; 267 off_t ret = 0;
195 int rc = sscanf(str.c_str(), "%" PRIi64, &ret); 268 int rc = sscanf(str.c_str(), "%" PRIi64, &ret);
196 if (rc < 1) { 269 if (rc < 1) {
197 // failure 270 // failure
198 return 0; 271 return 0;
199 } 272 }
200 return ret; 273 return ret;
201 } 274 }
275
276 // Update the last ping day preferences based on the server daystart
277 // response. Returns true on success, false otherwise.
278 bool UpdateLastPingDays(xmlDoc* doc, PrefsInterface* prefs) {
279 static const char kNamespace[] = "x";
280 static const char kDaystartNodeXpath[] = "/x:gupdate/x:daystart";
281 static const char kNsUrl[] = "http://www.google.com/update2/response";
282
283 scoped_ptr_malloc<xmlXPathObject, ScopedPtrXmlXPathObjectFree>
284 xpath_nodeset(GetNodeSet(doc,
285 ConstXMLStr(kDaystartNodeXpath),
286 ConstXMLStr(kNamespace),
287 ConstXMLStr(kNsUrl)));
288 TEST_AND_RETURN_FALSE(xpath_nodeset.get());
289 xmlNodeSet* nodeset = xpath_nodeset->nodesetval;
290 TEST_AND_RETURN_FALSE(nodeset && nodeset->nodeNr >= 1);
291 xmlNode* daystart_node = nodeset->nodeTab[0];
292 TEST_AND_RETURN_FALSE(xmlHasProp(daystart_node,
293 ConstXMLStr("elapsed_seconds")));
294
295 int64_t elapsed_seconds = 0;
296 TEST_AND_RETURN_FALSE(StringToInt64(XmlGetProperty(daystart_node,
297 "elapsed_seconds"),
298 &elapsed_seconds));
299 TEST_AND_RETURN_FALSE(elapsed_seconds >= 0);
300
301 // Remember the local time that matches the server's last midnight
302 // time.
303 Time daystart = Time::Now() - TimeDelta::FromSeconds(elapsed_seconds);
304 prefs->SetInt64(kPrefsLastActivePingDay, daystart.ToInternalValue());
305 prefs->SetInt64(kPrefsLastRollCallPingDay, daystart.ToInternalValue());
306 return true;
307 }
202 } // namespace {} 308 } // namespace {}
203 309
204 // If the transfer was successful, this uses libxml2 to parse the response 310 // If the transfer was successful, this uses libxml2 to parse the response
205 // and fill in the appropriate fields of the output object. Also, notifies 311 // and fill in the appropriate fields of the output object. Also, notifies
206 // the processor that we're done. 312 // the processor that we're done.
207 void OmahaRequestAction::TransferComplete(HttpFetcher *fetcher, 313 void OmahaRequestAction::TransferComplete(HttpFetcher *fetcher,
208 bool successful) { 314 bool successful) {
209 ScopedActionCompleter completer(processor_, this); 315 ScopedActionCompleter completer(processor_, this);
210 LOG(INFO) << "Omaha request response: " << string(response_buffer_.begin(), 316 LOG(INFO) << "Omaha request response: " << string(response_buffer_.begin(),
211 response_buffer_.end()); 317 response_buffer_.end());
(...skipping 17 matching lines...) Expand all
229 } 335 }
230 336
231 // parse our response and fill the fields in the output object 337 // parse our response and fill the fields in the output object
232 scoped_ptr_malloc<xmlDoc, ScopedPtrXmlDocFree> doc( 338 scoped_ptr_malloc<xmlDoc, ScopedPtrXmlDocFree> doc(
233 xmlParseMemory(&response_buffer_[0], response_buffer_.size())); 339 xmlParseMemory(&response_buffer_[0], response_buffer_.size()));
234 if (!doc.get()) { 340 if (!doc.get()) {
235 LOG(ERROR) << "Omaha response not valid XML"; 341 LOG(ERROR) << "Omaha response not valid XML";
236 return; 342 return;
237 } 343 }
238 344
345 // If a ping was sent, update the last ping day preferences based on
346 // the server daystart response.
347 if (ShouldPing(ping_active_days_) ||
348 ShouldPing(ping_roll_call_days_) ||
349 ping_active_days_ == kPingTimeJump ||
350 ping_roll_call_days_ == kPingTimeJump) {
351 LOG_IF(ERROR, !UpdateLastPingDays(doc.get(), prefs_))
352 << "Failed to update the last ping day preferences!";
353 }
354
239 static const char* kNamespace("x"); 355 static const char* kNamespace("x");
240 static const char* kUpdatecheckNodeXpath("/x:gupdate/x:app/x:updatecheck"); 356 static const char* kUpdatecheckNodeXpath("/x:gupdate/x:app/x:updatecheck");
241 static const char* kNsUrl("http://www.google.com/update2/response"); 357 static const char* kNsUrl("http://www.google.com/update2/response");
242 358
243 scoped_ptr_malloc<xmlXPathObject, ScopedPtrXmlXPathObjectFree> 359 scoped_ptr_malloc<xmlXPathObject, ScopedPtrXmlXPathObjectFree>
244 xpath_nodeset(GetNodeSet(doc.get(), 360 xpath_nodeset(GetNodeSet(doc.get(),
245 ConstXMLStr(kUpdatecheckNodeXpath), 361 ConstXMLStr(kUpdatecheckNodeXpath),
246 ConstXMLStr(kNamespace), 362 ConstXMLStr(kNamespace),
247 ConstXMLStr(kNsUrl))); 363 ConstXMLStr(kNsUrl)));
248 if (!xpath_nodeset.get()) { 364 if (!xpath_nodeset.get()) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 output_object.needs_admin = 404 output_object.needs_admin =
289 XmlGetProperty(updatecheck_node, "needsadmin") == "true"; 405 XmlGetProperty(updatecheck_node, "needsadmin") == "true";
290 output_object.prompt = XmlGetProperty(updatecheck_node, "Prompt") == "true"; 406 output_object.prompt = XmlGetProperty(updatecheck_node, "Prompt") == "true";
291 output_object.is_delta = 407 output_object.is_delta =
292 XmlGetProperty(updatecheck_node, "IsDelta") == "true"; 408 XmlGetProperty(updatecheck_node, "IsDelta") == "true";
293 SetOutputObject(output_object); 409 SetOutputObject(output_object);
294 return; 410 return;
295 } 411 }
296 412
297 }; // namespace chromeos_update_engine 413 }; // namespace chromeos_update_engine
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698