Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: net/proxy/proxy_resolver_v8.cc

Issue 118100: Avoid doing concurrent DNS resolves of the same hostname (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Get compiling on mac Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the 2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file. 3 // LICENSE file.
4 4
5 #include "net/proxy/proxy_resolver_v8.h" 5 #include "net/proxy/proxy_resolver_v8.h"
6 6
7 #include "base/compiler_specific.h"
7 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop.h"
10 #include "base/waitable_event.h"
8 #include "base/string_util.h" 11 #include "base/string_util.h"
9 #include "googleurl/src/gurl.h" 12 #include "googleurl/src/gurl.h"
10 #include "net/base/address_list.h" 13 #include "net/base/address_list.h"
11 #include "net/base/host_resolver.h" 14 #include "net/base/host_resolver.h"
12 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
13 #include "net/base/net_util.h" 16 #include "net/base/net_util.h"
14 #include "net/proxy/proxy_info.h" 17 #include "net/proxy/proxy_info.h"
15 #include "net/proxy/proxy_resolver_script.h" 18 #include "net/proxy/proxy_resolver_script.h"
16 #include "v8/include/v8.h" 19 #include "v8/include/v8.h"
17 20
(...skipping 25 matching lines...) Expand all
43 return false; 46 return false;
44 47
45 v8::HandleScope scope; 48 v8::HandleScope scope;
46 v8::Local<v8::String> str_object = object->ToString(); 49 v8::Local<v8::String> str_object = object->ToString();
47 if (str_object.IsEmpty()) 50 if (str_object.IsEmpty())
48 return false; 51 return false;
49 *result = V8StringToStdString(str_object); 52 *result = V8StringToStdString(str_object);
50 return true; 53 return true;
51 } 54 }
52 55
56 // Wrapper around HostResolver to give a sync API while running the resolve
57 // in async mode on |host_resolver_loop|. If |host_resolver_loop| is NULL,
58 // runs sync on the current thread (this mode is just used by testing).
59 class SyncHostResolverBridge
60 : public base::RefCountedThreadSafe<SyncHostResolverBridge> {
61 public:
62 SyncHostResolverBridge(HostResolver* host_resolver,
63 MessageLoop* host_resolver_loop)
64 : host_resolver_(host_resolver),
65 host_resolver_loop_(host_resolver_loop),
66 event_(false, false),
67 ALLOW_THIS_IN_INITIALIZER_LIST(
68 callback_(this, &SyncHostResolverBridge::OnResolveCompletion)) {
69 }
70
71 // Run the resolve on host_resolver_loop, and wait for result.
72 int Resolve(const std::string& hostname, net::AddressList* addresses) {
73 int kPort = 80; // Doesn't matter.
74
75 // Hack for tests -- run synchronously on current thread.
76 if (!host_resolver_loop_)
77 return host_resolver_->Resolve(hostname, kPort, addresses, NULL, NULL);
78
79 // Otherwise start an async resolve on the resolver's thread.
80 host_resolver_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
81 &SyncHostResolverBridge::StartResolve, hostname, kPort, addresses));
82
83 // Wait for the resolve to complete in the resolver's thread.
84 event_.Wait();
85 return err_;
86 }
87
88 private:
89 // Called on host_resolver_loop_.
90 void StartResolve(const std::string& hostname,
91 int port,
92 net::AddressList* addresses) {
93 DCHECK_EQ(host_resolver_loop_, MessageLoop::current());
94 int error = host_resolver_->Resolve(
95 hostname, port, addresses, &callback_, NULL);
96 if (error != ERR_IO_PENDING)
97 OnResolveCompletion(error); // Completed synchronously.
98 }
99
100 // Called on host_resolver_loop_.
101 void OnResolveCompletion(int result) {
102 DCHECK_EQ(host_resolver_loop_, MessageLoop::current());
103 err_ = result;
104 event_.Signal();
105 }
106
107 HostResolver* host_resolver_;
108 MessageLoop* host_resolver_loop_;
109
110 // Event to notify completion of resolve request.
111 base::WaitableEvent event_;
112
113 // Callback for when the resolve completes on host_resolver_loop_.
114 net::CompletionCallbackImpl<SyncHostResolverBridge> callback_;
115
116 // The result from the result request (set by in host_resolver_loop_).
117 int err_;
118 };
119
53 // JSBIndings implementation. 120 // JSBIndings implementation.
54 class DefaultJSBindings : public ProxyResolverV8::JSBindings { 121 class DefaultJSBindings : public ProxyResolverV8::JSBindings {
55 public: 122 public:
123 DefaultJSBindings(HostResolver* host_resolver,
124 MessageLoop* host_resolver_loop)
125 : host_resolver_(new SyncHostResolverBridge(
126 host_resolver, host_resolver_loop)) {}
127
56 // Handler for "alert(message)". 128 // Handler for "alert(message)".
57 virtual void Alert(const std::string& message) { 129 virtual void Alert(const std::string& message) {
58 LOG(INFO) << "PAC-alert: " << message; 130 LOG(INFO) << "PAC-alert: " << message;
59 } 131 }
60 132
61 // Handler for "myIpAddress()". Returns empty string on failure. 133 // Handler for "myIpAddress()". Returns empty string on failure.
62 virtual std::string MyIpAddress() { 134 virtual std::string MyIpAddress() {
63 // DnsResolve("") returns "", so no need to check for failure. 135 // DnsResolve("") returns "", so no need to check for failure.
64 return DnsResolve(GetHostName()); 136 return DnsResolve(GetHostName());
65 } 137 }
66 138
67 // Handler for "dnsResolve(host)". Returns empty string on failure. 139 // Handler for "dnsResolve(host)". Returns empty string on failure.
68 virtual std::string DnsResolve(const std::string& host) { 140 virtual std::string DnsResolve(const std::string& host) {
69 // TODO(eroman): Should this return our IP address, or fail, or 141 // TODO(eroman): Should this return our IP address, or fail, or
70 // simply be unspecified (works differently on windows and mac os x). 142 // simply be unspecified (works differently on windows and mac os x).
71 if (host.empty()) 143 if (host.empty())
72 return std::string(); 144 return std::string();
73 145
74 // Try to resolve synchronously. 146 // Do a sync resolve of the hostname.
75 net::AddressList address_list; 147 net::AddressList address_list;
76 const int kPort = 80; // Doesn't matter what this is. 148 int result = host_resolver_->Resolve(host, &address_list);
77 int result = host_resolver_.Resolve(host, kPort, &address_list, NULL);
78 149
79 if (result != OK) 150 if (result != OK)
80 return std::string(); // Failed. 151 return std::string(); // Failed.
81 152
82 if (!address_list.head()) 153 if (!address_list.head())
83 return std::string(); 154 return std::string();
84 155
85 // There may be multiple results; we will just use the first one. 156 // There may be multiple results; we will just use the first one.
86 // This returns empty string on failure. 157 // This returns empty string on failure.
87 return net::NetAddressToString(address_list.head()); 158 return net::NetAddressToString(address_list.head());
88 } 159 }
89 160
90 // Handler for when an error is encountered. |line_number| may be -1. 161 // Handler for when an error is encountered. |line_number| may be -1.
91 virtual void OnError(int line_number, const std::string& message) { 162 virtual void OnError(int line_number, const std::string& message) {
92 if (line_number == -1) 163 if (line_number == -1)
93 LOG(INFO) << "PAC-error: " << message; 164 LOG(INFO) << "PAC-error: " << message;
94 else 165 else
95 LOG(INFO) << "PAC-error: " << "line: " << line_number << ": " << message; 166 LOG(INFO) << "PAC-error: " << "line: " << line_number << ": " << message;
96 } 167 }
97 168
98 private: 169 private:
99 HostResolver host_resolver_; 170 scoped_refptr<SyncHostResolverBridge> host_resolver_;
100 }; 171 };
101 172
102 } // namespace 173 } // namespace
103 174
104 // ProxyResolverV8::Context --------------------------------------------------- 175 // ProxyResolverV8::Context ---------------------------------------------------
105 176
106 class ProxyResolverV8::Context { 177 class ProxyResolverV8::Context {
107 public: 178 public:
108 Context(JSBindings* js_bindings, const std::string& pac_data) 179 Context(JSBindings* js_bindings, const std::string& pac_data)
109 : js_bindings_(js_bindings) { 180 : js_bindings_(js_bindings) {
110 DCHECK(js_bindings != NULL); 181 DCHECK(js_bindings != NULL);
111 InitV8(pac_data); 182 InitV8(pac_data);
112 } 183 }
113 184
114 ~Context() { 185 ~Context() {
115 v8::Locker locked; 186 v8::Locker locked;
116 187
117 v8_this_.Dispose(); 188 v8_this_.Dispose();
118 v8_context_.Dispose(); 189 v8_context_.Dispose();
119 } 190 }
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 return v8::Undefined(); 330 return v8::Undefined();
260 } 331 }
261 332
262 std::string result = context->js_bindings_->DnsResolve(host); 333 std::string result = context->js_bindings_->DnsResolve(host);
263 334
264 // DoDnsResolve() returns empty string on failure. 335 // DoDnsResolve() returns empty string on failure.
265 return result.empty() ? v8::Null() : StdStringToV8String(result); 336 return result.empty() ? v8::Null() : StdStringToV8String(result);
266 } 337 }
267 338
268 JSBindings* js_bindings_; 339 JSBindings* js_bindings_;
269 HostResolver host_resolver_;
270 v8::Persistent<v8::External> v8_this_; 340 v8::Persistent<v8::External> v8_this_;
271 v8::Persistent<v8::Context> v8_context_; 341 v8::Persistent<v8::Context> v8_context_;
272 }; 342 };
273 343
274 // ProxyResolverV8 ------------------------------------------------------------ 344 // ProxyResolverV8 ------------------------------------------------------------
275 345
276 // the |false| argument to ProxyResolver means the ProxyService will handle
277 // downloading of the PAC script, and notify changes through SetPacScript().
278 ProxyResolverV8::ProxyResolverV8()
279 : ProxyResolver(false /*does_fetch*/),
280 js_bindings_(new DefaultJSBindings()) {
281 }
282
283 ProxyResolverV8::ProxyResolverV8( 346 ProxyResolverV8::ProxyResolverV8(
284 ProxyResolverV8::JSBindings* custom_js_bindings) 347 ProxyResolverV8::JSBindings* custom_js_bindings)
285 : ProxyResolver(false), js_bindings_(custom_js_bindings) { 348 : ProxyResolver(false), js_bindings_(custom_js_bindings) {
286 } 349 }
287 350
288 ProxyResolverV8::~ProxyResolverV8() {} 351 ProxyResolverV8::~ProxyResolverV8() {}
289 352
290 int ProxyResolverV8::GetProxyForURL(const GURL& query_url, 353 int ProxyResolverV8::GetProxyForURL(const GURL& query_url,
291 const GURL& /*pac_url*/, 354 const GURL& /*pac_url*/,
292 ProxyInfo* results) { 355 ProxyInfo* results) {
293 // If the V8 instance has not been initialized (either because SetPacScript() 356 // If the V8 instance has not been initialized (either because SetPacScript()
294 // wasn't called yet, or because it was called with empty string). 357 // wasn't called yet, or because it was called with empty string).
295 if (!context_.get()) 358 if (!context_.get())
296 return ERR_FAILED; 359 return ERR_FAILED;
297 360
298 // Otherwise call into V8. 361 // Otherwise call into V8.
299 return context_->ResolveProxy(query_url, results); 362 return context_->ResolveProxy(query_url, results);
300 } 363 }
301 364
302 void ProxyResolverV8::SetPacScript(const std::string& data) { 365 void ProxyResolverV8::SetPacScript(const std::string& data) {
303 context_.reset(); 366 context_.reset();
304 if (!data.empty()) 367 if (!data.empty())
305 context_.reset(new Context(js_bindings_.get(), data)); 368 context_.reset(new Context(js_bindings_.get(), data));
306 } 369 }
307 370
371 // static
372 ProxyResolverV8::JSBindings* ProxyResolverV8::CreateDefaultBindings(
373 HostResolver* host_resolver, MessageLoop* host_resolver_loop) {
374 return new DefaultJSBindings(host_resolver, host_resolver_loop);
375 }
376
308 } // namespace net 377 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698