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

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

Issue 25713007: Component updater on-demand logic with ResourceThrottle (Closed) Base URL: svn://chrome-svn/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/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/timer/timer.h" 24 #include "base/timer/timer.h"
24 #include "chrome/browser/browser_process.h" 25 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/component_updater/component_patcher.h" 26 #include "chrome/browser/component_updater/component_patcher.h"
26 #include "chrome/browser/component_updater/component_unpacker.h" 27 #include "chrome/browser/component_updater/component_unpacker.h"
27 #include "chrome/browser/component_updater/component_updater_ping_manager.h" 28 #include "chrome/browser/component_updater/component_updater_ping_manager.h"
28 #include "chrome/browser/component_updater/crx_update_item.h" 29 #include "chrome/browser/component_updater/crx_update_item.h"
29 #include "chrome/common/chrome_utility_messages.h" 30 #include "chrome/common/chrome_utility_messages.h"
30 #include "chrome/common/chrome_version_info.h" 31 #include "chrome/common/chrome_version_info.h"
31 #include "chrome/common/extensions/extension.h" 32 #include "chrome/common/extensions/extension.h"
32 #include "content/public/browser/browser_thread.h" 33 #include "content/public/browser/browser_thread.h"
34 #include "content/public/browser/resource_controller.h"
35 #include "content/public/browser/resource_throttle.h"
33 #include "content/public/browser/utility_process_host.h" 36 #include "content/public/browser/utility_process_host.h"
34 #include "content/public/browser/utility_process_host_client.h" 37 #include "content/public/browser/utility_process_host_client.h"
35 #include "net/base/escape.h" 38 #include "net/base/escape.h"
36 #include "net/base/load_flags.h" 39 #include "net/base/load_flags.h"
37 #include "net/base/net_errors.h" 40 #include "net/base/net_errors.h"
38 #include "net/url_request/url_fetcher.h" 41 #include "net/url_request/url_fetcher.h"
39 #include "net/url_request/url_fetcher_delegate.h" 42 #include "net/url_request/url_fetcher_delegate.h"
43 #include "net/url_request/url_request.h"
40 #include "net/url_request/url_request_status.h" 44 #include "net/url_request/url_request_status.h"
41 #include "url/gurl.h" 45 #include "url/gurl.h"
42 46
43 using content::BrowserThread; 47 using content::BrowserThread;
44 using content::UtilityProcessHost; 48 using content::UtilityProcessHost;
45 using content::UtilityProcessHostClient; 49 using content::UtilityProcessHostClient;
46 using extensions::Extension; 50 using extensions::Extension;
47 51
48 // The component updater is designed to live until process shutdown, so 52 // The component updater is designed to live until process shutdown, so
49 // base::Bind() calls are not refcounted. 53 // base::Bind() calls are not refcounted.
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 return HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0], 233 return HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0],
230 component.pk_hash.size()/2))); 234 component.pk_hash.size()/2)));
231 } 235 }
232 236
233 CrxComponentInfo::CrxComponentInfo() { 237 CrxComponentInfo::CrxComponentInfo() {
234 } 238 }
235 239
236 CrxComponentInfo::~CrxComponentInfo() { 240 CrxComponentInfo::~CrxComponentInfo() {
237 } 241 }
238 242
243 ///////////////////////////////////////////////////////////////////////////////
244 // In charge of blocking url requests until the |crx_id| component has been
245 // updated. This class is touched solely from the IO thread. The UI thread
246 // can post tasks to it via weak pointers. By default the request is blocked
247 // unless the CrxUpdateService calls Unblock().
248 class CUResourceThrottle
249 : public content::ResourceThrottle,
250 public base::SupportsWeakPtr<CUResourceThrottle> {
251 public:
252 explicit CUResourceThrottle(const net::URLRequest* request,
253 const char* crx_id);
254 virtual ~CUResourceThrottle();
255 // Overriden from ResourceThrottle.
256 virtual void WillStartRequest(bool* defer) OVERRIDE;
257 virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE;
258
259 void Unblock();
260
261 private:
262 enum State {
263 NEW,
264 BLOCKED,
265 UNBLOCKED
266 };
267
cpu_(ooo_6.6-7.5) 2013/10/30 18:15:41 it has 3 states because there is a strange require
268 std::string crx_id_;
269 State state_;
270 };
271
272 void UnblockResourceThrottle(base::WeakPtr<CUResourceThrottle> rt) {
273 BrowserThread::PostTask(
274 BrowserThread::IO,
275 FROM_HERE,
276 base::Bind(&CUResourceThrottle::Unblock, rt));
277 }
278
279 void UnblockandReapAllThrottles(
280 std::vector<base::WeakPtr<CUResourceThrottle>>* throttles) {
281 std::vector<base::WeakPtr<CUResourceThrottle>>::iterator it =
282 throttles->begin();
283 while (it != throttles->end()) {
284 UnblockResourceThrottle(*it);
285 ++it;
286 }
287 throttles->clear();
288 }
289
239 ////////////////////////////////////////////////////////////////////////////// 290 //////////////////////////////////////////////////////////////////////////////
240 // The one and only implementation of the ComponentUpdateService interface. In 291 // The one and only implementation of the ComponentUpdateService interface. In
241 // charge of running the show. The main method is ProcessPendingItems() which 292 // charge of running the show. The main method is ProcessPendingItems() which
242 // 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.
243 // 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
244 // 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
245 // 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
246 // 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_|
247 // in flight at a time. 298 // in flight at a time.
248 // 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
249 // 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
250 // 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
251 // thread. 302 // thread.
252 class CrxUpdateService : public ComponentUpdateService { 303 class CrxUpdateService : public ComponentUpdateService {
253 public: 304 public:
254 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); 305 explicit CrxUpdateService(ComponentUpdateService::Configurator* config);
255 306
256 virtual ~CrxUpdateService(); 307 virtual ~CrxUpdateService();
257 308
258 // Overrides for ComponentUpdateService. 309 // Overrides for ComponentUpdateService.
259 virtual Status Start() OVERRIDE; 310 virtual Status Start() OVERRIDE;
260 virtual Status Stop() OVERRIDE; 311 virtual Status Stop() OVERRIDE;
261 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE; 312 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE;
262 virtual Status OnDemandUpdate(const std::string& component_id) OVERRIDE; 313 virtual Status OnDemandUpdate(const std::string& component_id) OVERRIDE;
263 virtual void GetComponents( 314 virtual void GetComponents(
264 std::vector<CrxComponentInfo>* components) OVERRIDE; 315 std::vector<CrxComponentInfo>* components) OVERRIDE;
316 virtual content::ResourceThrottle* GetResourceThrottle(
317 net::URLRequest* request, const char* crx_id) OVERRIDE;
265 318
266 // The only purpose of this class is to forward the 319 // The only purpose of this class is to forward the
267 // UtilityProcessHostClient callbacks so CrxUpdateService does 320 // UtilityProcessHostClient callbacks so CrxUpdateService does
268 // not have to derive from it because that is refcounted. 321 // not have to derive from it because that is refcounted.
269 class ManifestParserBridge : public UtilityProcessHostClient { 322 class ManifestParserBridge : public UtilityProcessHostClient {
270 public: 323 public:
271 explicit ManifestParserBridge(CrxUpdateService* service) 324 explicit ManifestParserBridge(CrxUpdateService* service)
272 : service_(service) {} 325 : service_(service) {}
273 326
274 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
335 }; 388 };
336 389
337 // See ManifestParserBridge. 390 // See ManifestParserBridge.
338 void OnParseUpdateManifestSucceeded(const UpdateManifest::Results& results); 391 void OnParseUpdateManifestSucceeded(const UpdateManifest::Results& results);
339 392
340 // See ManifestParserBridge. 393 // See ManifestParserBridge.
341 void OnParseUpdateManifestFailed(const std::string& error_message); 394 void OnParseUpdateManifestFailed(const std::string& error_message);
342 395
343 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query); 396 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query);
344 397
398 Status OnDemandUpdateInternal(CrxUpdateItem* item);
399
345 void ProcessPendingItems(); 400 void ProcessPendingItems();
346 401
347 CrxUpdateItem* FindReadyComponent(); 402 CrxUpdateItem* FindReadyComponent();
348 403
349 void UpdateComponent(CrxUpdateItem* workitem); 404 void UpdateComponent(CrxUpdateItem* workitem);
350 405
351 void AddUpdateCheckItems(std::string* query); 406 void AddUpdateCheckItems(std::string* query);
352 407
353 void DoUpdateCheck(const std::string& query); 408 void DoUpdateCheck(const std::string& query);
354 409
(...skipping 12 matching lines...) Expand all
367 size_t ChangeItemStatus(CrxUpdateItem::Status from, 422 size_t ChangeItemStatus(CrxUpdateItem::Status from,
368 CrxUpdateItem::Status to); 423 CrxUpdateItem::Status to);
369 424
370 CrxUpdateItem* FindUpdateItemById(const std::string& id); 425 CrxUpdateItem* FindUpdateItemById(const std::string& id);
371 426
372 void NotifyComponentObservers(ComponentObserver::Events event, 427 void NotifyComponentObservers(ComponentObserver::Events event,
373 int extra) const; 428 int extra) const;
374 429
375 bool HasOnDemandItems() const; 430 bool HasOnDemandItems() const;
376 431
432 void OnNewResourceThrottle(base::WeakPtr<CUResourceThrottle> rt,
433 const char* crx_id);
434
377 scoped_ptr<ComponentUpdateService::Configurator> config_; 435 scoped_ptr<ComponentUpdateService::Configurator> config_;
378 436
379 scoped_ptr<ComponentPatcher> component_patcher_; 437 scoped_ptr<ComponentPatcher> component_patcher_;
380 438
381 scoped_ptr<net::URLFetcher> url_fetcher_; 439 scoped_ptr<net::URLFetcher> url_fetcher_;
382 440
383 scoped_ptr<component_updater::PingManager> ping_manager_; 441 scoped_ptr<component_updater::PingManager> ping_manager_;
384 442
385 // A collection of every work item. 443 // A collection of every work item.
386 typedef std::vector<CrxUpdateItem*> UpdateItems; 444 typedef std::vector<CrxUpdateItem*> UpdateItems;
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 switch (to) { 589 switch (to) {
532 case CrxUpdateItem::kCanUpdate: 590 case CrxUpdateItem::kCanUpdate:
533 observer->OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0); 591 observer->OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0);
534 break; 592 break;
535 case CrxUpdateItem::kUpdatingDiff: 593 case CrxUpdateItem::kUpdatingDiff:
536 case CrxUpdateItem::kUpdating: 594 case CrxUpdateItem::kUpdating:
537 observer->OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0); 595 observer->OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0);
538 break; 596 break;
539 case CrxUpdateItem::kUpdated: 597 case CrxUpdateItem::kUpdated:
540 observer->OnEvent(ComponentObserver::COMPONENT_UPDATED, 0); 598 observer->OnEvent(ComponentObserver::COMPONENT_UPDATED, 0);
599 UnblockandReapAllThrottles(&item->throttles);
jvoung (off chromium) 2013/10/30 18:50:41 is there a missing file in the patch (crx_update_i
541 break; 600 break;
542 case CrxUpdateItem::kUpToDate: 601 case CrxUpdateItem::kUpToDate:
543 case CrxUpdateItem::kNoUpdate: 602 case CrxUpdateItem::kNoUpdate:
544 observer->OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0); 603 observer->OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0);
604 UnblockandReapAllThrottles(&item->throttles);
545 break; 605 break;
546 case CrxUpdateItem::kNew: 606 case CrxUpdateItem::kNew:
547 case CrxUpdateItem::kChecking: 607 case CrxUpdateItem::kChecking:
548 case CrxUpdateItem::kDownloading: 608 case CrxUpdateItem::kDownloading:
549 case CrxUpdateItem::kDownloadingDiff: 609 case CrxUpdateItem::kDownloadingDiff:
550 case CrxUpdateItem::kLastStatus: 610 case CrxUpdateItem::kLastStatus:
551 // No notification for these states. 611 // No notification for these states.
552 break; 612 break;
cpu_(ooo_6.6-7.5) 2013/10/30 18:15:41 Did I got all the cases in 599 and 604? I think so
553 } 613 }
554 } 614 }
555 } 615 }
556 616
557 // Changes all the components in |work_items_| that have |from| status to 617 // Changes all the components in |work_items_| that have |from| status to
558 // |to| status and returns how many have been changed. 618 // |to| status and returns how many have been changed.
559 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from, 619 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from,
560 CrxUpdateItem::Status to) { 620 CrxUpdateItem::Status to) {
561 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 621 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
562 size_t count = 0; 622 size_t count = 0;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 item->diff_error_code = 0; 694 item->diff_error_code = 0;
635 item->diff_extra_code1 = 0; 695 item->diff_extra_code1 = 0;
636 return true; 696 return true;
637 } 697 }
638 698
639 // Start the process of checking for an update, for a particular component 699 // Start the process of checking for an update, for a particular component
640 // that was previously registered. 700 // that was previously registered.
641 // |component_id| is a value returned from GetCrxComponentID(). 701 // |component_id| is a value returned from GetCrxComponentID().
642 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdate( 702 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdate(
643 const std::string& component_id) { 703 const std::string& component_id) {
644 CrxUpdateItem* uit; 704 return OnDemandUpdateInternal(FindUpdateItemById(component_id));
645 uit = FindUpdateItemById(component_id); 705 }
706
707 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdateInternal(
708 CrxUpdateItem* uit) {
646 if (!uit) 709 if (!uit)
647 return kError; 710 return kError;
648
649 // Check if the request is too soon. 711 // Check if the request is too soon.
650 base::TimeDelta delta = base::Time::Now() - uit->last_check; 712 base::TimeDelta delta = base::Time::Now() - uit->last_check;
651 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay())) 713 if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay()))
652 return kError; 714 return kError;
653 715
654 switch (uit->status) { 716 switch (uit->status) {
655 // If the item is already in the process of being updated, there is 717 // If the item is already in the process of being updated, there is
656 // no point in this call, so return kInProgress. 718 // no point in this call, so return kInProgress.
657 case CrxUpdateItem::kChecking: 719 case CrxUpdateItem::kChecking:
658 case CrxUpdateItem::kCanUpdate: 720 case CrxUpdateItem::kCanUpdate:
(...skipping 17 matching lines...) Expand all
676 738
677 // In case the current delay is long, set the timer to a shorter value 739 // In case the current delay is long, set the timer to a shorter value
678 // to get the ball rolling. 740 // to get the ball rolling.
679 if (timer_.IsRunning()) { 741 if (timer_.IsRunning()) {
680 timer_.Stop(); 742 timer_.Stop();
681 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(config_->StepDelay()), 743 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(config_->StepDelay()),
682 this, &CrxUpdateService::ProcessPendingItems); 744 this, &CrxUpdateService::ProcessPendingItems);
683 } 745 }
684 746
685 return kOk; 747 return kOk;
748
686 } 749 }
687 750
688 void CrxUpdateService::GetComponents( 751 void CrxUpdateService::GetComponents(
689 std::vector<CrxComponentInfo>* components) { 752 std::vector<CrxComponentInfo>* components) {
690 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 753 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
691 for (UpdateItems::const_iterator it = work_items_.begin(); 754 for (UpdateItems::const_iterator it = work_items_.begin();
692 it != work_items_.end(); ++it) { 755 it != work_items_.end(); ++it) {
693 const CrxUpdateItem* item = *it; 756 const CrxUpdateItem* item = *it;
694 CrxComponentInfo info; 757 CrxComponentInfo info;
695 info.id = GetCrxComponentID(item->component); 758 info.id = GetCrxComponentID(item->component);
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 void CrxUpdateService::NotifyComponentObservers( 1125 void CrxUpdateService::NotifyComponentObservers(
1063 ComponentObserver::Events event, int extra) const { 1126 ComponentObserver::Events event, int extra) const {
1064 for (UpdateItems::const_iterator it = work_items_.begin(); 1127 for (UpdateItems::const_iterator it = work_items_.begin();
1065 it != work_items_.end(); ++it) { 1128 it != work_items_.end(); ++it) {
1066 ComponentObserver* observer = (*it)->component.observer; 1129 ComponentObserver* observer = (*it)->component.observer;
1067 if (observer) 1130 if (observer)
1068 observer->OnEvent(event, 0); 1131 observer->OnEvent(event, 0);
1069 } 1132 }
1070 } 1133 }
1071 1134
1135 content::ResourceThrottle* CrxUpdateService::GetResourceThrottle(
1136 net::URLRequest* request, const char* crx_id) {
1137 // We give the raw pointer to the caller, who will delete it at will
1138 // and we keep for ourselves a weak pointer to it so we can post tasks
1139 // from the UI thread without having to track lifetime directly.
1140 CUResourceThrottle* rt = new CUResourceThrottle(request, crx_id);
1141 BrowserThread::PostTask(
1142 BrowserThread::UI,
1143 FROM_HERE,
1144 base::Bind(&CrxUpdateService::OnNewResourceThrottle,
1145 base::Unretained(this),
1146 rt->AsWeakPtr(),
1147 crx_id));
1148 return rt;
1149 }
1150
1151 void CrxUpdateService::OnNewResourceThrottle(
1152 base::WeakPtr<CUResourceThrottle> rt, const char* crx_id) {
1153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1154 // Check if we can on-demand update, else unblock the request anyway.
1155 CrxUpdateItem* item = FindUpdateItemById(crx_id);
1156 Status status = OnDemandUpdateInternal(item);
1157 if (status == kOk || status == kInProgress) {
1158 item->throttles.push_back(rt);
1159 return;
1160 }
1161 UnblockResourceThrottle(rt);
1162 }
1163
1164 ///////////////////////////////////////////////////////////////////////////////
1165
1166 CUResourceThrottle::CUResourceThrottle(
1167 const net::URLRequest* request, const char* crx_id)
1168 : crx_id_(crx_id), state_(NEW) {
1169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1170 }
1171
1172 CUResourceThrottle::~CUResourceThrottle() {
1173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1174 }
1175
1176 void CUResourceThrottle::WillStartRequest(bool* defer) {
1177 if (state_ != UNBLOCKED) {
1178 state_ = BLOCKED;
1179 *defer = true;
1180 } else {
1181 *defer = false;
1182 }
1183 }
1184
1185 void CUResourceThrottle::WillRedirectRequest(const GURL& new_url, bool* defer) {
1186 WillStartRequest(defer);
1187 }
1188
1189 void CUResourceThrottle::Unblock() {
1190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1191 if (state_ == BLOCKED)
1192 controller()->Resume();
1193 state_ = UNBLOCKED;
cpu_(ooo_6.6-7.5) 2013/10/30 18:15:41 if I Resume() without have been blocked it trigger
1194 }
1195
1072 // The component update factory. Using the component updater as a singleton 1196 // The component update factory. Using the component updater as a singleton
1073 // is the job of the browser process. 1197 // is the job of the browser process.
1074 ComponentUpdateService* ComponentUpdateServiceFactory( 1198 ComponentUpdateService* ComponentUpdateServiceFactory(
1075 ComponentUpdateService::Configurator* config) { 1199 ComponentUpdateService::Configurator* config) {
1076 DCHECK(config); 1200 DCHECK(config);
1077 return new CrxUpdateService(config); 1201 return new CrxUpdateService(config);
1078 } 1202 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698