Request uncompressed images from data reduction proxy when saving.

When user saves an image, add headers requesting a pass through
from the data reduction proxy. Without this, images will be
saved in webp format which is not supported by most image viewers.
BUG=464436

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

Cr-Commit-Position: refs/heads/master@{#319681}
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index fc76b17..e83ab0a 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -695,9 +695,10 @@
                                   IDS_CONTENT_CONTEXT_COPYIMAGELOCATION);
   menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYIMAGE,
                                   IDS_CONTENT_CONTEXT_COPYIMAGE);
-  if (!browser_context_->IsOffTheRecord() &&
+  DataReductionProxyChromeSettings* settings =
       DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
-          browser_context_)->CanUseDataReductionProxy(params_.src_url)) {
+          browser_context_);
+  if (settings && settings->CanUseDataReductionProxy(params_.src_url)) {
     menu_model_.AddItemWithStringId(
         IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB,
         IDS_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB);
@@ -1390,7 +1391,17 @@
         RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU);
         const GURL& url = params_.src_url;
         content::Referrer referrer = CreateSaveAsReferrer(url, params_);
-        source_web_contents_->SaveFrame(url, referrer);
+
+        std::string headers;
+        DataReductionProxyChromeSettings* settings =
+            DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+                browser_context_);
+        if (params_.media_type == WebContextMenuData::MediaTypeImage &&
+            settings && settings->CanUseDataReductionProxy(params_.src_url)) {
+          headers = data_reduction_proxy::kDataReductionPassThroughHeader;
+        }
+
+        source_web_contents_->SaveFrameWithHeaders(url, referrer, headers);
       }
       break;
     }
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 8e7d5b7..e89f17a 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2302,6 +2302,12 @@
 
 void WebContentsImpl::SaveFrame(const GURL& url,
                                 const Referrer& referrer) {
+  SaveFrameWithHeaders(url, referrer, std::string());
+}
+
+void WebContentsImpl::SaveFrameWithHeaders(const GURL& url,
+                                           const Referrer& referrer,
+                                           const std::string& headers) {
   if (!GetLastCommittedURL().is_valid())
     return;
   if (delegate_ && delegate_->SaveFrame(url, referrer))
@@ -2325,10 +2331,22 @@
       DownloadUrlParameters::FromWebContents(this, url));
   params->set_referrer(referrer);
   params->set_post_id(post_id);
-  params->set_prefer_cache(true);
   if (post_id >= 0)
     params->set_method("POST");
   params->set_prompt(true);
+
+  if (headers.empty()) {
+    params->set_prefer_cache(true);
+  } else {
+    std::vector<std::string> key_value_list;
+    base::SplitString(headers, '\n', &key_value_list);
+    for (const auto& key_value : key_value_list) {
+      std::vector<std::string> pair;
+      base::SplitString(key_value, ':', &pair);
+      DCHECK_EQ(2ul, pair.size());
+      params->add_request_header(pair[0], pair[1]);
+    }
+  }
   dlm->DownloadUrl(params.Pass());
 }
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index c2777eb..e28edd2 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -306,6 +306,9 @@
                 const base::FilePath& dir_path,
                 SavePageType save_type) override;
   void SaveFrame(const GURL& url, const Referrer& referrer) override;
+  void SaveFrameWithHeaders(const GURL& url,
+                            const Referrer& referrer,
+                            const std::string& headers) override;
   void GenerateMHTML(const base::FilePath& file,
                      const base::Callback<void(int64)>& callback) override;
   const std::string& GetContentsMimeType() const override;
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index cdb7de0e..abdda45 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -474,10 +474,18 @@
                         const base::FilePath& dir_path,
                         SavePageType save_type) = 0;
 
-  // Saves the given frame's URL to the local filesystem..
+  // Saves the given frame's URL to the local filesystem.
   virtual void SaveFrame(const GURL& url,
                          const Referrer& referrer) = 0;
 
+  // Saves the given frame's URL to the local filesystem. The headers, if
+  // provided, is used to make a request to the URL rather than using cache.
+  // Format of |headers| is a new line separated list of key value pairs:
+  // "<key1>: <value1>\n<key2>: <value2>".
+  virtual void SaveFrameWithHeaders(const GURL& url,
+                                    const Referrer& referrer,
+                                    const std::string& headers) = 0;
+
   // Generate an MHTML representation of the current page in the given file.
   virtual void GenerateMHTML(
       const base::FilePath& file,