diff options
-rw-r--r-- | net/base/forwarding_net_log.cc | 101 | ||||
-rw-r--r-- | net/base/forwarding_net_log.h | 53 | ||||
-rw-r--r-- | net/base/forwarding_net_log_unittest.cc | 84 | ||||
-rw-r--r-- | net/base/net_log.h | 1 | ||||
-rw-r--r-- | net/base/net_log_event_type_list.h | 24 | ||||
-rw-r--r-- | net/net.gyp | 3 | ||||
-rw-r--r-- | net/proxy/multi_threaded_proxy_resolver.h | 2 | ||||
-rw-r--r-- | net/proxy/multi_threaded_proxy_resolver_unittest.cc | 2 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_js_bindings.cc | 188 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_js_bindings.h | 10 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_js_bindings_unittest.cc | 96 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_perftest.cc | 6 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_v8.cc | 52 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_v8_unittest.cc | 37 | ||||
-rw-r--r-- | net/proxy/proxy_service.cc | 30 |
15 files changed, 547 insertions, 142 deletions
diff --git a/net/base/forwarding_net_log.cc b/net/base/forwarding_net_log.cc new file mode 100644 index 0000000..6cea529 --- /dev/null +++ b/net/base/forwarding_net_log.cc @@ -0,0 +1,101 @@ +// Copyright (c) 2010 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 "net/base/forwarding_net_log.h" + +#include "base/lock.h" +#include "base/logging.h" +#include "base/message_loop.h" + +namespace net { + +// Reference-counted wrapper, so we can use PostThread and it can safely +// outlive the parent ForwardingNetLog. +class ForwardingNetLog::Core + : public base::RefCountedThreadSafe<ForwardingNetLog::Core> { + public: + Core(NetLog* impl, MessageLoop* loop) : impl_(impl), loop_(loop) { + DCHECK(impl); + DCHECK(loop); + } + + // Called once the parent ForwardingNetLog is being destroyed. It + // is invalid to access |loop_| and |impl_| afterwards. + void Orphan() { + AutoLock l(lock_); + loop_ = NULL; + impl_ = NULL; + } + + void AddEntry(EventType type, + const base::TimeTicks& time, + const Source& source, + EventPhase phase, + EventParameters* params) { + AutoLock l(lock_); + if (!loop_) + return; // Was orphaned. + + loop_->PostTask( + FROM_HERE, + NewRunnableMethod( + this, &Core::AddEntryOnLoop, type, time, source, phase, + scoped_refptr<EventParameters>(params))); + } + + private: + void AddEntryOnLoop(EventType type, + const base::TimeTicks& time, + const Source& source, + EventPhase phase, + scoped_refptr<EventParameters> params) { + AutoLock l(lock_); + if (!loop_) + return; // Was orphaned. + + DCHECK_EQ(MessageLoop::current(), loop_); + + // TODO(eroman): This shouldn't be necessary. See crbug.com/48806. + NetLog::Source effective_source = source; + if (effective_source.id == NetLog::Source::kInvalidId) + effective_source.id = impl_->NextID(); + + impl_->AddEntry(type, time, effective_source, phase, params); + } + + Lock lock_; + NetLog* impl_; + MessageLoop* loop_; +}; + +ForwardingNetLog::ForwardingNetLog(NetLog* impl, MessageLoop* loop) + : core_(new Core(impl, loop)) { +} + +ForwardingNetLog::~ForwardingNetLog() { + core_->Orphan(); +} + +void ForwardingNetLog::AddEntry(EventType type, + const base::TimeTicks& time, + const Source& source, + EventPhase phase, + EventParameters* params) { + core_->AddEntry(type, time, source, phase, params); +} + +uint32 ForwardingNetLog::NextID() { + // Can't forward a synchronous API. + CHECK(false) << "Not supported"; + return 0; +} + +bool ForwardingNetLog::HasListener() const { + // Can't forward a synchronous API. + CHECK(false) << "Not supported"; + return false; +} + +} // namespace net + diff --git a/net/base/forwarding_net_log.h b/net/base/forwarding_net_log.h new file mode 100644 index 0000000..a97d4acd --- /dev/null +++ b/net/base/forwarding_net_log.h @@ -0,0 +1,53 @@ +// Copyright (c) 2010 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 NET_BASE_FORWARDING_NET_LOG_H_ +#define NET_BASE_FORWARDING_NET_LOG_H_ + +#include "base/basictypes.h" +#include "net/base/net_log.h" + +class MessageLoop; + +namespace net { + +// ForwardingNetLog is a wrapper that can be called on any thread, and will +// forward any calls to NetLog::AddEntry() over to |impl| on the specified +// message loop. +// +// This allows using a non-threadsafe NetLog implementation from another +// thread. +// +// TODO(eroman): Explore making NetLog threadsafe and obviating the need +// for this class. +class ForwardingNetLog : public NetLog { + public: + // Both |impl| and |loop| must outlive the lifetime of this instance. + // |impl| will be operated only from |loop|. + ForwardingNetLog(NetLog* impl, MessageLoop* loop); + + // On destruction any outstanding call to AddEntry() which didn't make + // it to |loop| yet will be cancelled. + ~ForwardingNetLog(); + + // NetLog methods: + virtual void AddEntry(EventType type, + const base::TimeTicks& time, + const Source& source, + EventPhase phase, + EventParameters* params); + virtual uint32 NextID(); + virtual bool HasListener() const; + + private: + class Core; + scoped_refptr<Core> core_; + + DISALLOW_COPY_AND_ASSIGN(ForwardingNetLog); +}; + +} // namespace net + +#endif // NET_BASE_FORWARDING_NET_LOG_H_ + diff --git a/net/base/forwarding_net_log_unittest.cc b/net/base/forwarding_net_log_unittest.cc new file mode 100644 index 0000000..3f25129 --- /dev/null +++ b/net/base/forwarding_net_log_unittest.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2010 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 "net/base/forwarding_net_log.h" + +#include "base/message_loop.h" +#include "net/base/capturing_net_log.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +// Test forwarding a call to AddEntry() to another implementation, operating +// on this same message loop. +TEST(ForwardingNetLogTest, Basic) { + // Create a forwarding NetLog that sends messages to this same thread. + CapturingNetLog log(CapturingNetLog::kUnbounded); + ForwardingNetLog forwarding(&log, MessageLoop::current()); + + EXPECT_EQ(0u, log.entries().size()); + + NetLogStringParameter* params = new NetLogStringParameter("xxx", "yyy"); + + forwarding.AddEntry( + NetLog::TYPE_PAC_JAVASCRIPT_ALERT, + base::TimeTicks(), + NetLog::Source(), + NetLog::PHASE_NONE, + params); + + // Should still be empty, since we posted an async task. + EXPECT_EQ(0u, log.entries().size()); + + MessageLoop::current()->RunAllPending(); + + // After draining the message loop, we should now have executed the task + // and hence emitted the log entry. + ASSERT_EQ(1u, log.entries().size()); + + // Check that the forwarded call contained received all the right inputs. + EXPECT_EQ(NetLog::TYPE_PAC_JAVASCRIPT_ALERT, log.entries()[0].type); + EXPECT_EQ(NetLog::SOURCE_NONE, log.entries()[0].source.type); + EXPECT_EQ(NetLog::PHASE_NONE, log.entries()[0].phase); + EXPECT_EQ(params, log.entries()[0].extra_parameters.get()); + + // Check that the parameters is still referenced. (if the reference was + // lost then this will be a memory error and probaby crash). + EXPECT_EQ("yyy", params->value()); +} + +// Test forwarding a call to AddEntry() to another implementation that runs +// on the same message loop. However destroy the forwarder before the posted +// task has a chance to run. +TEST(ForwardingNetLogTest, Orphan) { + // Create a forwarding NetLog that sends messages to this same thread. + CapturingNetLog log(CapturingNetLog::kUnbounded); + { + ForwardingNetLog forwarding(&log, MessageLoop::current()); + EXPECT_EQ(0u, log.entries().size()); + + forwarding.AddEntry( + NetLog::TYPE_PAC_JAVASCRIPT_ALERT, + base::TimeTicks(), + NetLog::Source(), + NetLog::PHASE_NONE, + NULL); + + // Should still be empty, since we posted an async task. + EXPECT_EQ(0u, log.entries().size()); + } + + // At this point the ForwardingNetLog is deleted. However it had already + // posted a task to the message loop. Once we drain the message loop, we + // verify that the task didn't actually try to emit to the NetLog. + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0u, log.entries().size()); +} + +} // namespace + +} // namespace net + diff --git a/net/base/net_log.h b/net/base/net_log.h index a9d24f8..2f82ed4 100644 --- a/net/base/net_log.h +++ b/net/base/net_log.h @@ -101,6 +101,7 @@ class NetLog { // |params| - Optional (may be NULL) parameters for this event. // The specific subclass of EventParameters is defined // by the contract for events of this |type|. + // TODO(eroman): Take a scoped_refptr<> instead. virtual void AddEntry(EventType type, const base::TimeTicks& time, const Source& source, diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h index ecbf2f9..2fcd6fa 100644 --- a/net/base/net_log_event_type_list.h +++ b/net/base/net_log_event_type_list.h @@ -99,16 +99,32 @@ EVENT_TYPE(PROXY_SERVICE_RESOLVED_PROXY_LIST) // ------------------------------------------------------------------------ // Measures the time taken to execute the "myIpAddress()" javascript binding. -EVENT_TYPE(PROXY_RESOLVER_V8_MY_IP_ADDRESS) +EVENT_TYPE(PAC_JAVASCRIPT_MY_IP_ADDRESS) // Measures the time taken to execute the "myIpAddressEx()" javascript binding. -EVENT_TYPE(PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX) +EVENT_TYPE(PAC_JAVASCRIPT_MY_IP_ADDRESS_EX) // Measures the time taken to execute the "dnsResolve()" javascript binding. -EVENT_TYPE(PROXY_RESOLVER_V8_DNS_RESOLVE) +EVENT_TYPE(PAC_JAVASCRIPT_DNS_RESOLVE) // Measures the time taken to execute the "dnsResolveEx()" javascript binding. -EVENT_TYPE(PROXY_RESOLVER_V8_DNS_RESOLVE_EX) +EVENT_TYPE(PAC_JAVASCRIPT_DNS_RESOLVE_EX) + +// This event is emitted when a javascript error has been triggered by a +// PAC script. It contains the following event parameters: +// { +// "line_number": <The line number in the PAC script +// (or -1 if not applicable)>, +// "message": <The error message> +// } +EVENT_TYPE(PAC_JAVASCRIPT_ERROR) + +// This event is emitted when a PAC script called alert(). It contains the +// following event parameters: +// { +// "message": <The string of the alert> +// } +EVENT_TYPE(PAC_JAVASCRIPT_ALERT) // Measures the time that a proxy resolve request was stalled waiting for a // proxy resolver thread to free-up. diff --git a/net/net.gyp b/net/net.gyp index 6bbde7f..dd9ffea 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -62,6 +62,8 @@ 'base/file_stream_win.cc', 'base/filter.cc', 'base/filter.h', + 'base/forwarding_net_log.cc', + 'base/forwarding_net_log.h', 'base/gzip_filter.cc', 'base/gzip_filter.h', 'base/gzip_header.cc', @@ -654,6 +656,7 @@ 'base/file_stream_unittest.cc', 'base/filter_unittest.cc', 'base/filter_unittest.h', + 'base/forwarding_net_log_unittest.cc', 'base/gzip_filter_unittest.cc', 'base/host_cache_unittest.cc', 'base/host_mapping_rules_unittest.cc', diff --git a/net/proxy/multi_threaded_proxy_resolver.h b/net/proxy/multi_threaded_proxy_resolver.h index c192251..f3c9003 100644 --- a/net/proxy/multi_threaded_proxy_resolver.h +++ b/net/proxy/multi_threaded_proxy_resolver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. diff --git a/net/proxy/multi_threaded_proxy_resolver_unittest.cc b/net/proxy/multi_threaded_proxy_resolver_unittest.cc index f451c3a..5873775 100644 --- a/net/proxy/multi_threaded_proxy_resolver_unittest.cc +++ b/net/proxy/multi_threaded_proxy_resolver_unittest.cc @@ -46,7 +46,7 @@ class MockProxyResolver : public ProxyResolver { EXPECT_TRUE(request == NULL); // Write something into |net_log| (doesn't really have any meaning.) - net_log.BeginEvent(NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE, NULL); + net_log.BeginEvent(NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE, NULL); results->UseNamedProxy(query_url.host()); diff --git a/net/proxy/proxy_resolver_js_bindings.cc b/net/proxy/proxy_resolver_js_bindings.cc index 08a7fe7..56604cd 100644 --- a/net/proxy/proxy_resolver_js_bindings.cc +++ b/net/proxy/proxy_resolver_js_bindings.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/string_util.h" +#include "base/values.h" #include "net/base/address_list.h" #include "net/base/host_cache.h" #include "net/base/host_resolver.h" @@ -16,40 +17,162 @@ #include "net/proxy/proxy_resolver_request_context.h" namespace net { + namespace { +// Event parameters for a PAC error message (line number + message). +class ErrorNetlogParams : public NetLog::EventParameters { + public: + ErrorNetlogParams(int line_number, + const string16& message) + : line_number_(line_number), + message_(message) { + } + + virtual Value* ToValue() const { + DictionaryValue* dict = new DictionaryValue(); + dict->SetInteger(L"line_number", line_number_); + dict->SetStringFromUTF16(L"message", message_); + return dict; + } + + private: + const int line_number_; + const string16 message_; + + DISALLOW_COPY_AND_ASSIGN(ErrorNetlogParams); +}; + +// Event parameters for a PAC alert(). +class AlertNetlogParams : public NetLog::EventParameters { + public: + explicit AlertNetlogParams(const string16& message) : message_(message) { + } + + virtual Value* ToValue() const { + DictionaryValue* dict = new DictionaryValue(); + dict->SetStringFromUTF16(L"message", message_); + return dict; + } + + private: + const string16 message_; + + DISALLOW_COPY_AND_ASSIGN(AlertNetlogParams); +}; + // ProxyResolverJSBindings implementation. class DefaultJSBindings : public ProxyResolverJSBindings { public: - explicit DefaultJSBindings(HostResolver* host_resolver) - : host_resolver_(host_resolver) {} + DefaultJSBindings(HostResolver* host_resolver, NetLog* net_log) + : host_resolver_(host_resolver), + net_log_(net_log) { + } // Handler for "alert(message)". virtual void Alert(const string16& message) { LOG(INFO) << "PAC-alert: " << message; + + // Send to the NetLog. + LogEventToCurrentRequestAndGlobally(NetLog::TYPE_PAC_JAVASCRIPT_ALERT, + new AlertNetlogParams(message)); } // Handler for "myIpAddress()". // TODO(eroman): Perhaps enumerate the interfaces directly, using // getifaddrs(). virtual bool MyIpAddress(std::string* first_ip_address) { + LogEventToCurrentRequest(NetLog::PHASE_BEGIN, + NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS, + NULL); + + bool ok = MyIpAddressImpl(first_ip_address); + + LogEventToCurrentRequest(NetLog::PHASE_END, + NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS, + NULL); + return ok; + } + + // Handler for "myIpAddressEx()". + virtual bool MyIpAddressEx(std::string* ip_address_list) { + LogEventToCurrentRequest(NetLog::PHASE_BEGIN, + NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX, + NULL); + + bool ok = MyIpAddressExImpl(ip_address_list); + + LogEventToCurrentRequest(NetLog::PHASE_END, + NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX, + NULL); + return ok; + } + + // Handler for "dnsResolve(host)". + virtual bool DnsResolve(const std::string& host, + std::string* first_ip_address) { + LogEventToCurrentRequest(NetLog::PHASE_BEGIN, + NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE, + NULL); + + bool ok = DnsResolveImpl(host, first_ip_address); + + LogEventToCurrentRequest(NetLog::PHASE_END, + NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE, + NULL); + return ok; + } + + // Handler for "dnsResolveEx(host)". + virtual bool DnsResolveEx(const std::string& host, + std::string* ip_address_list) { + LogEventToCurrentRequest(NetLog::PHASE_BEGIN, + NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX, + NULL); + + bool ok = DnsResolveExImpl(host, ip_address_list); + + LogEventToCurrentRequest(NetLog::PHASE_END, + NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX, + NULL); + return ok; + } + + // Handler for when an error is encountered. |line_number| may be -1. + virtual void OnError(int line_number, const string16& message) { + // Send to the chrome log. + if (line_number == -1) + LOG(INFO) << "PAC-error: " << message; + else + LOG(INFO) << "PAC-error: " << "line: " << line_number << ": " << message; + + // Send the error to the NetLog. + LogEventToCurrentRequestAndGlobally( + NetLog::TYPE_PAC_JAVASCRIPT_ERROR, + new ErrorNetlogParams(line_number, message)); + } + + virtual void Shutdown() { + host_resolver_->Shutdown(); + } + + private: + bool MyIpAddressImpl(std::string* first_ip_address) { std::string my_hostname = GetHostName(); if (my_hostname.empty()) return false; - return DnsResolve(my_hostname, first_ip_address); + return DnsResolveImpl(my_hostname, first_ip_address); } - // Handler for "myIpAddressEx()". - virtual bool MyIpAddressEx(std::string* ip_address_list) { + bool MyIpAddressExImpl(std::string* ip_address_list) { std::string my_hostname = GetHostName(); if (my_hostname.empty()) return false; - return DnsResolveEx(my_hostname, ip_address_list); + return DnsResolveExImpl(my_hostname, ip_address_list); } - // Handler for "dnsResolve(host)". - virtual bool DnsResolve(const std::string& host, - std::string* first_ip_address) { + bool DnsResolveImpl(const std::string& host, + std::string* first_ip_address) { // Do a sync resolve of the hostname. // Disable IPv6 results. We do this because the PAC specification isn't // really IPv6 friendly, and Internet Explorer also restricts to IPv4. @@ -73,9 +196,8 @@ class DefaultJSBindings : public ProxyResolverJSBindings { return true; } - // Handler for "dnsResolveEx(host)". - virtual bool DnsResolveEx(const std::string& host, - std::string* ip_address_list) { + bool DnsResolveExImpl(const std::string& host, + std::string* ip_address_list) { // Do a sync resolve of the hostname. HostResolver::RequestInfo info(host, 80); // Port doesn't matter. AddressList address_list; @@ -102,19 +224,6 @@ class DefaultJSBindings : public ProxyResolverJSBindings { return true; } - // Handler for when an error is encountered. |line_number| may be -1. - virtual void OnError(int line_number, const string16& message) { - if (line_number == -1) - LOG(INFO) << "PAC-error: " << message; - else - LOG(INFO) << "PAC-error: " << "line: " << line_number << ": " << message; - } - - virtual void Shutdown() { - host_resolver_->Shutdown(); - } - - private: // Helper to execute a synchronous DNS resolve, using the per-request // DNS cache if there is one. int DnsResolveHelper(const HostResolver::RequestInfo& info, @@ -152,15 +261,40 @@ class DefaultJSBindings : public ProxyResolverJSBindings { return result; } + void LogEventToCurrentRequest( + NetLog::EventPhase phase, + NetLog::EventType type, + scoped_refptr<NetLog::EventParameters> params) { + if (current_request_context() && current_request_context()->net_log) + current_request_context()->net_log->AddEntry(type, phase, params); + } + + void LogEventToCurrentRequestAndGlobally( + NetLog::EventType type, + scoped_refptr<NetLog::EventParameters> params) { + LogEventToCurrentRequest(NetLog::PHASE_NONE, type, params); + + // Emit to the global NetLog event stream. + if (net_log_) { + net_log_->AddEntry( + type, + base::TimeTicks::Now(), + NetLog::Source(), + NetLog::PHASE_NONE, + params); + } + } + scoped_refptr<HostResolver> host_resolver_; + NetLog* net_log_; }; } // namespace // static ProxyResolverJSBindings* ProxyResolverJSBindings::CreateDefault( - HostResolver* host_resolver) { - return new DefaultJSBindings(host_resolver); + HostResolver* host_resolver, NetLog* net_log) { + return new DefaultJSBindings(host_resolver, net_log); } } // namespace net diff --git a/net/proxy/proxy_resolver_js_bindings.h b/net/proxy/proxy_resolver_js_bindings.h index b5912c4..ae13584 100644 --- a/net/proxy/proxy_resolver_js_bindings.h +++ b/net/proxy/proxy_resolver_js_bindings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -14,6 +14,7 @@ class MessageLoop; namespace net { class HostResolver; +class NetLog; struct ProxyResolverRequestContext; // Interface for the javascript bindings. @@ -58,12 +59,13 @@ class ProxyResolverJSBindings { virtual void Shutdown() = 0; // Creates a default javascript bindings implementation that will: - // - Send script error messages to LOG(INFO) - // - Send script alert()s to LOG(INFO) + // - Send script error messages to both LOG(INFO), and the NetLog. + // - Send script alert()s to both LOG(INFO), and the NetLog. // - Use the provided host resolver to service dnsResolve(). // // Note that |host_resolver| will be used in sync mode mode. - static ProxyResolverJSBindings* CreateDefault(HostResolver* host_resolver); + static ProxyResolverJSBindings* CreateDefault(HostResolver* host_resolver, + NetLog* net_log); // Sets details about the currently executing FindProxyForURL() request. void set_current_request_context( diff --git a/net/proxy/proxy_resolver_js_bindings_unittest.cc b/net/proxy/proxy_resolver_js_bindings_unittest.cc index 2559039..0124469 100644 --- a/net/proxy/proxy_resolver_js_bindings_unittest.cc +++ b/net/proxy/proxy_resolver_js_bindings_unittest.cc @@ -2,19 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "net/proxy/proxy_resolver_js_bindings.h" + #include "base/scoped_ptr.h" #include "base/string_util.h" #include "net/base/address_list.h" #include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" +#include "net/base/net_log_unittest.h" #include "net/base/net_util.h" #include "net/base/sys_addrinfo.h" -#include "net/proxy/proxy_resolver_js_bindings.h" #include "net/proxy/proxy_resolver_request_context.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { + namespace { // This is a HostResolver that synchronously resolves all hosts to the @@ -112,7 +115,7 @@ TEST(ProxyResolverJSBindingsTest, DnsResolve) { // Get a hold of a DefaultJSBindings* (it is a hidden impl class). scoped_ptr<ProxyResolverJSBindings> bindings( - ProxyResolverJSBindings::CreateDefault(host_resolver)); + ProxyResolverJSBindings::CreateDefault(host_resolver, NULL)); std::string ip_address; @@ -137,7 +140,7 @@ TEST(ProxyResolverJSBindingsTest, DnsResolve) { TEST(ProxyResolverJSBindingsTest, MyIpAddress) { // Get a hold of a DefaultJSBindings* (it is a hidden impl class). scoped_ptr<ProxyResolverJSBindings> bindings( - ProxyResolverJSBindings::CreateDefault(new MockHostResolver)); + ProxyResolverJSBindings::CreateDefault(new MockHostResolver, NULL)); // Our IP address is always going to be 127.0.0.1, since we are using a // mock host resolver. @@ -164,7 +167,7 @@ TEST(ProxyResolverJSBindingsTest, RestrictAddressFamily) { // Get a hold of a DefaultJSBindings* (it is a hidden impl class). scoped_ptr<ProxyResolverJSBindings> bindings( - ProxyResolverJSBindings::CreateDefault(host_resolver)); + ProxyResolverJSBindings::CreateDefault(host_resolver, NULL)); // Make it so requests resolve to particular address patterns based on family: // IPV4_ONLY --> 192.168.1.* @@ -221,7 +224,7 @@ TEST(ProxyResolverJSBindingsTest, ExFunctionsReturnList) { // Get a hold of a DefaultJSBindings* (it is a hidden impl class). scoped_ptr<ProxyResolverJSBindings> bindings( - ProxyResolverJSBindings::CreateDefault(host_resolver)); + ProxyResolverJSBindings::CreateDefault(host_resolver, NULL)); std::string ip_addresses; @@ -238,7 +241,7 @@ TEST(ProxyResolverJSBindingsTest, PerRequestDNSCache) { // Get a hold of a DefaultJSBindings* (it is a hidden impl class). scoped_ptr<ProxyResolverJSBindings> bindings( - ProxyResolverJSBindings::CreateDefault(host_resolver)); + ProxyResolverJSBindings::CreateDefault(host_resolver, NULL)); std::string ip_address; @@ -281,5 +284,86 @@ TEST(ProxyResolverJSBindingsTest, PerRequestDNSCache) { bindings->set_current_request_context(NULL); } +// Test that when a binding is called, it logs to the per-request NetLog. +TEST(ProxyResolverJSBindingsTest, NetLog) { + scoped_refptr<MockFailingHostResolver> host_resolver( + new MockFailingHostResolver); + + CapturingNetLog global_log(CapturingNetLog::kUnbounded); + + // Get a hold of a DefaultJSBindings* (it is a hidden impl class). + scoped_ptr<ProxyResolverJSBindings> bindings( + ProxyResolverJSBindings::CreateDefault(host_resolver, &global_log)); + + // Attach a capturing NetLog as the current request's log stream. + CapturingNetLog log(CapturingNetLog::kUnbounded); + BoundNetLog bound_log(NetLog::Source(NetLog::SOURCE_NONE, 0), &log); + ProxyResolverRequestContext context(&bound_log, NULL); + bindings->set_current_request_context(&context); + + std::string ip_address; + + ASSERT_EQ(0u, log.entries().size()); + + // Call all the bindings. Each call should be logging something to + // our NetLog. + + bindings->MyIpAddress(&ip_address); + EXPECT_EQ(2u, log.entries().size()); + EXPECT_TRUE(LogContainsBeginEvent( + log.entries(), 0, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS)); + EXPECT_TRUE(LogContainsEndEvent( + log.entries(), 1, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS)); + + bindings->MyIpAddressEx(&ip_address); + EXPECT_EQ(4u, log.entries().size()); + EXPECT_TRUE(LogContainsBeginEvent( + log.entries(), 2, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX)); + EXPECT_TRUE(LogContainsEndEvent( + log.entries(), 3, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX)); + + bindings->DnsResolve("foo", &ip_address); + EXPECT_EQ(6u, log.entries().size()); + EXPECT_TRUE(LogContainsBeginEvent( + log.entries(), 4, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE)); + EXPECT_TRUE(LogContainsEndEvent( + log.entries(), 5, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE)); + + bindings->DnsResolveEx("foo", &ip_address); + EXPECT_EQ(8u, log.entries().size()); + EXPECT_TRUE(LogContainsBeginEvent( + log.entries(), 6, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX)); + EXPECT_TRUE(LogContainsEndEvent( + log.entries(), 7, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX)); + + // Nothing has been emitted globally yet. + EXPECT_EQ(0u, global_log.entries().size()); + + bindings->OnError(30, string16()); + EXPECT_EQ(9u, log.entries().size()); + EXPECT_TRUE(LogContainsEvent( + log.entries(), 8, NetLog::TYPE_PAC_JAVASCRIPT_ERROR, + NetLog::PHASE_NONE)); + + // We also emit errors to the top-level log stream. + EXPECT_EQ(1u, global_log.entries().size()); + EXPECT_TRUE(LogContainsEvent( + global_log.entries(), 0, NetLog::TYPE_PAC_JAVASCRIPT_ERROR, + NetLog::PHASE_NONE)); + + bindings->Alert(string16()); + EXPECT_EQ(10u, log.entries().size()); + EXPECT_TRUE(LogContainsEvent( + log.entries(), 9, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, + NetLog::PHASE_NONE)); + + // We also emit javascript alerts to the top-level log stream. + EXPECT_EQ(2u, global_log.entries().size()); + EXPECT_TRUE(LogContainsEvent( + global_log.entries(), 1, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, + NetLog::PHASE_NONE)); +} + } // namespace + } // namespace net diff --git a/net/proxy/proxy_resolver_perftest.cc b/net/proxy/proxy_resolver_perftest.cc index 6f7d340..3dd1f59 100644 --- a/net/proxy/proxy_resolver_perftest.cc +++ b/net/proxy/proxy_resolver_perftest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -192,9 +192,11 @@ TEST(ProxyResolverPerfTest, ProxyResolverMac) { TEST(ProxyResolverPerfTest, ProxyResolverV8) { net::ProxyResolverJSBindings* js_bindings = - net::ProxyResolverJSBindings::CreateDefault(new net::MockHostResolver); + net::ProxyResolverJSBindings::CreateDefault( + new net::MockHostResolver, NULL); net::ProxyResolverV8 resolver(js_bindings); PacPerfSuiteRunner runner(&resolver, "ProxyResolverV8"); runner.RunAllTests(); } + diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc index 4a47b345..78906b8 100644 --- a/net/proxy/proxy_resolver_v8.cc +++ b/net/proxy/proxy_resolver_v8.cc @@ -455,19 +455,9 @@ class ProxyResolverV8::Context { { v8::Unlocker unlocker; - LogEventToCurrentRequest(context, - NetLog::PHASE_BEGIN, - NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS, - NULL); - // We shouldn't be called with any arguments, but will not complain if // we are. success = context->js_bindings_->MyIpAddress(&result); - - LogEventToCurrentRequest(context, - NetLog::PHASE_END, - NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS, - NULL); } if (!success) @@ -487,19 +477,9 @@ class ProxyResolverV8::Context { { v8::Unlocker unlocker; - LogEventToCurrentRequest(context, - NetLog::PHASE_BEGIN, - NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX, - NULL); - // We shouldn't be called with any arguments, but will not complain if // we are. success = context->js_bindings_->MyIpAddressEx(&ip_address_list); - - LogEventToCurrentRequest(context, - NetLog::PHASE_END, - NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX, - NULL); } if (!success) @@ -522,18 +502,7 @@ class ProxyResolverV8::Context { { v8::Unlocker unlocker; - - LogEventToCurrentRequest(context, - NetLog::PHASE_BEGIN, - NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE, - NULL); - success = context->js_bindings_->DnsResolve(hostname, &ip_address); - - LogEventToCurrentRequest(context, - NetLog::PHASE_END, - NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE, - NULL); } return success ? ASCIIStringToV8String(ip_address) : v8::Null(); @@ -554,19 +523,8 @@ class ProxyResolverV8::Context { { v8::Unlocker unlocker; - - LogEventToCurrentRequest(context, - NetLog::PHASE_BEGIN, - NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX, - NULL); - success = context->js_bindings_->DnsResolveEx(hostname, &ip_address_list); - - LogEventToCurrentRequest(context, - NetLog::PHASE_END, - NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX, - NULL); } if (!success) @@ -575,16 +533,6 @@ class ProxyResolverV8::Context { return ASCIIStringToV8String(ip_address_list); } - static void LogEventToCurrentRequest(Context* context, - NetLog::EventPhase phase, - NetLog::EventType type, - NetLog::EventParameters* params) { - if (context->js_bindings_->current_request_context()) { - context->js_bindings_->current_request_context()->net_log->AddEntry( - type, phase, params); - } - } - ProxyResolverJSBindings* js_bindings_; v8::Persistent<v8::External> v8_this_; v8::Persistent<v8::Context> v8_context_; diff --git a/net/proxy/proxy_resolver_v8_unittest.cc b/net/proxy/proxy_resolver_v8_unittest.cc index ae664b2..afe79e3 100644 --- a/net/proxy/proxy_resolver_v8_unittest.cc +++ b/net/proxy/proxy_resolver_v8_unittest.cc @@ -7,8 +7,8 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "googleurl/src/gurl.h" -#include "net/base/net_log_unittest.h" #include "net/base/net_errors.h" +#include "net/base/net_log_unittest.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_resolver_js_bindings.h" #include "net/proxy/proxy_resolver_v8.h" @@ -458,41 +458,6 @@ TEST(ProxyResolverV8Test, BindingCalledDuringInitialization) { ASSERT_EQ(0U, bindings->dns_resolves_ex.size()); } -// Test that calls to the myIpAddress() and dnsResolve() bindings get -// logged to the NetLog parameter. -TEST(ProxyResolverV8Test, NetLog) { - ProxyResolverV8WithMockBindings resolver; - int result = resolver.SetPacScriptFromDisk("simple.js"); - EXPECT_EQ(OK, result); - - ProxyInfo proxy_info; - CapturingBoundNetLog log(CapturingNetLog::kUnbounded); - result = resolver.GetProxyForURL(kQueryUrl, &proxy_info, NULL, NULL, - log.bound()); - - EXPECT_EQ(OK, result); - EXPECT_FALSE(proxy_info.is_direct()); - EXPECT_EQ("c:100", proxy_info.proxy_server().ToURI()); - - // Note that dnsResolve() was never called directly, but it appears - // in the NetLog. This is because it gets called indirectly by - // isInNet() and isResolvable(). - - EXPECT_EQ(6u, log.entries().size()); - EXPECT_TRUE(LogContainsBeginEvent( - log.entries(), 0, NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS)); - EXPECT_TRUE(LogContainsEndEvent( - log.entries(), 1, NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS)); - EXPECT_TRUE(LogContainsBeginEvent( - log.entries(), 2, NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE)); - EXPECT_TRUE(LogContainsEndEvent( - log.entries(), 3, NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE)); - EXPECT_TRUE(LogContainsBeginEvent( - log.entries(), 4, NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE)); - EXPECT_TRUE(LogContainsEndEvent( - log.entries(), 5, NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE)); -} - // Try loading a PAC script that ends with a comment and has no terminal // newline. This should not cause problems with the PAC utility functions // that we add to the script's environment. diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index e6dc15e..5dee33c 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -11,6 +11,7 @@ #include "base/message_loop.h" #include "base/string_util.h" #include "googleurl/src/gurl.h" +#include "net/base/forwarding_net_log.h" #include "net/base/net_log.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" @@ -79,23 +80,29 @@ class ProxyResolverNull : public ProxyResolver { // This factory creates V8ProxyResolvers with appropriate javascript bindings. class ProxyResolverFactoryForV8 : public ProxyResolverFactory { public: - // Both |async_host_resolver| and |host_resolver_loop| must remain valid for - // duration of our lifetime. + // |async_host_resolver|, |io_loop| and |net_log| must remain + // valid for the duration of our lifetime. + // Both |async_host_resolver| and |net_log| will only be operated on + // |io_loop|. ProxyResolverFactoryForV8(HostResolver* async_host_resolver, - MessageLoop* host_resolver_loop) + MessageLoop* io_loop, + NetLog* net_log) : ProxyResolverFactory(true /*expects_pac_bytes*/), async_host_resolver_(async_host_resolver), - host_resolver_loop_(host_resolver_loop) { + io_loop_(io_loop), + forwarding_net_log_( + net_log ? new ForwardingNetLog(net_log, io_loop) : NULL) { } virtual ProxyResolver* CreateProxyResolver() { // Create a synchronous host resolver wrapper that operates - // |async_host_resolver_| on |host_resolver_loop_|. + // |async_host_resolver_| on |io_loop_|. SyncHostResolverBridge* sync_host_resolver = - new SyncHostResolverBridge(async_host_resolver_, host_resolver_loop_); + new SyncHostResolverBridge(async_host_resolver_, io_loop_); ProxyResolverJSBindings* js_bindings = - ProxyResolverJSBindings::CreateDefault(sync_host_resolver); + ProxyResolverJSBindings::CreateDefault(sync_host_resolver, + forwarding_net_log_.get()); // ProxyResolverV8 takes ownership of |js_bindings|. return new ProxyResolverV8(js_bindings); @@ -103,7 +110,11 @@ class ProxyResolverFactoryForV8 : public ProxyResolverFactory { private: scoped_refptr<HostResolver> async_host_resolver_; - MessageLoop* host_resolver_loop_; + MessageLoop* io_loop_; + + // Thread-safe wrapper around a non-threadsafe NetLog implementation. This + // enables the proxy resolver to emit log messages from the PAC thread. + scoped_ptr<ForwardingNetLog> forwarding_net_log_; }; // Creates ProxyResolvers using a non-V8 implementation. @@ -277,7 +288,8 @@ ProxyService* ProxyService::Create( sync_resolver_factory = new ProxyResolverFactoryForV8( url_request_context->host_resolver(), - io_loop); + io_loop, + net_log); } else { sync_resolver_factory = new ProxyResolverFactoryForNonV8(); } |