Download chain of responsibility for url and fetcher fallback.

BUG=304354

Review URL: https://codereview.chromium.org/85263004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238017 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc
index 774a21bc..b790dad 100644
--- a/chrome/browser/component_updater/component_updater_service.cc
+++ b/chrome/browser/component_updater/component_updater_service.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/component_updater/component_unpacker.h"
 #include "chrome/browser/component_updater/component_updater_ping_manager.h"
 #include "chrome/browser/component_updater/component_updater_utils.h"
+#include "chrome/browser/component_updater/crx_downloader.h"
 #include "chrome/browser/component_updater/crx_update_item.h"
 #include "chrome/browser/component_updater/update_response.h"
 #include "chrome/common/chrome_version_info.h"
@@ -41,7 +42,6 @@
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request.h"
-#include "net/url_request/url_request_status.h"
 #include "url/gurl.h"
 
 using content::BrowserThread;
@@ -101,52 +101,6 @@
   return new DelegateWithContext<Del, Ctx>(delegate, context);
 }
 
-// Helper to start a url request using |fetcher| with the common flags.
-void StartFetch(net::URLFetcher* fetcher,
-                net::URLRequestContextGetter* context_getter,
-                bool save_to_file,
-                scoped_refptr<base::SequencedTaskRunner> task_runner) {
-  fetcher->SetRequestContext(context_getter);
-  fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
-                        net::LOAD_DO_NOT_SAVE_COOKIES |
-                        net::LOAD_DISABLE_CACHE);
-  // TODO(cpu): Define our retry and backoff policy.
-  fetcher->SetAutomaticallyRetryOn5xx(false);
-  if (save_to_file) {
-    fetcher->SaveResponseToTemporaryFile(task_runner);
-  }
-  fetcher->Start();
-}
-
-// Returns true if the url request of |fetcher| was succesful.
-bool FetchSuccess(const net::URLFetcher& fetcher) {
-  return (fetcher.GetStatus().status() == net::URLRequestStatus::SUCCESS) &&
-         (fetcher.GetResponseCode() == 200);
-}
-
-// Returns the error code which occured during the fetch.The function returns 0
-// if the fetch was successful. If errors happen, the function could return a
-// network error, an http response code, or the status of the fetch, if the
-// fetch is pending or canceled.
-int GetFetchError(const net::URLFetcher& fetcher) {
-  if (FetchSuccess(fetcher))
-    return 0;
-
-  const net::URLRequestStatus::Status status(fetcher.GetStatus().status());
-  if (status == net::URLRequestStatus::FAILED)
-    return fetcher.GetStatus().error();
-
-  if (status == net::URLRequestStatus::IO_PENDING ||
-      status == net::URLRequestStatus::CANCELED)
-    return status;
-
-  const int response_code(fetcher.GetResponseCode());
-  if (status == net::URLRequestStatus::SUCCESS && response_code != 200)
-    return response_code;
-
-  return -1;
-  }
-
 // Returns true if a differential update is available for the update item.
 bool IsDiffUpdateAvailable(const CrxUpdateItem* update_item) {
   return update_item->diff_crx_url.is_valid();
@@ -290,9 +244,6 @@
   void OnURLFetchComplete(const net::URLFetcher* source,
                           UpdateContext* context);
 
-  void OnURLFetchComplete(const net::URLFetcher* source,
-                          CRXContext* context);
-
  private:
   enum ErrorCategory {
     kErrorNone = 0,
@@ -311,6 +262,10 @@
       const component_updater::UpdateResponse::Results& results);
   void OnParseUpdateResponseFailed(const std::string& error_message);
 
+  void DownloadComplete(scoped_ptr<CRXContext> crx_context,
+                        int error,
+                        const base::FilePath& response);
+
   Status OnDemandUpdateInternal(CrxUpdateItem* item);
 
   void ProcessPendingItems();
@@ -330,7 +285,7 @@
 
   void ParseResponse(const std::string& xml);
 
-  void Install(const CRXContext* context, const base::FilePath& crx_path);
+  void Install(scoped_ptr<CRXContext> context, const base::FilePath& crx_path);
 
   void DoneInstalling(const std::string& component_id,
                       ComponentUnpacker::Error error,
@@ -359,6 +314,8 @@
 
   scoped_ptr<component_updater::PingManager> ping_manager_;
 
+  scoped_ptr<component_updater::CrxDownloader> crx_downloader_;
+
   // A collection of every work item.
   typedef std::vector<CrxUpdateItem*> UpdateItems;
   UpdateItems work_items_;
@@ -702,11 +659,11 @@
 }
 
 void CrxUpdateService::UpdateComponent(CrxUpdateItem* workitem) {
-  CRXContext* context = new CRXContext;
-  context->pk_hash = workitem->component.pk_hash;
-  context->id = workitem->id;
-  context->installer = workitem->component.installer;
-  context->fingerprint = workitem->next_fp;
+  scoped_ptr<CRXContext> crx_context(new CRXContext);
+  crx_context->pk_hash = workitem->component.pk_hash;
+  crx_context->id = workitem->id;
+  crx_context->installer = workitem->component.installer;
+  crx_context->fingerprint = workitem->next_fp;
   GURL package_url;
   if (CanTryDiffUpdate(workitem, *config_)) {
     package_url = workitem->diff_crx_url;
@@ -715,13 +672,13 @@
     package_url = workitem->crx_url;
     ChangeItemState(workitem, CrxUpdateItem::kDownloading);
   }
-  url_fetcher_.reset(net::URLFetcher::Create(
-      0, package_url, net::URLFetcher::GET,
-      MakeContextDelegate(this, context)));
-  StartFetch(url_fetcher_.get(),
-             config_->RequestContext(),
-             true,
-             blocking_task_runner_);
+  crx_downloader_.reset(component_updater::CrxDownloader::Create(
+      config_->RequestContext(),
+      blocking_task_runner_,
+      base::Bind(&CrxUpdateService::DownloadComplete,
+                 base::Unretained(this),
+                 base::Passed(&crx_context))));
+  crx_downloader_->StartDownloadFromUrl(package_url);
 }
 
 // Sets the state of the component to be checked for updates. After the
@@ -843,7 +800,7 @@
 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source,
                                           UpdateContext* context) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (FetchSuccess(*source)) {
+  if (component_updater::FetchSuccess(*source)) {
     std::string xml;
     source->GetResponseAsString(&xml);
     url_fetcher_.reset();
@@ -949,35 +906,34 @@
 // Called when the CRX package has been downloaded to a temporary location.
 // Here we fire the notifications and schedule the component-specific installer
 // to be called in the file thread.
-void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source,
-                                          CRXContext* context) {
+void CrxUpdateService::DownloadComplete(scoped_ptr<CRXContext> crx_context,
+                                        int error,
+                                        const base::FilePath& temp_crx_path) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  scoped_ptr<CRXContext> crx_context(context);
-
   CrxUpdateItem* crx = FindUpdateItemById(crx_context->id);
   DCHECK(crx->status == CrxUpdateItem::kDownloadingDiff ||
          crx->status == CrxUpdateItem::kDownloading);
 
-  if (!FetchSuccess(*source)) {
+  if (error) {
     if (crx->status == CrxUpdateItem::kDownloadingDiff) {
       crx->diff_error_category = kNetworkError;
-      crx->diff_error_code = GetFetchError(*source);
+      crx->diff_error_code = error;
       crx->diff_update_failed = true;
       size_t count = ChangeItemStatus(CrxUpdateItem::kDownloadingDiff,
                                       CrxUpdateItem::kCanUpdate);
       DCHECK_EQ(count, 1ul);
-      url_fetcher_.reset();
+      crx_downloader_.reset();
 
       ScheduleNextRun(kStepDelayShort);
       return;
     }
     crx->error_category = kNetworkError;
-    crx->error_code = GetFetchError(*source);
+    crx->error_code = error;
     size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading,
                                     CrxUpdateItem::kNoUpdate);
     DCHECK_EQ(count, 1ul);
-    url_fetcher_.reset();
+    crx_downloader_.reset();
 
     // At this point, since both the differential and the full downloads failed,
     // the update for this component has finished with an error.
@@ -986,9 +942,6 @@
     // Move on to the next update, if there is one available.
     ScheduleNextRun(kStepDelayMedium);
   } else {
-    base::FilePath temp_crx_path;
-    CHECK(source->GetResponseAsFilePath(true, &temp_crx_path));
-
     size_t count = 0;
     if (crx->status == CrxUpdateItem::kDownloadingDiff) {
       count = ChangeItemStatus(CrxUpdateItem::kDownloadingDiff,
@@ -999,14 +952,14 @@
     }
     DCHECK_EQ(count, 1ul);
 
-    url_fetcher_.reset();
+    crx_downloader_.reset();
 
     // Why unretained? See comment at top of file.
     blocking_task_runner_->PostDelayedTask(
         FROM_HERE,
         base::Bind(&CrxUpdateService::Install,
                    base::Unretained(this),
-                   crx_context.release(),
+                   base::Passed(&crx_context),
                    temp_crx_path),
         base::TimeDelta::FromMilliseconds(config_->StepDelay()));
   }
@@ -1016,7 +969,7 @@
 // calling the component specific installer. All that is handled by the
 // |unpacker|. If there is an error this function is in charge of deleting
 // the files created.
-void CrxUpdateService::Install(const CRXContext* context,
+void CrxUpdateService::Install(scoped_ptr<CRXContext> context,
                                const base::FilePath& crx_path) {
   // This function owns the file at |crx_path| and the |context| object.
   ComponentUnpacker unpacker(context->pk_hash,
@@ -1033,7 +986,6 @@
       base::Bind(&CrxUpdateService::DoneInstalling, base::Unretained(this),
                  context->id, unpacker.error(), unpacker.extended_error()),
       base::TimeDelta::FromMilliseconds(config_->StepDelay()));
-  delete context;
 }
 
 // Installation has been completed. Adjust the component status and