AU: Restrict to HTTPS for official builds.

Also, fix multi http fetcher unit tests to predictably force non-expensive
connections.

BUG=7945
TEST=unit tests; tested on device with dev server as well as with
no /root/.dev_mode, dev server, omaha update

Change-Id: Iacc0188b464ec018fc0dbbc8d7d447386113ceb7

Review URL: http://codereview.chromium.org/4004004
diff --git a/http_fetcher_unittest.cc b/http_fetcher_unittest.cc
index bd16768..6c420a0 100644
--- a/http_fetcher_unittest.cc
+++ b/http_fetcher_unittest.cc
@@ -136,6 +136,7 @@
     ret->set_idle_seconds(1);
     ret->set_retry_seconds(1);
     ret->SetConnectionAsExpensive(false);
+    ret->SetBuildType(false);
     return ret;
   }
   HttpFetcher* NewSmallFetcher() {
@@ -169,6 +170,8 @@
     // Speed up test execution.
     ret->set_idle_seconds(1);
     ret->set_retry_seconds(1);
+    ret->SetConnectionAsExpensive(false);
+    ret->SetBuildType(false);
     return ret;
   }
   bool IsMulti() const { return true; }
@@ -613,6 +616,8 @@
         dynamic_cast<MultiHttpFetcher<LibcurlHttpFetcher>*>(fetcher.get());
     ASSERT_TRUE(multi_fetcher);
     multi_fetcher->set_ranges(ranges);
+    multi_fetcher->SetConnectionAsExpensive(false);
+    multi_fetcher->SetBuildType(false);
     fetcher->set_delegate(&delegate);
 
     StartTransferArgs start_xfer_args = {fetcher.get(), url};
@@ -698,7 +703,7 @@
 }
 
 namespace {
-class ExpensiveConnectionTestDelegate : public HttpFetcherDelegate {
+class BlockedTransferTestDelegate : public HttpFetcherDelegate {
  public:
   virtual void ReceivedBytes(HttpFetcher* fetcher,
                              const char* bytes, int length) {
@@ -713,28 +718,37 @@
 
 }  // namespace
 
-TYPED_TEST(HttpFetcherTest, ExpensiveConnectionTest) {
+TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
   if (this->IsMock() || this->IsMulti())
     return;
-  typename TestFixture::HttpServer server;
-  
-  ASSERT_TRUE(server.started_);
 
-  GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
-  ExpensiveConnectionTestDelegate delegate;
-  delegate.loop_ = loop;
+  for (int i = 0; i < 2; i++) {
+    typename TestFixture::HttpServer server;
 
-  scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
-  dynamic_cast<LibcurlHttpFetcher*>(
-      fetcher.get())->SetConnectionAsExpensive(true);
-  fetcher->set_delegate(&delegate);
+    ASSERT_TRUE(server.started_);
 
-  StartTransferArgs start_xfer_args =
-      { fetcher.get(), LocalServerUrlForPath(this->SmallUrl()) };
+    GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
+    BlockedTransferTestDelegate delegate;
+    delegate.loop_ = loop;
 
-  g_timeout_add(0, StartTransfer, &start_xfer_args);
-  g_main_loop_run(loop);
-  g_main_loop_unref(loop);
+    scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
+    LibcurlHttpFetcher* curl_fetcher =
+        dynamic_cast<LibcurlHttpFetcher*>(fetcher.get());
+    bool is_expensive_connection = (i == 0);
+    bool is_official_build = (i == 1);
+    LOG(INFO) << "is_expensive_connection: " << is_expensive_connection;
+    LOG(INFO) << "is_official_build: " << is_official_build;
+    curl_fetcher->SetConnectionAsExpensive(is_expensive_connection);
+    curl_fetcher->SetBuildType(is_official_build);
+    fetcher->set_delegate(&delegate);
+
+    StartTransferArgs start_xfer_args =
+        { fetcher.get(), LocalServerUrlForPath(this->SmallUrl()) };
+
+    g_timeout_add(0, StartTransfer, &start_xfer_args);
+    g_main_loop_run(loop);
+    g_main_loop_unref(loop);
+  }
 }
 
 }  // namespace chromeos_update_engine
diff --git a/libcurl_http_fetcher.cc b/libcurl_http_fetcher.cc
index 9cacf86..a921725 100644
--- a/libcurl_http_fetcher.cc
+++ b/libcurl_http_fetcher.cc
@@ -43,6 +43,10 @@
   return FlimFlamProxy::IsExpensiveConnectionType(type);
 }
 
+bool LibcurlHttpFetcher::IsOfficialBuild() const {
+  return force_build_type_ ? forced_official_build_ : utils::IsOfficialBuild();
+}
+
 void LibcurlHttpFetcher::ResumeTransfer(const std::string& url) {
   LOG(INFO) << "Starting/Resuming transfer";
   CHECK(!transfer_in_progress_);
@@ -82,9 +86,7 @@
     url_to_use = "";  // Sabotage the URL
   }
 
-  CHECK_EQ(curl_easy_setopt(curl_handle_,
-                            CURLOPT_URL,
-                            url_to_use.c_str()),
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_URL, url_to_use.c_str()),
            CURLE_OK);
 
   // If the connection drops under 10 bytes/sec for 3 minutes, reconnect.
