From d8bc364a3ad2c83ed9638c7033e3f798ebadbdcd Mon Sep 17 00:00:00 2001 From: "mef@chromium.org" Date: Tue, 5 Aug 2014 21:03:12 +0000 Subject: Add method getAllHeaders to get HttpUrlRequest response headers. It handles multiple headers with the same name. For compatibility with HttpUrlConnection it includes Http status line as value for NULL key. BUG=390267 Review URL: https://codereview.chromium.org/423163007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287597 0039d316-1c4b-4281-b951-d872f2087c98 --- .../chromium/net/HttpUrlConnectionUrlRequest.java | 9 +++++- .../java/src/org/chromium/net/HttpUrlRequest.java | 8 ++++++ .../java/src/org/chromium/net/UrlRequest.java | 30 ++++++++++++++++++++ .../cronet/android/org_chromium_net_UrlRequest.cc | 33 ++++++++++++++++++++++ .../cronet_sample_apk/CronetSampleActivity.java | 1 + components/cronet/android/url_request_peer.cc | 7 +++++ components/cronet/android/url_request_peer.h | 4 +++ 7 files changed, 91 insertions(+), 1 deletion(-) diff --git a/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java index 33c940c..2bae943 100644 --- a/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java +++ b/components/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java @@ -476,7 +476,6 @@ class HttpUrlConnectionUrlRequest implements HttpUrlRequest { return mContentType; } - @Override public String getHeader(String name) { if (mConnection == null) { @@ -492,6 +491,14 @@ class HttpUrlConnectionUrlRequest implements HttpUrlRequest { return null; } + @Override + public Map> getAllHeaders() { + if (mConnection == null) { + throw new IllegalStateException("Response headers not available"); + } + return mConnection.getHeaderFields(); + } + private void validateNotStarted() { if (mStarted) { throw new IllegalStateException("Request already started"); diff --git a/components/cronet/android/java/src/org/chromium/net/HttpUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/HttpUrlRequest.java index fbf5178..6501d19 100644 --- a/components/cronet/android/java/src/org/chromium/net/HttpUrlRequest.java +++ b/components/cronet/android/java/src/org/chromium/net/HttpUrlRequest.java @@ -7,6 +7,8 @@ package org.chromium.net; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; +import java.util.List; +import java.util.Map; /** * HTTP request (GET or POST). @@ -134,6 +136,12 @@ public interface HttpUrlRequest { */ String getHeader(String name); + /** + * Returns an unmodifiable map of the response-header fields and values. + * The null key is mapped to the HTTP status line for compatibility with + * HttpUrlConnection. + */ + Map> getAllHeaders(); /** * Returns the exception that occurred while executing the request of null diff --git a/components/cronet/android/java/src/org/chromium/net/UrlRequest.java b/components/cronet/android/java/src/org/chromium/net/UrlRequest.java index 9aef008..0d978a4 100644 --- a/components/cronet/android/java/src/org/chromium/net/UrlRequest.java +++ b/components/cronet/android/java/src/org/chromium/net/UrlRequest.java @@ -15,7 +15,9 @@ import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -276,6 +278,14 @@ public class UrlRequest { return nativeGetHeader(mUrlRequestPeer, name); } + // All response headers. + public Map> getAllHeaders() { + validateHeadersAvailable(); + ResponseHeadersMap result = new ResponseHeadersMap(); + nativeGetAllHeaders(mUrlRequestPeer, result); + return result; + } + /** * A callback invoked when the first chunk of the response has arrived. */ @@ -335,6 +345,19 @@ public class UrlRequest { } } + /** + * Appends header |name| with value |value| to |headersMap|. + */ + @SuppressWarnings("unused") + @CalledByNative + private void onAppendResponseHeader(ResponseHeadersMap headersMap, + String name, String value) { + if (!headersMap.containsKey(name)) { + headersMap.put(name, new ArrayList()); + } + headersMap.get(name).add(value); + } + private void validateNotRecycled() { if (mRecycled) { throw new IllegalStateException("Accessing recycled request"); @@ -389,4 +412,11 @@ public class UrlRequest { private native long nativeGetContentLength(long urlRequestPeer); private native String nativeGetHeader(long urlRequestPeer, String name); + + private native void nativeGetAllHeaders(long urlRequestPeer, + ResponseHeadersMap headers); + + // Explicit class to work around JNI-generator generics confusion. + private class ResponseHeadersMap extends HashMap> { + } } diff --git a/components/cronet/android/org_chromium_net_UrlRequest.cc b/components/cronet/android/org_chromium_net_UrlRequest.cc index f96f164..8ec8b7a 100644 --- a/components/cronet/android/org_chromium_net_UrlRequest.cc +++ b/components/cronet/android/org_chromium_net_UrlRequest.cc @@ -12,6 +12,7 @@ #include "jni/UrlRequest_jni.h" #include "net/base/net_errors.h" #include "net/base/request_priority.h" +#include "net/http/http_response_headers.h" using base::android::ConvertUTF8ToJavaString; @@ -307,4 +308,36 @@ static jstring GetHeader( } } +static void GetAllHeaders(JNIEnv* env, + jobject object, + jlong urlRequestPeer, + jobject headersMap) { + URLRequestPeer* request = reinterpret_cast(urlRequestPeer); + if (request == NULL) + return; + + net::HttpResponseHeaders* headers = request->GetResponseHeaders(); + if (headers == NULL) + return; + + void* iter = NULL; + std::string header_name; + std::string header_value; + while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) { + ScopedJavaLocalRef name = + ConvertUTF8ToJavaString(env, header_name); + ScopedJavaLocalRef value = + ConvertUTF8ToJavaString(env, header_value); + Java_UrlRequest_onAppendResponseHeader( + env, object, headersMap, name.Release(), value.Release()); + } + + // Some implementations (notably HttpURLConnection) include a mapping for the + // null key; in HTTP's case, this maps to the HTTP status line. + ScopedJavaLocalRef status_line = + ConvertUTF8ToJavaString(env, headers->GetStatusLine()); + Java_UrlRequest_onAppendResponseHeader( + env, object, headersMap, NULL, status_line.Release()); +} + } // namespace cronet diff --git a/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleActivity.java b/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleActivity.java index 5e1a812..9676278 100644 --- a/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleActivity.java +++ b/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/CronetSampleActivity.java @@ -98,6 +98,7 @@ public class CronetSampleActivity extends Activity { public void onResponseStarted(HttpUrlRequest request) { Log.i(TAG, "****** Response Started, content length is " + request.getContentLength()); + Log.i(TAG, "*** Headers Are *** " + request.getAllHeaders()); } @Override diff --git a/components/cronet/android/url_request_peer.cc b/components/cronet/android/url_request_peer.cc index 4c81194..37385cf 100644 --- a/components/cronet/android/url_request_peer.cc +++ b/components/cronet/android/url_request_peer.cc @@ -67,6 +67,13 @@ std::string URLRequestPeer::GetHeader(const std::string &name) const { return value; } +net::HttpResponseHeaders* URLRequestPeer::GetResponseHeaders() const { + if (url_request_ == NULL) { + return NULL; + } + return url_request_->response_headers(); +} + void URLRequestPeer::Start() { context_->GetNetworkTaskRunner()->PostTask( FROM_HERE, diff --git a/components/cronet/android/url_request_peer.h b/components/cronet/android/url_request_peer.h index e8d79a6..5aa265d 100644 --- a/components/cronet/android/url_request_peer.h +++ b/components/cronet/android/url_request_peer.h @@ -18,6 +18,7 @@ namespace net { class GrowableIOBuffer; +class HttpResponseHeaders; class UploadDataStream; } // namespace net @@ -90,6 +91,9 @@ class URLRequestPeer : public net::URLRequest::Delegate { // Returns the value of the specified response header. std::string GetHeader(const std::string& name) const; + // Get all response headers, as a HttpResponseHeaders object. + net::HttpResponseHeaders* GetResponseHeaders() const; + // Returns the overall number of bytes read. size_t bytes_read() const { return bytes_read_; } -- cgit v1.1