summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/api/streams_private/streams_private_api.cc29
-rw-r--r--chrome/browser/extensions/api/streams_private/streams_private_apitest.cc41
-rw-r--r--chrome/common/extensions/api/streams_private.idl7
-rw-r--r--chrome/test/data/extensions/api_test/streams_private/handle_mime_type/background.js20
-rw-r--r--chrome/test/data/extensions/api_test/streams_private/handle_mime_type/manifest.json1
-rw-r--r--content/browser/loader/resource_dispatcher_host_impl.cc9
-rw-r--r--content/browser/streams/stream.cc4
-rw-r--r--content/browser/streams/stream.h8
-rw-r--r--content/browser/streams/stream_handle_impl.cc12
-rw-r--r--content/browser/streams/stream_handle_impl.h6
-rw-r--r--content/public/browser/stream_handle.h7
11 files changed, 121 insertions, 23 deletions
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_api.cc b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
index 7909b11..9327399 100644
--- a/chrome/browser/extensions/api/streams_private/streams_private_api.cc
+++ b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
@@ -19,6 +19,31 @@
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_system.h"
+#include "net/http/http_response_headers.h"
+
+namespace {
+
+void CreateResponseHeadersDictionary(const net::HttpResponseHeaders* headers,
+ base::DictionaryValue* result) {
+ if (!headers)
+ return;
+
+ void* iter = NULL;
+ std::string header_name;
+ std::string header_value;
+ while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
+ base::Value* existing_value = NULL;
+ if (result->Get(header_name, &existing_value)) {
+ base::StringValue* existing_string_value =
+ static_cast<base::StringValue*>(existing_value);
+ existing_string_value->GetString()->append(", ").append(header_value);
+ } else {
+ result->SetString(header_name, header_value);
+ }
+ }
+}
+
+} // namespace
namespace extensions {
@@ -55,7 +80,9 @@ void StreamsPrivateAPI::ExecuteMimeTypeHandler(
if (expected_content_size <= INT_MAX)
size = expected_content_size;
info.expected_content_size = size;
- info.response_headers = stream->GetResponseHeaders();
+
+ CreateResponseHeadersDictionary(stream->GetResponseHeaders().get(),
+ &info.response_headers.additional_properties);
scoped_ptr<Event> event(
new Event(streams_private::OnExecuteMimeTypeHandler::kEventName,
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc b/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
index 378b924..fd418c9 100644
--- a/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
+++ b/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
@@ -61,6 +61,17 @@ scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
return response.PassAs<HttpResponse>();
}
+ // For relative path "/spreadsheet_path.xls", return success response with
+ // MIME type "application/xls".
+ if (request.relative_url == "/spreadsheet_path.xls") {
+ response->set_code(net::HTTP_OK);
+ response->set_content_type("application/msexcel");
+ // Test that multiple headers with the same name are merged.
+ response->AddCustomHeader("Test-Header", "part1");
+ response->AddCustomHeader("Test-Header", "part2");
+ return response.PassAs<HttpResponse>();
+ }
+
// For relative path "/text_path_attch.txt", return success response with
// MIME type "text/plain" and content "txt content". Also, set content
// disposition to be attachment.
@@ -380,4 +391,34 @@ IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, DirectDownload) {
EXPECT_TRUE(catcher.GetNextResult());
}
+// Tests that response headers are correctly passed to the API and that multiple
+// repsonse headers with the same name are merged correctly.
+IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, Headers) {
+#if defined(OS_WIN) && defined(USE_ASH)
+ // Disable this test in Metro+Ash for now (http://crbug.com/262796).
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
+ return;
+#endif
+
+ ASSERT_TRUE(LoadTestExtension()) << message_;
+
+ ResultCatcher catcher;
+
+ ui_test_utils::NavigateToURL(browser(),
+ test_server_->GetURL("/spreadsheet_path.xls"));
+
+ // Wait for the response from the test server.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // There should be no downloads started by the navigation.
+ DownloadManager* download_manager = GetDownloadManager();
+ std::vector<DownloadItem*> downloads;
+ download_manager->GetAllDownloads(&downloads);
+ ASSERT_EQ(0u, downloads.size());
+
+ // The test extension should receive onExecuteContentHandler event with MIME
+ // type 'application/msexcel' (and call chrome.test.notifySuccess).
+ EXPECT_TRUE(catcher.GetNextResult());
+}
+
} // namespace
diff --git a/chrome/common/extensions/api/streams_private.idl b/chrome/common/extensions/api/streams_private.idl
index e566def..2d3bada 100644
--- a/chrome/common/extensions/api/streams_private.idl
+++ b/chrome/common/extensions/api/streams_private.idl
@@ -22,8 +22,11 @@ namespace streamsPrivate {
// information on the size it will be -1.
long expectedContentSize;
- // The HTTP response headers of the intercepted request.
- DOMString responseHeaders;
+ // The HTTP response headers of the intercepted request stored as a
+ // dictionary mapping header name to header value. If a header name appears
+ // multiple times, the header values are merged in the dictionary and
+ // separated by a ", ".
+ object responseHeaders;
};
interface Events {
diff --git a/chrome/test/data/extensions/api_test/streams_private/handle_mime_type/background.js b/chrome/test/data/extensions/api_test/streams_private/handle_mime_type/background.js
index bb55f97..d7ccdd8 100644
--- a/chrome/test/data/extensions/api_test/streams_private/handle_mime_type/background.js
+++ b/chrome/test/data/extensions/api_test/streams_private/handle_mime_type/background.js
@@ -12,8 +12,24 @@ chrome.streamsPrivate.onExecuteMimeTypeHandler.addListener(
// the MIME type 'application/msword' means the test has succeeded.
if (params.mimeType == 'application/msword') {
var headers = params.responseHeaders;
- if (headers.indexOf('Content-Type: application/msword') == -1 ||
- headers.indexOf('HTTP/1.1 200 OK') == -1) {
+ if (headers['Content-Type'] != 'application/msword') {
+ chrome.test.notifyFail(
+ 'HTTP request header did not contain expected attributes.');
+ hasFailed = true;
+ } else {
+ chrome.test.notifyPass();
+ }
+ return;
+ }
+
+ // The tests are setup so resources with MIME type 'application/msexcel' are
+ // meant to be handled by the extension. The extension getting an event with
+ // the MIME type 'application/msexcel' means the test has succeeded. This also
+ // tests that repeated headers are correctly merged.
+ if (params.mimeType == 'application/msexcel') {
+ var headers = params.responseHeaders;
+ if (headers['Content-Type'] != 'application/msexcel' ||
+ headers['Test-Header'] != 'part1, part2') {
chrome.test.notifyFail(
'HTTP request header did not contain expected attributes.');
hasFailed = true;
diff --git a/chrome/test/data/extensions/api_test/streams_private/handle_mime_type/manifest.json b/chrome/test/data/extensions/api_test/streams_private/handle_mime_type/manifest.json
index bc7758f..3de039c 100644
--- a/chrome/test/data/extensions/api_test/streams_private/handle_mime_type/manifest.json
+++ b/chrome/test/data/extensions/api_test/streams_private/handle_mime_type/manifest.json
@@ -8,6 +8,7 @@
},
"mime_types": [
"application/msword",
+ "application/msexcel",
"text/plain"
],
"permissions": [
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 1199957..9234315 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -610,9 +610,6 @@ ResourceDispatcherHostImpl::MaybeInterceptAsStream(net::URLRequest* request,
ResourceResponse* response) {
ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
const std::string& mime_type = response->head.mime_type;
- std::string response_headers;
- if (response->head.headers)
- response->head.headers->GetNormalizedHeaders(&response_headers);
GURL origin;
std::string target_id;
@@ -639,8 +636,10 @@ ResourceDispatcherHostImpl::MaybeInterceptAsStream(net::URLRequest* request,
info->GetChildID(),
info->GetRouteID(),
target_id,
- handler->stream()->CreateHandle(request->url(), mime_type,
- response_headers),
+ handler->stream()->CreateHandle(
+ request->url(),
+ mime_type,
+ response->head.headers),
request->GetExpectedContentSize());
return handler.PassAs<ResourceHandler>();
}
diff --git a/content/browser/streams/stream.cc b/content/browser/streams/stream.cc
index ca0cf1b..d10770c 100644
--- a/content/browser/streams/stream.cc
+++ b/content/browser/streams/stream.cc
@@ -7,11 +7,13 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/values.h"
#include "content/browser/streams/stream_handle_impl.h"
#include "content/browser/streams/stream_read_observer.h"
#include "content/browser/streams/stream_registry.h"
#include "content/browser/streams/stream_write_observer.h"
#include "net/base/io_buffer.h"
+#include "net/http/http_response_headers.h"
namespace {
// Start throttling the connection at about 1MB.
@@ -161,7 +163,7 @@ Stream::StreamState Stream::ReadRawData(net::IOBuffer* buf,
scoped_ptr<StreamHandle> Stream::CreateHandle(
const GURL& original_url,
const std::string& mime_type,
- const std::string& response_headers) {
+ scoped_refptr<net::HttpResponseHeaders> response_headers) {
CHECK(!stream_handle_);
stream_handle_ = new StreamHandleImpl(weak_ptr_factory_.GetWeakPtr(),
original_url,
diff --git a/content/browser/streams/stream.h b/content/browser/streams/stream.h
index e439b72..e7e9586 100644
--- a/content/browser/streams/stream.h
+++ b/content/browser/streams/stream.h
@@ -13,6 +13,7 @@
#include "url/gurl.h"
namespace net {
+class HttpResponseHeaders;
class IOBuffer;
}
@@ -77,9 +78,10 @@ class CONTENT_EXPORT Stream : public base::RefCountedThreadSafe<Stream> {
// and STREAM_COMPLETE if the stream is finalized and all data has been read.
StreamState ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read);
- scoped_ptr<StreamHandle> CreateHandle(const GURL& original_url,
- const std::string& mime_type,
- const std::string& response_headers);
+ scoped_ptr<StreamHandle> CreateHandle(
+ const GURL& original_url,
+ const std::string& mime_type,
+ scoped_refptr<net::HttpResponseHeaders> response_headers);
void CloseHandle();
// Indicates whether there is space in the buffer to add more data.
diff --git a/content/browser/streams/stream_handle_impl.cc b/content/browser/streams/stream_handle_impl.cc
index cdba12b..d13bdc6 100644
--- a/content/browser/streams/stream_handle_impl.cc
+++ b/content/browser/streams/stream_handle_impl.cc
@@ -8,13 +8,15 @@
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
#include "content/browser/streams/stream.h"
+#include "net/http/http_response_headers.h"
namespace content {
-StreamHandleImpl::StreamHandleImpl(const base::WeakPtr<Stream>& stream,
- const GURL& original_url,
- const std::string& mime_type,
- const std::string& response_headers)
+StreamHandleImpl::StreamHandleImpl(
+ const base::WeakPtr<Stream>& stream,
+ const GURL& original_url,
+ const std::string& mime_type,
+ scoped_refptr<net::HttpResponseHeaders> response_headers)
: stream_(stream),
url_(stream->url()),
original_url_(original_url),
@@ -39,7 +41,7 @@ const std::string& StreamHandleImpl::GetMimeType() {
return mime_type_;
}
-const std::string& StreamHandleImpl::GetResponseHeaders() {
+scoped_refptr<net::HttpResponseHeaders> StreamHandleImpl::GetResponseHeaders() {
return response_headers_;
}
diff --git a/content/browser/streams/stream_handle_impl.h b/content/browser/streams/stream_handle_impl.h
index deb094f..fc8f5355 100644
--- a/content/browser/streams/stream_handle_impl.h
+++ b/content/browser/streams/stream_handle_impl.h
@@ -22,7 +22,7 @@ class StreamHandleImpl : public StreamHandle {
StreamHandleImpl(const base::WeakPtr<Stream>& stream,
const GURL& original_url,
const std::string& mime_type,
- const std::string& response_headers);
+ scoped_refptr<net::HttpResponseHeaders> response_headers);
virtual ~StreamHandleImpl();
private:
@@ -30,13 +30,13 @@ class StreamHandleImpl : public StreamHandle {
virtual const GURL& GetURL() OVERRIDE;
virtual const GURL& GetOriginalURL() OVERRIDE;
virtual const std::string& GetMimeType() OVERRIDE;
- virtual const std::string& GetResponseHeaders() OVERRIDE;
+ virtual scoped_refptr<net::HttpResponseHeaders> GetResponseHeaders() OVERRIDE;
base::WeakPtr<Stream> stream_;
GURL url_;
GURL original_url_;
std::string mime_type_;
- std::string response_headers_;
+ scoped_refptr<net::HttpResponseHeaders> response_headers_;
base::MessageLoopProxy* stream_message_loop_;
};
diff --git a/content/public/browser/stream_handle.h b/content/public/browser/stream_handle.h
index 877c51d..b87402e 100644
--- a/content/public/browser/stream_handle.h
+++ b/content/public/browser/stream_handle.h
@@ -6,9 +6,14 @@
#define CONTENT_PUBLIC_BROWSER_STREAM_HANDLE_H_
#include "base/callback.h"
+#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "url/gurl.h"
+namespace net {
+class HttpResponseHeaders;
+}
+
namespace content {
class CONTENT_EXPORT StreamHandle {
@@ -25,7 +30,7 @@ class CONTENT_EXPORT StreamHandle {
virtual const std::string& GetMimeType() = 0;
// Get the HTTP response headers associated with this Stream.
- virtual const std::string& GetResponseHeaders() = 0;
+ virtual scoped_refptr<net::HttpResponseHeaders> GetResponseHeaders() = 0;
};
} // namespace content