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/update_checker.h"
7 #include "base/compiler_specific.h"
8 #include "base/logging.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/threading/thread_checker.h"
11 #include "components/component_updater/component_updater_configurator.h"
12 #include "components/component_updater/component_updater_utils.h"
13 #include "components/component_updater/crx_update_item.h"
14 #include "net/url_request/url_fetcher.h"
15 #include "net/url_request/url_fetcher_delegate.h"
18 namespace component_updater
{
20 // Builds an update check request for |components|. |additional_attributes| is
21 // serialized as part of the <request> element of the request to customize it
22 // with data that is not platform or component specific. For each |item|, a
23 // corresponding <app> element is created and inserted as a child node of
26 // An app element looks like this:
27 // <app appid="hnimpnehoodheedghdeeijklkeaacbdc"
28 // version="0.1.2.3" installsource="ondemand">
31 // <package fp="abcd" />
34 std::string
BuildUpdateCheckRequest(const Configurator
& config
,
35 const std::vector
<CrxUpdateItem
*>& items
,
36 const std::string
& additional_attributes
) {
37 std::string app_elements
;
38 for (size_t i
= 0; i
!= items
.size(); ++i
) {
39 const CrxUpdateItem
* item
= items
[i
];
40 std::string
app("<app ");
41 base::StringAppendF(&app
,
42 "appid=\"%s\" version=\"%s\"",
44 item
->component
.version
.GetString().c_str());
46 base::StringAppendF(&app
, " installsource=\"ondemand\"");
47 base::StringAppendF(&app
, ">");
48 base::StringAppendF(&app
, "<updatecheck />");
49 if (!item
->component
.fingerprint
.empty()) {
50 base::StringAppendF(&app
,
52 "<package fp=\"%s\"/>"
54 item
->component
.fingerprint
.c_str());
56 base::StringAppendF(&app
, "</app>");
57 app_elements
.append(app
);
58 VLOG(1) << "Appending to update request: " << app
;
61 return BuildProtocolRequest(config
.GetBrowserVersion().GetString(),
64 config
.GetOSLongName(),
66 additional_attributes
);
69 class UpdateCheckerImpl
: public UpdateChecker
, public net::URLFetcherDelegate
{
71 UpdateCheckerImpl(const Configurator
& config
,
72 const UpdateCheckCallback
& update_check_callback
);
73 virtual ~UpdateCheckerImpl();
75 // Overrides for UpdateChecker.
76 virtual bool CheckForUpdates(
77 const std::vector
<CrxUpdateItem
*>& items_to_check
,
78 const std::string
& additional_attributes
) OVERRIDE
;
80 // Overrides for UrlFetcher.
81 virtual void OnURLFetchComplete(const net::URLFetcher
* source
) OVERRIDE
;
84 const Configurator
& config_
;
85 const UpdateCheckCallback update_check_callback_
;
87 scoped_ptr
<net::URLFetcher
> url_fetcher_
;
89 base::ThreadChecker thread_checker_
;
91 DISALLOW_COPY_AND_ASSIGN(UpdateCheckerImpl
);
94 scoped_ptr
<UpdateChecker
> UpdateChecker::Create(
95 const Configurator
& config
,
96 const UpdateCheckCallback
& update_check_callback
) {
97 scoped_ptr
<UpdateCheckerImpl
> update_checker(
98 new UpdateCheckerImpl(config
, update_check_callback
));
99 return update_checker
.PassAs
<UpdateChecker
>();
102 UpdateCheckerImpl::UpdateCheckerImpl(
103 const Configurator
& config
,
104 const UpdateCheckCallback
& update_check_callback
)
105 : config_(config
), update_check_callback_(update_check_callback
) {
108 UpdateCheckerImpl::~UpdateCheckerImpl() {
109 DCHECK(thread_checker_
.CalledOnValidThread());
112 bool UpdateCheckerImpl::CheckForUpdates(
113 const std::vector
<CrxUpdateItem
*>& items_to_check
,
114 const std::string
& additional_attributes
) {
115 DCHECK(thread_checker_
.CalledOnValidThread());
118 return false; // Another fetch is in progress.
120 url_fetcher_
.reset(SendProtocolRequest(
122 BuildUpdateCheckRequest(config_
, items_to_check
, additional_attributes
),
124 config_
.RequestContext()));
129 void UpdateCheckerImpl::OnURLFetchComplete(const net::URLFetcher
* source
) {
130 DCHECK(thread_checker_
.CalledOnValidThread());
131 DCHECK(url_fetcher_
.get() == source
);
134 std::string error_message
;
135 UpdateResponse update_response
;
137 if (FetchSuccess(*source
)) {
139 source
->GetResponseAsString(&xml
);
140 if (!update_response
.Parse(xml
)) {
142 error_message
= update_response
.errors();
143 VLOG(1) << "Update request failed: " << error_message
;
146 error
= GetFetchError(*source
);
147 error_message
.assign("network error");
148 VLOG(1) << "Update request failed: network error";
151 url_fetcher_
.reset();
152 update_check_callback_
.Run(error
, error_message
, update_response
.results());
155 } // namespace component_updater