Chromium Code Reviews| 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 <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/compiler_specific.h" |
| 14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
| 15 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/memory/scoped_ptr.h" | 17 #include "base/memory/scoped_ptr.h" |
| 18 #include "base/memory/weak_ptr.h" | 18 #include "base/memory/weak_ptr.h" |
| 19 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
| 20 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
| 21 #include "base/strings/string_piece.h" | 21 #include "base/strings/string_piece.h" |
| 22 #include "base/strings/string_util.h" | 22 #include "base/strings/string_util.h" |
| 23 #include "base/strings/stringprintf.h" | 23 #include "base/strings/stringprintf.h" |
| 24 #include "base/threading/sequenced_worker_pool.h" | 24 #include "base/threading/sequenced_worker_pool.h" |
| 25 #include "base/timer/timer.h" | 25 #include "base/timer/timer.h" |
| 26 #include "chrome/browser/browser_process.h" | 26 #include "chrome/browser/browser_process.h" |
| 27 #include "chrome/browser/component_updater/component_patcher.h" | 27 #include "chrome/browser/component_updater/component_patcher.h" |
| 28 #include "chrome/browser/component_updater/component_unpacker.h" | 28 #include "chrome/browser/component_updater/component_unpacker.h" |
| 29 #include "chrome/browser/component_updater/component_updater_ping_manager.h" | 29 #include "chrome/browser/component_updater/component_updater_ping_manager.h" |
| 30 #include "chrome/browser/component_updater/component_updater_utils.h" | |
| 30 #include "chrome/browser/component_updater/crx_update_item.h" | 31 #include "chrome/browser/component_updater/crx_update_item.h" |
| 32 #include "chrome/browser/component_updater/update_manifest.h" | |
| 31 #include "chrome/common/chrome_version_info.h" | 33 #include "chrome/common/chrome_version_info.h" |
| 32 #include "chrome/common/extensions/update_manifest.h" | |
| 33 #include "content/public/browser/browser_thread.h" | 34 #include "content/public/browser/browser_thread.h" |
| 34 #include "content/public/browser/resource_controller.h" | 35 #include "content/public/browser/resource_controller.h" |
| 35 #include "content/public/browser/resource_throttle.h" | 36 #include "content/public/browser/resource_throttle.h" |
| 36 #include "extensions/common/extension.h" | 37 #include "extensions/common/extension.h" |
| 37 #include "net/base/escape.h" | 38 #include "net/base/escape.h" |
| 38 #include "net/base/load_flags.h" | 39 #include "net/base/load_flags.h" |
| 39 #include "net/base/net_errors.h" | 40 #include "net/base/net_errors.h" |
| 40 #include "net/url_request/url_fetcher.h" | 41 #include "net/url_request/url_fetcher.h" |
| 41 #include "net/url_request/url_fetcher_delegate.h" | 42 #include "net/url_request/url_fetcher_delegate.h" |
| 42 #include "net/url_request/url_request.h" | 43 #include "net/url_request/url_request.h" |
| 43 #include "net/url_request/url_request_status.h" | 44 #include "net/url_request/url_request_status.h" |
| 44 #include "url/gurl.h" | 45 #include "url/gurl.h" |
| 45 | 46 |
| 46 using content::BrowserThread; | 47 using content::BrowserThread; |
| 47 using extensions::Extension; | |
| 48 | 48 |
| 49 // The component updater is designed to live until process shutdown, so | 49 // The component updater is designed to live until process shutdown, so |
| 50 // base::Bind() calls are not refcounted. | 50 // base::Bind() calls are not refcounted. |
| 51 | 51 |
| 52 namespace { | 52 namespace { |
| 53 | 53 |
| 54 // Extends an omaha compatible update check url |query| string. Does | |
| 55 // not mutate the string if it would be longer than |limit| chars. | |
| 56 bool AddQueryString(const std::string& id, | |
| 57 const std::string& version, | |
| 58 const std::string& fingerprint, | |
| 59 bool ondemand, | |
| 60 size_t limit, | |
| 61 std::string* query) { | |
| 62 std::string additional = | |
| 63 base::StringPrintf("id=%s&v=%s&fp=%s&uc%s", | |
| 64 id.c_str(), | |
| 65 version.c_str(), | |
| 66 fingerprint.c_str(), | |
| 67 ondemand ? "&installsource=ondemand" : ""); | |
| 68 additional = "x=" + net::EscapeQueryParamValue(additional, true); | |
| 69 if ((additional.size() + query->size() + 1) > limit) | |
| 70 return false; | |
| 71 if (!query->empty()) | |
| 72 query->append(1, '&'); | |
| 73 query->append(additional); | |
| 74 return true; | |
| 75 } | |
| 76 | |
| 77 // Create the final omaha compatible query. The |extra| is optional and can | |
| 78 // be null. It should contain top level (non-escaped) parameters. | |
| 79 std::string MakeFinalQuery(const std::string& host, | |
| 80 const std::string& query, | |
| 81 const char* extra) { | |
| 82 std::string request(host); | |
| 83 request.append(1, '?'); | |
| 84 if (extra) { | |
| 85 request.append(extra); | |
| 86 request.append(1, '&'); | |
| 87 } | |
| 88 request.append(query); | |
| 89 return request; | |
| 90 } | |
| 91 | |
| 92 // Produces an extension-like friendly |id|. This might be removed in the | 54 // Produces an extension-like friendly |id|. This might be removed in the |
| 93 // future if we roll our on packing tools. | 55 // future if we roll our on packing tools. |
| 94 static std::string HexStringToID(const std::string& hexstr) { | 56 static std::string HexStringToID(const std::string& hexstr) { |
| 95 std::string id; | 57 std::string id; |
| 96 for (size_t i = 0; i < hexstr.size(); ++i) { | 58 for (size_t i = 0; i < hexstr.size(); ++i) { |
| 97 int val; | 59 int val(0); |
| 98 if (base::HexStringToInt(base::StringPiece(hexstr.begin() + i, | 60 if (base::HexStringToInt(base::StringPiece(hexstr.begin() + i, |
| 99 hexstr.begin() + i + 1), | 61 hexstr.begin() + i + 1), |
| 100 &val)) { | 62 &val)) { |
| 101 id.append(1, val + 'a'); | 63 id.append(1, val + 'a'); |
| 102 } else { | 64 } else { |
| 103 id.append(1, 'a'); | 65 id.append(1, 'a'); |
| 104 } | 66 } |
| 105 } | 67 } |
| 106 DCHECK(Extension::IdIsValid(id)); | 68 DCHECK(extensions::Extension::IdIsValid(id)); |
| 107 return id; | 69 return id; |
| 108 } | 70 } |
| 109 | 71 |
| 110 // Helper to do version check for components. | 72 // Returns true if the |proposed| version is newer than |current| version. |
| 111 bool IsVersionNewer(const Version& current, const std::string& proposed) { | 73 bool IsVersionNewer(const Version& current, const std::string& proposed) { |
| 112 Version proposed_ver(proposed); | 74 Version proposed_ver(proposed); |
| 113 if (!proposed_ver.IsValid()) | 75 return proposed_ver.IsValid() && current.CompareTo(proposed_ver) < 0; |
| 114 return false; | |
| 115 return (current.CompareTo(proposed_ver) < 0); | |
| 116 } | 76 } |
| 117 | 77 |
| 118 // Helper template class that allows our main class to have separate | 78 // Helper template class that allows our main class to have separate |
| 119 // OnURLFetchComplete() callbacks for different types of url requests | 79 // OnURLFetchComplete() callbacks for different types of url requests |
| 120 // they are differentiated by the |Ctx| type. | 80 // they are differentiated by the |Ctx| type. |
| 121 template <typename Del, typename Ctx> | 81 template <typename Del, typename Ctx> |
| 122 class DelegateWithContext : public net::URLFetcherDelegate { | 82 class DelegateWithContext : public net::URLFetcherDelegate { |
| 123 public: | 83 public: |
| 124 DelegateWithContext(Del* delegate, Ctx* context) | 84 DelegateWithContext(Del* delegate, Ctx* context) |
| 125 : delegate_(delegate), context_(context) {} | 85 : delegate_(delegate), context_(context) {} |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 // can post tasks to it via weak pointers. By default the request is blocked | 203 // can post tasks to it via weak pointers. By default the request is blocked |
| 244 // unless the CrxUpdateService calls Unblock(). | 204 // unless the CrxUpdateService calls Unblock(). |
| 245 // The lifetime is controlled by Chrome's resource loader so the component | 205 // The lifetime is controlled by Chrome's resource loader so the component |
| 246 // updater cannot touch objects from this class except via weak pointers. | 206 // updater cannot touch objects from this class except via weak pointers. |
| 247 class CUResourceThrottle | 207 class CUResourceThrottle |
| 248 : public content::ResourceThrottle, | 208 : public content::ResourceThrottle, |
| 249 public base::SupportsWeakPtr<CUResourceThrottle> { | 209 public base::SupportsWeakPtr<CUResourceThrottle> { |
| 250 public: | 210 public: |
| 251 explicit CUResourceThrottle(const net::URLRequest* request); | 211 explicit CUResourceThrottle(const net::URLRequest* request); |
| 252 virtual ~CUResourceThrottle(); | 212 virtual ~CUResourceThrottle(); |
| 213 | |
| 253 // Overriden from ResourceThrottle. | 214 // Overriden from ResourceThrottle. |
| 254 virtual void WillStartRequest(bool* defer) OVERRIDE; | 215 virtual void WillStartRequest(bool* defer) OVERRIDE; |
| 255 virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; | 216 virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; |
| 256 | 217 |
| 257 // Component updater calls this function via PostTask to unblock the request. | 218 // Component updater calls this function via PostTask to unblock the request. |
| 258 void Unblock(); | 219 void Unblock(); |
| 259 | 220 |
| 260 typedef std::vector<base::WeakPtr<CUResourceThrottle> > WeakPtrVector; | 221 typedef std::vector<base::WeakPtr<CUResourceThrottle> > WeakPtrVector; |
| 261 | 222 |
| 262 private: | 223 private: |
| 263 enum State { | 224 enum State { |
| 264 NEW, | 225 NEW, |
| 265 BLOCKED, | 226 BLOCKED, |
| 266 UNBLOCKED | 227 UNBLOCKED |
| 267 }; | 228 }; |
| 268 | 229 |
| 269 State state_; | 230 State state_; |
| 270 }; | 231 }; |
| 271 | 232 |
| 272 void UnblockResourceThrottle(base::WeakPtr<CUResourceThrottle> rt) { | 233 void UnblockResourceThrottle(base::WeakPtr<CUResourceThrottle> rt) { |
| 273 BrowserThread::PostTask( | 234 BrowserThread::PostTask( |
| 274 BrowserThread::IO, | 235 BrowserThread::IO, |
| 275 FROM_HERE, | 236 FROM_HERE, |
| 276 base::Bind(&CUResourceThrottle::Unblock, rt)); | 237 base::Bind(&CUResourceThrottle::Unblock, rt)); |
| 277 } | 238 } |
| 278 | 239 |
| 279 void UnblockandReapAllThrottles(CUResourceThrottle::WeakPtrVector* throttles) { | 240 void UnblockandReapAllThrottles(CUResourceThrottle::WeakPtrVector* throttles) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 292 // eligible for update, we only do one thing at a time with pauses in between | 253 // eligible for update, we only do one thing at a time with pauses in between |
| 293 // the tasks. Also when we do network requests there is only one |url_fetcher_| | 254 // the tasks. Also when we do network requests there is only one |url_fetcher_| |
| 294 // in flight at a time. | 255 // in flight at a time. |
| 295 // There are no locks in this code, the main structure |work_items_| is mutated | 256 // There are no locks in this code, the main structure |work_items_| is mutated |
| 296 // only from the UI thread. The unpack and installation is done in the file | 257 // only from the UI thread. The unpack and installation is done in the file |
| 297 // thread and the network requests are done in the IO thread and in the file | 258 // thread and the network requests are done in the IO thread and in the file |
| 298 // thread. | 259 // thread. |
| 299 class CrxUpdateService : public ComponentUpdateService { | 260 class CrxUpdateService : public ComponentUpdateService { |
| 300 public: | 261 public: |
| 301 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); | 262 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); |
| 302 | |
| 303 virtual ~CrxUpdateService(); | 263 virtual ~CrxUpdateService(); |
| 304 | 264 |
| 305 // Overrides for ComponentUpdateService. | 265 // Overrides for ComponentUpdateService. |
| 306 virtual Status Start() OVERRIDE; | 266 virtual Status Start() OVERRIDE; |
| 307 virtual Status Stop() OVERRIDE; | 267 virtual Status Stop() OVERRIDE; |
| 308 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE; | 268 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE; |
| 309 virtual Status OnDemandUpdate(const std::string& component_id) OVERRIDE; | 269 virtual Status OnDemandUpdate(const std::string& component_id) OVERRIDE; |
| 310 virtual void GetComponents( | 270 virtual void GetComponents( |
| 311 std::vector<CrxComponentInfo>* components) OVERRIDE; | 271 std::vector<CrxComponentInfo>* components) OVERRIDE; |
| 312 virtual content::ResourceThrottle* GetOnDemandResourceThrottle( | 272 virtual content::ResourceThrottle* GetOnDemandResourceThrottle( |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 340 kUnpackError, | 300 kUnpackError, |
| 341 kInstallError, | 301 kInstallError, |
| 342 }; | 302 }; |
| 343 | 303 |
| 344 enum StepDelayInterval { | 304 enum StepDelayInterval { |
| 345 kStepDelayShort = 0, | 305 kStepDelayShort = 0, |
| 346 kStepDelayMedium, | 306 kStepDelayMedium, |
| 347 kStepDelayLong, | 307 kStepDelayLong, |
| 348 }; | 308 }; |
| 349 | 309 |
| 350 | 310 void OnParseUpdateManifestSucceeded( |
| 351 void OnParseUpdateManifestSucceeded(const UpdateManifest::Results& results); | 311 const component_updater::UpdateManifest::Results& results); |
| 352 | |
| 353 void OnParseUpdateManifestFailed(const std::string& error_message); | 312 void OnParseUpdateManifestFailed(const std::string& error_message); |
| 354 | 313 |
| 355 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query); | |
| 356 | |
| 357 Status OnDemandUpdateInternal(CrxUpdateItem* item); | 314 Status OnDemandUpdateInternal(CrxUpdateItem* item); |
| 358 | 315 |
| 359 void ProcessPendingItems(); | 316 void ProcessPendingItems(); |
| 360 | 317 |
| 361 CrxUpdateItem* FindReadyComponent(); | 318 CrxUpdateItem* FindReadyComponent(); |
| 362 | 319 |
| 363 void UpdateComponent(CrxUpdateItem* workitem); | 320 void UpdateComponent(CrxUpdateItem* workitem); |
| 364 | 321 |
| 365 void AddUpdateCheckItems(std::string* query); | 322 void AddItemToUpdateCheck(CrxUpdateItem* item, |
| 366 | 323 std::string* update_check_items); |
| 367 void DoUpdateCheck(const std::string& query); | 324 |
| 325 void AddUpdateCheckItems(std::string* update_check_items); | |
| 326 | |
| 327 void DoUpdateCheck(const std::string& update_check_items); | |
| 368 | 328 |
| 369 void ScheduleNextRun(StepDelayInterval step_delay); | 329 void ScheduleNextRun(StepDelayInterval step_delay); |
| 370 | 330 |
| 371 void ParseManifest(const std::string& xml); | 331 void ParseManifest(const std::string& xml); |
| 372 | 332 |
| 373 void Install(const CRXContext* context, const base::FilePath& crx_path); | 333 void Install(const CRXContext* context, const base::FilePath& crx_path); |
| 374 | 334 |
| 375 void DoneInstalling(const std::string& component_id, | 335 void DoneInstalling(const std::string& component_id, |
| 376 ComponentUnpacker::Error error, | 336 ComponentUnpacker::Error error, |
| 377 int extended_error); | 337 int extended_error); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 629 | 589 |
| 630 work_items_.push_back(uit); | 590 work_items_.push_back(uit); |
| 631 // If this is the first component registered we call Start to | 591 // If this is the first component registered we call Start to |
| 632 // schedule the first timer. | 592 // schedule the first timer. |
| 633 if (running_ && (work_items_.size() == 1)) | 593 if (running_ && (work_items_.size() == 1)) |
| 634 Start(); | 594 Start(); |
| 635 | 595 |
| 636 return kOk; | 596 return kOk; |
| 637 } | 597 } |
| 638 | 598 |
| 639 // Sets a component to be checked for updates. | |
| 640 // The component to add is |item| and the |query| string is modified with the | |
| 641 // required omaha compatible query. Returns false when the query string is | |
| 642 // longer than specified by UrlSizeLimit(). | |
| 643 bool CrxUpdateService::AddItemToUpdateCheck(CrxUpdateItem* item, | |
| 644 std::string* query) { | |
| 645 if (!AddQueryString(item->id, | |
| 646 item->component.version.GetString(), | |
| 647 item->component.fingerprint, | |
| 648 item->on_demand, | |
| 649 config_->UrlSizeLimit(), | |
| 650 query)) | |
| 651 return false; | |
| 652 | |
| 653 ChangeItemState(item, CrxUpdateItem::kChecking); | |
| 654 item->last_check = base::Time::Now(); | |
| 655 item->previous_version = item->component.version; | |
| 656 item->next_version = Version(); | |
| 657 item->previous_fp = item->component.fingerprint; | |
| 658 item->next_fp.clear(); | |
| 659 item->diff_update_failed = false; | |
| 660 item->error_category = 0; | |
| 661 item->error_code = 0; | |
| 662 item->extra_code1 = 0; | |
| 663 item->diff_error_category = 0; | |
| 664 item->diff_error_code = 0; | |
| 665 item->diff_extra_code1 = 0; | |
| 666 return true; | |
| 667 } | |
| 668 | |
| 669 // Start the process of checking for an update, for a particular component | 599 // Start the process of checking for an update, for a particular component |
| 670 // that was previously registered. | 600 // that was previously registered. |
| 671 // |component_id| is a value returned from GetCrxComponentID(). | 601 // |component_id| is a value returned from GetCrxComponentID(). |
| 672 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdate( | 602 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdate( |
| 673 const std::string& component_id) { | 603 const std::string& component_id) { |
| 674 return OnDemandUpdateInternal(FindUpdateItemById(component_id)); | 604 return OnDemandUpdateInternal(FindUpdateItemById(component_id)); |
| 675 } | 605 } |
| 676 | 606 |
| 677 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdateInternal( | 607 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdateInternal( |
| 678 CrxUpdateItem* uit) { | 608 CrxUpdateItem* uit) { |
| 679 if (!uit) | 609 if (!uit) |
| 680 return kError; | 610 return kError; |
| 611 | |
| 681 // Check if the request is too soon. | 612 // Check if the request is too soon. |
| 682 base::TimeDelta delta = base::Time::Now() - uit->last_check; | 613 base::TimeDelta delta = base::Time::Now() - uit->last_check; |
| 683 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay())) | 614 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay())) |
| 684 return kError; | 615 return kError; |
| 685 | 616 |
| 686 switch (uit->status) { | 617 switch (uit->status) { |
| 687 // If the item is already in the process of being updated, there is | 618 // If the item is already in the process of being updated, there is |
| 688 // no point in this call, so return kInProgress. | 619 // no point in this call, so return kInProgress. |
| 689 case CrxUpdateItem::kChecking: | 620 case CrxUpdateItem::kChecking: |
| 690 case CrxUpdateItem::kCanUpdate: | 621 case CrxUpdateItem::kCanUpdate: |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 732 } | 663 } |
| 733 | 664 |
| 734 // This is the main loop of the component updater. | 665 // This is the main loop of the component updater. |
| 735 void CrxUpdateService::ProcessPendingItems() { | 666 void CrxUpdateService::ProcessPendingItems() { |
| 736 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 667 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 737 CrxUpdateItem* ready_upgrade = FindReadyComponent(); | 668 CrxUpdateItem* ready_upgrade = FindReadyComponent(); |
| 738 if (ready_upgrade) { | 669 if (ready_upgrade) { |
| 739 UpdateComponent(ready_upgrade); | 670 UpdateComponent(ready_upgrade); |
| 740 return; | 671 return; |
| 741 } | 672 } |
| 742 std::string query; | 673 std::string update_check_items; |
| 743 AddUpdateCheckItems(&query); | 674 AddUpdateCheckItems(&update_check_items); |
| 744 if (!query.empty()) { | 675 if (!update_check_items.empty()) { |
| 745 DoUpdateCheck(query); | 676 DoUpdateCheck(update_check_items); |
| 746 return; | 677 return; |
| 747 } | 678 } |
| 748 // No components to update. The next check will be after a long sleep. | 679 // No components to update. The next check will be after a long sleep. |
| 749 ScheduleNextRun(kStepDelayLong); | 680 ScheduleNextRun(kStepDelayLong); |
| 750 } | 681 } |
| 751 | 682 |
| 752 CrxUpdateItem* CrxUpdateService::FindReadyComponent() { | 683 CrxUpdateItem* CrxUpdateService::FindReadyComponent() { |
| 753 class Helper { | 684 class Helper { |
| 754 public: | 685 public: |
| 755 static bool IsReadyOnDemand(CrxUpdateItem* item) { | 686 static bool IsReadyOnDemand(CrxUpdateItem* item) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 786 } | 717 } |
| 787 url_fetcher_.reset(net::URLFetcher::Create( | 718 url_fetcher_.reset(net::URLFetcher::Create( |
| 788 0, package_url, net::URLFetcher::GET, | 719 0, package_url, net::URLFetcher::GET, |
| 789 MakeContextDelegate(this, context))); | 720 MakeContextDelegate(this, context))); |
| 790 StartFetch(url_fetcher_.get(), | 721 StartFetch(url_fetcher_.get(), |
| 791 config_->RequestContext(), | 722 config_->RequestContext(), |
| 792 true, | 723 true, |
| 793 blocking_task_runner_); | 724 blocking_task_runner_); |
| 794 } | 725 } |
| 795 | 726 |
| 796 // Given that our |work_items_| list is expected to contain relatively few | 727 // Sets the state of the component to be checked for updates. After the |
| 797 // items, we simply loop several times. | 728 // function is called, the <app> element corresponding to the |item| parameter |
| 798 void CrxUpdateService::AddUpdateCheckItems(std::string* query){ | 729 // is appended to the |update_check_items|. |
| 730 void CrxUpdateService::AddItemToUpdateCheck(CrxUpdateItem* item, | |
| 731 std::string* update_check_items) { | |
| 732 // The app element corresponding to an update items looks like this: | |
| 733 // <app appid="hnimpnehoodheedghdeeijklkeaacbdc" | |
| 734 // version="0.1.2.3" installsource="ondemand"> | |
| 735 // <updatecheck /> | |
| 736 // <packages> | |
| 737 // <package fp="abcd" /> | |
| 738 // </packages> | |
| 739 // </app> | |
| 740 std::string app_attributes; | |
| 741 base::StringAppendF(&app_attributes, | |
| 742 "appid=\"%s\" version=\"%s\"", | |
| 743 item->id.c_str(), | |
| 744 item->component.version.GetString().c_str()); | |
| 745 if (item->on_demand) | |
| 746 base::StringAppendF(&app_attributes, " installsource=\"ondemand\""); | |
| 747 | |
| 748 std::string app; | |
| 749 if (item->component.fingerprint.empty()) | |
| 750 base::StringAppendF(&app, | |
| 751 "<app %s>" | |
| 752 "<updatecheck />" | |
| 753 "</app>", | |
| 754 app_attributes.c_str()); | |
| 755 else | |
| 756 base::StringAppendF(&app, | |
| 757 "<app %s>" | |
| 758 "<updatecheck />" | |
| 759 "<packages>" | |
| 760 "<package fp=\"%s\"/>" | |
| 761 "</packages>" | |
| 762 "</app>", | |
| 763 app_attributes.c_str(), | |
| 764 item->component.fingerprint.c_str()); | |
| 765 | |
| 766 update_check_items->append(app); | |
| 767 | |
| 768 ChangeItemState(item, CrxUpdateItem::kChecking); | |
| 769 item->last_check = base::Time::Now(); | |
| 770 item->previous_version = item->component.version; | |
| 771 item->next_version = Version(); | |
| 772 item->previous_fp = item->component.fingerprint; | |
| 773 item->next_fp.clear(); | |
| 774 item->diff_update_failed = false; | |
| 775 item->error_category = 0; | |
| 776 item->error_code = 0; | |
| 777 item->extra_code1 = 0; | |
| 778 item->diff_error_category = 0; | |
| 779 item->diff_error_code = 0; | |
| 780 item->diff_extra_code1 = 0; | |
| 781 } | |
| 782 | |
| 783 // Builds the sequence of <app> elements in the update check and returns it | |
| 784 // in the |update_check_items| parameter. | |
| 785 void CrxUpdateService::AddUpdateCheckItems(std::string* update_check_items){ | |
| 786 // Given that our |work_items_| list is expected to contain relatively few | |
| 787 // items, we simply loop several times. | |
| 799 for (UpdateItems::const_iterator it = work_items_.begin(); | 788 for (UpdateItems::const_iterator it = work_items_.begin(); |
| 800 it != work_items_.end(); ++it) { | 789 it != work_items_.end(); ++it) { |
| 801 CrxUpdateItem* item = *it; | 790 CrxUpdateItem* item = *it; |
| 802 if (item->status != CrxUpdateItem::kNew) | 791 if (item->status != CrxUpdateItem::kNew) |
| 803 continue; | 792 continue; |
| 804 if (!AddItemToUpdateCheck(item, query)) | 793 AddItemToUpdateCheck(item, update_check_items); |
| 805 break; | |
| 806 } | 794 } |
| 807 | 795 |
| 808 // Next we can go back to components we already checked, here | 796 // Next we can go back to components we already checked, here |
|
waffles
2013/11/18 22:15:59
Can't we get rid of these three separate loops alt
Sorin Jianu
2013/11/19 04:25:45
If we do that, I will do it in another change.
| |
| 809 // we can also batch them in a single url request, as long as | 797 // we can also batch them in a single url request, as long as |
| 810 // we have not checked them recently. | 798 // we have not checked them recently. |
| 811 const base::TimeDelta min_delta_time = | 799 const base::TimeDelta min_delta_time = |
| 812 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); | 800 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); |
| 813 | 801 |
| 814 for (UpdateItems::const_iterator it = work_items_.begin(); | 802 for (UpdateItems::const_iterator it = work_items_.begin(); |
| 815 it != work_items_.end(); ++it) { | 803 it != work_items_.end(); ++it) { |
| 816 CrxUpdateItem* item = *it; | 804 CrxUpdateItem* item = *it; |
| 817 if ((item->status != CrxUpdateItem::kNoUpdate) && | 805 if ((item->status != CrxUpdateItem::kNoUpdate) && |
| 818 (item->status != CrxUpdateItem::kUpToDate)) | 806 (item->status != CrxUpdateItem::kUpToDate)) |
| 819 continue; | 807 continue; |
| 820 base::TimeDelta delta = base::Time::Now() - item->last_check; | 808 base::TimeDelta delta = base::Time::Now() - item->last_check; |
| 821 if (delta < min_delta_time) | 809 if (delta < min_delta_time) |
| 822 continue; | 810 continue; |
| 823 if (!AddItemToUpdateCheck(item, query)) | 811 AddItemToUpdateCheck(item, update_check_items); |
| 824 break; | |
| 825 } | 812 } |
| 826 | 813 |
| 827 // Finally, we check components that we already updated as long as | 814 // Finally, we check components that we already updated as long as |
| 828 // we have not checked them recently. | 815 // we have not checked them recently. |
| 829 for (UpdateItems::const_iterator it = work_items_.begin(); | 816 for (UpdateItems::const_iterator it = work_items_.begin(); |
| 830 it != work_items_.end(); ++it) { | 817 it != work_items_.end(); ++it) { |
| 831 CrxUpdateItem* item = *it; | 818 CrxUpdateItem* item = *it; |
| 832 if (item->status != CrxUpdateItem::kUpdated) | 819 if (item->status != CrxUpdateItem::kUpdated) |
| 833 continue; | 820 continue; |
| 834 base::TimeDelta delta = base::Time::Now() - item->last_check; | 821 base::TimeDelta delta = base::Time::Now() - item->last_check; |
| 835 if (delta < min_delta_time) | 822 if (delta < min_delta_time) |
| 836 continue; | 823 continue; |
| 837 if (!AddItemToUpdateCheck(item, query)) | 824 AddItemToUpdateCheck(item, update_check_items); |
| 838 break; | 825 } |
| 839 } | 826 } |
| 840 } | 827 |
| 841 | 828 // Sends an update request. The |update_check_items| parameter |
| 842 void CrxUpdateService::DoUpdateCheck(const std::string& query) { | 829 // contains the sequence of <app> xml elements of the update check. |
| 843 const std::string full_query = | 830 void CrxUpdateService::DoUpdateCheck(const std::string& update_check_items) { |
| 844 MakeFinalQuery(config_->UpdateUrl().spec(), | 831 using component_updater::BuildProtocolRequest; |
| 845 query, | 832 url_fetcher_.reset(component_updater::SendProtocolRequest( |
| 846 config_->ExtraRequestParams()); | 833 config_->UpdateUrl(), |
| 847 | 834 BuildProtocolRequest(update_check_items), |
| 848 url_fetcher_.reset(net::URLFetcher::Create( | 835 MakeContextDelegate(this, new UpdateContext()), |
| 849 0, GURL(full_query), net::URLFetcher::GET, | 836 config_->RequestContext())); |
| 850 MakeContextDelegate(this, new UpdateContext()))); | |
| 851 StartFetch(url_fetcher_.get(), | |
| 852 config_->RequestContext(), | |
| 853 false, | |
| 854 blocking_task_runner_); | |
| 855 } | 837 } |
| 856 | 838 |
| 857 // Called when we got a response from the update server. It consists of an xml | 839 // Called when we got a response from the update server. It consists of an xml |
| 858 // document following the omaha update scheme. | 840 // document following the omaha update scheme. |
| 859 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source, | 841 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source, |
| 860 UpdateContext* context) { | 842 UpdateContext* context) { |
| 861 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 843 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 862 if (FetchSuccess(*source)) { | 844 if (FetchSuccess(*source)) { |
| 863 std::string xml; | 845 std::string xml; |
| 864 source->GetResponseAsString(&xml); | 846 source->GetResponseAsString(&xml); |
| 865 url_fetcher_.reset(); | 847 url_fetcher_.reset(); |
| 866 ParseManifest(xml); | 848 ParseManifest(xml); |
| 867 } else { | 849 } else { |
| 868 url_fetcher_.reset(); | 850 url_fetcher_.reset(); |
| 869 CrxUpdateService::OnParseUpdateManifestFailed("network error"); | 851 CrxUpdateService::OnParseUpdateManifestFailed("network error"); |
| 870 } | 852 } |
| 871 delete context; | 853 delete context; |
| 872 } | 854 } |
| 873 | 855 |
| 874 // Parsing the manifest is either done right now for tests or in a sandboxed | 856 // Parsing the manifest is either done right now for tests or in a sandboxed |
| 875 // process for the production environment. This mitigates the case where an | 857 // process for the production environment. This mitigates the case where an |
|
waffles
2013/11/18 22:15:59
This comment seems to be out of date.
Sorin Jianu
2013/11/19 04:25:45
Done.
| |
| 876 // attacker was able to feed us a malicious xml string. | 858 // attacker was able to feed us a malicious xml string. |
| 877 void CrxUpdateService::ParseManifest(const std::string& xml) { | 859 void CrxUpdateService::ParseManifest(const std::string& xml) { |
| 878 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 860 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 879 UpdateManifest manifest; | 861 component_updater::UpdateManifest manifest; |
| 880 if (!manifest.Parse(xml)) | 862 if (manifest.Parse(xml)) |
| 881 CrxUpdateService::OnParseUpdateManifestFailed(manifest.errors()); | 863 CrxUpdateService::OnParseUpdateManifestSucceeded(manifest.results()); |
| 882 else | 864 else |
| 883 CrxUpdateService::OnParseUpdateManifestSucceeded(manifest.results()); | 865 CrxUpdateService::OnParseUpdateManifestFailed(manifest.errors()); |
| 884 } | 866 } |
| 885 | 867 |
| 886 // A valid Omaha update check has arrived, from only the list of components that | 868 // A valid Omaha update check has arrived, from only the list of components that |
| 887 // we are currently upgrading we check for a match in which the server side | 869 // we are currently upgrading we check for a match in which the server side |
| 888 // version is newer, if so we queue them for an upgrade. The next time we call | 870 // version is newer, if so we queue them for an upgrade. The next time we call |
| 889 // ProcessPendingItems() one of them will be drafted for the upgrade process. | 871 // ProcessPendingItems() one of them will be drafted for the upgrade process. |
| 890 void CrxUpdateService::OnParseUpdateManifestSucceeded( | 872 void CrxUpdateService::OnParseUpdateManifestSucceeded( |
| 891 const UpdateManifest::Results& results) { | 873 const component_updater::UpdateManifest::Results& results) { |
| 892 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 874 size_t num_updates_pending = 0; |
|
waffles
2013/11/18 22:15:59
Why not just a bool?
Sorin Jianu
2013/11/19 04:25:45
Because it was a size_t before and it seems useful
| |
| 893 size_t update_pending = 0; | 875 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 894 std::vector<UpdateManifest::Result>::const_iterator it; | 876 std::vector<component_updater::UpdateManifest::Result>::const_iterator it; |
| 895 for (it = results.list.begin(); it != results.list.end(); ++it) { | 877 for (it = results.list.begin(); it != results.list.end(); ++it) { |
| 896 CrxUpdateItem* crx = FindUpdateItemById(it->extension_id); | 878 CrxUpdateItem* crx = FindUpdateItemById(it->extension_id); |
| 897 if (!crx) | 879 if (!crx) |
| 898 continue; | 880 continue; |
| 899 | 881 |
| 900 if (crx->status != CrxUpdateItem::kChecking) | 882 if (crx->status != CrxUpdateItem::kChecking) { |
| 883 NOTREACHED(); | |
| 901 continue; // Not updating this component now. | 884 continue; // Not updating this component now. |
| 902 | 885 } |
| 903 if (it->version.empty()) { | 886 |
| 887 if (it->manifest.version.empty()) { | |
| 904 // No version means no update available. | 888 // No version means no update available. |
| 905 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); | 889 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); |
| 906 continue; | 890 continue; |
| 907 } | 891 } |
| 908 if (!IsVersionNewer(crx->component.version, it->version)) { | 892 |
| 909 // Our component is up to date. | 893 if (!IsVersionNewer(crx->component.version, it->manifest.version)) { |
| 894 // The component is up to date. | |
| 910 ChangeItemState(crx, CrxUpdateItem::kUpToDate); | 895 ChangeItemState(crx, CrxUpdateItem::kUpToDate); |
| 911 continue; | 896 continue; |
| 912 } | 897 } |
| 913 if (!it->browser_min_version.empty()) { | 898 |
| 914 if (IsVersionNewer(chrome_version_, it->browser_min_version)) { | 899 if (!it->manifest.browser_min_version.empty()) { |
| 915 // Does not apply for this chrome version. | 900 if (IsVersionNewer(chrome_version_, it->manifest.browser_min_version)) { |
| 901 // The component is not compatible with this Chrome version. | |
| 916 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); | 902 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); |
| 917 continue; | 903 continue; |
| 918 } | 904 } |
| 919 } | 905 } |
| 920 // All test passed. Queue an upgrade for this component and fire the | 906 |
| 921 // notifications. | 907 if (it->manifest.packages.size() != 1) { |
| 922 crx->crx_url = it->crx_url; | 908 // Assume one and only one package per component. |
| 923 crx->diff_crx_url = it->diff_crx_url; | 909 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); |
| 910 continue; | |
| 911 } | |
| 912 | |
| 913 // Parse the members of the result and queue an upgrade for this component. | |
| 914 crx->next_version = Version(it->manifest.version); | |
| 915 | |
| 916 typedef component_updater:: | |
| 917 UpdateManifest::Result::Manifest::Package Package; | |
| 918 const Package& package(it->manifest.packages[0]); | |
| 919 crx->next_fp = package.fingerprint; | |
| 920 | |
| 921 // Select the first url from the list of urls until support for | |
| 922 // fall back urls is implemented. | |
| 923 if (!it->crx_urls.empty()) | |
|
waffles
2013/11/18 22:15:59
What happens if <urls> is empty? When do we reset
Sorin Jianu
2013/11/19 04:25:45
Thank you. I am now resetting the urls along with
| |
| 924 crx->crx_url = it->crx_urls[0].Resolve(package.name); | |
| 925 if (!it->crx_diffurls.empty()) | |
|
waffles
2013/11/18 22:15:59
Same as above for diffurls, except that the parser
Sorin Jianu
2013/11/19 04:25:45
Done. If the GURLs are empty, then the download co
| |
| 926 crx->diff_crx_url = it->crx_diffurls[0].Resolve(package.namediff); | |
| 927 | |
| 924 ChangeItemState(crx, CrxUpdateItem::kCanUpdate); | 928 ChangeItemState(crx, CrxUpdateItem::kCanUpdate); |
| 925 crx->next_version = Version(it->version); | 929 ++num_updates_pending; |
| 926 crx->next_fp = it->package_fingerprint; | 930 } |
| 927 ++update_pending; | 931 |
| 928 } | 932 // All components that are not included in the update response are |
| 929 | 933 // considered up to date. |
| 930 // All the components that are not mentioned in the manifest we | |
| 931 // consider them up to date. | |
| 932 ChangeItemStatus(CrxUpdateItem::kChecking, CrxUpdateItem::kUpToDate); | 934 ChangeItemStatus(CrxUpdateItem::kChecking, CrxUpdateItem::kUpToDate); |
| 933 | 935 |
| 934 // If there are updates pending we do a short wait, otherwise we take | 936 // If there are updates pending we do a short wait, otherwise we take |
| 935 // a longer delay until we check the components again. | 937 // a longer delay until we check the components again. |
| 936 ScheduleNextRun(update_pending > 0 ? kStepDelayShort : kStepDelayMedium); | 938 ScheduleNextRun(num_updates_pending > 0 ? kStepDelayShort : kStepDelayMedium); |
| 937 } | 939 } |
| 938 | 940 |
| 939 void CrxUpdateService::OnParseUpdateManifestFailed( | 941 void CrxUpdateService::OnParseUpdateManifestFailed( |
| 940 const std::string& error_message) { | 942 const std::string& error_message) { |
| 941 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 943 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 942 size_t count = ChangeItemStatus(CrxUpdateItem::kChecking, | 944 size_t count = ChangeItemStatus(CrxUpdateItem::kChecking, |
| 943 CrxUpdateItem::kNoUpdate); | 945 CrxUpdateItem::kNoUpdate); |
| 944 DCHECK_GT(count, 0ul); | 946 DCHECK_GT(count, 0ul); |
| 945 ScheduleNextRun(kStepDelayLong); | 947 ScheduleNextRun(kStepDelayLong); |
| 946 } | 948 } |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1157 state_ = UNBLOCKED; | 1159 state_ = UNBLOCKED; |
| 1158 } | 1160 } |
| 1159 | 1161 |
| 1160 // The component update factory. Using the component updater as a singleton | 1162 // The component update factory. Using the component updater as a singleton |
| 1161 // is the job of the browser process. | 1163 // is the job of the browser process. |
| 1162 ComponentUpdateService* ComponentUpdateServiceFactory( | 1164 ComponentUpdateService* ComponentUpdateServiceFactory( |
| 1163 ComponentUpdateService::Configurator* config) { | 1165 ComponentUpdateService::Configurator* config) { |
| 1164 DCHECK(config); | 1166 DCHECK(config); |
| 1165 return new CrxUpdateService(config); | 1167 return new CrxUpdateService(config); |
| 1166 } | 1168 } |
| OLD | NEW |