Allow file:// payload urls on non-Brillo boards.

Non-Brillo targets will initially provide payloads from a local file
plus an offset and size. This patch allows file:// URIs on those
targets.

Bug: 25631949
TEST=`update_engine_client --update --follow --payload=file:///some/file`

Change-Id: I90f807b385b9c39ede80faa335e61388a06d58ea
diff --git a/common/libcurl_http_fetcher.cc b/common/libcurl_http_fetcher.cc
index b735703..761b74e 100644
--- a/common/libcurl_http_fetcher.cc
+++ b/common/libcurl_http_fetcher.cc
@@ -63,21 +63,26 @@
 
 bool LibcurlHttpFetcher::GetProxyType(const string& proxy,
                                       curl_proxytype* out_type) {
-  if (base::StartsWith(proxy, "socks5://", base::CompareCase::SENSITIVE) ||
-      base::StartsWith(proxy, "socks://", base::CompareCase::SENSITIVE)) {
+  if (base::StartsWith(
+          proxy, "socks5://", base::CompareCase::INSENSITIVE_ASCII) ||
+      base::StartsWith(
+          proxy, "socks://", base::CompareCase::INSENSITIVE_ASCII)) {
     *out_type = CURLPROXY_SOCKS5_HOSTNAME;
     return true;
   }
-  if (base::StartsWith(proxy, "socks4://", base::CompareCase::SENSITIVE)) {
+  if (base::StartsWith(
+          proxy, "socks4://", base::CompareCase::INSENSITIVE_ASCII)) {
     *out_type = CURLPROXY_SOCKS4A;
     return true;
   }
-  if (base::StartsWith(proxy, "http://", base::CompareCase::SENSITIVE) ||
-      base::StartsWith(proxy, "https://", base::CompareCase::SENSITIVE)) {
+  if (base::StartsWith(
+          proxy, "http://", base::CompareCase::INSENSITIVE_ASCII) ||
+      base::StartsWith(
+          proxy, "https://", base::CompareCase::INSENSITIVE_ASCII)) {
     *out_type = CURLPROXY_HTTP;
     return true;
   }
-  if (base::StartsWith(proxy, kNoProxy, base::CompareCase::SENSITIVE)) {
+  if (base::StartsWith(proxy, kNoProxy, base::CompareCase::INSENSITIVE_ASCII)) {
     // known failure case. don't log.
     return false;
   }
@@ -193,10 +198,22 @@
   // Lock down the appropriate curl options for HTTP or HTTPS depending on
   // the url.
   if (hardware_->IsOfficialBuild()) {
-    if (base::StartsWith(url_, "http://", base::CompareCase::INSENSITIVE_ASCII))
+    if (base::StartsWith(
+            url_, "http://", base::CompareCase::INSENSITIVE_ASCII)) {
       SetCurlOptionsForHttp();
-    else
+    } else if (base::StartsWith(
+                   url_, "https://", base::CompareCase::INSENSITIVE_ASCII)) {
       SetCurlOptionsForHttps();
+#if !defined(__CHROMEOS__) && !defined(__BRILLO__)
+    } else if (base::StartsWith(
+                   url_, "file://", base::CompareCase::INSENSITIVE_ASCII)) {
+      SetCurlOptionsForFile();
+#endif
+    } else {
+      LOG(ERROR) << "Received invalid URI: " << url_;
+      // Lock down to no protocol supported for the transfer.
+      CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_PROTOCOLS, 0), CURLE_OK);
+    }
   } else {
     LOG(INFO) << "Not setting http(s) curl options because we are "
               << "running a dev/test image";
@@ -243,6 +260,15 @@
   }
 }
 
+// Lock down only the protocol in case of a local file.
+void LibcurlHttpFetcher::SetCurlOptionsForFile() {
+  LOG(INFO) << "Setting up curl options for FILE";
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_PROTOCOLS, CURLPROTO_FILE),
+           CURLE_OK);
+  CHECK_EQ(
+      curl_easy_setopt(curl_handle_, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_FILE),
+      CURLE_OK);
+}
 
 // Begins the transfer, which must not have already been started.
 void LibcurlHttpFetcher::BeginTransfer(const string& url) {
@@ -577,9 +603,12 @@
 
 void LibcurlHttpFetcher::GetHttpResponseCode() {
   long http_response_code = 0;  // NOLINT(runtime/int) - curl needs long.
-  if (curl_easy_getinfo(curl_handle_,
-                        CURLINFO_RESPONSE_CODE,
-                        &http_response_code) == CURLE_OK) {
+  if (base::StartsWith(url_, "file://", base::CompareCase::INSENSITIVE_ASCII)) {
+    // Fake out a valid response code for file:// URLs.
+    http_response_code_ = 299;
+  } else if (curl_easy_getinfo(curl_handle_,
+                               CURLINFO_RESPONSE_CODE,
+                               &http_response_code) == CURLE_OK) {
     http_response_code_ = static_cast<int>(http_response_code);
   }
 }
diff --git a/common/libcurl_http_fetcher.h b/common/libcurl_http_fetcher.h
index 900c973..66dbb18 100644
--- a/common/libcurl_http_fetcher.h
+++ b/common/libcurl_http_fetcher.h
@@ -165,6 +165,9 @@
   // Sets the curl options for HTTPS URL.
   void SetCurlOptionsForHttps();
 
+  // Sets the curl options for file URI.
+  void SetCurlOptionsForFile();
+
   // Convert a proxy URL into a curl proxy type, if applicable. Returns true iff
   // conversion was successful, false otherwise (in which case nothing is
   // written to |out_type|).