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