AU: Manual proxy support

Utilize the ChromeProxyResolver to resolve proxies in our network
requests. This means the following changes:

- HttpFetcher classes take a ProxyResolver* in their ctor. Also, a few
  useful functions in HttpFetcher to allow subclasses to iterate
  through the proxies.

- LibcurlHttpFetcher support for using the ProxyResolver. It will
  attempt to use each proxy in the order specified. If any data comes
  in from any proxy, it won't continue down the list and will continue
  to use that proxy for its lifetime.

- UpdateAttempter can choose, for a given update session, whether or
  not to use the ChromeProxyResolver or DirectProxyResolver. For now,
  the logic is: for automatic checks, 80% of the time use
  ChromeProxyResolver, 20% DirectProxyResolver. For manual checks, the
  first 19 manual checks in a row use Chrome, then once it uses
  Direct, then starts over again. The idea is that the updater doesn't
  necessarily trust Chrome, so some requests should skip it. If a
  manual check is performed, the user likely wants her proxy settings
  honored, so use them, but don't allow frequent manual checks to
  starve out usage of the DirectProxyResolver.

- Updates to tests

BUG=3167
TEST=unittests, tested on device

Review URL: http://codereview.chromium.org/5205002

Change-Id: Iee0f589e5b28d4b804afe1f5b6729ba066d48d62
diff --git a/update_attempter.cc b/update_attempter.cc
index ef6a949..4e7d7bf 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -14,6 +14,7 @@
 #include <tr1/memory>
 #include <vector>
 
+#include <base/rand_util.h>
 #include <glib.h>
 #include <metrics/metrics_library.h>
 
@@ -43,6 +44,10 @@
 const char* kUpdateCompletedMarker =
     "/var/run/update_engine_autoupdate_completed";
 
+namespace {
+const int kMaxConsecutiveObeyProxyRequests = 20;
+}  // namespace {}
+
 const char* UpdateStatusToString(UpdateStatus status) {
   switch (status) {
     case UPDATE_STATUS_IDLE:
@@ -89,7 +94,8 @@
 }
 
 UpdateAttempter::UpdateAttempter(PrefsInterface* prefs,
-                                 MetricsLibraryInterface* metrics_lib)
+                                 MetricsLibraryInterface* metrics_lib,
+                                 DbusGlibInterface* dbus_iface)
     : processor_(new ActionProcessor()),
       dbus_service_(NULL),
       prefs_(prefs),
@@ -104,7 +110,10 @@
       last_checked_time_(0),
       new_version_("0.0.0.0"),
       new_size_(0),
-      is_full_update_(false) {
+      is_full_update_(false),
+      proxy_manual_checks_(0),
+      obeying_proxies_(true),
+      chrome_proxy_resolver_(dbus_iface) {
   if (utils::FileExists(kUpdateCompletedMarker))
     status_ = UPDATE_STATUS_UPDATED_NEED_REBOOT;
 }
@@ -114,7 +123,8 @@
 }
 
 void UpdateAttempter::Update(const std::string& app_version,
-                             const std::string& omaha_url) {
+                             const std::string& omaha_url,
+                             bool obey_proxies) {
   if (status_ == UPDATE_STATUS_UPDATED_NEED_REBOOT) {
     LOG(INFO) << "Not updating b/c we already updated and we're waiting for "
               << "reboot";
@@ -129,6 +139,24 @@
     LOG(ERROR) << "Unable to initialize Omaha request device params.";
     return;
   }
+  
+  obeying_proxies_ = true;
+  if (obey_proxies || proxy_manual_checks_ == 0) {
+    LOG(INFO) << "forced to obey proxies";
+    // If forced to obey proxies, every 20th request will not use proxies
+    proxy_manual_checks_++;
+    LOG(INFO) << "proxy manual checks: " << proxy_manual_checks_;
+    if (proxy_manual_checks_ >= kMaxConsecutiveObeyProxyRequests) {
+      proxy_manual_checks_ = 0;
+      obeying_proxies_ = false;
+    }
+  } else if (base::RandInt(0, 4) == 0) {
+    obeying_proxies_ = false;
+  }
+  LOG_IF(INFO, !obeying_proxies_) << "To help ensure updates work, this update "
+      "check we are ignoring the proxy settings and using "
+      "direct connections.";
+
   DisableDeltaUpdateIfNeeded();
   CHECK(!processor_->IsRunning());
   processor_->set_delegate(this);
@@ -138,7 +166,7 @@
       new OmahaRequestAction(prefs_,
                              omaha_request_params_,
                              NULL,
-                             new LibcurlHttpFetcher));
+                             new LibcurlHttpFetcher(GetProxyResolver())));
   shared_ptr<OmahaResponseHandlerAction> response_handler_action(
       new OmahaResponseHandlerAction(prefs_));
   shared_ptr<FilesystemCopierAction> filesystem_copier_action(
@@ -150,22 +178,23 @@
                              omaha_request_params_,
                              new OmahaEvent(
                                  OmahaEvent::kTypeUpdateDownloadStarted),
-                             new LibcurlHttpFetcher));
+                             new LibcurlHttpFetcher(GetProxyResolver())));
   shared_ptr<DownloadAction> download_action(
-      new DownloadAction(prefs_, new MultiHttpFetcher<LibcurlHttpFetcher>));
+      new DownloadAction(prefs_, new MultiHttpFetcher<LibcurlHttpFetcher>(
+          GetProxyResolver())));
   shared_ptr<OmahaRequestAction> download_finished_action(
       new OmahaRequestAction(prefs_,
                              omaha_request_params_,
                              new OmahaEvent(
                                  OmahaEvent::kTypeUpdateDownloadFinished),
-                             new LibcurlHttpFetcher));
+                             new LibcurlHttpFetcher(GetProxyResolver())));
   shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
       new PostinstallRunnerAction);
   shared_ptr<OmahaRequestAction> update_complete_action(
       new OmahaRequestAction(prefs_,
                              omaha_request_params_,
                              new OmahaEvent(OmahaEvent::kTypeUpdateComplete),
-                             new LibcurlHttpFetcher));
+                             new LibcurlHttpFetcher(GetProxyResolver())));
 
   download_action->set_delegate(this);
   response_handler_action_ = response_handler_action;
@@ -212,7 +241,7 @@
               << UpdateStatusToString(status_) << ", so not checking.";
     return;
   }
-  Update(app_version, omaha_url);
+  Update(app_version, omaha_url, true);
 }
 
 bool UpdateAttempter::RebootIfNeeded() {
@@ -435,7 +464,7 @@
       new OmahaRequestAction(prefs_,
                              omaha_request_params_,
                              error_event_.release(),  // Pass ownership.
-                             new LibcurlHttpFetcher));
+                             new LibcurlHttpFetcher(GetProxyResolver())));
   actions_.push_back(shared_ptr<AbstractAction>(error_event_action));
   processor_->EnqueueAction(error_event_action.get());
   SetStatusAndNotify(UPDATE_STATUS_REPORTING_ERROR_EVENT);