| OLD | NEW |
| 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 <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/at_exit.h" | 10 #include "base/at_exit.h" |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 class CrxUpdateService : public ComponentUpdateService { | 246 class CrxUpdateService : public ComponentUpdateService { |
| 247 public: | 247 public: |
| 248 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); | 248 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); |
| 249 | 249 |
| 250 virtual ~CrxUpdateService(); | 250 virtual ~CrxUpdateService(); |
| 251 | 251 |
| 252 // Overrides for ComponentUpdateService. | 252 // Overrides for ComponentUpdateService. |
| 253 virtual Status Start() OVERRIDE; | 253 virtual Status Start() OVERRIDE; |
| 254 virtual Status Stop() OVERRIDE; | 254 virtual Status Stop() OVERRIDE; |
| 255 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE; | 255 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE; |
| 256 virtual Status PingUpdateCheck(const CrxComponent& component) OVERRIDE; |
| 256 | 257 |
| 257 // The only purpose of this class is to forward the | 258 // The only purpose of this class is to forward the |
| 258 // UtilityProcessHostClient callbacks so CrxUpdateService does | 259 // UtilityProcessHostClient callbacks so CrxUpdateService does |
| 259 // not have to derive from it because that is refcounted. | 260 // not have to derive from it because that is refcounted. |
| 260 class ManifestParserBridge : public UtilityProcessHostClient { | 261 class ManifestParserBridge : public UtilityProcessHostClient { |
| 261 public: | 262 public: |
| 262 explicit ManifestParserBridge(CrxUpdateService* service) | 263 explicit ManifestParserBridge(CrxUpdateService* service) |
| 263 : service_(service) {} | 264 : service_(service) {} |
| 264 | 265 |
| 265 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { | 266 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 const UpdateManifest::Results& results); | 317 const UpdateManifest::Results& results); |
| 317 | 318 |
| 318 // See ManifestParserBridge. | 319 // See ManifestParserBridge. |
| 319 void OnParseUpdateManifestFailed( | 320 void OnParseUpdateManifestFailed( |
| 320 const std::string& error_message); | 321 const std::string& error_message); |
| 321 | 322 |
| 322 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query); | 323 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query); |
| 323 | 324 |
| 324 void ProcessPendingItems(); | 325 void ProcessPendingItems(); |
| 325 | 326 |
| 327 typedef std::vector<CrxUpdateItem*> UpdateItems; |
| 328 void ProcessWorkItems(const UpdateItems& work_items); |
| 329 |
| 326 void ScheduleNextRun(bool step_delay); | 330 void ScheduleNextRun(bool step_delay); |
| 327 | 331 |
| 328 void ParseManifest(const std::string& xml); | 332 void ParseManifest(const std::string& xml); |
| 329 | 333 |
| 330 void Install(const CRXContext* context, const FilePath& crx_path); | 334 void Install(const CRXContext* context, const FilePath& crx_path); |
| 331 | 335 |
| 332 void DoneInstalling(const std::string& component_id, | 336 void DoneInstalling(const std::string& component_id, |
| 333 ComponentUnpacker::Error error); | 337 ComponentUnpacker::Error error); |
| 334 | 338 |
| 335 size_t ChangeItemStatus(CrxUpdateItem::Status from, | 339 size_t ChangeItemStatus(CrxUpdateItem::Status from, |
| 336 CrxUpdateItem::Status to); | 340 CrxUpdateItem::Status to); |
| 337 | 341 |
| 338 CrxUpdateItem* FindUpdateItemById(const std::string& id); | 342 CrxUpdateItem* FindUpdateItemById(const std::string& id); |
| 339 | 343 |
| 340 scoped_ptr<Config> config_; | 344 scoped_ptr<Config> config_; |
| 341 | 345 |
| 342 scoped_ptr<net::URLFetcher> url_fetcher_; | 346 scoped_ptr<net::URLFetcher> url_fetcher_; |
| 343 | 347 |
| 344 typedef std::vector<CrxUpdateItem*> UpdateItems; | |
| 345 UpdateItems work_items_; | 348 UpdateItems work_items_; |
| 346 | 349 |
| 347 base::OneShotTimer<CrxUpdateService> timer_; | 350 base::OneShotTimer<CrxUpdateService> timer_; |
| 348 | 351 |
| 349 Version chrome_version_; | 352 Version chrome_version_; |
| 350 | 353 |
| 351 bool running_; | 354 bool running_; |
| 352 | 355 |
| 353 DISALLOW_COPY_AND_ASSIGN(CrxUpdateService); | 356 DISALLOW_COPY_AND_ASSIGN(CrxUpdateService); |
| 354 }; | 357 }; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 uit->component = component; | 484 uit->component = component; |
| 482 work_items_.push_back(uit); | 485 work_items_.push_back(uit); |
| 483 // If this is the first component registered we call Start to | 486 // If this is the first component registered we call Start to |
| 484 // schedule the first timer. | 487 // schedule the first timer. |
| 485 if (running_ && (work_items_.size() == 1)) | 488 if (running_ && (work_items_.size() == 1)) |
| 486 Start(); | 489 Start(); |
| 487 | 490 |
| 488 return kOk; | 491 return kOk; |
| 489 } | 492 } |
| 490 | 493 |
| 494 // Start the process of checking for an update, for a particular component |
| 495 // that was previously registered. If the component does not exist return |
| 496 // kError, otherwise kOk. |
| 497 ComponentUpdateService::Status CrxUpdateService::PingUpdateCheck( |
| 498 const CrxComponent& component) { |
| 499 if (component.pk_hash.empty() || |
| 500 !component.version.IsValid() || |
| 501 !component.installer) |
| 502 return kError; |
| 503 |
| 504 std::string id = |
| 505 HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0], |
| 506 component.pk_hash.size()/2))); |
| 507 CrxUpdateItem* uit; |
| 508 uit = FindUpdateItemById(id); |
| 509 if (!uit) |
| 510 return kError; |
| 511 |
| 512 UpdateItems one_item; |
| 513 one_item.push_back(uit); |
| 514 |
| 515 ProcessWorkItems(one_item); |
| 516 return kOk; |
| 517 } |
| 518 |
| 491 // Sets a component to be checked for updates. | 519 // Sets a component to be checked for updates. |
| 492 // The componet to add is |crxit| and the |query| string is modified with the | 520 // The componet to add is |crxit| and the |query| string is modified with the |
| 493 // required omaha compatible query. Returns false when the query strings | 521 // required omaha compatible query. Returns false when the query strings |
| 494 // is longer than specified by UrlSizeLimit(). | 522 // is longer than specified by UrlSizeLimit(). |
| 495 bool CrxUpdateService::AddItemToUpdateCheck(CrxUpdateItem* item, | 523 bool CrxUpdateService::AddItemToUpdateCheck(CrxUpdateItem* item, |
| 496 std::string* query) { | 524 std::string* query) { |
| 497 if (!AddQueryString(item->id, | 525 if (!AddQueryString(item->id, |
| 498 item->component.version.GetString(), | 526 item->component.version.GetString(), |
| 499 config_->UrlSizeLimit(), query)) | 527 config_->UrlSizeLimit(), query)) |
| 500 return false; | 528 return false; |
| 501 item->status = CrxUpdateItem::kChecking; | 529 item->status = CrxUpdateItem::kChecking; |
| 502 item->last_check = base::Time::Now(); | 530 item->last_check = base::Time::Now(); |
| 503 return true; | 531 return true; |
| 504 } | 532 } |
| 505 | 533 |
| 506 // Here is where the work gets scheduled. Given that our |work_items_| list | 534 // Here is where the work gets scheduled. |
| 535 void CrxUpdateService::ProcessPendingItems() { |
| 536 ProcessWorkItems(work_items_); |
| 537 } |
| 538 |
| 539 // Here is where the work gets scheduled. Given that our |work_items| list |
| 507 // is expected to be ten or less items, we simply loop several times. | 540 // is expected to be ten or less items, we simply loop several times. |
| 508 void CrxUpdateService::ProcessPendingItems() { | 541 void CrxUpdateService::ProcessWorkItems(const UpdateItems& work_items) { |
| 509 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 542 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 510 // First check for ready upgrades and do one. The first | 543 // First check for ready upgrades and do one. The first |
| 511 // step is to fetch the crx package. | 544 // step is to fetch the crx package. |
| 512 for (UpdateItems::const_iterator it = work_items_.begin(); | 545 for (UpdateItems::const_iterator it = work_items.begin(); |
| 513 it != work_items_.end(); ++it) { | 546 it != work_items.end(); ++it) { |
| 514 CrxUpdateItem* item = *it; | 547 CrxUpdateItem* item = *it; |
| 515 if (item->status != CrxUpdateItem::kCanUpdate) | 548 if (item->status != CrxUpdateItem::kCanUpdate) |
| 516 continue; | 549 continue; |
| 517 // Found component to update, start the process. | 550 // Found component to update, start the process. |
| 518 item->status = CrxUpdateItem::kDownloading; | 551 item->status = CrxUpdateItem::kDownloading; |
| 519 CRXContext* context = new CRXContext; | 552 CRXContext* context = new CRXContext; |
| 520 context->pk_hash = item->component.pk_hash; | 553 context->pk_hash = item->component.pk_hash; |
| 521 context->id = item->id; | 554 context->id = item->id; |
| 522 context->installer = item->component.installer; | 555 context->installer = item->component.installer; |
| 523 url_fetcher_.reset(net::URLFetcher::Create( | 556 url_fetcher_.reset(net::URLFetcher::Create( |
| 524 0, item->crx_url, net::URLFetcher::GET, | 557 0, item->crx_url, net::URLFetcher::GET, |
| 525 MakeContextDelegate(this, context))); | 558 MakeContextDelegate(this, context))); |
| 526 StartFetch(url_fetcher_.get(), config_->RequestContext(), true); | 559 StartFetch(url_fetcher_.get(), config_->RequestContext(), true); |
| 527 return; | 560 return; |
| 528 } | 561 } |
| 529 | 562 |
| 530 for (size_t ix = 0; ix != arraysize(kManifestSources); ++ix) { | 563 for (size_t ix = 0; ix != arraysize(kManifestSources); ++ix) { |
| 531 const CrxComponent::UrlSource manifest_source = kManifestSources[ix]; | 564 const CrxComponent::UrlSource manifest_source = kManifestSources[ix]; |
| 532 | 565 |
| 533 std::string query; | 566 std::string query; |
| 534 // If no pending upgrades, we check if there are new components we have not | 567 // If no pending upgrades, we check if there are new components we have not |
| 535 // checked against the server. We can batch some in a single url request. | 568 // checked against the server. We can batch some in a single url request. |
| 536 for (UpdateItems::const_iterator it = work_items_.begin(); | 569 for (UpdateItems::const_iterator it = work_items.begin(); |
| 537 it != work_items_.end(); ++it) { | 570 it != work_items.end(); ++it) { |
| 538 CrxUpdateItem* item = *it; | 571 CrxUpdateItem* item = *it; |
| 539 if (item->status != CrxUpdateItem::kNew) | 572 if (item->status != CrxUpdateItem::kNew) |
| 540 continue; | 573 continue; |
| 541 if (item->component.source != manifest_source) | 574 if (item->component.source != manifest_source) |
| 542 continue; | 575 continue; |
| 543 if (!AddItemToUpdateCheck(item, &query)) | 576 if (!AddItemToUpdateCheck(item, &query)) |
| 544 break; | 577 break; |
| 545 } | 578 } |
| 546 | 579 |
| 547 // Next we can go back to components we already checked, here | 580 // Next we can go back to components we already checked, here |
| 548 // we can also batch them in a single url request, as long as | 581 // we can also batch them in a single url request, as long as |
| 549 // we have not checked them recently. | 582 // we have not checked them recently. |
| 550 const base::TimeDelta min_delta_time = | 583 const base::TimeDelta min_delta_time = |
| 551 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); | 584 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); |
| 552 | 585 |
| 553 for (UpdateItems::const_iterator it = work_items_.begin(); | 586 for (UpdateItems::const_iterator it = work_items.begin(); |
| 554 it != work_items_.end(); ++it) { | 587 it != work_items.end(); ++it) { |
| 555 CrxUpdateItem* item = *it; | 588 CrxUpdateItem* item = *it; |
| 556 if ((item->status != CrxUpdateItem::kNoUpdate) && | 589 if ((item->status != CrxUpdateItem::kNoUpdate) && |
| 557 (item->status != CrxUpdateItem::kUpToDate)) | 590 (item->status != CrxUpdateItem::kUpToDate)) |
| 558 continue; | 591 continue; |
| 559 if (item->component.source != manifest_source) | 592 if (item->component.source != manifest_source) |
| 560 continue; | 593 continue; |
| 561 base::TimeDelta delta = base::Time::Now() - item->last_check; | 594 base::TimeDelta delta = base::Time::Now() - item->last_check; |
| 562 if (delta < min_delta_time) | 595 if (delta < min_delta_time) |
| 563 continue; | 596 continue; |
| 564 if (!AddItemToUpdateCheck(item, &query)) | 597 if (!AddItemToUpdateCheck(item, &query)) |
| 565 break; | 598 break; |
| 566 } | 599 } |
| 567 | 600 |
| 568 // Finally, we check components that we already updated as long as | 601 // Finally, we check components that we already updated as long as |
| 569 // we have not checked them recently. | 602 // we have not checked them recently. |
| 570 for (UpdateItems::const_iterator it = work_items_.begin(); | 603 for (UpdateItems::const_iterator it = work_items.begin(); |
| 571 it != work_items_.end(); ++it) { | 604 it != work_items.end(); ++it) { |
| 572 CrxUpdateItem* item = *it; | 605 CrxUpdateItem* item = *it; |
| 573 if (item->status != CrxUpdateItem::kUpdated) | 606 if (item->status != CrxUpdateItem::kUpdated) |
| 574 continue; | 607 continue; |
| 575 if (item->component.source != manifest_source) | 608 if (item->component.source != manifest_source) |
| 576 continue; | 609 continue; |
| 577 base::TimeDelta delta = base::Time::Now() - item->last_check; | 610 base::TimeDelta delta = base::Time::Now() - item->last_check; |
| 578 if (delta < min_delta_time) | 611 if (delta < min_delta_time) |
| 579 continue; | 612 continue; |
| 580 if (!AddItemToUpdateCheck(item, &query)) | 613 if (!AddItemToUpdateCheck(item, &query)) |
| 581 break; | 614 break; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 595 0, GURL(full_query), net::URLFetcher::GET, | 628 0, GURL(full_query), net::URLFetcher::GET, |
| 596 MakeContextDelegate(this, new UpdateContext()))); | 629 MakeContextDelegate(this, new UpdateContext()))); |
| 597 StartFetch(url_fetcher_.get(), config_->RequestContext(), false); | 630 StartFetch(url_fetcher_.get(), config_->RequestContext(), false); |
| 598 return; | 631 return; |
| 599 } | 632 } |
| 600 | 633 |
| 601 // No components to update. Next check after the long sleep. | 634 // No components to update. Next check after the long sleep. |
| 602 ScheduleNextRun(false); | 635 ScheduleNextRun(false); |
| 603 } | 636 } |
| 604 | 637 |
| 605 // Caled when we got a response from the update server. It consists of an xml | 638 // Called when we got a response from the update server. It consists of an xml |
| 606 // document following the omaha update scheme. | 639 // document following the omaha update scheme. |
| 607 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source, | 640 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source, |
| 608 UpdateContext* context) { | 641 UpdateContext* context) { |
| 609 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 642 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 610 if (FetchSuccess(*source)) { | 643 if (FetchSuccess(*source)) { |
| 611 std::string xml; | 644 std::string xml; |
| 612 source->GetResponseAsString(&xml); | 645 source->GetResponseAsString(&xml); |
| 613 url_fetcher_.reset(); | 646 url_fetcher_.reset(); |
| 614 ParseManifest(xml); | 647 ParseManifest(xml); |
| 615 } else { | 648 } else { |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 ScheduleNextRun(false); | 832 ScheduleNextRun(false); |
| 800 } | 833 } |
| 801 | 834 |
| 802 // The component update factory. Using the component updater as a singleton | 835 // The component update factory. Using the component updater as a singleton |
| 803 // is the job of the browser process. | 836 // is the job of the browser process. |
| 804 ComponentUpdateService* ComponentUpdateServiceFactory( | 837 ComponentUpdateService* ComponentUpdateServiceFactory( |
| 805 ComponentUpdateService::Configurator* config) { | 838 ComponentUpdateService::Configurator* config) { |
| 806 DCHECK(config); | 839 DCHECK(config); |
| 807 return new CrxUpdateService(config); | 840 return new CrxUpdateService(config); |
| 808 } | 841 } |
| OLD | NEW |