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/stl_util.h" | 19 #include "base/stl_util.h" |
19 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
20 #include "base/strings/string_piece.h" | 21 #include "base/strings/string_piece.h" |
21 #include "base/strings/string_util.h" | 22 #include "base/strings/string_util.h" |
22 #include "base/strings/stringprintf.h" | 23 #include "base/strings/stringprintf.h" |
23 #include "base/threading/sequenced_worker_pool.h" | 24 #include "base/threading/sequenced_worker_pool.h" |
24 #include "base/timer/timer.h" | 25 #include "base/timer/timer.h" |
25 #include "chrome/browser/browser_process.h" | 26 #include "chrome/browser/browser_process.h" |
26 #include "chrome/browser/component_updater/component_patcher.h" | 27 #include "chrome/browser/component_updater/component_patcher.h" |
27 #include "chrome/browser/component_updater/component_unpacker.h" | 28 #include "chrome/browser/component_updater/component_unpacker.h" |
28 #include "chrome/browser/component_updater/component_updater_ping_manager.h" | 29 #include "chrome/browser/component_updater/component_updater_ping_manager.h" |
29 #include "chrome/browser/component_updater/crx_update_item.h" | 30 #include "chrome/browser/component_updater/crx_update_item.h" |
30 #include "chrome/common/chrome_utility_messages.h" | 31 #include "chrome/common/chrome_utility_messages.h" |
31 #include "chrome/common/chrome_version_info.h" | 32 #include "chrome/common/chrome_version_info.h" |
32 #include "chrome/common/extensions/extension.h" | 33 #include "chrome/common/extensions/extension.h" |
33 #include "content/public/browser/browser_thread.h" | 34 #include "content/public/browser/browser_thread.h" |
| 35 #include "content/public/browser/resource_controller.h" |
| 36 #include "content/public/browser/resource_throttle.h" |
34 #include "content/public/browser/utility_process_host.h" | 37 #include "content/public/browser/utility_process_host.h" |
35 #include "content/public/browser/utility_process_host_client.h" | 38 #include "content/public/browser/utility_process_host_client.h" |
36 #include "net/base/escape.h" | 39 #include "net/base/escape.h" |
37 #include "net/base/load_flags.h" | 40 #include "net/base/load_flags.h" |
38 #include "net/base/net_errors.h" | 41 #include "net/base/net_errors.h" |
39 #include "net/url_request/url_fetcher.h" | 42 #include "net/url_request/url_fetcher.h" |
40 #include "net/url_request/url_fetcher_delegate.h" | 43 #include "net/url_request/url_fetcher_delegate.h" |
| 44 #include "net/url_request/url_request.h" |
41 #include "net/url_request/url_request_status.h" | 45 #include "net/url_request/url_request_status.h" |
42 #include "url/gurl.h" | 46 #include "url/gurl.h" |
43 | 47 |
44 using content::BrowserThread; | 48 using content::BrowserThread; |
45 using content::UtilityProcessHost; | 49 using content::UtilityProcessHost; |
46 using content::UtilityProcessHostClient; | 50 using content::UtilityProcessHostClient; |
47 using extensions::Extension; | 51 using extensions::Extension; |
48 | 52 |
49 // The component updater is designed to live until process shutdown, so | 53 // The component updater is designed to live until process shutdown, so |
50 // base::Bind() calls are not refcounted. | 54 // base::Bind() calls are not refcounted. |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 return HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0], | 234 return HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0], |
231 component.pk_hash.size()/2))); | 235 component.pk_hash.size()/2))); |
232 } | 236 } |
233 | 237 |
234 CrxComponentInfo::CrxComponentInfo() { | 238 CrxComponentInfo::CrxComponentInfo() { |
235 } | 239 } |
236 | 240 |
237 CrxComponentInfo::~CrxComponentInfo() { | 241 CrxComponentInfo::~CrxComponentInfo() { |
238 } | 242 } |
239 | 243 |
| 244 /////////////////////////////////////////////////////////////////////////////// |
| 245 // In charge of blocking url requests until the |crx_id| component has been |
| 246 // updated. This class is touched solely from the IO thread. The UI thread |
| 247 // can post tasks to it via weak pointers. By default the request is blocked |
| 248 // unless the CrxUpdateService calls Unblock(). |
| 249 // The lifetime is controlled by Chrome's resource loader so the component |
| 250 // updater cannot touch objects from this class except via weak pointers. |
| 251 class CUResourceThrottle |
| 252 : public content::ResourceThrottle, |
| 253 public base::SupportsWeakPtr<CUResourceThrottle> { |
| 254 public: |
| 255 explicit CUResourceThrottle(const net::URLRequest* request); |
| 256 virtual ~CUResourceThrottle(); |
| 257 // Overriden from ResourceThrottle. |
| 258 virtual void WillStartRequest(bool* defer) OVERRIDE; |
| 259 virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; |
| 260 |
| 261 // Component updater calls this function via PostTask to unblock the request. |
| 262 void Unblock(); |
| 263 |
| 264 typedef std::vector<base::WeakPtr<CUResourceThrottle> > WeakPtrVector; |
| 265 |
| 266 private: |
| 267 enum State { |
| 268 NEW, |
| 269 BLOCKED, |
| 270 UNBLOCKED |
| 271 }; |
| 272 |
| 273 State state_; |
| 274 }; |
| 275 |
| 276 void UnblockResourceThrottle(base::WeakPtr<CUResourceThrottle> rt) { |
| 277 BrowserThread::PostTask( |
| 278 BrowserThread::IO, |
| 279 FROM_HERE, |
| 280 base::Bind(&CUResourceThrottle::Unblock, rt)); |
| 281 } |
| 282 |
| 283 void UnblockandReapAllThrottles(CUResourceThrottle::WeakPtrVector* throttles) { |
| 284 CUResourceThrottle::WeakPtrVector::iterator it; |
| 285 for (it = throttles->begin(); it != throttles->end(); ++it) |
| 286 UnblockResourceThrottle(*it); |
| 287 throttles->clear(); |
| 288 } |
| 289 |
240 ////////////////////////////////////////////////////////////////////////////// | 290 ////////////////////////////////////////////////////////////////////////////// |
241 // The one and only implementation of the ComponentUpdateService interface. In | 291 // The one and only implementation of the ComponentUpdateService interface. In |
242 // charge of running the show. The main method is ProcessPendingItems() which | 292 // charge of running the show. The main method is ProcessPendingItems() which |
243 // is called periodically to do the upgrades/installs or the update checks. | 293 // is called periodically to do the upgrades/installs or the update checks. |
244 // An important consideration here is to be as "low impact" as we can to the | 294 // An important consideration here is to be as "low impact" as we can to the |
245 // rest of the browser, so even if we have many components registered and | 295 // rest of the browser, so even if we have many components registered and |
246 // eligible for update, we only do one thing at a time with pauses in between | 296 // eligible for update, we only do one thing at a time with pauses in between |
247 // the tasks. Also when we do network requests there is only one |url_fetcher_| | 297 // the tasks. Also when we do network requests there is only one |url_fetcher_| |
248 // in flight at a time. | 298 // in flight at a time. |
249 // There are no locks in this code, the main structure |work_items_| is mutated | 299 // There are no locks in this code, the main structure |work_items_| is mutated |
250 // only from the UI thread. The unpack and installation is done in the file | 300 // only from the UI thread. The unpack and installation is done in the file |
251 // thread and the network requests are done in the IO thread and in the file | 301 // thread and the network requests are done in the IO thread and in the file |
252 // thread. | 302 // thread. |
253 class CrxUpdateService : public ComponentUpdateService { | 303 class CrxUpdateService : public ComponentUpdateService { |
254 public: | 304 public: |
255 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); | 305 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); |
256 | 306 |
257 virtual ~CrxUpdateService(); | 307 virtual ~CrxUpdateService(); |
258 | 308 |
259 // Overrides for ComponentUpdateService. | 309 // Overrides for ComponentUpdateService. |
260 virtual Status Start() OVERRIDE; | 310 virtual Status Start() OVERRIDE; |
261 virtual Status Stop() OVERRIDE; | 311 virtual Status Stop() OVERRIDE; |
262 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE; | 312 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE; |
263 virtual Status OnDemandUpdate(const std::string& component_id) OVERRIDE; | 313 virtual Status OnDemandUpdate(const std::string& component_id) OVERRIDE; |
264 virtual void GetComponents( | 314 virtual void GetComponents( |
265 std::vector<CrxComponentInfo>* components) OVERRIDE; | 315 std::vector<CrxComponentInfo>* components) OVERRIDE; |
| 316 virtual content::ResourceThrottle* GetOnDemandResourceThrottle( |
| 317 net::URLRequest* request, const std::string& crx_id) OVERRIDE; |
266 | 318 |
267 // The only purpose of this class is to forward the | 319 // The only purpose of this class is to forward the |
268 // UtilityProcessHostClient callbacks so CrxUpdateService does | 320 // UtilityProcessHostClient callbacks so CrxUpdateService does |
269 // not have to derive from it because that is refcounted. | 321 // not have to derive from it because that is refcounted. |
270 class ManifestParserBridge : public UtilityProcessHostClient { | 322 class ManifestParserBridge : public UtilityProcessHostClient { |
271 public: | 323 public: |
272 explicit ManifestParserBridge(CrxUpdateService* service) | 324 explicit ManifestParserBridge(CrxUpdateService* service) |
273 : service_(service) {} | 325 : service_(service) {} |
274 | 326 |
275 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { | 327 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 }; | 388 }; |
337 | 389 |
338 // See ManifestParserBridge. | 390 // See ManifestParserBridge. |
339 void OnParseUpdateManifestSucceeded(const UpdateManifest::Results& results); | 391 void OnParseUpdateManifestSucceeded(const UpdateManifest::Results& results); |
340 | 392 |
341 // See ManifestParserBridge. | 393 // See ManifestParserBridge. |
342 void OnParseUpdateManifestFailed(const std::string& error_message); | 394 void OnParseUpdateManifestFailed(const std::string& error_message); |
343 | 395 |
344 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query); | 396 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query); |
345 | 397 |
| 398 Status OnDemandUpdateInternal(CrxUpdateItem* item); |
| 399 |
346 void ProcessPendingItems(); | 400 void ProcessPendingItems(); |
347 | 401 |
348 CrxUpdateItem* FindReadyComponent(); | 402 CrxUpdateItem* FindReadyComponent(); |
349 | 403 |
350 void UpdateComponent(CrxUpdateItem* workitem); | 404 void UpdateComponent(CrxUpdateItem* workitem); |
351 | 405 |
352 void AddUpdateCheckItems(std::string* query); | 406 void AddUpdateCheckItems(std::string* query); |
353 | 407 |
354 void DoUpdateCheck(const std::string& query); | 408 void DoUpdateCheck(const std::string& query); |
355 | 409 |
(...skipping 12 matching lines...) Expand all Loading... |
368 size_t ChangeItemStatus(CrxUpdateItem::Status from, | 422 size_t ChangeItemStatus(CrxUpdateItem::Status from, |
369 CrxUpdateItem::Status to); | 423 CrxUpdateItem::Status to); |
370 | 424 |
371 CrxUpdateItem* FindUpdateItemById(const std::string& id); | 425 CrxUpdateItem* FindUpdateItemById(const std::string& id); |
372 | 426 |
373 void NotifyComponentObservers(ComponentObserver::Events event, | 427 void NotifyComponentObservers(ComponentObserver::Events event, |
374 int extra) const; | 428 int extra) const; |
375 | 429 |
376 bool HasOnDemandItems() const; | 430 bool HasOnDemandItems() const; |
377 | 431 |
| 432 void OnNewResourceThrottle(base::WeakPtr<CUResourceThrottle> rt, |
| 433 const std::string& crx_id); |
| 434 |
378 scoped_ptr<ComponentUpdateService::Configurator> config_; | 435 scoped_ptr<ComponentUpdateService::Configurator> config_; |
379 | 436 |
380 scoped_ptr<ComponentPatcher> component_patcher_; | 437 scoped_ptr<ComponentPatcher> component_patcher_; |
381 | 438 |
382 scoped_ptr<net::URLFetcher> url_fetcher_; | 439 scoped_ptr<net::URLFetcher> url_fetcher_; |
383 | 440 |
384 scoped_ptr<component_updater::PingManager> ping_manager_; | 441 scoped_ptr<component_updater::PingManager> ping_manager_; |
385 | 442 |
386 // A collection of every work item. | 443 // A collection of every work item. |
387 typedef std::vector<CrxUpdateItem*> UpdateItems; | 444 typedef std::vector<CrxUpdateItem*> UpdateItems; |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 break; | 609 break; |
553 case CrxUpdateItem::kNew: | 610 case CrxUpdateItem::kNew: |
554 case CrxUpdateItem::kChecking: | 611 case CrxUpdateItem::kChecking: |
555 case CrxUpdateItem::kDownloading: | 612 case CrxUpdateItem::kDownloading: |
556 case CrxUpdateItem::kDownloadingDiff: | 613 case CrxUpdateItem::kDownloadingDiff: |
557 case CrxUpdateItem::kLastStatus: | 614 case CrxUpdateItem::kLastStatus: |
558 // No notification for these states. | 615 // No notification for these states. |
559 break; | 616 break; |
560 } | 617 } |
561 } | 618 } |
| 619 |
| 620 // Free possible pending network requests. |
| 621 if ((to == CrxUpdateItem::kUpdated) || |
| 622 (to == CrxUpdateItem::kUpToDate) || |
| 623 (to == CrxUpdateItem::kNoUpdate)) { |
| 624 UnblockandReapAllThrottles(&item->throttles); |
| 625 } |
562 } | 626 } |
563 | 627 |
564 // Changes all the components in |work_items_| that have |from| status to | 628 // Changes all the components in |work_items_| that have |from| status to |
565 // |to| status and returns how many have been changed. | 629 // |to| status and returns how many have been changed. |
566 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from, | 630 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from, |
567 CrxUpdateItem::Status to) { | 631 CrxUpdateItem::Status to) { |
568 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 632 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
569 size_t count = 0; | 633 size_t count = 0; |
570 for (UpdateItems::iterator it = work_items_.begin(); | 634 for (UpdateItems::iterator it = work_items_.begin(); |
571 it != work_items_.end(); ++it) { | 635 it != work_items_.end(); ++it) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 item->diff_error_code = 0; | 705 item->diff_error_code = 0; |
642 item->diff_extra_code1 = 0; | 706 item->diff_extra_code1 = 0; |
643 return true; | 707 return true; |
644 } | 708 } |
645 | 709 |
646 // Start the process of checking for an update, for a particular component | 710 // Start the process of checking for an update, for a particular component |
647 // that was previously registered. | 711 // that was previously registered. |
648 // |component_id| is a value returned from GetCrxComponentID(). | 712 // |component_id| is a value returned from GetCrxComponentID(). |
649 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdate( | 713 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdate( |
650 const std::string& component_id) { | 714 const std::string& component_id) { |
651 CrxUpdateItem* uit; | 715 return OnDemandUpdateInternal(FindUpdateItemById(component_id)); |
652 uit = FindUpdateItemById(component_id); | 716 } |
| 717 |
| 718 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdateInternal( |
| 719 CrxUpdateItem* uit) { |
653 if (!uit) | 720 if (!uit) |
654 return kError; | 721 return kError; |
655 | |
656 // Check if the request is too soon. | 722 // Check if the request is too soon. |
657 base::TimeDelta delta = base::Time::Now() - uit->last_check; | 723 base::TimeDelta delta = base::Time::Now() - uit->last_check; |
658 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay())) | 724 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay())) |
659 return kError; | 725 return kError; |
660 | 726 |
661 switch (uit->status) { | 727 switch (uit->status) { |
662 // If the item is already in the process of being updated, there is | 728 // If the item is already in the process of being updated, there is |
663 // no point in this call, so return kInProgress. | 729 // no point in this call, so return kInProgress. |
664 case CrxUpdateItem::kChecking: | 730 case CrxUpdateItem::kChecking: |
665 case CrxUpdateItem::kCanUpdate: | 731 case CrxUpdateItem::kCanUpdate: |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 void CrxUpdateService::NotifyComponentObservers( | 1139 void CrxUpdateService::NotifyComponentObservers( |
1074 ComponentObserver::Events event, int extra) const { | 1140 ComponentObserver::Events event, int extra) const { |
1075 for (UpdateItems::const_iterator it = work_items_.begin(); | 1141 for (UpdateItems::const_iterator it = work_items_.begin(); |
1076 it != work_items_.end(); ++it) { | 1142 it != work_items_.end(); ++it) { |
1077 ComponentObserver* observer = (*it)->component.observer; | 1143 ComponentObserver* observer = (*it)->component.observer; |
1078 if (observer) | 1144 if (observer) |
1079 observer->OnEvent(event, 0); | 1145 observer->OnEvent(event, 0); |
1080 } | 1146 } |
1081 } | 1147 } |
1082 | 1148 |
| 1149 content::ResourceThrottle* CrxUpdateService::GetOnDemandResourceThrottle( |
| 1150 net::URLRequest* request, const std::string& crx_id) { |
| 1151 // We give the raw pointer to the caller, who will delete it at will |
| 1152 // and we keep for ourselves a weak pointer to it so we can post tasks |
| 1153 // from the UI thread without having to track lifetime directly. |
| 1154 CUResourceThrottle* rt = new CUResourceThrottle(request); |
| 1155 BrowserThread::PostTask( |
| 1156 BrowserThread::UI, |
| 1157 FROM_HERE, |
| 1158 base::Bind(&CrxUpdateService::OnNewResourceThrottle, |
| 1159 base::Unretained(this), |
| 1160 rt->AsWeakPtr(), |
| 1161 crx_id)); |
| 1162 return rt; |
| 1163 } |
| 1164 |
| 1165 void CrxUpdateService::OnNewResourceThrottle( |
| 1166 base::WeakPtr<CUResourceThrottle> rt, const std::string& crx_id) { |
| 1167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1168 // Check if we can on-demand update, else unblock the request anyway. |
| 1169 CrxUpdateItem* item = FindUpdateItemById(crx_id); |
| 1170 Status status = OnDemandUpdateInternal(item); |
| 1171 if (status == kOk || status == kInProgress) { |
| 1172 item->throttles.push_back(rt); |
| 1173 return; |
| 1174 } |
| 1175 UnblockResourceThrottle(rt); |
| 1176 } |
| 1177 |
| 1178 /////////////////////////////////////////////////////////////////////////////// |
| 1179 |
| 1180 CUResourceThrottle::CUResourceThrottle(const net::URLRequest* request) |
| 1181 : state_(NEW) { |
| 1182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 1183 } |
| 1184 |
| 1185 CUResourceThrottle::~CUResourceThrottle() { |
| 1186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 1187 } |
| 1188 |
| 1189 void CUResourceThrottle::WillStartRequest(bool* defer) { |
| 1190 if (state_ != UNBLOCKED) { |
| 1191 state_ = BLOCKED; |
| 1192 *defer = true; |
| 1193 } else { |
| 1194 *defer = false; |
| 1195 } |
| 1196 } |
| 1197 |
| 1198 void CUResourceThrottle::WillRedirectRequest(const GURL& new_url, bool* defer) { |
| 1199 WillStartRequest(defer); |
| 1200 } |
| 1201 |
| 1202 void CUResourceThrottle::Unblock() { |
| 1203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 1204 if (state_ == BLOCKED) |
| 1205 controller()->Resume(); |
| 1206 state_ = UNBLOCKED; |
| 1207 } |
| 1208 |
1083 // The component update factory. Using the component updater as a singleton | 1209 // The component update factory. Using the component updater as a singleton |
1084 // is the job of the browser process. | 1210 // is the job of the browser process. |
1085 ComponentUpdateService* ComponentUpdateServiceFactory( | 1211 ComponentUpdateService* ComponentUpdateServiceFactory( |
1086 ComponentUpdateService::Configurator* config) { | 1212 ComponentUpdateService::Configurator* config) { |
1087 DCHECK(config); | 1213 DCHECK(config); |
1088 return new CrxUpdateService(config); | 1214 return new CrxUpdateService(config); |
1089 } | 1215 } |
OLD | NEW |