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

Side by Side Diff: components/update_client/update_checker.cc

Issue 2835803002: Refactor the UpdateEngine and its actions in the component updater. (Closed)
Patch Set: feedback up to #6 Created 3 years, 8 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 "components/update_client/update_checker.h" 5 #include "components/update_client/update_checker.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <string> 10 #include <string>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h" 14 #include "base/bind_helpers.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/macros.h" 17 #include "base/macros.h"
18 #include "base/memory/ptr_util.h"
18 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
19 #include "base/threading/thread_checker.h" 20 #include "base/threading/thread_checker.h"
20 #include "base/threading/thread_task_runner_handle.h" 21 #include "base/threading/thread_task_runner_handle.h"
22 #include "components/update_client/component.h"
21 #include "components/update_client/configurator.h" 23 #include "components/update_client/configurator.h"
22 #include "components/update_client/crx_update_item.h"
23 #include "components/update_client/persisted_data.h" 24 #include "components/update_client/persisted_data.h"
24 #include "components/update_client/request_sender.h" 25 #include "components/update_client/request_sender.h"
25 #include "components/update_client/update_client.h" 26 #include "components/update_client/update_client.h"
26 #include "components/update_client/updater_state.h" 27 #include "components/update_client/updater_state.h"
27 #include "components/update_client/utils.h" 28 #include "components/update_client/utils.h"
28 #include "url/gurl.h" 29 #include "url/gurl.h"
29 30
30 namespace update_client { 31 namespace update_client {
31 32
32 namespace { 33 namespace {
33 34
34 // Returns a sanitized version of the brand or an empty string otherwise. 35 // Returns a sanitized version of the brand or an empty string otherwise.
35 std::string SanitizeBrand(const std::string& brand) { 36 std::string SanitizeBrand(const std::string& brand) {
36 return IsValidBrand(brand) ? brand : std::string(""); 37 return IsValidBrand(brand) ? brand : std::string("");
37 } 38 }
38 39
39 // Filters invalid attributes from |installer_attributes|. 40 // Filters invalid attributes from |installer_attributes|.
40 update_client::InstallerAttributes SanitizeInstallerAttributes( 41 update_client::InstallerAttributes SanitizeInstallerAttributes(
41 const update_client::InstallerAttributes& installer_attributes) { 42 const update_client::InstallerAttributes& installer_attributes) {
42 update_client::InstallerAttributes sanitized_attrs; 43 update_client::InstallerAttributes sanitized_attrs;
43 for (const auto& attr : installer_attributes) { 44 for (const auto& attr : installer_attributes) {
44 if (IsValidInstallerAttribute(attr)) 45 if (IsValidInstallerAttribute(attr))
45 sanitized_attrs.insert(attr); 46 sanitized_attrs.insert(attr);
46 } 47 }
47 return sanitized_attrs; 48 return sanitized_attrs;
48 } 49 }
49 50
50 // Returns true if at least one item requires network encryption. 51 // Returns true if at least one item requires network encryption.
51 bool IsEncryptionRequired(const IdToCrxUpdateItemMap& items) { 52 bool IsEncryptionRequired(const IdToComponentPtrMap& components) {
52 for (const auto& item : items) { 53 for (const auto& item : components) {
53 if (item.second->component.requires_network_encryption) 54 const auto& component = item.second;
55 if (component->crx_component().requires_network_encryption)
54 return true; 56 return true;
55 } 57 }
56 return false; 58 return false;
57 } 59 }
58 60
59 // Builds an update check request for |components|. |additional_attributes| is 61 // Builds an update check request for |components|. |additional_attributes| is
60 // serialized as part of the <request> element of the request to customize it 62 // serialized as part of the <request> element of the request to customize it
61 // with data that is not platform or component specific. For each |item|, a 63 // with data that is not platform or component specific. For each |item|, a
62 // corresponding <app> element is created and inserted as a child node of 64 // corresponding <app> element is created and inserted as a child node of
63 // the <request>. 65 // the <request>.
64 // 66 //
65 // An app element looks like this: 67 // An app element looks like this:
66 // <app appid="hnimpnehoodheedghdeeijklkeaacbdc" 68 // <app appid="hnimpnehoodheedghdeeijklkeaacbdc"
67 // version="0.1.2.3" installsource="ondemand"> 69 // version="0.1.2.3" installsource="ondemand">
68 // <updatecheck/> 70 // <updatecheck/>
69 // <packages> 71 // <packages>
70 // <package fp="abcd"/> 72 // <package fp="abcd"/>
71 // </packages> 73 // </packages>
72 // </app> 74 // </app>
73 std::string BuildUpdateCheckRequest( 75 std::string BuildUpdateCheckRequest(
74 const Configurator& config, 76 const Configurator& config,
75 const IdToCrxUpdateItemMap& items, 77 const std::vector<std::string>& ids_checked,
78 const IdToComponentPtrMap& components,
76 PersistedData* metadata, 79 PersistedData* metadata,
77 const std::string& additional_attributes, 80 const std::string& additional_attributes,
78 bool enabled_component_updates, 81 bool enabled_component_updates,
79 const std::unique_ptr<UpdaterState::Attributes>& updater_state_attributes) { 82 const std::unique_ptr<UpdaterState::Attributes>& updater_state_attributes) {
80 const std::string brand(SanitizeBrand(config.GetBrand())); 83 const std::string brand(SanitizeBrand(config.GetBrand()));
81 std::string app_elements; 84 std::string app_elements;
82 for (const auto& item_pair : items) { 85 for (const auto& id : ids_checked) {
83 const CrxUpdateItem* item = item_pair.second.get(); 86 DCHECK_EQ(1u, components.count(id));
87 const Component& component = *components.at(id);
88
84 const update_client::InstallerAttributes installer_attributes( 89 const update_client::InstallerAttributes installer_attributes(
85 SanitizeInstallerAttributes(item->component.installer_attributes)); 90 SanitizeInstallerAttributes(
91 component.crx_component().installer_attributes));
86 std::string app("<app "); 92 std::string app("<app ");
87 base::StringAppendF(&app, "appid=\"%s\" version=\"%s\"", item->id.c_str(), 93 base::StringAppendF(&app, "appid=\"%s\" version=\"%s\"",
88 item->component.version.GetString().c_str()); 94 component.id().c_str(),
95 component.crx_component().version.GetString().c_str());
89 if (!brand.empty()) 96 if (!brand.empty())
90 base::StringAppendF(&app, " brand=\"%s\"", brand.c_str()); 97 base::StringAppendF(&app, " brand=\"%s\"", brand.c_str());
91 if (item->on_demand) 98 if (component.on_demand())
92 base::StringAppendF(&app, " installsource=\"ondemand\""); 99 base::StringAppendF(&app, " installsource=\"ondemand\"");
93 for (const auto& attr : installer_attributes) { 100 for (const auto& attr : installer_attributes) {
94 base::StringAppendF(&app, " %s=\"%s\"", attr.first.c_str(), 101 base::StringAppendF(&app, " %s=\"%s\"", attr.first.c_str(),
95 attr.second.c_str()); 102 attr.second.c_str());
96 } 103 }
97 const std::string cohort = metadata->GetCohort(item->id); 104 const std::string cohort = metadata->GetCohort(component.id());
98 const std::string cohort_name = metadata->GetCohortName(item->id); 105 const std::string cohort_name = metadata->GetCohortName(component.id());
99 const std::string cohort_hint = metadata->GetCohortHint(item->id); 106 const std::string cohort_hint = metadata->GetCohortHint(component.id());
100 if (!cohort.empty()) 107 if (!cohort.empty())
101 base::StringAppendF(&app, " cohort=\"%s\"", cohort.c_str()); 108 base::StringAppendF(&app, " cohort=\"%s\"", cohort.c_str());
102 if (!cohort_name.empty()) 109 if (!cohort_name.empty())
103 base::StringAppendF(&app, " cohortname=\"%s\"", cohort_name.c_str()); 110 base::StringAppendF(&app, " cohortname=\"%s\"", cohort_name.c_str());
104 if (!cohort_hint.empty()) 111 if (!cohort_hint.empty())
105 base::StringAppendF(&app, " cohorthint=\"%s\"", cohort_hint.c_str()); 112 base::StringAppendF(&app, " cohorthint=\"%s\"", cohort_hint.c_str());
106 base::StringAppendF(&app, ">"); 113 base::StringAppendF(&app, ">");
107 114
108 base::StringAppendF(&app, "<updatecheck"); 115 base::StringAppendF(&app, "<updatecheck");
109 if (item->component.supports_group_policy_enable_component_updates && 116 if (component.crx_component()
117 .supports_group_policy_enable_component_updates &&
110 !enabled_component_updates) { 118 !enabled_component_updates) {
111 base::StringAppendF(&app, " updatedisabled=\"true\""); 119 base::StringAppendF(&app, " updatedisabled=\"true\"");
112 } 120 }
113 base::StringAppendF(&app, "/>"); 121 base::StringAppendF(&app, "/>");
114 122
115 base::StringAppendF(&app, "<ping rd=\"%d\" ping_freshness=\"%s\"/>", 123 base::StringAppendF(&app, "<ping rd=\"%d\" ping_freshness=\"%s\"/>",
116 metadata->GetDateLastRollCall(item->id), 124 metadata->GetDateLastRollCall(component.id()),
117 metadata->GetPingFreshness(item->id).c_str()); 125 metadata->GetPingFreshness(component.id()).c_str());
118 if (!item->component.fingerprint.empty()) { 126 if (!component.crx_component().fingerprint.empty()) {
119 base::StringAppendF(&app, 127 base::StringAppendF(&app,
120 "<packages>" 128 "<packages>"
121 "<package fp=\"%s\"/>" 129 "<package fp=\"%s\"/>"
122 "</packages>", 130 "</packages>",
123 item->component.fingerprint.c_str()); 131 component.crx_component().fingerprint.c_str());
124 } 132 }
125 base::StringAppendF(&app, "</app>"); 133 base::StringAppendF(&app, "</app>");
126 app_elements.append(app); 134 app_elements.append(app);
127 VLOG(1) << "Appending to update request: " << app; 135 VLOG(1) << "Appending to update request: " << app;
128 } 136 }
129 137
130 // Include the updater state in the update check request. 138 // Include the updater state in the update check request.
131 return BuildProtocolRequest( 139 return BuildProtocolRequest(
132 config.GetProdId(), config.GetBrowserVersion().GetString(), 140 config.GetProdId(), config.GetBrowserVersion().GetString(),
133 config.GetChannel(), config.GetLang(), config.GetOSLongName(), 141 config.GetChannel(), config.GetLang(), config.GetOSLongName(),
134 config.GetDownloadPreference(), app_elements, additional_attributes, 142 config.GetDownloadPreference(), app_elements, additional_attributes,
135 updater_state_attributes); 143 updater_state_attributes);
136 } 144 }
137 145
138 class UpdateCheckerImpl : public UpdateChecker { 146 class UpdateCheckerImpl : public UpdateChecker {
139 public: 147 public:
140 UpdateCheckerImpl(const scoped_refptr<Configurator>& config, 148 UpdateCheckerImpl(const scoped_refptr<Configurator>& config,
141 PersistedData* metadata); 149 PersistedData* metadata);
142 ~UpdateCheckerImpl() override; 150 ~UpdateCheckerImpl() override;
143 151
144 // Overrides for UpdateChecker. 152 // Overrides for UpdateChecker.
145 bool CheckForUpdates( 153 bool CheckForUpdates(
146 const IdToCrxUpdateItemMap& items_to_check, 154 const std::vector<std::string>& ids_checked,
155 const IdToComponentPtrMap& components,
147 const std::string& additional_attributes, 156 const std::string& additional_attributes,
148 bool enabled_component_updates, 157 bool enabled_component_updates,
149 const UpdateCheckCallback& update_check_callback) override; 158 const UpdateCheckCallback& update_check_callback) override;
150 159
151 private: 160 private:
152 void ReadUpdaterStateAttributes(); 161 void ReadUpdaterStateAttributes();
153 void CheckForUpdatesHelper(const IdToCrxUpdateItemMap& items_to_check, 162 void CheckForUpdatesHelper(const IdToComponentPtrMap& components,
154 const std::string& additional_attributes, 163 const std::string& additional_attributes,
155 bool enabled_component_updates); 164 bool enabled_component_updates);
165 void OnRequestSenderComplete(const IdToComponentPtrMap& components,
166 int error,
167 const std::string& response,
168 int retry_after_sec);
169 void UpdateCheckSucceeded(const IdToComponentPtrMap& components,
170 const UpdateResponse::Results& results,
171 int retry_after_sec);
172 void UpdateCheckFailed(const IdToComponentPtrMap& components,
173 int error,
174 int retry_after_sec);
156 175
157 void OnRequestSenderComplete(
158 std::unique_ptr<std::vector<std::string>> ids_checked,
159 int error,
160 const std::string& response,
161 int retry_after_sec);
162 base::ThreadChecker thread_checker_; 176 base::ThreadChecker thread_checker_;
163 177
164 const scoped_refptr<Configurator> config_; 178 const scoped_refptr<Configurator> config_;
165 PersistedData* metadata_; 179 PersistedData* metadata_ = nullptr;
180 std::vector<std::string> ids_checked_;
166 UpdateCheckCallback update_check_callback_; 181 UpdateCheckCallback update_check_callback_;
167 std::unique_ptr<UpdaterState::Attributes> updater_state_attributes_; 182 std::unique_ptr<UpdaterState::Attributes> updater_state_attributes_;
168 std::unique_ptr<RequestSender> request_sender_; 183 std::unique_ptr<RequestSender> request_sender_;
169 184
170 DISALLOW_COPY_AND_ASSIGN(UpdateCheckerImpl); 185 DISALLOW_COPY_AND_ASSIGN(UpdateCheckerImpl);
171 }; 186 };
172 187
173 UpdateCheckerImpl::UpdateCheckerImpl(const scoped_refptr<Configurator>& config, 188 UpdateCheckerImpl::UpdateCheckerImpl(const scoped_refptr<Configurator>& config,
174 PersistedData* metadata) 189 PersistedData* metadata)
175 : config_(config), metadata_(metadata) {} 190 : config_(config), metadata_(metadata) {}
176 191
177 UpdateCheckerImpl::~UpdateCheckerImpl() { 192 UpdateCheckerImpl::~UpdateCheckerImpl() {
178 DCHECK(thread_checker_.CalledOnValidThread()); 193 DCHECK(thread_checker_.CalledOnValidThread());
179 } 194 }
180 195
181 bool UpdateCheckerImpl::CheckForUpdates( 196 bool UpdateCheckerImpl::CheckForUpdates(
182 const IdToCrxUpdateItemMap& items_to_check, 197 const std::vector<std::string>& ids_checked,
198 const IdToComponentPtrMap& components,
183 const std::string& additional_attributes, 199 const std::string& additional_attributes,
184 bool enabled_component_updates, 200 bool enabled_component_updates,
185 const UpdateCheckCallback& update_check_callback) { 201 const UpdateCheckCallback& update_check_callback) {
186 DCHECK(thread_checker_.CalledOnValidThread()); 202 DCHECK(thread_checker_.CalledOnValidThread());
187 203
204 ids_checked_ = ids_checked;
188 update_check_callback_ = update_check_callback; 205 update_check_callback_ = update_check_callback;
189 206
190 return config_->GetSequencedTaskRunner()->PostTaskAndReply( 207 return config_->GetSequencedTaskRunner()->PostTaskAndReply(
191 FROM_HERE, base::Bind(&UpdateCheckerImpl::ReadUpdaterStateAttributes, 208 FROM_HERE,
192 base::Unretained(this)), 209 base::Bind(&UpdateCheckerImpl::ReadUpdaterStateAttributes,
210 base::Unretained(this)),
193 base::Bind(&UpdateCheckerImpl::CheckForUpdatesHelper, 211 base::Bind(&UpdateCheckerImpl::CheckForUpdatesHelper,
194 base::Unretained(this), base::ConstRef(items_to_check), 212 base::Unretained(this), base::ConstRef(components),
195 additional_attributes, enabled_component_updates)); 213 additional_attributes, enabled_component_updates));
196 } 214 }
197 215
198 // This function runs on the blocking pool task runner. 216 // This function runs on the blocking pool task runner.
199 void UpdateCheckerImpl::ReadUpdaterStateAttributes() { 217 void UpdateCheckerImpl::ReadUpdaterStateAttributes() {
200 const bool is_machine_install = !config_->IsPerUserInstall(); 218 const bool is_machine_install = !config_->IsPerUserInstall();
201 updater_state_attributes_ = UpdaterState::GetState(is_machine_install); 219 updater_state_attributes_ = UpdaterState::GetState(is_machine_install);
202 } 220 }
203 221
204 void UpdateCheckerImpl::CheckForUpdatesHelper( 222 void UpdateCheckerImpl::CheckForUpdatesHelper(
205 const IdToCrxUpdateItemMap& items_to_check, 223 const IdToComponentPtrMap& components,
206 const std::string& additional_attributes, 224 const std::string& additional_attributes,
207 bool enabled_component_updates) { 225 bool enabled_component_updates) {
208 DCHECK(thread_checker_.CalledOnValidThread()); 226 DCHECK(thread_checker_.CalledOnValidThread());
209 227
210 auto urls(config_->UpdateUrl()); 228 auto urls(config_->UpdateUrl());
211 if (IsEncryptionRequired(items_to_check)) 229 if (IsEncryptionRequired(components))
212 RemoveUnsecureUrls(&urls); 230 RemoveUnsecureUrls(&urls);
213 231
214 std::unique_ptr<std::vector<std::string>> ids_checked( 232 request_sender_ = base::MakeUnique<RequestSender>(config_);
215 new std::vector<std::string>());
216 for (const auto& item : items_to_check)
217 ids_checked->push_back(item.second->id);
218 request_sender_.reset(new RequestSender(config_));
219 request_sender_->Send( 233 request_sender_->Send(
220 config_->EnabledCupSigning(), 234 config_->EnabledCupSigning(),
221 BuildUpdateCheckRequest(*config_, items_to_check, metadata_, 235 BuildUpdateCheckRequest(*config_, ids_checked_, components, metadata_,
222 additional_attributes, enabled_component_updates, 236 additional_attributes, enabled_component_updates,
223 updater_state_attributes_), 237 updater_state_attributes_),
224 urls, base::Bind(&UpdateCheckerImpl::OnRequestSenderComplete, 238 urls,
225 base::Unretained(this), base::Passed(&ids_checked))); 239 base::Bind(&UpdateCheckerImpl::OnRequestSenderComplete,
240 base::Unretained(this), base::ConstRef(components)));
226 } 241 }
227 242
228 void UpdateCheckerImpl::OnRequestSenderComplete( 243 void UpdateCheckerImpl::OnRequestSenderComplete(
229 std::unique_ptr<std::vector<std::string>> ids_checked, 244 const IdToComponentPtrMap& components,
230 int error, 245 int error,
231 const std::string& response, 246 const std::string& response,
232 int retry_after_sec) { 247 int retry_after_sec) {
233 DCHECK(thread_checker_.CalledOnValidThread()); 248 DCHECK(thread_checker_.CalledOnValidThread());
234 249
235 if (!error) { 250 if (error) {
236 UpdateResponse update_response; 251 VLOG(1) << "RequestSender failed " << error;
237 if (update_response.Parse(response)) { 252 UpdateCheckFailed(components, error, retry_after_sec);
238 int daynum = update_response.results().daystart_elapsed_days; 253 return;
239 if (daynum != UpdateResponse::kNoDaystart) 254 }
240 metadata_->SetDateLastRollCall(*ids_checked, daynum);
241 for (const auto& result : update_response.results().list) {
242 auto entry = result.cohort_attrs.find(UpdateResponse::Result::kCohort);
243 if (entry != result.cohort_attrs.end())
244 metadata_->SetCohort(result.extension_id, entry->second);
245 entry = result.cohort_attrs.find(UpdateResponse::Result::kCohortName);
246 if (entry != result.cohort_attrs.end())
247 metadata_->SetCohortName(result.extension_id, entry->second);
248 entry = result.cohort_attrs.find(UpdateResponse::Result::kCohortHint);
249 if (entry != result.cohort_attrs.end())
250 metadata_->SetCohortHint(result.extension_id, entry->second);
251 }
252 base::ThreadTaskRunnerHandle::Get()->PostTask(
253 FROM_HERE, base::Bind(update_check_callback_, error,
254 update_response.results(), retry_after_sec));
255 return;
256 }
257 255
258 error = -1; 256 UpdateResponse update_response;
257 if (!update_response.Parse(response)) {
259 VLOG(1) << "Parse failed " << update_response.errors(); 258 VLOG(1) << "Parse failed " << update_response.errors();
259 UpdateCheckFailed(components, -1, retry_after_sec);
260 return;
261 }
262
263 DCHECK_EQ(0, error);
264 UpdateCheckSucceeded(components, update_response.results(), retry_after_sec);
265 }
266
267 void UpdateCheckerImpl::UpdateCheckSucceeded(
268 const IdToComponentPtrMap& components,
269 const UpdateResponse::Results& results,
270 int retry_after_sec) {
271 DCHECK(thread_checker_.CalledOnValidThread());
272
273 const int daynum = results.daystart_elapsed_days;
274 if (daynum != UpdateResponse::kNoDaystart)
275 metadata_->SetDateLastRollCall(ids_checked_, daynum);
276 for (const auto& result : results.list) {
277 auto entry = result.cohort_attrs.find(UpdateResponse::Result::kCohort);
278 if (entry != result.cohort_attrs.end())
279 metadata_->SetCohort(result.extension_id, entry->second);
280 entry = result.cohort_attrs.find(UpdateResponse::Result::kCohortName);
281 if (entry != result.cohort_attrs.end())
282 metadata_->SetCohortName(result.extension_id, entry->second);
283 entry = result.cohort_attrs.find(UpdateResponse::Result::kCohortHint);
284 if (entry != result.cohort_attrs.end())
285 metadata_->SetCohortHint(result.extension_id, entry->second);
286 }
287
288 for (const auto& result : results.list) {
289 const auto& id = result.extension_id;
290 const auto it = components.find(id);
291 if (it != components.end())
292 it->second->SetParseResult(result);
260 } 293 }
261 294
262 base::ThreadTaskRunnerHandle::Get()->PostTask( 295 base::ThreadTaskRunnerHandle::Get()->PostTask(
263 FROM_HERE, base::Bind(update_check_callback_, error, 296 FROM_HERE, base::Bind(update_check_callback_, 0, retry_after_sec));
264 UpdateResponse::Results(), retry_after_sec)); 297 }
298
299 void UpdateCheckerImpl::UpdateCheckFailed(const IdToComponentPtrMap& components,
300 int error,
301 int retry_after_sec) {
302 DCHECK(thread_checker_.CalledOnValidThread());
303 DCHECK_NE(0, error);
304 for (const auto& item : components) {
305 DCHECK(item.second);
306 Component& component = *item.second;
307 component.set_update_check_error(error);
308 }
309
310 base::ThreadTaskRunnerHandle::Get()->PostTask(
311 FROM_HERE, base::Bind(update_check_callback_, error, retry_after_sec));
265 } 312 }
266 313
267 } // namespace 314 } // namespace
268 315
269 std::unique_ptr<UpdateChecker> UpdateChecker::Create( 316 std::unique_ptr<UpdateChecker> UpdateChecker::Create(
270 const scoped_refptr<Configurator>& config, 317 const scoped_refptr<Configurator>& config,
271 PersistedData* persistent) { 318 PersistedData* persistent) {
272 return std::unique_ptr<UpdateChecker>( 319 return base::MakeUnique<UpdateCheckerImpl>(config, persistent);
273 new UpdateCheckerImpl(config, persistent));
274 } 320 }
275 321
276 } // namespace update_client 322 } // namespace update_client
OLDNEW
« no previous file with comments | « components/update_client/update_checker.h ('k') | components/update_client/update_checker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698