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

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

Issue 74893002: Changed the update protocol for component updater from v2 to v3. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/component_updater/component_updater_service.h" 5 #include "chrome/browser/component_updater/component_updater_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/at_exit.h" 11 #include "base/at_exit.h"
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/compiler_specific.h" 13 #include "base/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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698