- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / component_updater / component_updater_service.cc
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/component_updater/component_updater_service.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <vector>
10
11 #include "base/at_exit.h"
12 #include "base/bind.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/logging.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_piece.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/threading/sequenced_worker_pool.h"
25 #include "base/timer/timer.h"
26 #include "chrome/browser/browser_process.h"
27 #include "chrome/browser/component_updater/component_patcher.h"
28 #include "chrome/browser/component_updater/component_unpacker.h"
29 #include "chrome/browser/component_updater/component_updater_ping_manager.h"
30 #include "chrome/browser/component_updater/crx_update_item.h"
31 #include "chrome/common/chrome_utility_messages.h"
32 #include "chrome/common/chrome_version_info.h"
33 #include "chrome/common/extensions/extension.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"
37 #include "content/public/browser/utility_process_host.h"
38 #include "content/public/browser/utility_process_host_client.h"
39 #include "net/base/escape.h"
40 #include "net/base/load_flags.h"
41 #include "net/base/net_errors.h"
42 #include "net/url_request/url_fetcher.h"
43 #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"
46 #include "url/gurl.h"
47
48 using content::BrowserThread;
49 using content::UtilityProcessHost;
50 using content::UtilityProcessHostClient;
51 using extensions::Extension;
52
53 // The component updater is designed to live until process shutdown, so
54 // base::Bind() calls are not refcounted.
55
56 namespace {
57
58 // Extends an omaha compatible update check url |query| string. Does
59 // not mutate the string if it would be longer than |limit| chars.
60 bool AddQueryString(const std::string& id,
61                     const std::string& version,
62                     const std::string& fingerprint,
63                     bool ondemand,
64                     size_t limit,
65                     std::string* query) {
66   std::string additional =
67       base::StringPrintf("id=%s&v=%s&fp=%s&uc%s",
68                          id.c_str(),
69                          version.c_str(),
70                          fingerprint.c_str(),
71                          ondemand ? "&installsource=ondemand" : "");
72   additional = "x=" + net::EscapeQueryParamValue(additional, true);
73   if ((additional.size() + query->size() + 1) > limit)
74     return false;
75   if (!query->empty())
76     query->append(1, '&');
77   query->append(additional);
78   return true;
79 }
80
81 // Create the final omaha compatible query. The |extra| is optional and can
82 // be null. It should contain top level (non-escaped) parameters.
83 std::string MakeFinalQuery(const std::string& host,
84                            const std::string& query,
85                            const char* extra) {
86   std::string request(host);
87   request.append(1, '?');
88   if (extra) {
89     request.append(extra);
90     request.append(1, '&');
91   }
92   request.append(query);
93   return request;
94 }
95
96 // Produces an extension-like friendly |id|. This might be removed in the
97 // future if we roll our on packing tools.
98 static std::string HexStringToID(const std::string& hexstr) {
99   std::string id;
100   for (size_t i = 0; i < hexstr.size(); ++i) {
101     int val;
102     if (base::HexStringToInt(base::StringPiece(hexstr.begin() + i,
103                                                hexstr.begin() + i + 1),
104                              &val)) {
105       id.append(1, val + 'a');
106     } else {
107       id.append(1, 'a');
108     }
109   }
110   DCHECK(Extension::IdIsValid(id));
111   return id;
112 }
113
114 // Helper to do version check for components.
115 bool IsVersionNewer(const Version& current, const std::string& proposed) {
116   Version proposed_ver(proposed);
117   if (!proposed_ver.IsValid())
118     return false;
119   return (current.CompareTo(proposed_ver) < 0);
120 }
121
122 // Helper template class that allows our main class to have separate
123 // OnURLFetchComplete() callbacks for different types of url requests
124 // they are differentiated by the |Ctx| type.
125 template <typename Del, typename Ctx>
126 class DelegateWithContext : public net::URLFetcherDelegate {
127  public:
128   DelegateWithContext(Del* delegate, Ctx* context)
129     : delegate_(delegate), context_(context) {}
130
131   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
132     delegate_->OnURLFetchComplete(source, context_);
133     delete this;
134   }
135
136  private:
137   ~DelegateWithContext() {}
138
139   Del* delegate_;
140   Ctx* context_;
141 };
142 // This function creates the right DelegateWithContext using template inference.
143 template <typename Del, typename Ctx>
144 net::URLFetcherDelegate* MakeContextDelegate(Del* delegate, Ctx* context) {
145   return new DelegateWithContext<Del, Ctx>(delegate, context);
146 }
147
148 // Helper to start a url request using |fetcher| with the common flags.
149 void StartFetch(net::URLFetcher* fetcher,
150                 net::URLRequestContextGetter* context_getter,
151                 bool save_to_file,
152                 scoped_refptr<base::SequencedTaskRunner> task_runner) {
153   fetcher->SetRequestContext(context_getter);
154   fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
155                         net::LOAD_DO_NOT_SAVE_COOKIES |
156                         net::LOAD_DISABLE_CACHE);
157   // TODO(cpu): Define our retry and backoff policy.
158   fetcher->SetAutomaticallyRetryOn5xx(false);
159   if (save_to_file) {
160     fetcher->SaveResponseToTemporaryFile(task_runner);
161   }
162   fetcher->Start();
163 }
164
165 // Returns true if the url request of |fetcher| was succesful.
166 bool FetchSuccess(const net::URLFetcher& fetcher) {
167   return (fetcher.GetStatus().status() == net::URLRequestStatus::SUCCESS) &&
168          (fetcher.GetResponseCode() == 200);
169 }
170
171 // Returns the error code which occured during the fetch.The function returns 0
172 // if the fetch was successful. If errors happen, the function could return a
173 // network error, an http response code, or the status of the fetch, if the
174 // fetch is pending or canceled.
175 int GetFetchError(const net::URLFetcher& fetcher) {
176   if (FetchSuccess(fetcher))
177     return 0;
178
179   const net::URLRequestStatus::Status status(fetcher.GetStatus().status());
180   if (status == net::URLRequestStatus::FAILED)
181     return fetcher.GetStatus().error();
182
183   if (status == net::URLRequestStatus::IO_PENDING ||
184       status == net::URLRequestStatus::CANCELED)
185     return status;
186
187   const int response_code(fetcher.GetResponseCode());
188   if (status == net::URLRequestStatus::SUCCESS && response_code != 200)
189     return response_code;
190
191   return -1;
192   }
193
194 // Returns true if a differential update is available for the update item.
195 bool IsDiffUpdateAvailable(const CrxUpdateItem* update_item) {
196   return update_item->diff_crx_url.is_valid();
197 }
198
199 // Returns true if a differential update is available, it has not failed yet,
200 // and the configuration allows it.
201 bool CanTryDiffUpdate(const CrxUpdateItem* update_item,
202                       const ComponentUpdateService::Configurator& config) {
203   return IsDiffUpdateAvailable(update_item) &&
204          !update_item->diff_update_failed &&
205          config.DeltasEnabled();
206 }
207
208 }  // namespace
209
210 CrxUpdateItem::CrxUpdateItem()
211     : status(kNew),
212       on_demand(false),
213       diff_update_failed(false),
214       error_category(0),
215       error_code(0),
216       extra_code1(0),
217       diff_error_category(0),
218       diff_error_code(0),
219       diff_extra_code1(0) {
220 }
221
222 CrxUpdateItem::~CrxUpdateItem() {
223 }
224
225 CrxComponent::CrxComponent()
226     : installer(NULL),
227       observer(NULL) {
228 }
229
230 CrxComponent::~CrxComponent() {
231 }
232
233 std::string GetCrxComponentID(const CrxComponent& component) {
234   return HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0],
235                                           component.pk_hash.size()/2)));
236 }
237
238 CrxComponentInfo::CrxComponentInfo() {
239 }
240
241 CrxComponentInfo::~CrxComponentInfo() {
242 }
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
290 //////////////////////////////////////////////////////////////////////////////
291 // The one and only implementation of the ComponentUpdateService interface. In
292 // charge of running the show. The main method is ProcessPendingItems() which
293 // 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
295 // 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
297 // the tasks. Also when we do network requests there is only one |url_fetcher_|
298 // in flight at a time.
299 // 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
301 // thread and the network requests are done in the IO thread and in the file
302 // thread.
303 class CrxUpdateService : public ComponentUpdateService {
304  public:
305   explicit CrxUpdateService(ComponentUpdateService::Configurator* config);
306
307   virtual ~CrxUpdateService();
308
309   // Overrides for ComponentUpdateService.
310   virtual Status Start() OVERRIDE;
311   virtual Status Stop() OVERRIDE;
312   virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE;
313   virtual Status OnDemandUpdate(const std::string& component_id) OVERRIDE;
314   virtual void GetComponents(
315       std::vector<CrxComponentInfo>* components) OVERRIDE;
316   virtual content::ResourceThrottle* GetOnDemandResourceThrottle(
317       net::URLRequest* request, const std::string& crx_id) OVERRIDE;
318
319   // The only purpose of this class is to forward the
320   // UtilityProcessHostClient callbacks so CrxUpdateService does
321   // not have to derive from it because that is refcounted.
322   class ManifestParserBridge : public UtilityProcessHostClient {
323    public:
324     explicit ManifestParserBridge(CrxUpdateService* service)
325         : service_(service) {}
326
327     virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
328       bool handled = true;
329       IPC_BEGIN_MESSAGE_MAP(ManifestParserBridge, message)
330         IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseUpdateManifest_Succeeded,
331                             OnParseUpdateManifestSucceeded)
332         IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseUpdateManifest_Failed,
333                             OnParseUpdateManifestFailed)
334         IPC_MESSAGE_UNHANDLED(handled = false)
335       IPC_END_MESSAGE_MAP()
336       return handled;
337     }
338
339    private:
340     virtual ~ManifestParserBridge() {}
341
342     // Omaha update response XML was successfully parsed.
343     void OnParseUpdateManifestSucceeded(const UpdateManifest::Results& r) {
344       service_->OnParseUpdateManifestSucceeded(r);
345     }
346     // Omaha update response XML could not be parsed.
347     void OnParseUpdateManifestFailed(const std::string& e) {
348       service_->OnParseUpdateManifestFailed(e);
349     }
350
351     CrxUpdateService* service_;
352     DISALLOW_COPY_AND_ASSIGN(ManifestParserBridge);
353   };
354
355   // Context for a update check url request. See DelegateWithContext above.
356   struct UpdateContext {
357     base::Time start;
358     UpdateContext() : start(base::Time::Now()) {}
359   };
360
361   // Context for a crx download url request. See DelegateWithContext above.
362   struct CRXContext {
363     ComponentInstaller* installer;
364     std::vector<uint8> pk_hash;
365     std::string id;
366     std::string fingerprint;
367     CRXContext() : installer(NULL) {}
368   };
369
370   void OnURLFetchComplete(const net::URLFetcher* source,
371                           UpdateContext* context);
372
373   void OnURLFetchComplete(const net::URLFetcher* source,
374                           CRXContext* context);
375
376  private:
377   enum ErrorCategory {
378     kErrorNone = 0,
379     kNetworkError,
380     kUnpackError,
381     kInstallError,
382   };
383
384   enum StepDelayInterval {
385     kStepDelayShort = 0,
386     kStepDelayMedium,
387     kStepDelayLong,
388   };
389
390   // See ManifestParserBridge.
391   void OnParseUpdateManifestSucceeded(const UpdateManifest::Results& results);
392
393   // See ManifestParserBridge.
394   void OnParseUpdateManifestFailed(const std::string& error_message);
395
396   bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query);
397
398   Status OnDemandUpdateInternal(CrxUpdateItem* item);
399
400   void ProcessPendingItems();
401
402   CrxUpdateItem* FindReadyComponent();
403
404   void UpdateComponent(CrxUpdateItem* workitem);
405
406   void AddUpdateCheckItems(std::string* query);
407
408   void DoUpdateCheck(const std::string& query);
409
410   void ScheduleNextRun(StepDelayInterval step_delay);
411
412   void ParseManifest(const std::string& xml);
413
414   void Install(const CRXContext* context, const base::FilePath& crx_path);
415
416   void DoneInstalling(const std::string& component_id,
417                       ComponentUnpacker::Error error,
418                       int extended_error);
419
420   void ChangeItemState(CrxUpdateItem* item, CrxUpdateItem::Status to);
421
422   size_t ChangeItemStatus(CrxUpdateItem::Status from,
423                           CrxUpdateItem::Status to);
424
425   CrxUpdateItem* FindUpdateItemById(const std::string& id);
426
427   void NotifyComponentObservers(ComponentObserver::Events event,
428                                 int extra) const;
429
430   bool HasOnDemandItems() const;
431
432   void OnNewResourceThrottle(base::WeakPtr<CUResourceThrottle> rt,
433                              const std::string& crx_id);
434
435   scoped_ptr<ComponentUpdateService::Configurator> config_;
436
437   scoped_ptr<ComponentPatcher> component_patcher_;
438
439   scoped_ptr<net::URLFetcher> url_fetcher_;
440
441   scoped_ptr<component_updater::PingManager> ping_manager_;
442
443   // A collection of every work item.
444   typedef std::vector<CrxUpdateItem*> UpdateItems;
445   UpdateItems work_items_;
446
447   base::OneShotTimer<CrxUpdateService> timer_;
448
449   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
450
451   const Version chrome_version_;
452
453   bool running_;
454
455   DISALLOW_COPY_AND_ASSIGN(CrxUpdateService);
456 };
457
458 //////////////////////////////////////////////////////////////////////////////
459
460 CrxUpdateService::CrxUpdateService(ComponentUpdateService::Configurator* config)
461     : config_(config),
462       component_patcher_(config->CreateComponentPatcher()),
463       ping_manager_(new component_updater::PingManager(
464           config->PingUrl(),
465           config->RequestContext())),
466       blocking_task_runner_(BrowserThread::GetBlockingPool()->
467           GetSequencedTaskRunnerWithShutdownBehavior(
468               BrowserThread::GetBlockingPool()->GetSequenceToken(),
469               base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
470       chrome_version_(chrome::VersionInfo().Version()),
471       running_(false) {
472 }
473
474 CrxUpdateService::~CrxUpdateService() {
475   // Because we are a singleton, at this point only the UI thread should be
476   // alive, this simplifies the management of the work that could be in
477   // flight in other threads.
478   Stop();
479   STLDeleteElements(&work_items_);
480 }
481
482 ComponentUpdateService::Status CrxUpdateService::Start() {
483   // Note that RegisterComponent will call Start() when the first
484   // component is registered, so it can be called twice. This way
485   // we avoid scheduling the timer if there is no work to do.
486   running_ = true;
487   if (work_items_.empty())
488     return kOk;
489
490   NotifyComponentObservers(ComponentObserver::COMPONENT_UPDATER_STARTED, 0);
491
492   timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(config_->InitialDelay()),
493                this, &CrxUpdateService::ProcessPendingItems);
494   return kOk;
495 }
496
497 // Stop the main check + update loop. In flight operations will be
498 // completed.
499 ComponentUpdateService::Status CrxUpdateService::Stop() {
500   running_ = false;
501   timer_.Stop();
502   return kOk;
503 }
504
505 bool CrxUpdateService::HasOnDemandItems() const {
506   class Helper {
507    public:
508     static bool IsOnDemand(CrxUpdateItem* item) {
509       return item->on_demand;
510     }
511   };
512   return std::find_if(work_items_.begin(),
513                       work_items_.end(),
514                       Helper::IsOnDemand) != work_items_.end();
515 }
516
517 // This function sets the timer which will call ProcessPendingItems() or
518 // ProcessRequestedItem() if there is an on_demand item.  There
519 // are three kinds of waits:
520 //  - a short delay, when there is immediate work to be done.
521 //  - a medium delay, when there are updates to be applied within the current
522 //    update cycle, or there are components that are still unchecked.
523 //  - a long delay when a full check/update cycle has completed for all
524 //    components.
525 void CrxUpdateService::ScheduleNextRun(StepDelayInterval step_delay) {
526   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
527   DCHECK(url_fetcher_.get() == NULL);
528   CHECK(!timer_.IsRunning());
529   // It could be the case that Stop() had been called while a url request
530   // or unpacking was in flight, if so we arrive here but |running_| is
531   // false. In that case do not loop again.
532   if (!running_)
533     return;
534
535   // Keep the delay short if in the middle of an update (step_delay),
536   // or there are new requested_work_items_ that have not been processed yet.
537   int64 delay_seconds = 0;
538   if (!HasOnDemandItems()) {
539     switch (step_delay) {
540       case kStepDelayShort:
541         delay_seconds = config_->StepDelay();
542         break;
543       case kStepDelayMedium:
544         delay_seconds = config_->StepDelayMedium();
545         break;
546       case kStepDelayLong:
547         delay_seconds = config_->NextCheckDelay();
548         break;
549     }
550   } else {
551     delay_seconds = config_->StepDelay();
552   }
553
554   if (step_delay != kStepDelayShort) {
555     NotifyComponentObservers(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0);
556
557     // Zero is only used for unit tests.
558     if (0 == delay_seconds)
559       return;
560   }
561
562   timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(delay_seconds),
563                this, &CrxUpdateService::ProcessPendingItems);
564 }
565
566 // Given a extension-like component id, find the associated component.
567 CrxUpdateItem* CrxUpdateService::FindUpdateItemById(const std::string& id) {
568   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
569   CrxUpdateItem::FindById finder(id);
570   UpdateItems::iterator it = std::find_if(work_items_.begin(),
571                                           work_items_.end(),
572                                           finder);
573   if (it == work_items_.end())
574     return NULL;
575   return (*it);
576 }
577
578 // Changes a component's status, clearing on_demand and firing notifications as
579 // necessary. By convention, this is the only function that can change a
580 // CrxUpdateItem's |status|.
581 // TODO(waffles): Do we want to add DCHECKS for valid state transitions here?
582 void CrxUpdateService::ChangeItemState(CrxUpdateItem* item,
583                                        CrxUpdateItem::Status to) {
584   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
585   if (to == CrxUpdateItem::kNoUpdate ||
586       to == CrxUpdateItem::kUpdated ||
587       to == CrxUpdateItem::kUpToDate) {
588     item->on_demand = false;
589   }
590
591   item->status = to;
592
593   ComponentObserver* observer = item->component.observer;
594   if (observer) {
595     switch (to) {
596       case CrxUpdateItem::kCanUpdate:
597         observer->OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0);
598         break;
599       case CrxUpdateItem::kUpdatingDiff:
600       case CrxUpdateItem::kUpdating:
601         observer->OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0);
602         break;
603       case CrxUpdateItem::kUpdated:
604         observer->OnEvent(ComponentObserver::COMPONENT_UPDATED, 0);
605         break;
606       case CrxUpdateItem::kUpToDate:
607       case CrxUpdateItem::kNoUpdate:
608         observer->OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0);
609         break;
610       case CrxUpdateItem::kNew:
611       case CrxUpdateItem::kChecking:
612       case CrxUpdateItem::kDownloading:
613       case CrxUpdateItem::kDownloadingDiff:
614       case CrxUpdateItem::kLastStatus:
615         // No notification for these states.
616         break;
617     }
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   }
626 }
627
628 // Changes all the components in |work_items_| that have |from| status to
629 // |to| status and returns how many have been changed.
630 size_t CrxUpdateService::ChangeItemStatus(CrxUpdateItem::Status from,
631                                           CrxUpdateItem::Status to) {
632   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
633   size_t count = 0;
634   for (UpdateItems::iterator it = work_items_.begin();
635        it != work_items_.end(); ++it) {
636     CrxUpdateItem* item = *it;
637     if (item->status != from)
638       continue;
639     ChangeItemState(item, to);
640     ++count;
641   }
642   return count;
643 }
644
645 // Adds a component to be checked for upgrades. If the component exists it
646 // it will be replaced and the return code is kReplaced.
647 //
648 // TODO(cpu): Evaluate if we want to support un-registration.
649 ComponentUpdateService::Status CrxUpdateService::RegisterComponent(
650     const CrxComponent& component) {
651   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
652   if (component.pk_hash.empty() ||
653       !component.version.IsValid() ||
654       !component.installer)
655     return kError;
656
657   std::string id =
658     HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0],
659                                      component.pk_hash.size()/2)));
660   CrxUpdateItem* uit;
661   uit = FindUpdateItemById(id);
662   if (uit) {
663     uit->component = component;
664     return kReplaced;
665   }
666
667   uit = new CrxUpdateItem;
668   uit->id.swap(id);
669   uit->component = component;
670
671   work_items_.push_back(uit);
672   // If this is the first component registered we call Start to
673   // schedule the first timer.
674   if (running_ && (work_items_.size() == 1))
675     Start();
676
677   return kOk;
678 }
679
680 // Sets a component to be checked for updates.
681 // The component to add is |item| and the |query| string is modified with the
682 // required omaha compatible query. Returns false when the query string is
683 // longer than specified by UrlSizeLimit().
684 bool CrxUpdateService::AddItemToUpdateCheck(CrxUpdateItem* item,
685                                             std::string* query) {
686   if (!AddQueryString(item->id,
687                       item->component.version.GetString(),
688                       item->component.fingerprint,
689                       item->on_demand,
690                       config_->UrlSizeLimit(),
691                       query))
692     return false;
693
694   ChangeItemState(item, CrxUpdateItem::kChecking);
695   item->last_check = base::Time::Now();
696   item->previous_version = item->component.version;
697   item->next_version = Version();
698   item->previous_fp = item->component.fingerprint;
699   item->next_fp.clear();
700   item->diff_update_failed = false;
701   item->error_category = 0;
702   item->error_code = 0;
703   item->extra_code1 = 0;
704   item->diff_error_category = 0;
705   item->diff_error_code = 0;
706   item->diff_extra_code1 = 0;
707   return true;
708 }
709
710 // Start the process of checking for an update, for a particular component
711 // that was previously registered.
712 // |component_id| is a value returned from GetCrxComponentID().
713 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdate(
714     const std::string& component_id) {
715   return OnDemandUpdateInternal(FindUpdateItemById(component_id));
716 }
717
718 ComponentUpdateService::Status CrxUpdateService::OnDemandUpdateInternal(
719     CrxUpdateItem* uit) {
720   if (!uit)
721     return kError;
722   // Check if the request is too soon.
723   base::TimeDelta delta = base::Time::Now() - uit->last_check;
724   if (delta < base::TimeDelta::FromSeconds(config_->OnDemandDelay()))
725     return kError;
726
727   switch (uit->status) {
728     // If the item is already in the process of being updated, there is
729     // no point in this call, so return kInProgress.
730     case CrxUpdateItem::kChecking:
731     case CrxUpdateItem::kCanUpdate:
732     case CrxUpdateItem::kDownloadingDiff:
733     case CrxUpdateItem::kDownloading:
734     case CrxUpdateItem::kUpdatingDiff:
735     case CrxUpdateItem::kUpdating:
736       return kInProgress;
737     // Otherwise the item was already checked a while back (or it is new),
738     // set its status to kNew to give it a slightly higher priority.
739     case CrxUpdateItem::kNew:
740     case CrxUpdateItem::kUpdated:
741     case CrxUpdateItem::kUpToDate:
742     case CrxUpdateItem::kNoUpdate:
743       ChangeItemState(uit, CrxUpdateItem::kNew);
744       uit->on_demand = true;
745       break;
746     case CrxUpdateItem::kLastStatus:
747       NOTREACHED() << uit->status;
748   }
749
750   // In case the current delay is long, set the timer to a shorter value
751   // to get the ball rolling.
752   if (timer_.IsRunning()) {
753     timer_.Stop();
754     timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(config_->StepDelay()),
755                  this, &CrxUpdateService::ProcessPendingItems);
756   }
757
758   return kOk;
759 }
760
761 void CrxUpdateService::GetComponents(
762     std::vector<CrxComponentInfo>* components) {
763   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
764   for (UpdateItems::const_iterator it = work_items_.begin();
765        it != work_items_.end(); ++it) {
766     const CrxUpdateItem* item = *it;
767     CrxComponentInfo info;
768     info.id = GetCrxComponentID(item->component);
769     info.version = item->component.version.GetString();
770     info.name = item->component.name;
771     components->push_back(info);
772   }
773 }
774
775 // This is the main loop of the component updater.
776 void CrxUpdateService::ProcessPendingItems() {
777   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
778   CrxUpdateItem* ready_upgrade = FindReadyComponent();
779   if (ready_upgrade) {
780     UpdateComponent(ready_upgrade);
781     return;
782   }
783   std::string query;
784   AddUpdateCheckItems(&query);
785   if (!query.empty()) {
786     DoUpdateCheck(query);
787     return;
788   }
789   // No components to update. The next check will be after a long sleep.
790   ScheduleNextRun(kStepDelayLong);
791 }
792
793 CrxUpdateItem* CrxUpdateService::FindReadyComponent() {
794   class Helper {
795    public:
796     static bool IsReadyOnDemand(CrxUpdateItem* item) {
797       return item->on_demand && IsReady(item);
798     }
799     static bool IsReady(CrxUpdateItem* item) {
800       return item->status == CrxUpdateItem::kCanUpdate;
801     }
802   };
803
804   std::vector<CrxUpdateItem*>::iterator it = std::find_if(
805       work_items_.begin(), work_items_.end(), Helper::IsReadyOnDemand);
806   if (it != work_items_.end())
807     return *it;
808   it = std::find_if(work_items_.begin(), work_items_.end(), Helper::IsReady);
809   if (it != work_items_.end())
810     return *it;
811   return NULL;
812 }
813
814 void CrxUpdateService::UpdateComponent(CrxUpdateItem* workitem) {
815   CRXContext* context = new CRXContext;
816   context->pk_hash = workitem->component.pk_hash;
817   context->id = workitem->id;
818   context->installer = workitem->component.installer;
819   context->fingerprint = workitem->next_fp;
820   GURL package_url;
821   if (CanTryDiffUpdate(workitem, *config_)) {
822     package_url = workitem->diff_crx_url;
823     ChangeItemState(workitem, CrxUpdateItem::kDownloadingDiff);
824   } else {
825     package_url = workitem->crx_url;
826     ChangeItemState(workitem, CrxUpdateItem::kDownloading);
827   }
828   url_fetcher_.reset(net::URLFetcher::Create(
829       0, package_url, net::URLFetcher::GET,
830       MakeContextDelegate(this, context)));
831   StartFetch(url_fetcher_.get(),
832              config_->RequestContext(),
833              true,
834              blocking_task_runner_);
835 }
836
837 // Given that our |work_items_| list is expected to contain relatively few
838 // items, we simply loop several times.
839 void CrxUpdateService::AddUpdateCheckItems(std::string* query){
840   for (UpdateItems::const_iterator it = work_items_.begin();
841        it != work_items_.end(); ++it) {
842     CrxUpdateItem* item = *it;
843     if (item->status != CrxUpdateItem::kNew)
844       continue;
845     if (!AddItemToUpdateCheck(item, query))
846       break;
847   }
848
849   // Next we can go back to components we already checked, here
850   // we can also batch them in a single url request, as long as
851   // we have not checked them recently.
852   const base::TimeDelta min_delta_time =
853       base::TimeDelta::FromSeconds(config_->MinimumReCheckWait());
854
855   for (UpdateItems::const_iterator it = work_items_.begin();
856        it != work_items_.end(); ++it) {
857     CrxUpdateItem* item = *it;
858     if ((item->status != CrxUpdateItem::kNoUpdate) &&
859         (item->status != CrxUpdateItem::kUpToDate))
860       continue;
861     base::TimeDelta delta = base::Time::Now() - item->last_check;
862     if (delta < min_delta_time)
863       continue;
864     if (!AddItemToUpdateCheck(item, query))
865       break;
866   }
867
868   // Finally, we check components that we already updated as long as
869   // we have not checked them recently.
870   for (UpdateItems::const_iterator it = work_items_.begin();
871        it != work_items_.end(); ++it) {
872     CrxUpdateItem* item = *it;
873     if (item->status != CrxUpdateItem::kUpdated)
874       continue;
875     base::TimeDelta delta = base::Time::Now() - item->last_check;
876     if (delta < min_delta_time)
877       continue;
878     if (!AddItemToUpdateCheck(item, query))
879       break;
880   }
881 }
882
883 void CrxUpdateService::DoUpdateCheck(const std::string& query) {
884   const std::string full_query =
885       MakeFinalQuery(config_->UpdateUrl().spec(),
886                      query,
887                      config_->ExtraRequestParams());
888
889   url_fetcher_.reset(net::URLFetcher::Create(
890       0, GURL(full_query), net::URLFetcher::GET,
891       MakeContextDelegate(this, new UpdateContext())));
892   StartFetch(url_fetcher_.get(),
893              config_->RequestContext(),
894              false,
895              blocking_task_runner_);
896 }
897
898 // Called when we got a response from the update server. It consists of an xml
899 // document following the omaha update scheme.
900 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source,
901                                           UpdateContext* context) {
902   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
903   if (FetchSuccess(*source)) {
904     std::string xml;
905     source->GetResponseAsString(&xml);
906     url_fetcher_.reset();
907     ParseManifest(xml);
908   } else {
909     url_fetcher_.reset();
910     CrxUpdateService::OnParseUpdateManifestFailed("network error");
911   }
912   delete context;
913 }
914
915 // Parsing the manifest is either done right now for tests or in a sandboxed
916 // process for the production environment. This mitigates the case where an
917 // attacker was able to feed us a malicious xml string.
918 void CrxUpdateService::ParseManifest(const std::string& xml) {
919   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
920   if (config_->InProcess()) {
921     UpdateManifest manifest;
922     if (!manifest.Parse(xml))
923        CrxUpdateService::OnParseUpdateManifestFailed(manifest.errors());
924     else
925        CrxUpdateService::OnParseUpdateManifestSucceeded(manifest.results());
926   } else {
927     UtilityProcessHost* host =
928         UtilityProcessHost::Create(new ManifestParserBridge(this),
929                                    base::MessageLoopProxy::current().get());
930     host->EnableZygote();
931     host->Send(new ChromeUtilityMsg_ParseUpdateManifest(xml));
932   }
933 }
934
935 // A valid Omaha update check has arrived, from only the list of components that
936 // we are currently upgrading we check for a match in which the server side
937 // version is newer, if so we queue them for an upgrade. The next time we call
938 // ProcessPendingItems() one of them will be drafted for the upgrade process.
939 void CrxUpdateService::OnParseUpdateManifestSucceeded(
940     const UpdateManifest::Results& results) {
941   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
942   size_t update_pending = 0;
943   std::vector<UpdateManifest::Result>::const_iterator it;
944   for (it = results.list.begin(); it != results.list.end(); ++it) {
945     CrxUpdateItem* crx = FindUpdateItemById(it->extension_id);
946     if (!crx)
947       continue;
948
949     if (crx->status != CrxUpdateItem::kChecking)
950       continue;  // Not updating this component now.
951
952     if (it->version.empty()) {
953       // No version means no update available.
954       ChangeItemState(crx, CrxUpdateItem::kNoUpdate);
955       continue;
956     }
957     if (!IsVersionNewer(crx->component.version, it->version)) {
958       // Our component is up to date.
959       ChangeItemState(crx, CrxUpdateItem::kUpToDate);
960       continue;
961     }
962     if (!it->browser_min_version.empty()) {
963       if (IsVersionNewer(chrome_version_, it->browser_min_version)) {
964         // Does not apply for this chrome version.
965         ChangeItemState(crx, CrxUpdateItem::kNoUpdate);
966         continue;
967       }
968     }
969     // All test passed. Queue an upgrade for this component and fire the
970     // notifications.
971     crx->crx_url = it->crx_url;
972     crx->diff_crx_url = it->diff_crx_url;
973     ChangeItemState(crx, CrxUpdateItem::kCanUpdate);
974     crx->next_version = Version(it->version);
975     crx->next_fp = it->package_fingerprint;
976     ++update_pending;
977   }
978
979   // All the components that are not mentioned in the manifest we
980   // consider them up to date.
981   ChangeItemStatus(CrxUpdateItem::kChecking, CrxUpdateItem::kUpToDate);
982
983   // If there are updates pending we do a short wait, otherwise we take
984   // a longer delay until we check the components again.
985   ScheduleNextRun(update_pending > 0 ? kStepDelayShort : kStepDelayMedium);
986 }
987
988 void CrxUpdateService::OnParseUpdateManifestFailed(
989     const std::string& error_message) {
990   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
991   size_t count = ChangeItemStatus(CrxUpdateItem::kChecking,
992                                   CrxUpdateItem::kNoUpdate);
993   DCHECK_GT(count, 0ul);
994   ScheduleNextRun(kStepDelayLong);
995 }
996
997 // Called when the CRX package has been downloaded to a temporary location.
998 // Here we fire the notifications and schedule the component-specific installer
999 // to be called in the file thread.
1000 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source,
1001                                           CRXContext* context) {
1002   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1003
1004   scoped_ptr<CRXContext> crx_context(context);
1005
1006   CrxUpdateItem* crx = FindUpdateItemById(crx_context->id);
1007   DCHECK(crx->status == CrxUpdateItem::kDownloadingDiff ||
1008          crx->status == CrxUpdateItem::kDownloading);
1009
1010   if (!FetchSuccess(*source)) {
1011     if (crx->status == CrxUpdateItem::kDownloadingDiff) {
1012       crx->diff_error_category = kNetworkError;
1013       crx->diff_error_code = GetFetchError(*source);
1014       crx->diff_update_failed = true;
1015       size_t count = ChangeItemStatus(CrxUpdateItem::kDownloadingDiff,
1016                                       CrxUpdateItem::kCanUpdate);
1017       DCHECK_EQ(count, 1ul);
1018       url_fetcher_.reset();
1019
1020       ScheduleNextRun(kStepDelayShort);
1021       return;
1022     }
1023     crx->error_category = kNetworkError;
1024     crx->error_code = GetFetchError(*source);
1025     size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading,
1026                                     CrxUpdateItem::kNoUpdate);
1027     DCHECK_EQ(count, 1ul);
1028     url_fetcher_.reset();
1029
1030     // At this point, since both the differential and the full downloads failed,
1031     // the update for this component has finished with an error.
1032     ping_manager_->OnUpdateComplete(crx);
1033
1034     // Move on to the next update, if there is one available.
1035     ScheduleNextRun(kStepDelayMedium);
1036   } else {
1037     base::FilePath temp_crx_path;
1038     CHECK(source->GetResponseAsFilePath(true, &temp_crx_path));
1039
1040     size_t count = 0;
1041     if (crx->status == CrxUpdateItem::kDownloadingDiff) {
1042       count = ChangeItemStatus(CrxUpdateItem::kDownloadingDiff,
1043                                CrxUpdateItem::kUpdatingDiff);
1044     } else {
1045       count = ChangeItemStatus(CrxUpdateItem::kDownloading,
1046                                CrxUpdateItem::kUpdating);
1047     }
1048     DCHECK_EQ(count, 1ul);
1049
1050     url_fetcher_.reset();
1051
1052     // Why unretained? See comment at top of file.
1053     blocking_task_runner_->PostDelayedTask(
1054         FROM_HERE,
1055         base::Bind(&CrxUpdateService::Install,
1056                    base::Unretained(this),
1057                    crx_context.release(),
1058                    temp_crx_path),
1059         base::TimeDelta::FromMilliseconds(config_->StepDelay()));
1060   }
1061 }
1062
1063 // Install consists of digital signature verification, unpacking and then
1064 // calling the component specific installer. All that is handled by the
1065 // |unpacker|. If there is an error this function is in charge of deleting
1066 // the files created.
1067 void CrxUpdateService::Install(const CRXContext* context,
1068                                const base::FilePath& crx_path) {
1069   // This function owns the file at |crx_path| and the |context| object.
1070   ComponentUnpacker unpacker(context->pk_hash,
1071                              crx_path,
1072                              context->fingerprint,
1073                              component_patcher_.get(),
1074                              context->installer);
1075   if (!base::DeleteFile(crx_path, false))
1076     NOTREACHED() << crx_path.value();
1077   // Why unretained? See comment at top of file.
1078   BrowserThread::PostDelayedTask(
1079       BrowserThread::UI,
1080       FROM_HERE,
1081       base::Bind(&CrxUpdateService::DoneInstalling, base::Unretained(this),
1082                  context->id, unpacker.error(), unpacker.extended_error()),
1083       base::TimeDelta::FromMilliseconds(config_->StepDelay()));
1084   delete context;
1085 }
1086
1087 // Installation has been completed. Adjust the component status and
1088 // schedule the next check. Schedule a short delay before trying the full
1089 // update when the differential update failed.
1090 void CrxUpdateService::DoneInstalling(const std::string& component_id,
1091                                       ComponentUnpacker::Error error,
1092                                       int extra_code) {
1093   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1094
1095   ErrorCategory error_category = kErrorNone;
1096   switch (error) {
1097     case ComponentUnpacker::kNone:
1098       break;
1099     case ComponentUnpacker::kInstallerError:
1100       error_category = kInstallError;
1101       break;
1102     default:
1103       error_category = kUnpackError;
1104       break;
1105   }
1106
1107   const bool is_success = error == ComponentUnpacker::kNone;
1108
1109   CrxUpdateItem* item = FindUpdateItemById(component_id);
1110   if (item->status == CrxUpdateItem::kUpdatingDiff && !is_success) {
1111     item->diff_error_category = error_category;
1112     item->diff_error_code = error;
1113     item->diff_extra_code1 = extra_code;
1114     item->diff_update_failed = true;
1115     size_t count = ChangeItemStatus(CrxUpdateItem::kUpdatingDiff,
1116                                     CrxUpdateItem::kCanUpdate);
1117     DCHECK_EQ(count, 1ul);
1118     ScheduleNextRun(kStepDelayShort);
1119     return;
1120     }
1121
1122   if (is_success) {
1123     ChangeItemState(item, CrxUpdateItem::kUpdated);
1124     item->component.version = item->next_version;
1125     item->component.fingerprint = item->next_fp;
1126   } else {
1127     ChangeItemState(item, CrxUpdateItem::kNoUpdate);
1128     item->error_category = error_category;
1129     item->error_code = error;
1130     item->extra_code1 = extra_code;
1131   }
1132
1133   ping_manager_->OnUpdateComplete(item);
1134
1135   // Move on to the next update, if there is one available.
1136   ScheduleNextRun(kStepDelayMedium);
1137 }
1138
1139 void CrxUpdateService::NotifyComponentObservers(
1140     ComponentObserver::Events event, int extra) const {
1141   for (UpdateItems::const_iterator it = work_items_.begin();
1142        it != work_items_.end(); ++it) {
1143     ComponentObserver* observer = (*it)->component.observer;
1144     if (observer)
1145       observer->OnEvent(event, 0);
1146   }
1147 }
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
1209 // The component update factory. Using the component updater as a singleton
1210 // is the job of the browser process.
1211 ComponentUpdateService* ComponentUpdateServiceFactory(
1212     ComponentUpdateService::Configurator* config) {
1213   DCHECK(config);
1214   return new CrxUpdateService(config);
1215 }