Generate an etag for chrome-extension:// file requests.

This allows code downstream to use those headers as caching
signals, and optionally cache extension files, or files
derived from extension files.

Whenever an etag is sent, send "cache-control: no-cache"
so that downstream users know it's a good idea to
revalidate.

One downstream is PNaCl, which would like to use standard
cache-related http response headers to determine how
to cache translations of bitcode.  Currently, only bitcode
downloaded from web servers have such headers, and this CL
adds headers for bitcode "downloaded" from chrome extensions.

See chromium-dev discussion: "Add to HttpResponse headers
for chrome/browser/extensions/extension_protocols"


BUG=https://code.google.com/p/nativeclient/issues/detail?id=2992

Review URL: https://chromiumcodereview.appspot.com/15963003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203830 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc
index 9f70a06..6848b56 100644
--- a/chrome/browser/extensions/extension_protocols_unittest.cc
+++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/file_util.h"
 #include "base/message_loop.h"
+#include "base/string_util.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_info_map.h"
 #include "chrome/browser/extensions/extension_protocols.h"
@@ -63,6 +64,27 @@
   return extension;
 }
 
+scoped_refptr<Extension> CreateTestResponseHeaderExtension() {
+  DictionaryValue manifest;
+  manifest.SetString("name", "An extension with web-accessible resources");
+  manifest.SetString("version", "2");
+
+  ListValue* web_accessible_list = new ListValue();
+  web_accessible_list->AppendString("test.dat");
+  manifest.Set("web_accessible_resources", web_accessible_list);
+
+  base::FilePath path;
+  EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+  path = path.AppendASCII("extensions").AppendASCII("response_headers");
+
+  std::string error;
+  scoped_refptr<Extension> extension(
+      Extension::Create(path, Manifest::UNPACKED, manifest,
+                        Extension::NO_FLAGS, &error));
+  EXPECT_TRUE(extension.get()) << error;
+  return extension;
+}
+
 class ExtensionProtocolTest : public testing::Test {
  public:
   ExtensionProtocolTest()
@@ -215,4 +237,38 @@
   }
 }
 
+// Tests that a URL request for resource from an extension returns a few
+// expected response headers.
+TEST_F(ExtensionProtocolTest, ResourceRequestResponseHeaders) {
+  // Register a non-incognito extension protocol handler.
+  SetProtocolHandler(false);
+
+  scoped_refptr<Extension> extension = CreateTestResponseHeaderExtension();
+  extension_info_map_->AddExtension(extension, base::Time::Now(), false);
+
+  {
+    net::URLRequest request(extension->GetResourceURL("test.dat"),
+                            &test_delegate_,
+                            resource_context_.GetRequestContext());
+    StartRequest(&request, ResourceType::MEDIA);
+    EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
+
+    // Check that cache-related headers are set.
+    std::string etag;
+    request.GetResponseHeaderByName("ETag", &etag);
+    EXPECT_TRUE(StartsWithASCII(etag, "\"", false));
+    EXPECT_TRUE(EndsWith(etag, "\"", false));
+
+    std::string revalidation_header;
+    request.GetResponseHeaderByName("cache-control", &revalidation_header);
+    EXPECT_EQ("no-cache", revalidation_header);
+
+    // We set test.dat as web-accessible, so it should have a CORS header.
+    std::string access_control;
+    request.GetResponseHeaderByName("Access-Control-Allow-Origin",
+                                    &access_control);
+    EXPECT_EQ("*", access_control);
+  }
+}
+
 }  // namespace extensions