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

Side by Side Diff: chrome/browser/component_updater/component_updater_service.cc

Issue 15908002: Differential updates for components. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 6 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/component_updater/component_updater_service.h" 5 #include "chrome/browser/component_updater/component_updater_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/at_exit.h" 11 #include "base/at_exit.h"
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/compiler_specific.h"
13 #include "base/file_util.h" 14 #include "base/file_util.h"
14 #include "base/files/file_path.h" 15 #include "base/files/file_path.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
17 #include "base/stl_util.h" 18 #include "base/stl_util.h"
18 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_piece.h" 20 #include "base/strings/string_piece.h"
20 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h" 22 #include "base/strings/stringprintf.h"
22 #include "base/timer.h" 23 #include "base/timer.h"
23 #include "chrome/browser/browser_process.h" 24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/component_updater/component_patcher.h"
24 #include "chrome/browser/component_updater/component_unpacker.h" 26 #include "chrome/browser/component_updater/component_unpacker.h"
25 #include "chrome/common/chrome_notification_types.h" 27 #include "chrome/common/chrome_notification_types.h"
26 #include "chrome/common/chrome_utility_messages.h" 28 #include "chrome/common/chrome_utility_messages.h"
27 #include "chrome/common/chrome_version_info.h" 29 #include "chrome/common/chrome_version_info.h"
28 #include "chrome/common/extensions/extension.h" 30 #include "chrome/common/extensions/extension.h"
31 #include "chrome/common/omaha_query_params/omaha_query_params.h"
29 #include "content/public/browser/browser_thread.h" 32 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/notification_service.h" 33 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/utility_process_host.h" 34 #include "content/public/browser/utility_process_host.h"
32 #include "content/public/browser/utility_process_host_client.h" 35 #include "content/public/browser/utility_process_host_client.h"
33 #include "googleurl/src/gurl.h" 36 #include "googleurl/src/gurl.h"
34 #include "net/base/escape.h" 37 #include "net/base/escape.h"
35 #include "net/base/load_flags.h" 38 #include "net/base/load_flags.h"
36 #include "net/base/net_errors.h" 39 #include "net/base/net_errors.h"
37 #include "net/url_request/url_fetcher.h" 40 #include "net/url_request/url_fetcher.h"
38 #include "net/url_request/url_fetcher_delegate.h" 41 #include "net/url_request/url_fetcher_delegate.h"
39 #include "net/url_request/url_request_status.h" 42 #include "net/url_request/url_request_status.h"
40 43
41 using content::BrowserThread; 44 using content::BrowserThread;
42 using content::UtilityProcessHost; 45 using content::UtilityProcessHost;
43 using content::UtilityProcessHostClient; 46 using content::UtilityProcessHostClient;
44 using extensions::Extension; 47 using extensions::Extension;
45 48
46 // The component updater is designed to live until process shutdown, so 49 // The component updater is designed to live until process shutdown, so
47 // base::Bind() calls are not refcounted. 50 // base::Bind() calls are not refcounted.
48 51
49 namespace { 52 namespace {
53
50 // Manifest sources, from most important to least important. 54 // Manifest sources, from most important to least important.
51 const CrxComponent::UrlSource kManifestSources[] = { 55 const CrxComponent::UrlSource kManifestSources[] = {
52 CrxComponent::BANDAID, 56 CrxComponent::BANDAID,
53 CrxComponent::CWS_PUBLIC, 57 CrxComponent::CWS_PUBLIC,
54 CrxComponent::CWS_SANDBOX 58 CrxComponent::CWS_SANDBOX,
55 }; 59 };
56 60
57 // Extends an omaha compatible update check url |query| string. Does 61 // Extends an omaha compatible update check url |query| string. Does
58 // not mutate the string if it would be longer than |limit| chars. 62 // not mutate the string if it would be longer than |limit| chars.
59 bool AddQueryString(const std::string& id, 63 bool AddQueryString(const std::string& id,
60 const std::string& version, 64 const std::string& version,
65 const std::string& fingerprint,
61 size_t limit, 66 size_t limit,
62 std::string* query) { 67 std::string* query) {
63 std::string additional = 68 std::string additional =
64 base::StringPrintf("id=%s&v=%s&uc", id.c_str(), version.c_str()); 69 base::StringPrintf("id=%s&v=%s&fp=%s&uc",
70 id.c_str(), version.c_str(), fingerprint.c_str());
65 additional = "x=" + net::EscapeQueryParamValue(additional, true); 71 additional = "x=" + net::EscapeQueryParamValue(additional, true);
66 if ((additional.size() + query->size() + 1) > limit) 72 if ((additional.size() + query->size() + 1) > limit)
67 return false; 73 return false;
68 if (!query->empty()) 74 if (!query->empty())
69 query->append(1, '&'); 75 query->append(1, '&');
70 query->append(additional); 76 query->append(additional);
71 return true; 77 return true;
72 } 78 }
73 79
74 // Create the final omaha compatible query. The |extra| is optional and can 80 // Create the final omaha compatible query. The |extra| is optional and can
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 net::LOAD_DISABLE_CACHE); 162 net::LOAD_DISABLE_CACHE);
157 // TODO(cpu): Define our retry and backoff policy. 163 // TODO(cpu): Define our retry and backoff policy.
158 fetcher->SetAutomaticallyRetryOn5xx(false); 164 fetcher->SetAutomaticallyRetryOn5xx(false);
159 if (save_to_file) { 165 if (save_to_file) {
160 fetcher->SaveResponseToTemporaryFile( 166 fetcher->SaveResponseToTemporaryFile(
161 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); 167 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
162 } 168 }
163 fetcher->Start(); 169 fetcher->Start();
164 } 170 }
165 171
166 // Returs true if the url request of |fetcher| was succesful. 172 // Returns true if the url request of |fetcher| was succesful.
167 bool FetchSuccess(const net::URLFetcher& fetcher) { 173 bool FetchSuccess(const net::URLFetcher& fetcher) {
168 return (fetcher.GetStatus().status() == net::URLRequestStatus::SUCCESS) && 174 return (fetcher.GetStatus().status() == net::URLRequestStatus::SUCCESS) &&
169 (fetcher.GetResponseCode() == 200); 175 (fetcher.GetResponseCode() == 200);
170 } 176 }
171 177
172 // This is the one and only per-item state structure. Designed to be hosted 178 // This is the one and only per-item state structure. Designed to be hosted
173 // in a std::vector or a std::list. The two main members are |component| 179 // in a std::vector or a std::list. The two main members are |component|
174 // which is supplied by the the component updater client and |status| which 180 // which is supplied by the the component updater client and |status| which
175 // is modified as the item is processed by the update pipeline. The expected 181 // is modified as the item is processed by the update pipeline. The expected
176 // transition graph is: 182 // transition graph is:
177 // error error error 183 //
178 // +--kNoUpdate<------<-------+------<------+------<------+ 184 // kNew
179 // | | | | 185 // |
180 // V yes | | | 186 // V
181 // kNew --->kChecking-->[update?]----->kCanUpdate-->kDownloading-->kUpdating 187 // +----------------------> kChecking -<---------+-----<-------+
182 // ^ | | 188 // | | | |
183 // | |no | 189 // | error V no | |
184 // |--kUpToDate<---+ | 190 // kNoUpdate <---------------- [update?] ->---- kUpToDate kUpdated
185 // | success | 191 // ^ | ^
186 // +--kUpdated<-------------------------------------------+ 192 // | yes | |
193 // | diff=false V |
194 // | +-----------> kCanUpdate |
195 // | | | |
196 // | | V no |
197 // | | [differential update?]->----+ |
198 // | | | | |
199 // | | yes | | |
200 // | | error V | |
201 // | +---------<- kDownloadingDiff | |
202 // | | | | |
203 // | | | | |
204 // | | error V | |
205 // | +---------<- kUpdatingDiff ->--------|-----------+ success
206 // | | |
207 // | error V |
208 // +----------------------------------------- kDownloading |
209 // | | |
210 // | error V |
211 // +------------------------------------------ kUpdating ->----+ success
187 // 212 //
188 struct CrxUpdateItem { 213 struct CrxUpdateItem {
189 enum Status { 214 enum Status {
190 kNew, 215 kNew,
191 kChecking, 216 kChecking,
192 kCanUpdate, 217 kCanUpdate,
218 kDownloadingDiff,
193 kDownloading, 219 kDownloading,
220 kUpdatingDiff,
194 kUpdating, 221 kUpdating,
195 kUpdated, 222 kUpdated,
196 kUpToDate, 223 kUpToDate,
197 kNoUpdate, 224 kNoUpdate,
198 kLastStatus 225 kLastStatus
199 }; 226 };
200 227
201 Status status; 228 Status status;
229 std::string id;
230 CrxComponent component;
231
232 base::Time last_check;
233
234 // True if the update response includes an update for this component.
235 bool is_update_available;
cpu_(ooo_6.6-7.5) 2013/06/20 22:30:54 how is different from status = CrxUpdateItem::kCan
Sorin Jianu 2013/06/20 23:51:59 removed.
236
237 // These members are initialized with their corresponding values from the
238 // update server response.
202 GURL crx_url; 239 GURL crx_url;
203 std::string id; 240 GURL diff_crx_url;
204 base::Time last_check; 241 int size;
205 CrxComponent component; 242 int diff_size;
243
244 // The from/to version and fingerprint values.
245 Version previous_version;
206 Version next_version; 246 Version next_version;
247 std::string previous_fp;
248 std::string next_fp;
207 249
208 CrxUpdateItem() : status(kNew) {} 250 // True if the differential update failed for any reason.
251 bool diff_update_failed;
252
253 CrxUpdateItem()
254 : status(kNew),
255 is_update_available(false),
256 size(0),
257 diff_size(0),
258 diff_update_failed(false) {
259 }
209 260
210 // Function object used to find a specific component. 261 // Function object used to find a specific component.
211 class FindById { 262 class FindById {
212 public: 263 public:
213 explicit FindById(const std::string& id) : id_(id) {} 264 explicit FindById(const std::string& id) : id_(id) {}
214 265
215 bool operator() (CrxUpdateItem* item) const { 266 bool operator() (CrxUpdateItem* item) const {
216 return (item->id == id_); 267 return (item->id == id_);
217 } 268 }
218 private: 269 private:
219 const std::string& id_; 270 const std::string& id_;
220 }; 271 };
221 }; 272 };
222 273
274 // Returns true if a differential update is available for the update item.
275 bool IsDiffUpdateAvailable(const CrxUpdateItem* update_item) {
276 return update_item->diff_crx_url.is_valid();
277 }
278
279 // Returns true if a differential update is available, it has not failed yet,
280 // and the configuration allows it.
281 bool CanTryDiffUpdate(const CrxUpdateItem* update_item,
282 const ComponentUpdateService::Configurator& config) {
283 return IsDiffUpdateAvailable(update_item) &&
284 !update_item->diff_update_failed &&
285 config.DeltasEnabled();
286 }
287
223 } // namespace. 288 } // namespace.
224 289
225 typedef ComponentUpdateService::Configurator Config;
226
227 CrxComponent::CrxComponent() 290 CrxComponent::CrxComponent()
228 : installer(NULL), 291 : installer(NULL),
229 source(BANDAID) { 292 source(BANDAID) {
230 } 293 }
231 294
232 CrxComponent::~CrxComponent() { 295 CrxComponent::~CrxComponent() {
233 } 296 }
234 297
235 ////////////////////////////////////////////////////////////////////////////// 298 //////////////////////////////////////////////////////////////////////////////
236 // The one and only implementation of the ComponentUpdateService interface. In 299 // The one and only implementation of the ComponentUpdateService interface. In
237 // charge of running the show. The main method is ProcessPendingItems() which 300 // charge of running the show. The main method is ProcessPendingItems() which
238 // is called periodically to do the upgrades/installs or the update checks. 301 // is called periodically to do the upgrades/installs or the update checks.
239 // An important consideration here is to be as "low impact" as we can to the 302 // An important consideration here is to be as "low impact" as we can to the
240 // rest of the browser, so even if we have many components registered and 303 // rest of the browser, so even if we have many components registered and
241 // eligible for update, we only do one thing at a time with pauses in between 304 // eligible for update, we only do one thing at a time with pauses in between
242 // the tasks. Also when we do network requests there is only one |url_fetcher_| 305 // the tasks. Also when we do network requests there is only one |url_fetcher_|
243 // in flight at at a time. 306 // in flight at a time.
244 // There are no locks in this code, the main structure |work_items_| is mutated 307 // There are no locks in this code, the main structure |work_items_| is mutated
245 // only from the UI thread. The unpack and installation is done in the file 308 // only from the UI thread. The unpack and installation is done in the file
246 // thread and the network requests are done in the IO thread and in the file 309 // thread and the network requests are done in the IO thread and in the file
247 // thread. 310 // thread.
248 class CrxUpdateService : public ComponentUpdateService { 311 class CrxUpdateService : public ComponentUpdateService {
249 public: 312 public:
250 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); 313 explicit CrxUpdateService(ComponentUpdateService::Configurator* config);
251 314
252 virtual ~CrxUpdateService(); 315 virtual ~CrxUpdateService();
253 316
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 struct UpdateContext { 360 struct UpdateContext {
298 base::Time start; 361 base::Time start;
299 UpdateContext() : start(base::Time::Now()) {} 362 UpdateContext() : start(base::Time::Now()) {}
300 }; 363 };
301 364
302 // Context for a crx download url request. See DelegateWithContext above. 365 // Context for a crx download url request. See DelegateWithContext above.
303 struct CRXContext { 366 struct CRXContext {
304 ComponentInstaller* installer; 367 ComponentInstaller* installer;
305 std::vector<uint8> pk_hash; 368 std::vector<uint8> pk_hash;
306 std::string id; 369 std::string id;
370 std::string fingerprint;
307 CRXContext() : installer(NULL) {} 371 CRXContext() : installer(NULL) {}
308 }; 372 };
309 373
310 void OnURLFetchComplete(const net::URLFetcher* source, 374 void OnURLFetchComplete(const net::URLFetcher* source,
311 UpdateContext* context); 375 UpdateContext* context);
312 376
313 void OnURLFetchComplete(const net::URLFetcher* source, 377 void OnURLFetchComplete(const net::URLFetcher* source,
314 CRXContext* context); 378 CRXContext* context);
315 379
316 private: 380 private:
317 // See ManifestParserBridge. 381 // See ManifestParserBridge.
318 void OnParseUpdateManifestSucceeded( 382 void OnParseUpdateManifestSucceeded(
319 const UpdateManifest::Results& results); 383 const UpdateManifest::Results& results);
320 384
321 // See ManifestParserBridge. 385 // See ManifestParserBridge.
322 void OnParseUpdateManifestFailed( 386 void OnParseUpdateManifestFailed(const std::string& error_message);
323 const std::string& error_message);
324 387
325 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query); 388 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query);
326 389
327 void ProcessPendingItems(); 390 void ProcessPendingItems();
328 391
329 void ScheduleNextRun(bool step_delay); 392 void ScheduleNextRun(bool step_delay);
330 393
331 void ParseManifest(const std::string& xml); 394 void ParseManifest(const std::string& xml);
332 395
333 void Install(const CRXContext* context, const base::FilePath& crx_path); 396 void Install(const CRXContext* context, const base::FilePath& crx_path);
334 397
335 void DoneInstalling(const std::string& component_id, 398 void DoneInstalling(const std::string& component_id,
336 ComponentUnpacker::Error error); 399 ComponentUnpacker::Error error,
400 int extended_error);
337 401
338 size_t ChangeItemStatus(CrxUpdateItem::Status from, 402 size_t ChangeItemStatus(CrxUpdateItem::Status from,
339 CrxUpdateItem::Status to); 403 CrxUpdateItem::Status to);
340 404
341 CrxUpdateItem* FindUpdateItemById(const std::string& id); 405 CrxUpdateItem* FindUpdateItemById(const std::string& id);
342 406
343 scoped_ptr<Config> config_; 407 scoped_ptr<ComponentUpdateService::Configurator> config_;
408
409 scoped_ptr<ComponentPatcher> component_patcher_;
344 410
345 scoped_ptr<net::URLFetcher> url_fetcher_; 411 scoped_ptr<net::URLFetcher> url_fetcher_;
346 412
413 // A collection of every work item.
347 typedef std::vector<CrxUpdateItem*> UpdateItems; 414 typedef std::vector<CrxUpdateItem*> UpdateItems;
348 // A collection of every work item.
349 UpdateItems work_items_; 415 UpdateItems work_items_;
350 416
351 // A particular set of items from work_items_, which should be checked ASAP. 417 // A particular set of items from work_items_, which should be checked ASAP.
352 std::set<CrxUpdateItem*> requested_work_items_; 418 std::set<CrxUpdateItem*> requested_work_items_;
353 419
354 base::OneShotTimer<CrxUpdateService> timer_; 420 base::OneShotTimer<CrxUpdateService> timer_;
355 421
356 Version chrome_version_; 422 const Version chrome_version_;
423 const std::string prod_id_;
357 424
358 bool running_; 425 bool running_;
359 426
360 DISALLOW_COPY_AND_ASSIGN(CrxUpdateService); 427 DISALLOW_COPY_AND_ASSIGN(CrxUpdateService);
361 }; 428 };
362 429
363 ////////////////////////////////////////////////////////////////////////////// 430 //////////////////////////////////////////////////////////////////////////////
364 431
365 CrxUpdateService::CrxUpdateService( 432 CrxUpdateService::CrxUpdateService(ComponentUpdateService::Configurator* config)
366 ComponentUpdateService::Configurator* config)
367 : config_(config), 433 : config_(config),
434 component_patcher_(config->CreateComponentPatcher()),
368 chrome_version_(chrome::VersionInfo().Version()), 435 chrome_version_(chrome::VersionInfo().Version()),
436 prod_id_(chrome::OmahaQueryParams::GetProdIdString(
437 chrome::OmahaQueryParams::CHROME)),
369 running_(false) { 438 running_(false) {
370 } 439 }
371 440
372 CrxUpdateService::~CrxUpdateService() { 441 CrxUpdateService::~CrxUpdateService() {
373 // Because we are a singleton, at this point only the UI thread should be 442 // Because we are a singleton, at this point only the UI thread should be
374 // alive, this simplifies the management of the work that could be in 443 // alive, this simplifies the management of the work that could be in
375 // flight in other threads. 444 // flight in other threads.
376 Stop(); 445 Stop();
377 STLDeleteElements(&work_items_); 446 STLDeleteElements(&work_items_);
378 } 447 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 CrxUpdateItem::FindById finder(id); 512 CrxUpdateItem::FindById finder(id);
444 UpdateItems::iterator it = std::find_if(work_items_.begin(), 513 UpdateItems::iterator it = std::find_if(work_items_.begin(),
445 work_items_.end(), 514 work_items_.end(),
446 finder); 515 finder);
447 if (it == work_items_.end()) 516 if (it == work_items_.end())
448 return NULL; 517 return NULL;
449 return (*it); 518 return (*it);
450 } 519 }
451 520
452 // Changes all the components in |work_items_| that have |from| status to 521 // Changes all the components in |work_items_| that have |from| status to
453 // |to| statatus and returns how many have been changed. 522 // |to| status and returns how many have been changed.
454 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from, 523 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from,
455 CrxUpdateItem::Status to) { 524 CrxUpdateItem::Status to) {
456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 525 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
457 size_t count = 0; 526 size_t count = 0;
458 for (UpdateItems::iterator it = work_items_.begin(); 527 for (UpdateItems::iterator it = work_items_.begin();
459 it != work_items_.end(); ++it) { 528 it != work_items_.end(); ++it) {
460 CrxUpdateItem* item = *it; 529 CrxUpdateItem* item = *it;
461 if (item->status != from) 530 if (item->status != from)
462 continue; 531 continue;
463 item->status = to; 532 item->status = to;
(...skipping 20 matching lines...) Expand all
484 CrxUpdateItem* uit; 553 CrxUpdateItem* uit;
485 uit = FindUpdateItemById(id); 554 uit = FindUpdateItemById(id);
486 if (uit) { 555 if (uit) {
487 uit->component = component; 556 uit->component = component;
488 return kReplaced; 557 return kReplaced;
489 } 558 }
490 559
491 uit = new CrxUpdateItem; 560 uit = new CrxUpdateItem;
492 uit->id.swap(id); 561 uit->id.swap(id);
493 uit->component = component; 562 uit->component = component;
563
494 work_items_.push_back(uit); 564 work_items_.push_back(uit);
495 // If this is the first component registered we call Start to 565 // If this is the first component registered we call Start to
496 // schedule the first timer. 566 // schedule the first timer.
497 if (running_ && (work_items_.size() == 1)) 567 if (running_ && (work_items_.size() == 1))
498 Start(); 568 Start();
499 569
500 return kOk; 570 return kOk;
501 } 571 }
502 572
503 // Sets a component to be checked for updates. 573 // Sets a component to be checked for updates.
504 // The componet to add is |crxit| and the |query| string is modified with the 574 // The component to add is |crxit| and the |query| string is modified with the
505 // required omaha compatible query. Returns false when the query strings 575 // required omaha compatible query. Returns false when the query strings
506 // is longer than specified by UrlSizeLimit(). 576 // is longer than specified by UrlSizeLimit().
507 bool CrxUpdateService::AddItemToUpdateCheck(CrxUpdateItem* item, 577 bool CrxUpdateService::AddItemToUpdateCheck(CrxUpdateItem* item,
508 std::string* query) { 578 std::string* query) {
509 if (!AddQueryString(item->id, 579 if (!AddQueryString(item->id,
510 item->component.version.GetString(), 580 item->component.version.GetString(),
581 item->component.fingerprint,
511 config_->UrlSizeLimit(), query)) 582 config_->UrlSizeLimit(), query))
512 return false; 583 return false;
584
513 item->status = CrxUpdateItem::kChecking; 585 item->status = CrxUpdateItem::kChecking;
514 item->last_check = base::Time::Now(); 586 item->last_check = base::Time::Now();
587 item->is_update_available = false;
588 item->previous_version = item->component.version;
589 item->next_version = Version();
590 item->previous_fp = item->component.fingerprint;
591 item->next_fp.clear();
592 item->diff_update_failed = false;
515 return true; 593 return true;
516 } 594 }
517 595
518 // Start the process of checking for an update, for a particular component 596 // Start the process of checking for an update, for a particular component
519 // that was previously registered. 597 // that was previously registered.
520 ComponentUpdateService::Status CrxUpdateService::CheckForUpdateSoon( 598 ComponentUpdateService::Status CrxUpdateService::CheckForUpdateSoon(
521 const CrxComponent& component) { 599 const CrxComponent& component) {
522 if (component.pk_hash.empty() || 600 if (component.pk_hash.empty() ||
523 !component.version.IsValid() || 601 !component.version.IsValid() ||
524 !component.installer) 602 !component.installer)
525 return kError; 603 return kError;
526 604
527 std::string id = 605 std::string id =
528 HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0], 606 HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0],
529 component.pk_hash.size()/2))); 607 component.pk_hash.size()/2)));
530 608
531 CrxUpdateItem* uit; 609 CrxUpdateItem* uit;
532 uit = FindUpdateItemById(id); 610 uit = FindUpdateItemById(id);
533 if (!uit) 611 if (!uit)
534 return kError; 612 return kError;
535 613
536 // Check if the request is too soon. 614 // Check if the request is too soon.
537 base::TimeDelta delta = base::Time::Now() - uit->last_check; 615 base::TimeDelta delta = base::Time::Now() - uit->last_check;
538 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay())) { 616 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay()))
539 return kError; 617 return kError;
540 }
541 618
542 switch (uit->status) { 619 switch (uit->status) {
543 // If the item is already in the process of being updated, there is 620 // If the item is already in the process of being updated, there is
544 // no point in this call, so return kInProgress. 621 // no point in this call, so return kInProgress.
545 case CrxUpdateItem::kChecking: 622 case CrxUpdateItem::kChecking:
546 case CrxUpdateItem::kCanUpdate: 623 case CrxUpdateItem::kCanUpdate:
624 case CrxUpdateItem::kDownloadingDiff:
547 case CrxUpdateItem::kDownloading: 625 case CrxUpdateItem::kDownloading:
626 case CrxUpdateItem::kUpdatingDiff:
548 case CrxUpdateItem::kUpdating: 627 case CrxUpdateItem::kUpdating:
549 return kInProgress; 628 return kInProgress;
550 // Otherwise the item was already checked a while back (or it is new), 629 // Otherwise the item was already checked a while back (or it is new),
551 // set its status to kNew to give it a slightly higher priority. 630 // set its status to kNew to give it a slightly higher priority.
552 case CrxUpdateItem::kNew: 631 case CrxUpdateItem::kNew:
553 case CrxUpdateItem::kUpdated: 632 case CrxUpdateItem::kUpdated:
554 case CrxUpdateItem::kUpToDate: 633 case CrxUpdateItem::kUpToDate:
555 case CrxUpdateItem::kNoUpdate: 634 case CrxUpdateItem::kNoUpdate:
556 uit->status = CrxUpdateItem::kNew; 635 uit->status = CrxUpdateItem::kNew;
557 requested_work_items_.insert(uit); 636 requested_work_items_.insert(uit);
(...skipping 18 matching lines...) Expand all
576 void CrxUpdateService::ProcessPendingItems() { 655 void CrxUpdateService::ProcessPendingItems() {
577 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 656 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
578 // First check for ready upgrades and do one. The first 657 // First check for ready upgrades and do one. The first
579 // step is to fetch the crx package. 658 // step is to fetch the crx package.
580 for (UpdateItems::const_iterator it = work_items_.begin(); 659 for (UpdateItems::const_iterator it = work_items_.begin();
581 it != work_items_.end(); ++it) { 660 it != work_items_.end(); ++it) {
582 CrxUpdateItem* item = *it; 661 CrxUpdateItem* item = *it;
583 if (item->status != CrxUpdateItem::kCanUpdate) 662 if (item->status != CrxUpdateItem::kCanUpdate)
584 continue; 663 continue;
585 // Found component to update, start the process. 664 // Found component to update, start the process.
586 item->status = CrxUpdateItem::kDownloading;
587 CRXContext* context = new CRXContext; 665 CRXContext* context = new CRXContext;
588 context->pk_hash = item->component.pk_hash; 666 context->pk_hash = item->component.pk_hash;
589 context->id = item->id; 667 context->id = item->id;
590 context->installer = item->component.installer; 668 context->installer = item->component.installer;
669 context->fingerprint = item->next_fp;
670 GURL package_url;
671 if (CanTryDiffUpdate(item, *config_)) {
672 package_url = item->diff_crx_url;
673 item->status = CrxUpdateItem::kDownloadingDiff;
674 } else {
675 package_url = item->crx_url;
676 item->status = CrxUpdateItem::kDownloading;
677 }
591 url_fetcher_.reset(net::URLFetcher::Create( 678 url_fetcher_.reset(net::URLFetcher::Create(
592 0, item->crx_url, net::URLFetcher::GET, 679 0, package_url, net::URLFetcher::GET,
593 MakeContextDelegate(this, context))); 680 MakeContextDelegate(this, context)));
594 StartFetch(url_fetcher_.get(), config_->RequestContext(), true); 681 StartFetch(url_fetcher_.get(), config_->RequestContext(), true);
595 return; 682 return;
596 } 683 }
597 684
598 for (size_t ix = 0; ix != arraysize(kManifestSources); ++ix) { 685 for (size_t ix = 0; ix != arraysize(kManifestSources); ++ix) {
599 const CrxComponent::UrlSource manifest_source = kManifestSources[ix]; 686 const CrxComponent::UrlSource manifest_source = kManifestSources[ix];
600 687
601 std::string query; 688 std::string query;
602 // If no pending upgrades, we check if there are new components we have not 689 // If no pending upgrades, we check if there are new components we have not
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 delete context; 780 delete context;
694 } 781 }
695 782
696 // Parsing the manifest is either done right now for tests or in a sandboxed 783 // Parsing the manifest is either done right now for tests or in a sandboxed
697 // process for the production environment. This mitigates the case where an 784 // process for the production environment. This mitigates the case where an
698 // attacker was able to feed us a malicious xml string. 785 // attacker was able to feed us a malicious xml string.
699 void CrxUpdateService::ParseManifest(const std::string& xml) { 786 void CrxUpdateService::ParseManifest(const std::string& xml) {
700 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 787 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
701 if (config_->InProcess()) { 788 if (config_->InProcess()) {
702 UpdateManifest manifest; 789 UpdateManifest manifest;
703 if (!manifest.Parse(xml)) { 790 if (!manifest.Parse(xml))
704 CrxUpdateService::OnParseUpdateManifestFailed(manifest.errors()); 791 CrxUpdateService::OnParseUpdateManifestFailed(manifest.errors());
705 } else { 792 else
706 CrxUpdateService::OnParseUpdateManifestSucceeded(manifest.results()); 793 CrxUpdateService::OnParseUpdateManifestSucceeded(manifest.results());
707 }
708 } else { 794 } else {
709 UtilityProcessHost* host = 795 UtilityProcessHost* host =
710 UtilityProcessHost::Create(new ManifestParserBridge(this), 796 UtilityProcessHost::Create(new ManifestParserBridge(this),
711 base::MessageLoopProxy::current().get()); 797 base::MessageLoopProxy::current().get());
712 host->EnableZygote(); 798 host->EnableZygote();
713 host->Send(new ChromeUtilityMsg_ParseUpdateManifest(xml)); 799 host->Send(new ChromeUtilityMsg_ParseUpdateManifest(xml));
714 } 800 }
715 } 801 }
716 802
717 // A valid Omaha update check has arrived, from only the list of components that 803 // A valid Omaha update check has arrived, from only the list of components that
(...skipping 27 matching lines...) Expand all
745 } 831 }
746 if (!it->browser_min_version.empty()) { 832 if (!it->browser_min_version.empty()) {
747 if (IsVersionNewer(chrome_version_, it->browser_min_version)) { 833 if (IsVersionNewer(chrome_version_, it->browser_min_version)) {
748 // Does not apply for this chrome version. 834 // Does not apply for this chrome version.
749 crx->status = CrxUpdateItem::kNoUpdate; 835 crx->status = CrxUpdateItem::kNoUpdate;
750 continue; 836 continue;
751 } 837 }
752 } 838 }
753 // All test passed. Queue an upgrade for this component and fire the 839 // All test passed. Queue an upgrade for this component and fire the
754 // notifications. 840 // notifications.
841 crx->is_update_available = true;
755 crx->crx_url = it->crx_url; 842 crx->crx_url = it->crx_url;
843 crx->size = it->size;
844 crx->diff_crx_url = it->diff_crx_url;
845 crx->diff_size = it->diff_size;
756 crx->status = CrxUpdateItem::kCanUpdate; 846 crx->status = CrxUpdateItem::kCanUpdate;
757 crx->next_version = Version(it->version); 847 crx->next_version = Version(it->version);
848 crx->next_fp = it->package_fingerprint;
758 ++update_pending; 849 ++update_pending;
759 850
760 content::NotificationService::current()->Notify( 851 content::NotificationService::current()->Notify(
761 chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, 852 chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
762 content::Source<std::string>(&crx->id), 853 content::Source<std::string>(&crx->id),
763 content::NotificationService::NoDetails()); 854 content::NotificationService::NoDetails());
764 } 855 }
765 856
766 // All the components that are not mentioned in the manifest we 857 // All the components that are not mentioned in the manifest we
767 // consider them up to date. 858 // consider them up to date.
(...skipping 14 matching lines...) Expand all
782 } 873 }
783 874
784 // Called when the CRX package has been downloaded to a temporary location. 875 // Called when the CRX package has been downloaded to a temporary location.
785 // Here we fire the notifications and schedule the component-specific installer 876 // Here we fire the notifications and schedule the component-specific installer
786 // to be called in the file thread. 877 // to be called in the file thread.
787 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source, 878 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source,
788 CRXContext* context) { 879 CRXContext* context) {
789 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 880 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
790 int error_code = net::OK; 881 int error_code = net::OK;
791 882
883 CrxUpdateItem* crx = FindUpdateItemById(context->id);
884 DCHECK(crx->status == CrxUpdateItem::kDownloadingDiff ||
885 crx->status == CrxUpdateItem::kDownloading);
886
792 if (source->FileErrorOccurred(&error_code) || !FetchSuccess(*source)) { 887 if (source->FileErrorOccurred(&error_code) || !FetchSuccess(*source)) {
888 if (crx->status == CrxUpdateItem::kDownloadingDiff) {
889 size_t count = ChangeItemStatus(CrxUpdateItem::kDownloadingDiff,
890 CrxUpdateItem::kCanUpdate);
891 DCHECK_EQ(count, 1ul);
892 ScheduleNextRun(true);
893 return;
894 }
793 size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading, 895 size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading,
794 CrxUpdateItem::kNoUpdate); 896 CrxUpdateItem::kNoUpdate);
795 DCHECK_EQ(count, 1ul); 897 DCHECK_EQ(count, 1ul);
796 config_->OnEvent(Configurator::kNetworkError, CrxIdtoUMAId(context->id)); 898 config_->OnEvent(Configurator::kNetworkError, CrxIdtoUMAId(context->id));
797 url_fetcher_.reset(); 899 url_fetcher_.reset();
900
798 ScheduleNextRun(false); 901 ScheduleNextRun(false);
799 } else { 902 } else {
800 base::FilePath temp_crx_path; 903 base::FilePath temp_crx_path;
801 CHECK(source->GetResponseAsFilePath(true, &temp_crx_path)); 904 CHECK(source->GetResponseAsFilePath(true, &temp_crx_path));
802 size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading, 905
803 CrxUpdateItem::kUpdating); 906 size_t count = 0;
907 if (crx->status == CrxUpdateItem::kDownloadingDiff) {
908 count = ChangeItemStatus(CrxUpdateItem::kDownloadingDiff,
909 CrxUpdateItem::kUpdatingDiff);
910 } else {
911 count = ChangeItemStatus(CrxUpdateItem::kDownloading,
912 CrxUpdateItem::kUpdating);
913 }
804 DCHECK_EQ(count, 1ul); 914 DCHECK_EQ(count, 1ul);
915
805 url_fetcher_.reset(); 916 url_fetcher_.reset();
806 917
807 content::NotificationService::current()->Notify( 918 content::NotificationService::current()->Notify(
808 chrome::NOTIFICATION_COMPONENT_UPDATE_READY, 919 chrome::NOTIFICATION_COMPONENT_UPDATE_READY,
809 content::Source<std::string>(&context->id), 920 content::Source<std::string>(&context->id),
810 content::NotificationService::NoDetails()); 921 content::NotificationService::NoDetails());
811 922
812 // Why unretained? See comment at top of file. 923 // Why unretained? See comment at top of file.
813 BrowserThread::PostDelayedTask( 924 BrowserThread::PostDelayedTask(
814 BrowserThread::FILE, 925 BrowserThread::FILE,
815 FROM_HERE, 926 FROM_HERE,
816 base::Bind(&CrxUpdateService::Install, 927 base::Bind(&CrxUpdateService::Install,
817 base::Unretained(this), 928 base::Unretained(this),
818 context, 929 context,
819 temp_crx_path), 930 temp_crx_path),
820 base::TimeDelta::FromMilliseconds(config_->StepDelay())); 931 base::TimeDelta::FromMilliseconds(config_->StepDelay()));
821 } 932 }
822 } 933 }
823 934
824 // Install consists of digital signature verification, unpacking and then 935 // Install consists of digital signature verification, unpacking and then
825 // calling the component specific installer. All that is handled by the 936 // calling the component specific installer. All that is handled by the
826 // |unpacker|. If there is an error this function is in charge of deleting 937 // |unpacker|. If there is an error this function is in charge of deleting
827 // the files created. 938 // the files created.
828 void CrxUpdateService::Install(const CRXContext* context, 939 void CrxUpdateService::Install(const CRXContext* context,
829 const base::FilePath& crx_path) { 940 const base::FilePath& crx_path) {
830 // This function owns the |crx_path| and the |context| object. 941 // This function owns the |crx_path| and the |context| object.
831 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 942 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
832 ComponentUnpacker 943 ComponentUnpacker unpacker(context->pk_hash,
833 unpacker(context->pk_hash, crx_path, context->installer); 944 crx_path,
834 if (!file_util::Delete(crx_path, false)) { 945 context->fingerprint,
946 component_patcher_.get(),
947 context->installer);
948 if (!file_util::Delete(crx_path, false))
835 NOTREACHED() << crx_path.value(); 949 NOTREACHED() << crx_path.value();
836 }
837 // Why unretained? See comment at top of file. 950 // Why unretained? See comment at top of file.
838 BrowserThread::PostDelayedTask( 951 BrowserThread::PostDelayedTask(
839 BrowserThread::UI, 952 BrowserThread::UI,
840 FROM_HERE, 953 FROM_HERE,
841 base::Bind(&CrxUpdateService::DoneInstalling, base::Unretained(this), 954 base::Bind(&CrxUpdateService::DoneInstalling, base::Unretained(this),
842 context->id, unpacker.error()), 955 context->id, unpacker.error(), unpacker.extended_error()),
843 base::TimeDelta::FromMilliseconds(config_->StepDelay())); 956 base::TimeDelta::FromMilliseconds(config_->StepDelay()));
844 delete context; 957 delete context;
845 } 958 }
846 959
847 // Installation has been completed. Adjust the component status and 960 // Installation has been completed. Adjust the component status and
848 // schedule the next check. 961 // schedule the next check.
849 void CrxUpdateService::DoneInstalling(const std::string& component_id, 962 void CrxUpdateService::DoneInstalling(const std::string& component_id,
850 ComponentUnpacker::Error error) { 963 ComponentUnpacker::Error error,
964 int extra_code) {
851 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 965 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
852 966
853 CrxUpdateItem* item = FindUpdateItemById(component_id); 967 CrxUpdateItem* item = FindUpdateItemById(component_id);
968 if (item->status == CrxUpdateItem::kUpdatingDiff) {
969 if (error != ComponentUnpacker::kNone) {
970 item->diff_update_failed = true;
971 size_t count = ChangeItemStatus(CrxUpdateItem::kUpdatingDiff,
972 CrxUpdateItem::kCanUpdate);
973 DCHECK_EQ(count, 1ul);
974 ScheduleNextRun(true);
975 return;
976 }
977 }
978
854 item->status = (error == ComponentUnpacker::kNone) ? CrxUpdateItem::kUpdated : 979 item->status = (error == ComponentUnpacker::kNone) ? CrxUpdateItem::kUpdated :
855 CrxUpdateItem::kNoUpdate; 980 CrxUpdateItem::kNoUpdate;
856 if (item->status == CrxUpdateItem::kUpdated) 981 if (item->status == CrxUpdateItem::kUpdated) {
857 item->component.version = item->next_version; 982 item->component.version = item->next_version;
983 item->component.fingerprint = item->next_fp;
984 }
858 985
859 Configurator::Events event; 986 Configurator::Events event;
860 switch (error) { 987 switch (error) {
861 case ComponentUnpacker::kNone: 988 case ComponentUnpacker::kNone:
862 event = Configurator::kComponentUpdated; 989 event = Configurator::kComponentUpdated;
863 break; 990 break;
864 case ComponentUnpacker::kInstallerError: 991 case ComponentUnpacker::kInstallerError:
865 event = Configurator::kInstallerError; 992 event = Configurator::kInstallerError;
866 break; 993 break;
867 default: 994 default:
868 event = Configurator::kUnpackError; 995 event = Configurator::kUnpackError;
869 break; 996 break;
870 } 997 }
871 998
872 config_->OnEvent(event, CrxIdtoUMAId(component_id)); 999 config_->OnEvent(event, CrxIdtoUMAId(component_id));
873 ScheduleNextRun(false); 1000 ScheduleNextRun(false);
874 } 1001 }
875 1002
876 // The component update factory. Using the component updater as a singleton 1003 // The component update factory. Using the component updater as a singleton
877 // is the job of the browser process. 1004 // is the job of the browser process.
878 ComponentUpdateService* ComponentUpdateServiceFactory( 1005 ComponentUpdateService* ComponentUpdateServiceFactory(
879 ComponentUpdateService::Configurator* config) { 1006 ComponentUpdateService::Configurator* config) {
880 DCHECK(config); 1007 DCHECK(config);
881 return new CrxUpdateService(config); 1008 return new CrxUpdateService(config);
882 } 1009 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698