1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/component_updater/component_updater_ping_manager.h"
9 #include "base/compiler_specific.h"
10 #include "base/guid.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "components/component_updater/component_updater_configurator.h"
17 #include "components/component_updater/component_updater_utils.h"
18 #include "components/component_updater/crx_update_item.h"
19 #include "net/url_request/url_fetcher.h"
20 #include "net/url_request/url_fetcher_delegate.h"
23 namespace component_updater
{
25 // Returns a string literal corresponding to the value of the downloader |d|.
26 const char* DownloaderToString(CrxDownloader::DownloadMetrics::Downloader d
) {
28 case CrxDownloader::DownloadMetrics::kUrlFetcher
:
30 case CrxDownloader::DownloadMetrics::kBits
:
37 // Sends a fire and forget ping. The instances of this class have no
38 // ownership and they self-delete upon completion.
39 class PingSender
: public net::URLFetcherDelegate
{
43 void SendPing(const Configurator
& config
,
44 net::URLRequestContextGetter
* url_request_context_getter
,
45 const CrxUpdateItem
* item
);
48 virtual ~PingSender();
50 // Overrides for URLFetcherDelegate.
51 virtual void OnURLFetchComplete(const net::URLFetcher
* source
) OVERRIDE
;
53 static std::string
BuildPing(const Configurator
& config
,
54 const CrxUpdateItem
* item
);
55 static std::string
BuildDownloadCompleteEventElements(
56 const CrxUpdateItem
* item
);
57 static std::string
BuildUpdateCompleteEventElement(const CrxUpdateItem
* item
);
59 scoped_ptr
<net::URLFetcher
> url_fetcher_
;
61 DISALLOW_COPY_AND_ASSIGN(PingSender
);
64 PingSender::PingSender() {
67 PingSender::~PingSender() {
70 void PingSender::OnURLFetchComplete(const net::URLFetcher
* source
) {
74 void PingSender::SendPing(
75 const Configurator
& config
,
76 net::URLRequestContextGetter
* url_request_context_getter
,
77 const CrxUpdateItem
* item
) {
80 if (!config
.PingUrl().is_valid())
83 url_fetcher_
.reset(SendProtocolRequest(config
.PingUrl(),
84 BuildPing(config
, item
),
86 url_request_context_getter
));
89 // Builds a ping message for the specified update item.
90 std::string
PingSender::BuildPing(const Configurator
& config
,
91 const CrxUpdateItem
* item
) {
92 const char app_element_format
[] =
93 "<app appid=\"%s\" version=\"%s\" nextversion=\"%s\">"
97 const std::string
app_element(base::StringPrintf(
99 item
->id
.c_str(), // "appid"
100 item
->previous_version
.GetString().c_str(), // "version"
101 item
->next_version
.GetString().c_str(), // "nextversion"
102 BuildUpdateCompleteEventElement(item
).c_str(), // update event
103 BuildDownloadCompleteEventElements(item
).c_str())); // download events
105 return BuildProtocolRequest(config
.GetBrowserVersion().GetString(),
108 config
.GetOSLongName(),
113 // Returns a string representing a sequence of download complete events
114 // corresponding to each download metrics in |item|.
115 std::string
PingSender::BuildDownloadCompleteEventElements(
116 const CrxUpdateItem
* item
) {
117 using base::StringAppendF
;
118 std::string download_events
;
119 for (size_t i
= 0; i
!= item
->download_metrics
.size(); ++i
) {
120 const CrxDownloader::DownloadMetrics
& metrics
= item
->download_metrics
[i
];
121 std::string
event("<event eventtype=\"14\"");
122 StringAppendF(&event
, " eventresult=\"%d\"", metrics
.error
== 0);
123 StringAppendF(&event
,
124 " downloader=\"%s\"",
125 DownloaderToString(metrics
.downloader
));
127 StringAppendF(&event
, " errorcode=\"%d\"", metrics
.error
);
129 StringAppendF(&event
, " url=\"%s\"", metrics
.url
.spec().c_str());
131 // -1 means that the byte counts are not known.
132 if (metrics
.downloaded_bytes
!= -1) {
133 StringAppendF(&event
,
134 " downloaded=\"%s\"",
135 base::Int64ToString(metrics
.downloaded_bytes
).c_str());
137 if (metrics
.total_bytes
!= -1) {
138 StringAppendF(&event
,
140 base::Int64ToString(metrics
.total_bytes
).c_str());
143 if (metrics
.download_time_ms
) {
144 StringAppendF(&event
,
145 " download_time_ms=\"%s\"",
146 base::Uint64ToString(metrics
.download_time_ms
).c_str());
148 StringAppendF(&event
, "/>");
150 download_events
+= event
;
152 return download_events
;
155 // Returns a string representing one ping event xml element for an update item.
156 std::string
PingSender::BuildUpdateCompleteEventElement(
157 const CrxUpdateItem
* item
) {
158 DCHECK(item
->status
== CrxUpdateItem::kNoUpdate
||
159 item
->status
== CrxUpdateItem::kUpdated
);
161 using base::StringAppendF
;
163 std::string
ping_event("<event eventtype=\"3\"");
164 const int event_result
= item
->status
== CrxUpdateItem::kUpdated
;
165 StringAppendF(&ping_event
, " eventresult=\"%d\"", event_result
);
166 if (item
->error_category
)
167 StringAppendF(&ping_event
, " errorcat=\"%d\"", item
->error_category
);
168 if (item
->error_code
)
169 StringAppendF(&ping_event
, " errorcode=\"%d\"", item
->error_code
);
170 if (item
->extra_code1
)
171 StringAppendF(&ping_event
, " extracode1=\"%d\"", item
->extra_code1
);
172 if (HasDiffUpdate(item
))
173 StringAppendF(&ping_event
, " diffresult=\"%d\"", !item
->diff_update_failed
);
174 if (item
->diff_error_category
) {
176 &ping_event
, " differrorcat=\"%d\"", item
->diff_error_category
);
178 if (item
->diff_error_code
)
179 StringAppendF(&ping_event
, " differrorcode=\"%d\"", item
->diff_error_code
);
180 if (item
->diff_extra_code1
) {
182 &ping_event
, " diffextracode1=\"%d\"", item
->diff_extra_code1
);
184 if (!item
->previous_fp
.empty())
185 StringAppendF(&ping_event
, " previousfp=\"%s\"", item
->previous_fp
.c_str());
186 if (!item
->next_fp
.empty())
187 StringAppendF(&ping_event
, " nextfp=\"%s\"", item
->next_fp
.c_str());
188 StringAppendF(&ping_event
, "/>");
192 PingManager::PingManager(const Configurator
& config
) : config_(config
) {
195 PingManager::~PingManager() {
198 // Sends a fire and forget ping when the updates are complete. The ping
199 // sender object self-deletes after sending the ping.
200 void PingManager::OnUpdateComplete(const CrxUpdateItem
* item
) {
201 PingSender
* ping_sender(new PingSender
);
202 ping_sender
->SendPing(config_
, config_
.RequestContext(), item
);
205 } // namespace component_updater