summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkkhorimoto <kkhorimoto@google.com>2015-05-26 13:28:21 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-26 20:28:59 +0000
commit555f740c0f81262c44a5b1e48f1d56af7f6baca9 (patch)
tree7ecfc986723a2c0b173ce3b221fa632f53cd9c6d
parentee92e3890448e5d0fa00634d18308f0adb079211 (diff)
downloadchromium_src-555f740c0f81262c44a5b1e48f1d56af7f6baca9.zip
chromium_src-555f740c0f81262c44a5b1e48f1d56af7f6baca9.tar.gz
chromium_src-555f740c0f81262c44a5b1e48f1d56af7f6baca9.tar.bz2
Created HttpResponseHeadersUtil.
Since the net stack is not an option with WKWebView, generate headers from the WKNavigationResponse and pass them to the web state. Among other things, this will enable the web state to have an accurate MIME type. BUG=478058 Review URL: https://codereview.chromium.org/1126843002 Cr-Commit-Position: refs/heads/master@{#331422}
-rw-r--r--ios/net/http_response_headers_util.h28
-rw-r--r--ios/net/http_response_headers_util.mm46
-rw-r--r--ios/net/http_response_headers_util_unittest.mm57
-rw-r--r--ios/net/ios_net.gyp2
-rw-r--r--ios/net/ios_net_unittests.gyp1
-rw-r--r--ios/web/web_state/ui/crw_wk_web_view_web_controller.mm14
-rw-r--r--ios/web/web_state/web_state_impl.h3
7 files changed, 151 insertions, 0 deletions
diff --git a/ios/net/http_response_headers_util.h b/ios/net/http_response_headers_util.h
new file mode 100644
index 0000000..4bc0019
--- /dev/null
+++ b/ios/net/http_response_headers_util.h
@@ -0,0 +1,28 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_NET_HTTP_RESPONSE_HEADERS_UTIL_H_
+#define IOS_NET_HTTP_RESPONSE_HEADERS_UTIL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "net/http/http_response_headers.h"
+
+@class NSHTTPURLResponse;
+
+namespace net {
+
+// Placeholder status description since the actual text from the headers is not
+// available.
+extern const std::string kDummyHttpStatusDescription;
+
+// Constructs a net::HttpResponseHeaders from |response|.
+// Note: The HTTP version and the status code description are not accessible
+// from NSHTTPURLResponse, so HTTP/1.0 and kDummyHttpStatusDescription will
+// be used in the status line instead.
+scoped_refptr<HttpResponseHeaders> CreateHeadersFromNSHTTPURLResponse(
+ NSHTTPURLResponse* response);
+
+} // namespace net
+
+#endif // IOS_NET_HTTP_RESPONSE_HEADERS_UTIL_H_
diff --git a/ios/net/http_response_headers_util.mm b/ios/net/http_response_headers_util.mm
new file mode 100644
index 0000000..64d86b5
--- /dev/null
+++ b/ios/net/http_response_headers_util.mm
@@ -0,0 +1,46 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/net/http_response_headers_util.h"
+
+#include <Foundation/Foundation.h>
+
+#include "base/logging.h"
+#include "base/strings/sys_string_conversions.h"
+
+namespace {
+// String format used to create the http status line from the status code and
+// its localized description.
+NSString* const kHttpStatusLineFormat = @"HTTP %ld %s";
+// String format used to pass the header name/value pairs to the
+// HttpResponseHeaders.
+NSString* const kHeaderLineFormat = @"%@: %@";
+}
+
+namespace net {
+
+const std::string kDummyHttpStatusDescription = "DummyStatusDescription";
+
+scoped_refptr<HttpResponseHeaders> CreateHeadersFromNSHTTPURLResponse(
+ NSHTTPURLResponse* response) {
+ DCHECK(response);
+ // Create the status line and initialize the headers.
+ NSInteger status_code = response.statusCode;
+ std::string status_line = base::SysNSStringToUTF8([NSString
+ stringWithFormat:kHttpStatusLineFormat, static_cast<long>(status_code),
+ kDummyHttpStatusDescription.c_str()]);
+ scoped_refptr<HttpResponseHeaders> http_headers(
+ new HttpResponseHeaders(status_line));
+ // Iterate through |response|'s headers and add them to |http_headers|.
+ [response.allHeaderFields
+ enumerateKeysAndObjectsUsingBlock:^(NSString* header_name,
+ NSString* value, BOOL*) {
+ NSString* header_line =
+ [NSString stringWithFormat:kHeaderLineFormat, header_name, value];
+ http_headers->AddHeader(base::SysNSStringToUTF8(header_line));
+ }];
+ return http_headers.Pass();
+}
+
+} // namespae net
diff --git a/ios/net/http_response_headers_util_unittest.mm b/ios/net/http_response_headers_util_unittest.mm
new file mode 100644
index 0000000..27dfcb8
--- /dev/null
+++ b/ios/net/http_response_headers_util_unittest.mm
@@ -0,0 +1,57 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/net/http_response_headers_util.h"
+
+#import <Foundation/Foundation.h>
+
+#include <algorithm>
+
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/sys_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+// Returns true if all the information in |http_response| is present in
+// |http_response_headers|.
+bool AreHeadersEqual(NSHTTPURLResponse* http_response,
+ HttpResponseHeaders* http_response_headers) {
+ if (!http_response || !http_response_headers)
+ return false;
+ if (http_response.statusCode != http_response_headers->response_code())
+ return false;
+ __block bool all_headers_present = true;
+ [http_response.allHeaderFields
+ enumerateKeysAndObjectsUsingBlock:^(NSString* header_name,
+ NSString* header_value, BOOL* stop) {
+ std::string value;
+ http_response_headers->GetNormalizedHeader(
+ base::SysNSStringToUTF8(header_name), &value);
+ all_headers_present = (value == base::SysNSStringToUTF8(header_value));
+ *stop = !all_headers_present;
+ }];
+ return all_headers_present;
+}
+
+// Tests that HttpResponseHeaders created from NSHTTPURLResponses successfully
+// copy over the status code and the header names and values.
+TEST(HttpResponseHeadersUtilTest, CreateHeadersFromNSHTTPURLResponse) {
+ base::scoped_nsobject<NSHTTPURLResponse> http_response(
+ [[NSHTTPURLResponse alloc] initWithURL:[NSURL URLWithString:@"test.com"]
+ statusCode:200
+ HTTPVersion:@"HTTP/1.1"
+ headerFields:@{
+ @"headerName1" : @"headerValue1",
+ @"headerName2" : @"headerValue2",
+ @"headerName3" : @"headerValue3",
+ }]);
+ scoped_refptr<HttpResponseHeaders> http_response_headers =
+ CreateHeadersFromNSHTTPURLResponse(http_response);
+ EXPECT_TRUE(
+ AreHeadersEqual(http_response.get(), http_response_headers.get()));
+}
+
+} // namespace net.
diff --git a/ios/net/ios_net.gyp b/ios/net/ios_net.gyp
index 6208ce9..bd2e153 100644
--- a/ios/net/ios_net.gyp
+++ b/ios/net/ios_net.gyp
@@ -44,6 +44,8 @@
'crn_http_url_response.mm',
'http_protocol_logging.h',
'http_protocol_logging.mm',
+ 'http_response_headers_util.h',
+ 'http_response_headers_util.mm',
'nsurlrequest_util.h',
'nsurlrequest_util.mm',
'protocol_handler_util.h',
diff --git a/ios/net/ios_net_unittests.gyp b/ios/net/ios_net_unittests.gyp
index 8818b33..98d2410 100644
--- a/ios/net/ios_net_unittests.gyp
+++ b/ios/net/ios_net_unittests.gyp
@@ -26,6 +26,7 @@
'cookies/cookie_creation_time_manager_unittest.mm',
'cookies/cookie_store_ios_unittest.mm',
'cookies/system_cookie_util_unittest.mm',
+ 'http_response_headers_util_unittest.mm',
'nsurlrequest_util_unittest.mm',
'protocol_handler_util_unittest.mm',
'url_scheme_util_unittest.mm',
diff --git a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm
index c08ccab..7922cd6 100644
--- a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm
+++ b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/strings/sys_string_conversions.h"
#include "base/values.h"
+#import "ios/net/http_response_headers_util.h"
#import "ios/web/crw_network_activity_indicator_manager.h"
#import "ios/web/navigation/crw_session_controller.h"
#include "ios/web/navigation/web_load_params.h"
@@ -946,6 +947,19 @@ NSString* const kScriptImmediateName = @"crwebinvokeimmediate";
decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse
decisionHandler:
(void (^)(WKNavigationResponsePolicy))handler {
+ if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) {
+ // Create HTTP headers from the response.
+ // TODO(kkhorimoto): Due to the limited interface of NSHTTPURLResponse, some
+ // data in the HttpResponseHeaders generated here is inexact. Once
+ // UIWebView is no longer supported, update WebState's implementation so
+ // that the Content-Language and the MIME type can be set without using this
+ // imperfect conversion.
+ scoped_refptr<net::HttpResponseHeaders> HTTPHeaders =
+ net::CreateHeadersFromNSHTTPURLResponse(
+ static_cast<NSHTTPURLResponse*>(navigationResponse.response));
+ self.webStateImpl->OnHttpResponseHeadersReceived(
+ HTTPHeaders.get(), net::GURLWithNSURL(navigationResponse.response.URL));
+ }
if (navigationResponse.isForMainFrame)
self.documentMIMEType = navigationResponse.response.MIMEType;
handler(navigationResponse.canShowMIMEType ? WKNavigationResponsePolicyAllow :
diff --git a/ios/web/web_state/web_state_impl.h b/ios/web/web_state/web_state_impl.h
index b8695ec..067f96a 100644
--- a/ios/web/web_state/web_state_impl.h
+++ b/ios/web/web_state/web_state_impl.h
@@ -164,6 +164,9 @@ class WebStateImpl : public WebState, public NavigationManagerDelegate {
const base::string16& GetTitle() const;
// Gets the HTTP response headers associated with the current page.
+ // NOTE: For a WKWebView-based WebState, these headers are generated via
+ // net::CreateHeadersFromNSHTTPURLResponse(); see comments in
+ // http_response_headers_util.h for limitations.
net::HttpResponseHeaders* GetHttpResponseHeaders() const;
// Called when HTTP response headers are received.