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->crx_url = GURL(); |
| 771 item->diff_crx_url = GURL(); |
| 772 item->previous_version = item->component.version; |
| 773 item->next_version = Version(); |
| 774 item->previous_fp = item->component.fingerprint; |
| 775 item->next_fp.clear(); |
| 776 item->diff_update_failed = false; |
| 777 item->error_category = 0; |
| 778 item->error_code = 0; |
| 779 item->extra_code1 = 0; |
| 780 item->diff_error_category = 0; |
| 781 item->diff_error_code = 0; |
| 782 item->diff_extra_code1 = 0; |
| 783 } |
| 784 |
| 785 // Builds the sequence of <app> elements in the update check and returns it |
| 786 // in the |update_check_items| parameter. |
| 787 void CrxUpdateService::AddUpdateCheckItems(std::string* update_check_items) { |
| 788 // Given that our |work_items_| list is expected to contain relatively few |
| 789 // items, we simply loop several times. |
799 for (UpdateItems::const_iterator it = work_items_.begin(); | 790 for (UpdateItems::const_iterator it = work_items_.begin(); |
800 it != work_items_.end(); ++it) { | 791 it != work_items_.end(); ++it) { |
801 CrxUpdateItem* item = *it; | 792 CrxUpdateItem* item = *it; |
802 if (item->status != CrxUpdateItem::kNew) | 793 if (item->status != CrxUpdateItem::kNew) |
803 continue; | 794 continue; |
804 if (!AddItemToUpdateCheck(item, query)) | 795 AddItemToUpdateCheck(item, update_check_items); |
805 break; | |
806 } | 796 } |
807 | 797 |
808 // Next we can go back to components we already checked, here | 798 // Next we can go back to components we already checked, here |
809 // we can also batch them in a single url request, as long as | 799 // we can also batch them in a single url request, as long as |
810 // we have not checked them recently. | 800 // we have not checked them recently. |
811 const base::TimeDelta min_delta_time = | 801 const base::TimeDelta min_delta_time = |
812 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); | 802 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); |
813 | 803 |
814 for (UpdateItems::const_iterator it = work_items_.begin(); | 804 for (UpdateItems::const_iterator it = work_items_.begin(); |
815 it != work_items_.end(); ++it) { | 805 it != work_items_.end(); ++it) { |
816 CrxUpdateItem* item = *it; | 806 CrxUpdateItem* item = *it; |
817 if ((item->status != CrxUpdateItem::kNoUpdate) && | 807 if ((item->status != CrxUpdateItem::kNoUpdate) && |
818 (item->status != CrxUpdateItem::kUpToDate)) | 808 (item->status != CrxUpdateItem::kUpToDate)) |
819 continue; | 809 continue; |
820 base::TimeDelta delta = base::Time::Now() - item->last_check; | 810 base::TimeDelta delta = base::Time::Now() - item->last_check; |
821 if (delta < min_delta_time) | 811 if (delta < min_delta_time) |
822 continue; | 812 continue; |
823 if (!AddItemToUpdateCheck(item, query)) | 813 AddItemToUpdateCheck(item, update_check_items); |
824 break; | |
825 } | 814 } |
826 | 815 |
827 // Finally, we check components that we already updated as long as | 816 // Finally, we check components that we already updated as long as |
828 // we have not checked them recently. | 817 // we have not checked them recently. |
829 for (UpdateItems::const_iterator it = work_items_.begin(); | 818 for (UpdateItems::const_iterator it = work_items_.begin(); |
830 it != work_items_.end(); ++it) { | 819 it != work_items_.end(); ++it) { |
831 CrxUpdateItem* item = *it; | 820 CrxUpdateItem* item = *it; |
832 if (item->status != CrxUpdateItem::kUpdated) | 821 if (item->status != CrxUpdateItem::kUpdated) |
833 continue; | 822 continue; |
834 base::TimeDelta delta = base::Time::Now() - item->last_check; | 823 base::TimeDelta delta = base::Time::Now() - item->last_check; |
835 if (delta < min_delta_time) | 824 if (delta < min_delta_time) |
836 continue; | 825 continue; |
837 if (!AddItemToUpdateCheck(item, query)) | 826 AddItemToUpdateCheck(item, update_check_items); |
838 break; | 827 } |
839 } | 828 } |
840 } | 829 |
841 | 830 // Sends an update request. The |update_check_items| parameter |
842 void CrxUpdateService::DoUpdateCheck(const std::string& query) { | 831 // contains the sequence of <app> xml elements of the update check. |
843 const std::string full_query = | 832 void CrxUpdateService::DoUpdateCheck(const std::string& update_check_items) { |
844 MakeFinalQuery(config_->UpdateUrl().spec(), | 833 using component_updater::BuildProtocolRequest; |
845 query, | 834 url_fetcher_.reset(component_updater::SendProtocolRequest( |
846 config_->ExtraRequestParams()); | 835 config_->UpdateUrl(), |
847 | 836 BuildProtocolRequest(update_check_items), |
848 url_fetcher_.reset(net::URLFetcher::Create( | 837 MakeContextDelegate(this, new UpdateContext()), |
849 0, GURL(full_query), net::URLFetcher::GET, | 838 config_->RequestContext())); |
850 MakeContextDelegate(this, new UpdateContext()))); | |
851 StartFetch(url_fetcher_.get(), | |
852 config_->RequestContext(), | |
853 false, | |
854 blocking_task_runner_); | |
855 } | 839 } |
856 | 840 |
857 // Called when we got a response from the update server. It consists of an xml | 841 // Called when we got a response from the update server. It consists of an xml |
858 // document following the omaha update scheme. | 842 // document following the omaha update scheme. |
859 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source, | 843 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source, |
860 UpdateContext* context) { | 844 UpdateContext* context) { |
861 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 845 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
862 if (FetchSuccess(*source)) { | 846 if (FetchSuccess(*source)) { |
863 std::string xml; | 847 std::string xml; |
864 source->GetResponseAsString(&xml); | 848 source->GetResponseAsString(&xml); |
865 url_fetcher_.reset(); | 849 url_fetcher_.reset(); |
866 ParseManifest(xml); | 850 ParseManifest(xml); |
867 } else { | 851 } else { |
868 url_fetcher_.reset(); | 852 url_fetcher_.reset(); |
869 CrxUpdateService::OnParseUpdateManifestFailed("network error"); | 853 CrxUpdateService::OnParseUpdateManifestFailed("network error"); |
870 } | 854 } |
871 delete context; | 855 delete context; |
872 } | 856 } |
873 | 857 |
874 // 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 | |
876 // attacker was able to feed us a malicious xml string. | |
877 void CrxUpdateService::ParseManifest(const std::string& xml) { | 858 void CrxUpdateService::ParseManifest(const std::string& xml) { |
878 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 859 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
879 UpdateManifest manifest; | 860 component_updater::UpdateManifest manifest; |
880 if (!manifest.Parse(xml)) | 861 if (manifest.Parse(xml)) |
881 CrxUpdateService::OnParseUpdateManifestFailed(manifest.errors()); | 862 CrxUpdateService::OnParseUpdateManifestSucceeded(manifest.results()); |
882 else | 863 else |
883 CrxUpdateService::OnParseUpdateManifestSucceeded(manifest.results()); | 864 CrxUpdateService::OnParseUpdateManifestFailed(manifest.errors()); |
884 } | 865 } |
885 | 866 |
886 // A valid Omaha update check has arrived, from only the list of components that | 867 // 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 | 868 // 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 | 869 // 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. | 870 // ProcessPendingItems() one of them will be drafted for the upgrade process. |
890 void CrxUpdateService::OnParseUpdateManifestSucceeded( | 871 void CrxUpdateService::OnParseUpdateManifestSucceeded( |
891 const UpdateManifest::Results& results) { | 872 const component_updater::UpdateManifest::Results& results) { |
892 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 873 size_t num_updates_pending = 0; |
893 size_t update_pending = 0; | 874 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
894 std::vector<UpdateManifest::Result>::const_iterator it; | 875 std::vector<component_updater::UpdateManifest::Result>::const_iterator it; |
895 for (it = results.list.begin(); it != results.list.end(); ++it) { | 876 for (it = results.list.begin(); it != results.list.end(); ++it) { |
896 CrxUpdateItem* crx = FindUpdateItemById(it->extension_id); | 877 CrxUpdateItem* crx = FindUpdateItemById(it->extension_id); |
897 if (!crx) | 878 if (!crx) |
898 continue; | 879 continue; |
899 | 880 |
900 if (crx->status != CrxUpdateItem::kChecking) | 881 if (crx->status != CrxUpdateItem::kChecking) { |
| 882 NOTREACHED(); |
901 continue; // Not updating this component now. | 883 continue; // Not updating this component now. |
902 | 884 } |
903 if (it->version.empty()) { | 885 |
| 886 if (it->manifest.version.empty()) { |
904 // No version means no update available. | 887 // No version means no update available. |
905 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); | 888 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); |
906 continue; | 889 continue; |
907 } | 890 } |
908 if (!IsVersionNewer(crx->component.version, it->version)) { | 891 |
909 // Our component is up to date. | 892 if (!IsVersionNewer(crx->component.version, it->manifest.version)) { |
| 893 // The component is up to date. |
910 ChangeItemState(crx, CrxUpdateItem::kUpToDate); | 894 ChangeItemState(crx, CrxUpdateItem::kUpToDate); |
911 continue; | 895 continue; |
912 } | 896 } |
913 if (!it->browser_min_version.empty()) { | 897 |
914 if (IsVersionNewer(chrome_version_, it->browser_min_version)) { | 898 if (!it->manifest.browser_min_version.empty()) { |
915 // Does not apply for this chrome version. | 899 if (IsVersionNewer(chrome_version_, it->manifest.browser_min_version)) { |
| 900 // The component is not compatible with this Chrome version. |
916 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); | 901 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); |
917 continue; | 902 continue; |
918 } | 903 } |
919 } | 904 } |
920 // All test passed. Queue an upgrade for this component and fire the | 905 |
921 // notifications. | 906 if (it->manifest.packages.size() != 1) { |
922 crx->crx_url = it->crx_url; | 907 // Assume one and only one package per component. |
923 crx->diff_crx_url = it->diff_crx_url; | 908 ChangeItemState(crx, CrxUpdateItem::kNoUpdate); |
| 909 continue; |
| 910 } |
| 911 |
| 912 // Parse the members of the result and queue an upgrade for this component. |
| 913 crx->next_version = Version(it->manifest.version); |
| 914 |
| 915 typedef component_updater:: |
| 916 UpdateManifest::Result::Manifest::Package Package; |
| 917 const Package& package(it->manifest.packages[0]); |
| 918 crx->next_fp = package.fingerprint; |
| 919 |
| 920 // Select the first url from the list of urls until support for |
| 921 // fall back urls is implemented. |
| 922 if (!it->crx_urls.empty()) |
| 923 crx->crx_url = it->crx_urls[0].Resolve(package.name); |
| 924 if (!it->crx_diffurls.empty()) |
| 925 crx->diff_crx_url = it->crx_diffurls[0].Resolve(package.namediff); |
| 926 |
924 ChangeItemState(crx, CrxUpdateItem::kCanUpdate); | 927 ChangeItemState(crx, CrxUpdateItem::kCanUpdate); |
925 crx->next_version = Version(it->version); | 928 ++num_updates_pending; |
926 crx->next_fp = it->package_fingerprint; | 929 } |
927 ++update_pending; | 930 |
928 } | 931 // All components that are not included in the update response are |
929 | 932 // 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); | 933 ChangeItemStatus(CrxUpdateItem::kChecking, CrxUpdateItem::kUpToDate); |
933 | 934 |
934 // If there are updates pending we do a short wait, otherwise we take | 935 // If there are updates pending we do a short wait, otherwise we take |
935 // a longer delay until we check the components again. | 936 // a longer delay until we check the components again. |
936 ScheduleNextRun(update_pending > 0 ? kStepDelayShort : kStepDelayMedium); | 937 ScheduleNextRun(num_updates_pending > 0 ? kStepDelayShort : kStepDelayMedium); |
937 } | 938 } |
938 | 939 |
939 void CrxUpdateService::OnParseUpdateManifestFailed( | 940 void CrxUpdateService::OnParseUpdateManifestFailed( |
940 const std::string& error_message) { | 941 const std::string& error_message) { |
941 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 942 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
942 size_t count = ChangeItemStatus(CrxUpdateItem::kChecking, | 943 size_t count = ChangeItemStatus(CrxUpdateItem::kChecking, |
943 CrxUpdateItem::kNoUpdate); | 944 CrxUpdateItem::kNoUpdate); |
944 DCHECK_GT(count, 0ul); | 945 DCHECK_GT(count, 0ul); |
945 ScheduleNextRun(kStepDelayLong); | 946 ScheduleNextRun(kStepDelayLong); |
946 } | 947 } |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 state_ = UNBLOCKED; | 1158 state_ = UNBLOCKED; |
1158 } | 1159 } |
1159 | 1160 |
1160 // The component update factory. Using the component updater as a singleton | 1161 // The component update factory. Using the component updater as a singleton |
1161 // is the job of the browser process. | 1162 // is the job of the browser process. |
1162 ComponentUpdateService* ComponentUpdateServiceFactory( | 1163 ComponentUpdateService* ComponentUpdateServiceFactory( |
1163 ComponentUpdateService::Configurator* config) { | 1164 ComponentUpdateService::Configurator* config) { |
1164 DCHECK(config); | 1165 DCHECK(config); |
1165 return new CrxUpdateService(config); | 1166 return new CrxUpdateService(config); |
1166 } | 1167 } |
| 1168 |
OLD | NEW |