@@ -105,6 +107,16 @@
   CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_CAPATH, kCACertificatesPath),
            CURLE_OK);
 
+  // Restrict protocols to HTTPS in official builds.
+  if (IsOfficialBuild()) {
+    CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS),
+             CURLE_OK);
+    CHECK_EQ(curl_easy_setopt(curl_handle_,
+                              CURLOPT_REDIR_PROTOCOLS,
+                              CURLPROTO_HTTPS),
+             CURLE_OK);
+  }
+
   CHECK_EQ(curl_multi_add_handle(curl_multi_handle_, curl_handle_), CURLM_OK);
   transfer_in_progress_ = true;
 }
diff --git a/libcurl_http_fetcher.h b/libcurl_http_fetcher.h
index 2628ecc..25c4e49 100644
--- a/libcurl_http_fetcher.h
+++ b/libcurl_http_fetcher.h
@@ -35,6 +35,8 @@
         idle_seconds_(1),
         force_connection_type_(false),
         forced_expensive_connection_(false),
+        force_build_type_(false),
+        forced_official_build_(false),
         in_write_callback_(false),
         terminate_requested_(false) {}
 
@@ -69,12 +71,17 @@
 
   // Sets the retry timeout. Useful for testing.
   void set_retry_seconds(int seconds) { retry_seconds_ = seconds; }
-  
+
   void SetConnectionAsExpensive(bool is_expensive) {
     force_connection_type_ = true;
     forced_expensive_connection_ = is_expensive;
   }
 
+  void SetBuildType(bool is_official) {
+    force_build_type_ = true;
+    forced_official_build_ = is_official;
+  }
+
  private:
   // Asks libcurl for the http response code and stores it in the object.
   void GetHttpResponseCode();
@@ -133,6 +140,9 @@
   // expensive.
   bool ConnectionIsExpensive() const;
 
+  // Returns whether or not the current build is official.
+  bool IsOfficialBuild() const;
+
   // Handles for the libcurl library
   CURLM *curl_multi_handle_;
   CURL *curl_handle_;
@@ -168,15 +178,20 @@
 
   // Seconds to wait before asking libcurl to "perform".
   int idle_seconds_;
-  
+
   // If true, assume the network is expensive or not, according to
   // forced_expensive_connection_. (Useful for testing).
   bool force_connection_type_;
   bool forced_expensive_connection_;
 
+  // If true, assume the build is official or not, according to
+  // forced_official_build_. Useful for testing.
+  bool force_build_type_;
+  bool forced_official_build_;
+
   // If true, we are currently performing a write callback on the delegate.
   bool in_write_callback_;
-  
+
   // We can't clean everything up while we're in a write callback, so
   // if we get a terminate request, queue it until we can handle it.
   bool terminate_requested_;
diff --git a/multi_http_fetcher.h b/multi_http_fetcher.h
index 1972347..4328199 100644
--- a/multi_http_fetcher.h
+++ b/multi_http_fetcher.h
@@ -73,8 +73,7 @@
       fetchers_[current_index_]->Unpause();
   }
 
-  // These two function are overloaded in LibcurlHttp fetcher to speed
-  // testing.
+  // These functions are overloaded in LibcurlHttp fetcher for testing purposes.
   void set_idle_seconds(int seconds) {
     for (typename std::vector<std::tr1::shared_ptr<BaseHttpFetcher> >::iterator
              it = fetchers_.begin(),
@@ -89,6 +88,20 @@
       (*it)->set_retry_seconds(seconds);
     }
   }
+  void SetConnectionAsExpensive(bool is_expensive) {
+    for (typename std::vector<std::tr1::shared_ptr<BaseHttpFetcher> >::iterator
+             it = fetchers_.begin(),
+             e = fetchers_.end(); it != e; ++it) {
+      (*it)->SetConnectionAsExpensive(is_expensive);
+    }
+  }
+  void SetBuildType(bool is_official) {
+    for (typename std::vector<std::tr1::shared_ptr<BaseHttpFetcher> >::iterator
+             it = fetchers_.begin(),
+             e = fetchers_.end(); it != e; ++it) {
+      (*it)->SetBuildType(is_official);
+    }
+  }
 
  private:
   void SendTransferComplete(HttpFetcher* fetcher, bool successful) {
@@ -173,7 +186,7 @@
   }
 
   // If true, do not send any more data or TransferComplete to the delegate.
-  bool sent_transfer_complete_;  
+  bool sent_transfer_complete_;
 
   RangesVect ranges_;
   std::vector<std::tr1::shared_ptr<BaseHttpFetcher> > fetchers_;