| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // LICENSE file. | 3 // found in the 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/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "googleurl/src/gurl.h" | 9 #include "googleurl/src/gurl.h" |
| 10 #include "net/base/load_log.h" | |
| 11 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
| 11 #include "net/base/net_log.h" |
| 12 #include "net/proxy/proxy_info.h" | 12 #include "net/proxy/proxy_info.h" |
| 13 #include "net/proxy/proxy_resolver_js_bindings.h" | 13 #include "net/proxy/proxy_resolver_js_bindings.h" |
| 14 #include "net/proxy/proxy_resolver_script.h" | 14 #include "net/proxy/proxy_resolver_script.h" |
| 15 #include "v8/include/v8.h" | 15 #include "v8/include/v8.h" |
| 16 | 16 |
| 17 // Notes on the javascript environment: | 17 // Notes on the javascript environment: |
| 18 // | 18 // |
| 19 // For the majority of the PAC utility functions, we use the same code | 19 // For the majority of the PAC utility functions, we use the same code |
| 20 // as Firefox. See the javascript library that proxy_resolver_scipt.h | 20 // as Firefox. See the javascript library that proxy_resolver_scipt.h |
| 21 // pulls in. | 21 // pulls in. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 return true; | 95 return true; |
| 96 } | 96 } |
| 97 | 97 |
| 98 } // namespace | 98 } // namespace |
| 99 | 99 |
| 100 // ProxyResolverV8::Context --------------------------------------------------- | 100 // ProxyResolverV8::Context --------------------------------------------------- |
| 101 | 101 |
| 102 class ProxyResolverV8::Context { | 102 class ProxyResolverV8::Context { |
| 103 public: | 103 public: |
| 104 explicit Context(ProxyResolverJSBindings* js_bindings) | 104 explicit Context(ProxyResolverJSBindings* js_bindings) |
| 105 : js_bindings_(js_bindings), current_request_load_log_(NULL) { | 105 : js_bindings_(js_bindings), current_request_net_log_(NULL) { |
| 106 DCHECK(js_bindings != NULL); | 106 DCHECK(js_bindings != NULL); |
| 107 } | 107 } |
| 108 | 108 |
| 109 ~Context() { | 109 ~Context() { |
| 110 v8::Locker locked; | 110 v8::Locker locked; |
| 111 | 111 |
| 112 v8_this_.Dispose(); | 112 v8_this_.Dispose(); |
| 113 v8_context_.Dispose(); | 113 v8_context_.Dispose(); |
| 114 } | 114 } |
| 115 | 115 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 | 207 |
| 208 // At a minimum, the FindProxyForURL() function must be defined for this | 208 // At a minimum, the FindProxyForURL() function must be defined for this |
| 209 // to be a legitimiate PAC script. | 209 // to be a legitimiate PAC script. |
| 210 v8::Local<v8::Value> function; | 210 v8::Local<v8::Value> function; |
| 211 if (!GetFindProxyForURL(&function)) | 211 if (!GetFindProxyForURL(&function)) |
| 212 return ERR_PAC_SCRIPT_FAILED; | 212 return ERR_PAC_SCRIPT_FAILED; |
| 213 | 213 |
| 214 return OK; | 214 return OK; |
| 215 } | 215 } |
| 216 | 216 |
| 217 void SetCurrentRequestLoadLog(LoadLog* load_log) { | 217 void SetCurrentRequestNetLog(BoundNetLog* net_log) { |
| 218 current_request_load_log_ = load_log; | 218 current_request_net_log_ = net_log; |
| 219 } | 219 } |
| 220 | 220 |
| 221 void PurgeMemory() { | 221 void PurgeMemory() { |
| 222 v8::Locker locked; | 222 v8::Locker locked; |
| 223 // Repeatedly call the V8 idle notification until it returns true ("nothing | 223 // Repeatedly call the V8 idle notification until it returns true ("nothing |
| 224 // more to free"). Note that it makes more sense to do this than to | 224 // more to free"). Note that it makes more sense to do this than to |
| 225 // implement a new "delete everything" pass because object references make | 225 // implement a new "delete everything" pass because object references make |
| 226 // it difficult to free everything possible in just one pass. | 226 // it difficult to free everything possible in just one pass. |
| 227 while (!v8::V8::IdleNotification()) | 227 while (!v8::V8::IdleNotification()) |
| 228 ; | 228 ; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 | 286 |
| 287 context->js_bindings_->Alert(message); | 287 context->js_bindings_->Alert(message); |
| 288 return v8::Undefined(); | 288 return v8::Undefined(); |
| 289 } | 289 } |
| 290 | 290 |
| 291 // V8 callback for when "myIpAddress()" is invoked by the PAC script. | 291 // V8 callback for when "myIpAddress()" is invoked by the PAC script. |
| 292 static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) { | 292 static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) { |
| 293 Context* context = | 293 Context* context = |
| 294 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 294 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 295 | 295 |
| 296 LoadLog::BeginEvent(context->current_request_load_log_, | 296 context->current_request_net_log_->BeginEvent( |
| 297 LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS); | 297 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS); |
| 298 | 298 |
| 299 // We shouldn't be called with any arguments, but will not complain if | 299 // We shouldn't be called with any arguments, but will not complain if |
| 300 // we are. | 300 // we are. |
| 301 std::string result = context->js_bindings_->MyIpAddress(); | 301 std::string result = context->js_bindings_->MyIpAddress(); |
| 302 | 302 |
| 303 LoadLog::EndEvent(context->current_request_load_log_, | 303 context->current_request_net_log_->EndEvent( |
| 304 LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS); | 304 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS); |
| 305 | 305 |
| 306 if (result.empty()) | 306 if (result.empty()) |
| 307 result = "127.0.0.1"; | 307 result = "127.0.0.1"; |
| 308 return StdStringToV8String(result); | 308 return StdStringToV8String(result); |
| 309 } | 309 } |
| 310 | 310 |
| 311 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. | 311 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. |
| 312 static v8::Handle<v8::Value> MyIpAddressExCallback( | 312 static v8::Handle<v8::Value> MyIpAddressExCallback( |
| 313 const v8::Arguments& args) { | 313 const v8::Arguments& args) { |
| 314 Context* context = | 314 Context* context = |
| 315 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 315 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 316 | 316 |
| 317 LoadLog::BeginEvent(context->current_request_load_log_, | 317 context->current_request_net_log_->BeginEvent( |
| 318 LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX); | 318 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX); |
| 319 | 319 |
| 320 // We shouldn't be called with any arguments, but will not complain if | 320 // We shouldn't be called with any arguments, but will not complain if |
| 321 // we are. | 321 // we are. |
| 322 std::string result = context->js_bindings_->MyIpAddressEx(); | 322 std::string result = context->js_bindings_->MyIpAddressEx(); |
| 323 | 323 |
| 324 LoadLog::EndEvent(context->current_request_load_log_, | 324 context->current_request_net_log_->EndEvent( |
| 325 LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX); | 325 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX); |
| 326 | 326 |
| 327 return StdStringToV8String(result); | 327 return StdStringToV8String(result); |
| 328 } | 328 } |
| 329 | 329 |
| 330 // V8 callback for when "dnsResolve()" is invoked by the PAC script. | 330 // V8 callback for when "dnsResolve()" is invoked by the PAC script. |
| 331 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { | 331 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { |
| 332 Context* context = | 332 Context* context = |
| 333 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 333 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 334 | 334 |
| 335 // We need at least one argument. | 335 // We need at least one argument. |
| 336 std::string host; | 336 std::string host; |
| 337 if (args.Length() == 0) { | 337 if (args.Length() == 0) { |
| 338 host = "undefined"; | 338 host = "undefined"; |
| 339 } else { | 339 } else { |
| 340 if (!V8ObjectToString(args[0], &host)) | 340 if (!V8ObjectToString(args[0], &host)) |
| 341 return v8::Undefined(); | 341 return v8::Undefined(); |
| 342 } | 342 } |
| 343 | 343 |
| 344 LoadLog::BeginEvent(context->current_request_load_log_, | 344 context->current_request_net_log_->BeginEvent( |
| 345 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE); | 345 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE); |
| 346 | 346 |
| 347 std::string result = context->js_bindings_->DnsResolve(host); | 347 std::string result = context->js_bindings_->DnsResolve(host); |
| 348 | 348 |
| 349 LoadLog::EndEvent(context->current_request_load_log_, | 349 context->current_request_net_log_->EndEvent( |
| 350 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE); | 350 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE); |
| 351 | 351 |
| 352 // DnsResolve() returns empty string on failure. | 352 // DnsResolve() returns empty string on failure. |
| 353 return result.empty() ? v8::Null() : StdStringToV8String(result); | 353 return result.empty() ? v8::Null() : StdStringToV8String(result); |
| 354 } | 354 } |
| 355 | 355 |
| 356 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. | 356 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. |
| 357 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { | 357 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { |
| 358 Context* context = | 358 Context* context = |
| 359 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 359 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 360 | 360 |
| 361 // We need at least one argument. | 361 // We need at least one argument. |
| 362 std::string host; | 362 std::string host; |
| 363 if (args.Length() == 0) { | 363 if (args.Length() == 0) { |
| 364 host = "undefined"; | 364 host = "undefined"; |
| 365 } else { | 365 } else { |
| 366 if (!V8ObjectToString(args[0], &host)) | 366 if (!V8ObjectToString(args[0], &host)) |
| 367 return v8::Undefined(); | 367 return v8::Undefined(); |
| 368 } | 368 } |
| 369 | 369 |
| 370 LoadLog::BeginEvent(context->current_request_load_log_, | 370 context->current_request_net_log_->BeginEvent( |
| 371 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX); | 371 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX); |
| 372 | 372 |
| 373 std::string result = context->js_bindings_->DnsResolveEx(host); | 373 std::string result = context->js_bindings_->DnsResolveEx(host); |
| 374 | 374 |
| 375 LoadLog::EndEvent(context->current_request_load_log_, | 375 context->current_request_net_log_->EndEvent( |
| 376 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX); | 376 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX); |
| 377 | 377 |
| 378 return StdStringToV8String(result); | 378 return StdStringToV8String(result); |
| 379 } | 379 } |
| 380 | 380 |
| 381 ProxyResolverJSBindings* js_bindings_; | 381 ProxyResolverJSBindings* js_bindings_; |
| 382 LoadLog* current_request_load_log_; | 382 BoundNetLog* current_request_net_log_; |
| 383 v8::Persistent<v8::External> v8_this_; | 383 v8::Persistent<v8::External> v8_this_; |
| 384 v8::Persistent<v8::Context> v8_context_; | 384 v8::Persistent<v8::Context> v8_context_; |
| 385 }; | 385 }; |
| 386 | 386 |
| 387 // ProxyResolverV8 ------------------------------------------------------------ | 387 // ProxyResolverV8 ------------------------------------------------------------ |
| 388 | 388 |
| 389 ProxyResolverV8::ProxyResolverV8( | 389 ProxyResolverV8::ProxyResolverV8( |
| 390 ProxyResolverJSBindings* custom_js_bindings) | 390 ProxyResolverJSBindings* custom_js_bindings) |
| 391 : ProxyResolver(true /*expects_pac_bytes*/), | 391 : ProxyResolver(true /*expects_pac_bytes*/), |
| 392 js_bindings_(custom_js_bindings) { | 392 js_bindings_(custom_js_bindings) { |
| 393 } | 393 } |
| 394 | 394 |
| 395 ProxyResolverV8::~ProxyResolverV8() {} | 395 ProxyResolverV8::~ProxyResolverV8() {} |
| 396 | 396 |
| 397 int ProxyResolverV8::GetProxyForURL(const GURL& query_url, | 397 int ProxyResolverV8::GetProxyForURL(const GURL& query_url, |
| 398 ProxyInfo* results, | 398 ProxyInfo* results, |
| 399 CompletionCallback* /*callback*/, | 399 CompletionCallback* /*callback*/, |
| 400 RequestHandle* /*request*/, | 400 RequestHandle* /*request*/, |
| 401 LoadLog* load_log) { | 401 const BoundNetLog& net_log) { |
| 402 // If the V8 instance has not been initialized (either because | 402 // If the V8 instance has not been initialized (either because |
| 403 // SetPacScript() wasn't called yet, or because it failed. | 403 // SetPacScript() wasn't called yet, or because it failed. |
| 404 if (!context_.get()) | 404 if (!context_.get()) |
| 405 return ERR_FAILED; | 405 return ERR_FAILED; |
| 406 | 406 |
| 407 BoundNetLog log(net_log); |
| 408 |
| 407 // Otherwise call into V8. | 409 // Otherwise call into V8. |
| 408 context_->SetCurrentRequestLoadLog(load_log); | 410 context_->SetCurrentRequestNetLog(&log); |
| 409 int rv = context_->ResolveProxy(query_url, results); | 411 int rv = context_->ResolveProxy(query_url, results); |
| 410 context_->SetCurrentRequestLoadLog(NULL); | 412 context_->SetCurrentRequestNetLog(NULL); |
| 411 | 413 |
| 412 return rv; | 414 return rv; |
| 413 } | 415 } |
| 414 | 416 |
| 415 void ProxyResolverV8::CancelRequest(RequestHandle request) { | 417 void ProxyResolverV8::CancelRequest(RequestHandle request) { |
| 416 // This is a synchronous ProxyResolver; no possibility for async requests. | 418 // This is a synchronous ProxyResolver; no possibility for async requests. |
| 417 NOTREACHED(); | 419 NOTREACHED(); |
| 418 } | 420 } |
| 419 | 421 |
| 420 void ProxyResolverV8::PurgeMemory() { | 422 void ProxyResolverV8::PurgeMemory() { |
| 421 context_->PurgeMemory(); | 423 context_->PurgeMemory(); |
| 422 } | 424 } |
| 423 | 425 |
| 424 int ProxyResolverV8::SetPacScript(const GURL& /*url*/, | 426 int ProxyResolverV8::SetPacScript(const GURL& /*url*/, |
| 425 const std::string& bytes_utf8, | 427 const std::string& bytes_utf8, |
| 426 CompletionCallback* /*callback*/) { | 428 CompletionCallback* /*callback*/) { |
| 427 context_.reset(); | 429 context_.reset(); |
| 428 if (bytes_utf8.empty()) | 430 if (bytes_utf8.empty()) |
| 429 return ERR_PAC_SCRIPT_FAILED; | 431 return ERR_PAC_SCRIPT_FAILED; |
| 430 | 432 |
| 431 // Try parsing the PAC script. | 433 // Try parsing the PAC script. |
| 432 scoped_ptr<Context> context(new Context(js_bindings_.get())); | 434 scoped_ptr<Context> context(new Context(js_bindings_.get())); |
| 433 int rv = context->InitV8(bytes_utf8); | 435 int rv = context->InitV8(bytes_utf8); |
| 434 if (rv == OK) | 436 if (rv == OK) |
| 435 context_.reset(context.release()); | 437 context_.reset(context.release()); |
| 436 return rv; | 438 return rv; |
| 437 } | 439 } |
| 438 | 440 |
| 439 } // namespace net | 441 } // namespace net |
| OLD | NEW |