summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/base/forwarding_net_log.cc101
-rw-r--r--net/base/forwarding_net_log.h53
-rw-r--r--net/base/forwarding_net_log_unittest.cc84
-rw-r--r--net/base/net_log.h1
-rw-r--r--net/base/net_log_event_type_list.h24
-rw-r--r--net/net.gyp3
-rw-r--r--net/proxy/multi_threaded_proxy_resolver.h2
-rw-r--r--net/proxy/multi_threaded_proxy_resolver_unittest.cc2
-rw-r--r--net/proxy/proxy_resolver_js_bindings.cc188
-rw-r--r--net/proxy/proxy_resolver_js_bindings.h10
-rw-r--r--net/proxy/proxy_resolver_js_bindings_unittest.cc96
-rw-r--r--net/proxy/proxy_resolver_perftest.cc6
-rw-r--r--net/proxy/proxy_resolver_v8.cc52
-rw-r--r--net/proxy/proxy_resolver_v8_unittest.cc37
-rw-r--r--net/proxy/proxy_service.cc30
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();
}