summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbryner@chromium.org <bryner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-22 19:47:19 +0000
committerbryner@chromium.org <bryner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-22 19:47:19 +0000
commit6d81b488e8cc5e10eaeca0a4ee4819dc3f469a24 (patch)
treee628aa40ac26d26a6a9a46374001be983e7a7f41
parentf19572134235f4cceb76e85e1c064ba668bbd3bd (diff)
downloadchromium_src-6d81b488e8cc5e10eaeca0a4ee4819dc3f469a24.zip
chromium_src-6d81b488e8cc5e10eaeca0a4ee4819dc3f469a24.tar.gz
chromium_src-6d81b488e8cc5e10eaeca0a4ee4819dc3f469a24.tar.bz2
Propagate the remote socket address to URLRequest and to ViewHostMsg_FrameNavigate.
This will be used to run pre-classification checks for client-side phishing detection, and will also enable the socket address to be exposed via the webRequest extension API. This is adapted from the original patch by pmarks on http://codereview.chromium.org/6369003/ . BUG=51663 TEST=added socket address checks to various unittests Review URL: http://codereview.chromium.org/6488010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75620 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/pickle.cc14
-rw-r--r--base/pickle.h4
-rw-r--r--base/pickle_unittest.cc6
-rw-r--r--chrome/browser/renderer_host/test/render_view_host_browsertest.cc43
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.cc2
-rw-r--r--chrome/common/common_param_traits.cc22
-rw-r--r--chrome/common/common_param_traits.h10
-rw-r--r--chrome/common/common_param_traits_unittest.cc14
-rw-r--r--chrome/common/render_messages.cc6
-rw-r--r--chrome/common/render_messages_params.cc6
-rw-r--r--chrome/common/render_messages_params.h4
-rw-r--r--chrome/renderer/render_view.cc2
-rw-r--r--content/browser/renderer_host/resource_dispatcher_host.cc1
-rw-r--r--net/base/host_port_pair.cc8
-rw-r--r--net/base/host_port_pair.h4
-rw-r--r--net/ftp/ftp_network_transaction.cc12
-rw-r--r--net/ftp/ftp_network_transaction_unittest.cc7
-rw-r--r--net/ftp/ftp_response_info.h4
-rw-r--r--net/http/http_cache_unittest.cc26
-rw-r--r--net/http/http_network_transaction_unittest.cc3
-rw-r--r--net/http/http_response_info.cc17
-rw-r--r--net/http/http_response_info.h10
-rw-r--r--net/http/http_stream_parser.cc11
-rw-r--r--net/socket/socket_test_util.cc2
-rw-r--r--net/spdy/spdy_http_stream.cc11
-rw-r--r--net/spdy/spdy_network_transaction_unittest.cc3
-rw-r--r--net/url_request/url_request.cc6
-rw-r--r--net/url_request/url_request.h5
-rw-r--r--net/url_request/url_request_ftp_job.cc8
-rw-r--r--net/url_request/url_request_ftp_job.h1
-rw-r--r--net/url_request/url_request_http_job.cc7
-rw-r--r--net/url_request/url_request_http_job.h1
-rw-r--r--net/url_request/url_request_job.cc5
-rw-r--r--net/url_request/url_request_job.h5
-rw-r--r--net/url_request/url_request_unittest.cc30
-rw-r--r--webkit/glue/resource_loader_bridge.h4
-rw-r--r--webkit/glue/weburlloader_impl.cc3
37 files changed, 318 insertions, 9 deletions
diff --git a/base/pickle.cc b/base/pickle.cc
index e7d5768..116d3f1 100644
--- a/base/pickle.cc
+++ b/base/pickle.cc
@@ -157,6 +157,20 @@ bool Pickle::ReadSize(void** iter, size_t* result) const {
return true;
}
+bool Pickle::ReadUInt16(void** iter, uint16* result) const {
+ DCHECK(iter);
+ if (!*iter)
+ *iter = const_cast<char*>(payload());
+
+ if (!IteratorHasRoomFor(*iter, sizeof(*result)))
+ return false;
+
+ memcpy(result, *iter, sizeof(*result));
+
+ UpdateIter(iter, sizeof(*result));
+ return true;
+}
+
bool Pickle::ReadUInt32(void** iter, uint32* result) const {
DCHECK(iter);
if (!*iter)
diff --git a/base/pickle.h b/base/pickle.h
index ad08b7c..052aa33 100644
--- a/base/pickle.h
+++ b/base/pickle.h
@@ -68,6 +68,7 @@ class Pickle {
bool ReadInt(void** iter, int* result) const;
bool ReadLong(void** iter, long* result) const;
bool ReadSize(void** iter, size_t* result) const;
+ bool ReadUInt16(void** iter, uint16* result) const;
bool ReadUInt32(void** iter, uint32* result) const;
bool ReadInt64(void** iter, int64* result) const;
bool ReadUInt64(void** iter, uint64* result) const;
@@ -97,6 +98,9 @@ class Pickle {
bool WriteSize(size_t value) {
return WriteBytes(&value, sizeof(value));
}
+ bool WriteUInt16(uint16 value) {
+ return WriteBytes(&value, sizeof(value));
+ }
bool WriteUInt32(uint32 value) {
return WriteBytes(&value, sizeof(value));
}
diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc
index 39eaa1b..51330c7 100644
--- a/base/pickle_unittest.cc
+++ b/base/pickle_unittest.cc
@@ -19,6 +19,7 @@ const char testdata[] = "AAA\0BBB\0";
const int testdatalen = arraysize(testdata) - 1;
const bool testbool1 = false;
const bool testbool2 = true;
+const uint16 testuint16 = 32123;
// checks that the result
void VerifyResult(const Pickle& pickle) {
@@ -42,6 +43,10 @@ void VerifyResult(const Pickle& pickle) {
EXPECT_TRUE(pickle.ReadBool(&iter, &outbool));
EXPECT_EQ(testbool2, outbool);
+ uint16 outuint16;
+ EXPECT_TRUE(pickle.ReadUInt16(&iter, &outuint16));
+ EXPECT_EQ(testuint16, outuint16);
+
const char* outdata;
int outdatalen;
EXPECT_TRUE(pickle.ReadData(&iter, &outdata, &outdatalen));
@@ -66,6 +71,7 @@ TEST(PickleTest, EncodeDecode) {
EXPECT_TRUE(pickle.WriteWString(testwstr));
EXPECT_TRUE(pickle.WriteBool(testbool1));
EXPECT_TRUE(pickle.WriteBool(testbool2));
+ EXPECT_TRUE(pickle.WriteUInt16(testuint16));
EXPECT_TRUE(pickle.WriteData(testdata, testdatalen));
// Over allocate BeginWriteData so we can test TrimWriteData.
diff --git a/chrome/browser/renderer_host/test/render_view_host_browsertest.cc b/chrome/browser/renderer_host/test/render_view_host_browsertest.cc
index 6e37723..3081786 100644
--- a/chrome/browser/renderer_host/test/render_view_host_browsertest.cc
+++ b/chrome/browser/renderer_host/test/render_view_host_browsertest.cc
@@ -9,10 +9,13 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_observer.h"
#include "chrome/browser/tab_contents/tab_specific_content_settings.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/common/render_messages_params.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
+#include "net/base/host_port_pair.h"
#include "net/test/test_server.h"
typedef std::pair<int, Value*> ExecuteDetailType;
@@ -223,3 +226,43 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostTest, RedirectLoopCookies) {
EXPECT_TRUE(tab_contents->GetTabSpecificContentSettings()->IsContentBlocked(
CONTENT_SETTINGS_TYPE_COOKIES));
}
+
+class RenderViewHostTestTabContentsObserver : public TabContentsObserver {
+ public:
+ explicit RenderViewHostTestTabContentsObserver(TabContents* tab_contents)
+ : TabContentsObserver(tab_contents),
+ navigation_count_(0) {}
+ virtual ~RenderViewHostTestTabContentsObserver() {}
+
+ virtual void DidNavigateMainFramePostCommit(
+ const NavigationController::LoadCommittedDetails& details,
+ const ViewHostMsg_FrameNavigate_Params& params) {
+ observed_socket_address_ = params.socket_address;
+ ++navigation_count_;
+ }
+
+ const net::HostPortPair& observed_socket_address() const {
+ return observed_socket_address_;
+ }
+
+ int navigation_count() const { return navigation_count_; }
+
+ private:
+ net::HostPortPair observed_socket_address_;
+ int navigation_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderViewHostTestTabContentsObserver);
+};
+
+IN_PROC_BROWSER_TEST_F(RenderViewHostTest, FrameNavigateSocketAddress) {
+ ASSERT_TRUE(test_server()->Start());
+ RenderViewHostTestTabContentsObserver observer(
+ browser()->GetSelectedTabContents());
+
+ GURL test_url = test_server()->GetURL("files/simple.html");
+ ui_test_utils::NavigateToURL(browser(), test_url);
+
+ EXPECT_EQ(test_server()->host_port_pair().ToString(),
+ observer.observed_socket_address().ToString());
+ EXPECT_EQ(1, observer.navigation_count());
+}
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.cc b/chrome/browser/renderer_host/test/test_render_view_host.cc
index 4bab6c8..a711ff7 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.cc
+++ b/chrome/browser/renderer_host/test/test_render_view_host.cc
@@ -98,6 +98,8 @@ void TestRenderViewHost::SendNavigateWithTransition(
params.is_content_filtered = false;
params.was_within_same_page = false;
params.http_status_code = 0;
+ params.socket_address.set_host("2001:db8::1");
+ params.socket_address.set_port(80);
ViewHostMsg_FrameNavigate msg(1, params);
OnMsgNavigate(msg);
diff --git a/chrome/common/common_param_traits.cc b/chrome/common/common_param_traits.cc
index 64fa35c9..042b2ab 100644
--- a/chrome/common/common_param_traits.cc
+++ b/chrome/common/common_param_traits.cc
@@ -11,6 +11,7 @@
#include "chrome/common/thumbnail_score.h"
#include "chrome/common/web_apps.h"
#include "googleurl/src/gurl.h"
+#include "net/base/host_port_pair.h"
#include "net/base/upload_data.h"
#include "printing/backend/print_backend.h"
#include "printing/native_metafile.h"
@@ -290,6 +291,27 @@ void ParamTraits<WebApplicationInfo>::Log(const WebApplicationInfo& p,
l->append("<WebApplicationInfo>");
}
+void ParamTraits<net::HostPortPair>::Write(Message* m, const param_type& p) {
+ WriteParam(m, p.host());
+ WriteParam(m, p.port());
+}
+
+bool ParamTraits<net::HostPortPair>::Read(const Message* m, void** iter,
+ param_type* r) {
+ std::string host;
+ uint16 port;
+ if (!ReadParam(m, iter, &host) || !ReadParam(m, iter, &port))
+ return false;
+
+ r->set_host(host);
+ r->set_port(port);
+ return true;
+}
+
+void ParamTraits<net::HostPortPair>::Log(const param_type& p, std::string* l) {
+ l->append(p.ToString());
+}
+
void ParamTraits<net::URLRequestStatus>::Write(Message* m,
const param_type& p) {
WriteParam(m, static_cast<int>(p.status()));
diff --git a/chrome/common/common_param_traits.h b/chrome/common/common_param_traits.h
index f1e8cb0..860dcc6 100644
--- a/chrome/common/common_param_traits.h
+++ b/chrome/common/common_param_traits.h
@@ -50,6 +50,7 @@ class Size;
} // namespace gfx
namespace net {
+class HostPortPair;
class UploadData;
class URLRequestStatus;
}
@@ -263,6 +264,15 @@ struct ParamTraits<TransportDIB::Id> {
};
#endif
+// Traits for HostPortPair
+template<>
+struct ParamTraits<net::HostPortPair> {
+ typedef net::HostPortPair param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
// Traits for URLRequestStatus
template <>
struct ParamTraits<net::URLRequestStatus> {
diff --git a/chrome/common/common_param_traits_unittest.cc b/chrome/common/common_param_traits_unittest.cc
index a11ddd1..9a95c0f0 100644
--- a/chrome/common/common_param_traits_unittest.cc
+++ b/chrome/common/common_param_traits_unittest.cc
@@ -12,6 +12,7 @@
#include "googleurl/src/gurl.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_utils.h"
+#include "net/base/host_port_pair.h"
#include "printing/backend/print_backend.h"
#include "printing/native_metafile.h"
#include "printing/page_range.h"
@@ -286,3 +287,16 @@ TEST(IPCMessageTest, PrinterCapsAndDefaults) {
EXPECT_TRUE(input.defaults_mime_type == output.defaults_mime_type);
}
+// Tests net::HostPortPair serialization
+TEST(IPCMessageTest, HostPortPair) {
+ net::HostPortPair input("host.com", 12345);
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<net::HostPortPair>::Write(&msg, input);
+
+ net::HostPortPair output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ParamTraits<net::HostPortPair>::Read(&msg, &iter, &output));
+ EXPECT_EQ(input.host(), output.host());
+ EXPECT_EQ(input.port(), output.port());
+}
diff --git a/chrome/common/render_messages.cc b/chrome/common/render_messages.cc
index 5df43f7..2010064 100644
--- a/chrome/common/render_messages.cc
+++ b/chrome/common/render_messages.cc
@@ -443,6 +443,7 @@ void ParamTraits<webkit_glue::ResourceResponseInfo>::Write(
WriteParam(m, p.was_npn_negotiated);
WriteParam(m, p.was_alternate_protocol_available);
WriteParam(m, p.was_fetched_via_proxy);
+ WriteParam(m, p.socket_address);
}
bool ParamTraits<webkit_glue::ResourceResponseInfo>::Read(
@@ -465,7 +466,8 @@ bool ParamTraits<webkit_glue::ResourceResponseInfo>::Read(
ReadParam(m, iter, &r->was_fetched_via_spdy) &&
ReadParam(m, iter, &r->was_npn_negotiated) &&
ReadParam(m, iter, &r->was_alternate_protocol_available) &&
- ReadParam(m, iter, &r->was_fetched_via_proxy);
+ ReadParam(m, iter, &r->was_fetched_via_proxy) &&
+ ReadParam(m, iter, &r->socket_address);
}
void ParamTraits<webkit_glue::ResourceResponseInfo>::Log(
@@ -506,6 +508,8 @@ void ParamTraits<webkit_glue::ResourceResponseInfo>::Log(
LogParam(p.was_alternate_protocol_available, l);
l->append(", ");
LogParam(p.was_fetched_via_proxy, l);
+ l->append(", ");
+ LogParam(p.socket_address, l);
l->append(")");
}
diff --git a/chrome/common/render_messages_params.cc b/chrome/common/render_messages_params.cc
index 8e4a17b..79a941f 100644
--- a/chrome/common/render_messages_params.cc
+++ b/chrome/common/render_messages_params.cc
@@ -772,6 +772,7 @@ void ParamTraits<ViewHostMsg_FrameNavigate_Params>::Write(Message* m,
WriteParam(m, p.is_content_filtered);
WriteParam(m, p.was_within_same_page);
WriteParam(m, p.http_status_code);
+ WriteParam(m, p.socket_address);
}
bool ParamTraits<ViewHostMsg_FrameNavigate_Params>::Read(const Message* m,
@@ -794,7 +795,8 @@ bool ParamTraits<ViewHostMsg_FrameNavigate_Params>::Read(const Message* m,
ReadParam(m, iter, &p->is_post) &&
ReadParam(m, iter, &p->is_content_filtered) &&
ReadParam(m, iter, &p->was_within_same_page) &&
- ReadParam(m, iter, &p->http_status_code);
+ ReadParam(m, iter, &p->http_status_code) &&
+ ReadParam(m, iter, &p->socket_address);
}
void ParamTraits<ViewHostMsg_FrameNavigate_Params>::Log(const param_type& p,
@@ -833,6 +835,8 @@ void ParamTraits<ViewHostMsg_FrameNavigate_Params>::Log(const param_type& p,
LogParam(p.was_within_same_page, l);
l->append(", ");
LogParam(p.http_status_code, l);
+ l->append(", ");
+ LogParam(p.socket_address, l);
l->append(")");
}
diff --git a/chrome/common/render_messages_params.h b/chrome/common/render_messages_params.h
index d5bd158..fbd9dbb 100644
--- a/chrome/common/render_messages_params.h
+++ b/chrome/common/render_messages_params.h
@@ -28,6 +28,7 @@
#include "googleurl/src/gurl.h"
#include "ipc/ipc_param_traits.h"
#include "media/audio/audio_parameters.h"
+#include "net/base/host_port_pair.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
@@ -303,6 +304,9 @@ struct ViewHostMsg_FrameNavigate_Params {
// The status code of the HTTP request.
int http_status_code;
+
+ // Remote address of the socket which fetched this resource.
+ net::HostPortPair socket_address;
};
// Values that may be OR'd together to form the 'flags' parameter of a
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 53697cfef..97d38bf 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -1642,6 +1642,8 @@ void RenderView::UpdateURL(WebFrame* frame) {
params.page_id = page_id_;
params.frame_id = frame->identifier();
params.is_content_filtered = response.isContentFiltered();
+ params.socket_address.set_host(response.remoteIPAddress().utf8());
+ params.socket_address.set_port(response.remotePort());
params.was_within_same_page = navigation_state->was_within_same_page();
if (!navigation_state->security_info().empty()) {
// SSL state specified in the request takes precedence over the one in the
diff --git a/content/browser/renderer_host/resource_dispatcher_host.cc b/content/browser/renderer_host/resource_dispatcher_host.cc
index 94f5c5e..47709e5 100644
--- a/content/browser/renderer_host/resource_dispatcher_host.cc
+++ b/content/browser/renderer_host/resource_dispatcher_host.cc
@@ -183,6 +183,7 @@ void PopulateResourceResponse(net::URLRequest* request,
request->was_alternate_protocol_available();
response->response_head.was_fetched_via_proxy =
request->was_fetched_via_proxy();
+ response->response_head.socket_address = request->GetSocketAddress();
appcache::AppCacheInterceptor::GetExtraResponseInfo(
request,
&response->response_head.appcache_id,
diff --git a/net/base/host_port_pair.cc b/net/base/host_port_pair.cc
index 1c4406f..5164fcf 100644
--- a/net/base/host_port_pair.cc
+++ b/net/base/host_port_pair.cc
@@ -7,6 +7,8 @@
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
+#include "net/base/sys_addrinfo.h"
namespace net {
@@ -19,6 +21,12 @@ HostPortPair HostPortPair::FromURL(const GURL& url) {
return HostPortPair(url.HostNoBrackets(), url.EffectiveIntPort());
}
+// static
+HostPortPair HostPortPair::FromAddrInfo(const struct addrinfo* ai) {
+ return HostPortPair(NetAddressToString(ai),
+ GetPortFromSockaddr(ai->ai_addr, ai->ai_addrlen));
+}
+
std::string HostPortPair::ToString() const {
return base::StringPrintf("%s:%u", HostForURL().c_str(), port_);
}
diff --git a/net/base/host_port_pair.h b/net/base/host_port_pair.h
index 2c7bb9f..7488e6c 100644
--- a/net/base/host_port_pair.h
+++ b/net/base/host_port_pair.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/basictypes.h"
+struct addrinfo;
class GURL;
namespace net {
@@ -22,6 +23,9 @@ class HostPortPair {
// Creates a HostPortPair for the origin of |url|.
static HostPortPair FromURL(const GURL& url);
+ // Creates a HostPortPair from an addrinfo struct.
+ static HostPortPair FromAddrInfo(const struct addrinfo* ai);
+
// TODO(willchan): Define a functor instead.
// Comparator function so this can be placed in a std::map.
bool operator<(const HostPortPair& other) const {
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index d012818..3f35c83 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -9,6 +9,7 @@
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
+#include "net/base/address_list.h"
#include "net/base/connection_type_histograms.h"
#include "net/base/escape.h"
#include "net/base/net_errors.h"
@@ -620,8 +621,15 @@ int FtpNetworkTransaction::DoCtrlConnect() {
}
int FtpNetworkTransaction::DoCtrlConnectComplete(int result) {
- if (result == OK)
- next_state_ = STATE_CTRL_READ;
+ if (result == OK) {
+ // Put the peer's IP address and port into the response.
+ AddressList address;
+ result = ctrl_socket_->GetPeerAddress(&address);
+ if (result == OK) {
+ response_.socket_address = HostPortPair::FromAddrInfo(address.head());
+ next_state_ = STATE_CTRL_READ;
+ }
+ }
return result;
}
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc
index 8da3baf..1d86fba 100644
--- a/net/ftp/ftp_network_transaction_unittest.cc
+++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -9,6 +9,7 @@
#include "base/ref_counted.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
+#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_util.h"
@@ -831,6 +832,9 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransaction) {
EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_EQ("192.0.2.33",
+ transaction_.GetResponseInfo()->socket_address.host());
+ EXPECT_EQ(0, transaction_.GetResponseInfo()->socket_address.port());
}
TEST_F(FtpNetworkTransactionTest, DirectoryTransactionWithPasvFallback) {
@@ -904,6 +908,9 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransaction) {
// We pass an artificial value of 18 as a response to the SIZE command.
EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
+ EXPECT_EQ("192.0.2.33",
+ transaction_.GetResponseInfo()->socket_address.host());
+ EXPECT_EQ(0, transaction_.GetResponseInfo()->socket_address.port());
}
TEST_F(FtpNetworkTransactionTest, DownloadTransactionWithPasvFallback) {
diff --git a/net/ftp/ftp_response_info.h b/net/ftp/ftp_response_info.h
index 0c8884c..9db9018 100644
--- a/net/ftp/ftp_response_info.h
+++ b/net/ftp/ftp_response_info.h
@@ -7,6 +7,7 @@
#pragma once
#include "base/time.h"
+#include "net/base/host_port_pair.h"
namespace net {
@@ -36,6 +37,9 @@ class FtpResponseInfo {
// True if the response data is of a directory listing.
bool is_directory_listing;
+
+ // Remote address of the socket which fetched this resource.
+ HostPortPair socket_address;
};
} // namespace net
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index bf8cb6b..8d5fea4 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -11,6 +11,7 @@
#include "base/stringprintf.h"
#include "net/base/cache_type.h"
#include "net/base/cert_status_flags.h"
+#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/net_log_unittest.h"
@@ -3978,6 +3979,31 @@ TEST(HttpCache, WriteResponseInfo_Truncated) {
entry->Close();
}
+// Tests basic pickling/unpickling of HttpResponseInfo.
+TEST(HttpCache, PersistHttpResponseInfo) {
+ // Set some fields (add more if needed.)
+ net::HttpResponseInfo response1;
+ response1.was_cached = false;
+ response1.socket_address = net::HostPortPair("1.2.3.4", 80);
+ response1.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK");
+
+ // Pickle.
+ Pickle pickle;
+ response1.Persist(&pickle, false, false);
+
+ // Unpickle.
+ net::HttpResponseInfo response2;
+ bool response_truncated;
+ EXPECT_TRUE(response2.InitFromPickle(pickle, &response_truncated));
+ EXPECT_FALSE(response_truncated);
+
+ // Verify fields.
+ EXPECT_TRUE(response2.was_cached); // InitFromPickle sets this flag.
+ EXPECT_EQ("1.2.3.4", response2.socket_address.host());
+ EXPECT_EQ(80, response2.socket_address.port());
+ EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
+}
+
// Tests that we delete an entry when the request is cancelled before starting
// to read from the network.
TEST(HttpCache, DoomOnDestruction) {
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 8c87136..e54edf5 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -175,6 +175,9 @@ class HttpNetworkTransactionTest : public PlatformTest {
EXPECT_TRUE(response->headers != NULL);
out.status_line = response->headers->GetStatusLine();
+ EXPECT_EQ("192.0.2.33", response->socket_address.host());
+ EXPECT_EQ(0, response->socket_address.port());
+
rv = ReadTransaction(trans.get(), &out.response_data);
EXPECT_EQ(OK, rv);
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc
index 2c23faa..9b3444a 100644
--- a/net/http/http_response_info.cc
+++ b/net/http/http_response_info.cc
@@ -74,6 +74,7 @@ HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs)
was_npn_negotiated(rhs.was_npn_negotiated),
was_alternate_protocol_available(rhs.was_alternate_protocol_available),
was_fetched_via_proxy(rhs.was_fetched_via_proxy),
+ socket_address(rhs.socket_address),
request_time(rhs.request_time),
response_time(rhs.response_time),
auth_challenge(rhs.auth_challenge),
@@ -93,6 +94,7 @@ HttpResponseInfo& HttpResponseInfo::operator=(const HttpResponseInfo& rhs) {
was_npn_negotiated = rhs.was_npn_negotiated;
was_alternate_protocol_available = rhs.was_alternate_protocol_available;
was_fetched_via_proxy = rhs.was_fetched_via_proxy;
+ socket_address = rhs.socket_address;
request_time = rhs.request_time;
response_time = rhs.response_time;
auth_challenge = rhs.auth_challenge;
@@ -158,6 +160,18 @@ bool HttpResponseInfo::InitFromPickle(const Pickle& pickle,
return false;
}
+ // Read socket_address. This was not always present in the response info,
+ // so we don't fail if it can't be read. If additional fields are added in
+ // a future version, then they must only be read if this operation succeeds.
+ std::string socket_address_host;
+ if (pickle.ReadString(&iter, &socket_address_host)) {
+ // If the host was written, we always expect the port to follow.
+ uint16 socket_address_port;
+ if (!pickle.ReadUInt16(&iter, &socket_address_port))
+ return false;
+ socket_address = HostPortPair(socket_address_host, socket_address_port);
+ }
+
was_fetched_via_spdy = (flags & RESPONSE_INFO_WAS_SPDY) != 0;
was_npn_negotiated = (flags & RESPONSE_INFO_WAS_NPN) != 0;
@@ -223,6 +237,9 @@ void HttpResponseInfo::Persist(Pickle* pickle,
if (vary_data.is_valid())
vary_data.Persist(pickle);
+
+ pickle->WriteString(socket_address.host());
+ pickle->WriteUInt16(socket_address.port());
}
} // namespace net
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h
index 4fbea3d..e13f288 100644
--- a/net/http/http_response_info.h
+++ b/net/http/http_response_info.h
@@ -7,6 +7,7 @@
#pragma once
#include "base/time.h"
+#include "net/base/host_port_pair.h"
#include "net/base/ssl_info.h"
#include "net/http/http_vary_data.h"
@@ -60,6 +61,15 @@ class HttpResponseInfo {
// transparent proxy may have been involved.
bool was_fetched_via_proxy;
+ // Remote address of the socket which fetched this resource.
+ //
+ // NOTE: If the response was served from the cache (was_cached is true),
+ // the socket address will be set to the address that the content came from
+ // originally. This is true even if the response was re-validated using a
+ // different remote address, or if some of the content came from a byte-range
+ // request to a different address.
+ HostPortPair socket_address;
+
// The time at which the request was made that resulted in this response.
// For cached responses, this is the last time the cache entry was validated.
base::Time request_time;
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
index 20ebd87..6621f0b 100644
--- a/net/http/http_stream_parser.cc
+++ b/net/http/http_stream_parser.cc
@@ -6,6 +6,7 @@
#include "base/compiler_specific.h"
#include "base/metrics/histogram.h"
+#include "net/base/address_list.h"
#include "net/base/auth.h"
#include "net/base/io_buffer.h"
#include "net/base/ssl_cert_request_info.h"
@@ -65,6 +66,14 @@ int HttpStreamParser::SendRequest(const std::string& request_line,
request_line, headers)));
}
response_ = response;
+
+ // Put the peer's IP address and port into the response.
+ AddressList address;
+ int result = connection_->socket()->GetPeerAddress(&address);
+ if (result != OK)
+ return result;
+ response_->socket_address = HostPortPair::FromAddrInfo(address.head());
+
std::string request = request_line + headers.ToString();
scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request));
request_headers_ = new DrainableIOBuffer(headers_io_buf,
@@ -74,7 +83,7 @@ int HttpStreamParser::SendRequest(const std::string& request_line,
request_body_->set_chunk_callback(this);
io_state_ = STATE_SENDING_HEADERS;
- int result = DoLoop(OK);
+ result = DoLoop(OK);
if (result == ERR_IO_PENDING)
user_callback_ = callback;
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index d5ee9ae..dc89546 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -631,7 +631,7 @@ bool MockClientSocket::IsConnectedAndIdle() const {
}
int MockClientSocket::GetPeerAddress(AddressList* address) const {
- return net::SystemHostResolverProc("localhost", ADDRESS_FAMILY_UNSPECIFIED,
+ return net::SystemHostResolverProc("192.0.2.33", ADDRESS_FAMILY_UNSPECIFIED,
0, address, NULL);
}
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index 6a6abb2..e07578e 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -10,6 +10,8 @@
#include "base/logging.h"
#include "base/message_loop.h"
+#include "net/base/address_list.h"
+#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_util.h"
#include "net/http/http_request_headers.h"
@@ -230,8 +232,15 @@ int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
response_info_ = response;
+ // Put the peer's IP address and port into the response.
+ AddressList address;
+ int result = stream_->GetPeerAddress(&address);
+ if (result != OK)
+ return result;
+ response_info_->socket_address = HostPortPair::FromAddrInfo(address.head());
+
bool has_upload_data = request_body_stream_.get() != NULL;
- int result = stream_->SendRequest(has_upload_data);
+ result = stream_->SendRequest(has_upload_data);
if (result == ERR_IO_PENDING) {
CHECK(!user_callback_);
user_callback_ = callback;
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index de248cb..402f2f7 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -177,10 +177,11 @@ class SpdyNetworkTransactionTest
EXPECT_EQ(request_.url.SchemeIs("https"),
response->was_npn_negotiated);
}
+ EXPECT_EQ("192.0.2.33", response->socket_address.host());
+ EXPECT_EQ(0, response->socket_address.port());
output_.status_line = response->headers->GetStatusLine();
output_.response_info = *response; // Make a copy so we can verify.
output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
- return;
}
// Most tests will want to call this function. In particular, the MockReads
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 9e35fc0..848b810 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -9,6 +9,7 @@
#include "base/metrics/stats_counters.h"
#include "base/singleton.h"
#include "base/synchronization/lock.h"
+#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
@@ -272,6 +273,11 @@ void URLRequest::GetAllResponseHeaders(string* headers) {
}
}
+HostPortPair URLRequest::GetSocketAddress() const {
+ DCHECK(job_);
+ return job_->GetSocketAddress();
+}
+
net::HttpResponseHeaders* URLRequest::response_headers() const {
return response_info_.headers.get();
}
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index bb08a8f..a2ad24b 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -38,6 +38,7 @@ typedef std::vector<std::string> ResponseCookies;
namespace net {
class CookieOptions;
+class HostPortPair;
class IOBuffer;
class SSLCertRequestInfo;
class UploadData;
@@ -416,6 +417,10 @@ class URLRequest : public base::NonThreadSafe {
return response_info_.was_fetched_via_proxy;
}
+ // Returns the host and port that the content was fetched from. See
+ // http_response_info.h for caveats relating to cached content.
+ HostPortPair GetSocketAddress() const;
+
// Get all response headers, as a HttpResponseHeaders object. See comments
// in HttpResponseHeaders class as to the format of the data.
net::HttpResponseHeaders* response_headers() const;
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc
index 8c170ff..48f0639 100644
--- a/net/url_request/url_request_ftp_job.cc
+++ b/net/url_request/url_request_ftp_job.cc
@@ -8,6 +8,7 @@
#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
#include "net/base/auth.h"
+#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/ftp/ftp_response_info.h"
@@ -52,6 +53,13 @@ bool URLRequestFtpJob::GetMimeType(std::string* mime_type) const {
return false;
}
+HostPortPair URLRequestFtpJob::GetSocketAddress() const {
+ if (!transaction_.get()) {
+ return HostPortPair();
+ }
+ return transaction_->GetResponseInfo()->socket_address;
+}
+
URLRequestFtpJob::~URLRequestFtpJob() {
}
diff --git a/net/url_request/url_request_ftp_job.h b/net/url_request/url_request_ftp_job.h
index fe85ba3..84c54e1 100644
--- a/net/url_request/url_request_ftp_job.h
+++ b/net/url_request/url_request_ftp_job.h
@@ -31,6 +31,7 @@ class URLRequestFtpJob : public URLRequestJob {
// Overridden from URLRequestJob:
virtual bool GetMimeType(std::string* mime_type) const;
+ virtual HostPortPair GetSocketAddress() const;
private:
virtual ~URLRequestFtpJob();
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index de51284..563c85b 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -16,12 +16,13 @@
#include "net/base/cookie_policy.h"
#include "net/base/cookie_store.h"
#include "net/base/filter.h"
-#include "net/base/transport_security_state.h"
+#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/base/sdch_manager.h"
#include "net/base/ssl_cert_request_info.h"
+#include "net/base/transport_security_state.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
@@ -926,6 +927,10 @@ void URLRequestHttpJob::StopCaching() {
transaction_->StopCaching();
}
+HostPortPair URLRequestHttpJob::GetSocketAddress() const {
+ return response_info_ ? response_info_->socket_address : HostPortPair();
+}
+
URLRequestHttpJob::~URLRequestHttpJob() {
DCHECK(!sdch_test_control_ || !sdch_test_activated_);
if (!IsCachedContent()) {
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index 3f9356e..e1abf3e 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -85,6 +85,7 @@ class URLRequestHttpJob : public URLRequestJob {
virtual void ContinueDespiteLastError();
virtual bool ReadRawData(IOBuffer* buf, int buf_size, int *bytes_read);
virtual void StopCaching();
+ virtual HostPortPair GetSocketAddress() const;
// Keep a reference to the url request context to be sure it's not deleted
// before us.
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index ac05127..12c8d2e 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -9,6 +9,7 @@
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "net/base/auth.h"
+#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/mime_util.h"
@@ -398,6 +399,10 @@ void URLRequestJob::RecordPacketStats(StatisticSelector statistic) const {
}
}
+HostPortPair URLRequestJob::GetSocketAddress() const {
+ return HostPortPair();
+}
+
URLRequestJob::~URLRequestJob() {
g_url_request_job_tracker.RemoveJob(this);
}
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 3ac648b..b6c286a 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -15,6 +15,7 @@
#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "net/base/filter.h"
+#include "net/base/host_port_pair.h"
#include "net/base/load_states.h"
@@ -209,6 +210,10 @@ class URLRequestJob : public base::RefCounted<URLRequestJob>,
virtual int GetInputStreamBufferSize() const;
virtual void RecordPacketStats(StatisticSelector statistic) const;
+ // Returns the socket address for the connection.
+ // See url_request.h for details.
+ virtual HostPortPair GetSocketAddress() const;
+
protected:
friend class base::RefCounted<URLRequestJob>;
virtual ~URLRequestJob();
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 35573ed..3192b39 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -267,6 +267,10 @@ TEST_F(URLRequestTestHTTP, GetTest_NoCache) {
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
+ EXPECT_EQ(test_server_.host_port_pair().host(),
+ r.GetSocketAddress().host());
+ EXPECT_EQ(test_server_.host_port_pair().port(),
+ r.GetSocketAddress().port());
// TODO(eroman): Add back the NetLog tests...
}
@@ -287,6 +291,10 @@ TEST_F(URLRequestTestHTTP, GetTest) {
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
+ EXPECT_EQ(test_server_.host_port_pair().host(),
+ r.GetSocketAddress().host());
+ EXPECT_EQ(test_server_.host_port_pair().port(),
+ r.GetSocketAddress().port());
}
}
@@ -335,6 +343,10 @@ TEST_F(HTTPSRequestTest, HTTPSGetTest) {
EXPECT_FALSE(d.received_data_before_response());
EXPECT_NE(0, d.bytes_received());
CheckSSLInfo(r.ssl_info());
+ EXPECT_EQ(test_server.host_port_pair().host(),
+ r.GetSocketAddress().host());
+ EXPECT_EQ(test_server.host_port_pair().port(),
+ r.GetSocketAddress().port());
}
}
@@ -713,6 +725,8 @@ TEST_F(URLRequestTest, AboutBlankTest) {
EXPECT_TRUE(!r.is_pending());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(d.bytes_received(), 0);
+ EXPECT_EQ("", r.GetSocketAddress().host());
+ EXPECT_EQ(0, r.GetSocketAddress().port());
}
}
@@ -750,6 +764,8 @@ TEST_F(URLRequestTest, DataURLImageTest) {
EXPECT_TRUE(!r.is_pending());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(d.bytes_received(), 911);
+ EXPECT_EQ("", r.GetSocketAddress().host());
+ EXPECT_EQ(0, r.GetSocketAddress().port());
}
}
@@ -774,6 +790,8 @@ TEST_F(URLRequestTest, FileTest) {
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(d.bytes_received(), static_cast<int>(file_size));
+ EXPECT_EQ("", r.GetSocketAddress().host());
+ EXPECT_EQ(0, r.GetSocketAddress().port());
}
}
@@ -2373,6 +2391,10 @@ TEST_F(URLRequestTestFTP, FLAKY_FTPDirectoryListing) {
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_LT(0, d.bytes_received());
+ EXPECT_EQ(test_server_.host_port_pair().host(),
+ r.GetSocketAddress().host());
+ EXPECT_EQ(test_server_.host_port_pair().port(),
+ r.GetSocketAddress().port());
}
}
@@ -2398,6 +2420,10 @@ TEST_F(URLRequestTestFTP, FLAKY_FTPGetTestAnonymous) {
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(d.bytes_received(), static_cast<int>(file_size));
+ EXPECT_EQ(test_server_.host_port_pair().host(),
+ r.GetSocketAddress().host());
+ EXPECT_EQ(test_server_.host_port_pair().port(),
+ r.GetSocketAddress().port());
}
}
@@ -2422,6 +2448,10 @@ TEST_F(URLRequestTestFTP, FLAKY_FTPGetTest) {
file_util::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
+ EXPECT_EQ(test_server_.host_port_pair().host(),
+ r.GetSocketAddress().host());
+ EXPECT_EQ(test_server_.host_port_pair().port(),
+ r.GetSocketAddress().port());
EXPECT_EQ(1, d.response_started_count());
EXPECT_FALSE(d.received_data_before_response());
EXPECT_EQ(d.bytes_received(), static_cast<int>(file_size));
diff --git a/webkit/glue/resource_loader_bridge.h b/webkit/glue/resource_loader_bridge.h
index 23ebb35..e12f142 100644
--- a/webkit/glue/resource_loader_bridge.h
+++ b/webkit/glue/resource_loader_bridge.h
@@ -31,6 +31,7 @@
#include "base/time.h"
#include "base/values.h"
#include "googleurl/src/gurl.h"
+#include "net/base/host_port_pair.h"
#include "net/url_request/url_request_status.h"
#include "webkit/glue/resource_type.h"
@@ -182,6 +183,9 @@ struct ResourceResponseInfo {
// transparent proxy). The proxy could be any type of proxy, HTTP or SOCKS.
// Note: we cannot tell if a transparent proxy may have been involved.
bool was_fetched_via_proxy;
+
+ // Remote address of the socket which fetched this resource.
+ net::HostPortPair socket_address;
};
class ResourceLoaderBridge {
diff --git a/webkit/glue/weburlloader_impl.cc b/webkit/glue/weburlloader_impl.cc
index d4b5162..e461ca9 100644
--- a/webkit/glue/weburlloader_impl.cc
+++ b/webkit/glue/weburlloader_impl.cc
@@ -187,6 +187,9 @@ void PopulateURLResponse(
response->setWasAlternateProtocolAvailable(
info.was_alternate_protocol_available);
response->setWasFetchedViaProxy(info.was_fetched_via_proxy);
+ response->setRemoteIPAddress(
+ WebString::fromUTF8(info.socket_address.host()));
+ response->setRemotePort(info.socket_address.port());
response->setConnectionID(info.connection_id);
response->setConnectionReused(info.connection_reused);
response->setDownloadFilePath(FilePathToWebString(info.download_file_path));