diff options
-rw-r--r-- | net/proxy/proxy_resolver.h | 7 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_v8.cc | 14 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_v8.h | 1 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_v8_unittest.cc | 7 | ||||
-rw-r--r-- | net/proxy/proxy_service.cc | 5 | ||||
-rw-r--r-- | net/proxy/proxy_service.h | 5 | ||||
-rw-r--r-- | net/proxy/single_threaded_proxy_resolver.cc | 20 | ||||
-rw-r--r-- | net/proxy/single_threaded_proxy_resolver.h | 2 | ||||
-rw-r--r-- | net/proxy/single_threaded_proxy_resolver_unittest.cc | 21 |
9 files changed, 79 insertions, 3 deletions
diff --git a/net/proxy/proxy_resolver.h b/net/proxy/proxy_resolver.h index 58b09e6..2e83097b 100644 --- a/net/proxy/proxy_resolver.h +++ b/net/proxy/proxy_resolver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. @@ -70,6 +70,11 @@ class ProxyResolver { NOTREACHED(); } + // Frees any unneeded memory held by the resolver, e.g. garbage in the JS + // engine. Most subclasses don't need to do anything, so we provide a default + // no-op implementation. + virtual void PurgeMemory() {} + private: // Called to set the PAC script backend to use. If |pac_url| is invalid, // this is a request to use WPAD (auto detect). |bytes_utf8| may be empty if diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc index dee799b..7fd00bd 100644 --- a/net/proxy/proxy_resolver_v8.cc +++ b/net/proxy/proxy_resolver_v8.cc @@ -158,6 +158,16 @@ class ProxyResolverV8::Context { current_request_load_log_ = load_log; } + void PurgeMemory() { + v8::Locker locked; + // Repeatedly call the V8 idle notification until it returns true ("nothing + // more to free"). Note that it makes more sense to do this than to + // implement a new "delete everything" pass because object references make + // it difficult to free everything possible in just one pass. + while (!v8::V8::IdleNotification()) + ; + } + private: bool GetFindProxyForURL(v8::Local<v8::Value>* function) { *function = v8_context_->Global()->Get(v8::String::New("FindProxyForURL")); @@ -303,6 +313,10 @@ void ProxyResolverV8::CancelRequest(RequestHandle request) { NOTREACHED(); } +void ProxyResolverV8::PurgeMemory() { + context_->PurgeMemory(); +} + int ProxyResolverV8::SetPacScript(const GURL& /*url*/, const std::string& bytes_utf8, CompletionCallback* /*callback*/) { diff --git a/net/proxy/proxy_resolver_v8.h b/net/proxy/proxy_resolver_v8.h index ad81faa..236beab 100644 --- a/net/proxy/proxy_resolver_v8.h +++ b/net/proxy/proxy_resolver_v8.h @@ -51,6 +51,7 @@ class ProxyResolverV8 : public ProxyResolver { RequestHandle* /*request*/, LoadLog* load_log); virtual void CancelRequest(RequestHandle request); + virtual void PurgeMemory(); ProxyResolverJSBindings* js_bindings() const { return js_bindings_.get(); } diff --git a/net/proxy/proxy_resolver_v8_unittest.cc b/net/proxy/proxy_resolver_v8_unittest.cc index e37e643..c172093 100644 --- a/net/proxy/proxy_resolver_v8_unittest.cc +++ b/net/proxy/proxy_resolver_v8_unittest.cc @@ -161,6 +161,13 @@ TEST(ProxyResolverV8Test, Basic) { EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size()); EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); } + + // We call this so we'll have code coverage of the function and valgrind will + // make sure nothing bad happens. + // + // NOTE: This is here instead of in its own test so that we'll be calling it + // after having done something, in hopes it won't be a no-op. + resolver.PurgeMemory(); } TEST(ProxyResolverV8Test, BadReturnType) { diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index 637fbbd..6d881be 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -521,6 +521,11 @@ void ProxyService::ResetConfigService( UpdateConfig(); } +void ProxyService::PurgeMemory() { + if (resolver_.get()) + resolver_->PurgeMemory(); +} + void ProxyService::DidCompletePacRequest(int config_id, int result_code) { // If we get an error that indicates a bad PAC config, then we should // remember that, and not try the PAC config again for a while. diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index b38938f..c5c4516 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. @@ -100,6 +100,9 @@ class ProxyService : public base::RefCountedThreadSafe<ProxyService> { // |new_proxy_config_service|. void ResetConfigService(ProxyConfigService* new_proxy_config_service); + // Tells the resolver to purge any memory it does not need. + void PurgeMemory(); + // Returns the log for the most recent WPAD + PAC initialization. // (This shows how much time was spent downloading and parsing the // PAC scripts for the current configuration). diff --git a/net/proxy/single_threaded_proxy_resolver.cc b/net/proxy/single_threaded_proxy_resolver.cc index 01c35fa..af8d7bf 100644 --- a/net/proxy/single_threaded_proxy_resolver.cc +++ b/net/proxy/single_threaded_proxy_resolver.cc @@ -11,6 +11,18 @@ namespace net { +namespace { + +class PurgeMemoryTask : public base::RefCountedThreadSafe<PurgeMemoryTask> { + public: + explicit PurgeMemoryTask(ProxyResolver* resolver) : resolver_(resolver) {} + void PurgeMemory() { resolver_->PurgeMemory(); } + private: + ProxyResolver* resolver_; +}; + +} + // SingleThreadedProxyResolver::SetPacScriptTask ------------------------------ // Runs on the worker thread to call ProxyResolver::SetPacScript. @@ -255,6 +267,14 @@ void SingleThreadedProxyResolver::CancelSetPacScript() { outstanding_set_pac_script_task_ = NULL; } +void SingleThreadedProxyResolver::PurgeMemory() { + if (thread_.get()) { + scoped_refptr<PurgeMemoryTask> helper(new PurgeMemoryTask(resolver_.get())); + thread_->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(helper.get(), &PurgeMemoryTask::PurgeMemory)); + } +} + int SingleThreadedProxyResolver::SetPacScript( const GURL& pac_url, const std::string& pac_bytes, diff --git a/net/proxy/single_threaded_proxy_resolver.h b/net/proxy/single_threaded_proxy_resolver.h index 46c95a2..3d43309 100644 --- a/net/proxy/single_threaded_proxy_resolver.h +++ b/net/proxy/single_threaded_proxy_resolver.h @@ -23,7 +23,6 @@ namespace net { // are serviced in FIFO order. class SingleThreadedProxyResolver : public ProxyResolver { public: - // |resolver| is a synchronous ProxyResolver implementation. It doesn't // have to be thread-safe, since it is run on exactly one thread. The // constructor takes ownership of |resolver|. @@ -39,6 +38,7 @@ class SingleThreadedProxyResolver : public ProxyResolver { LoadLog* load_log); virtual void CancelRequest(RequestHandle request); virtual void CancelSetPacScript(); + virtual void PurgeMemory(); protected: // The wrapped (synchronous) ProxyResolver. diff --git a/net/proxy/single_threaded_proxy_resolver_unittest.cc b/net/proxy/single_threaded_proxy_resolver_unittest.cc index 7eee997..37bf14a 100644 --- a/net/proxy/single_threaded_proxy_resolver_unittest.cc +++ b/net/proxy/single_threaded_proxy_resolver_unittest.cc @@ -23,6 +23,7 @@ class MockProxyResolver : public ProxyResolver { : ProxyResolver(true /*expects_pac_bytes*/), wrong_loop_(MessageLoop::current()), request_count_(0), + purge_count_(0), resolve_latency_ms_(0) {} // ProxyResolver implementation: @@ -60,6 +61,13 @@ class MockProxyResolver : public ProxyResolver { return OK; } + virtual void PurgeMemory() { + CheckIsOnWorkerThread(); + ++purge_count_; + } + + int purge_count() const { return purge_count_; } + const std::string& last_pac_bytes() const { return last_pac_bytes_; } void SetResolveLatency(int latency_ms) { @@ -77,6 +85,7 @@ class MockProxyResolver : public ProxyResolver { MessageLoop* wrong_loop_; int request_count_; + int purge_count_; std::string last_pac_bytes_; int resolve_latency_ms_; }; @@ -195,6 +204,18 @@ TEST(SingleThreadedProxyResolverTest, Basic) { rv = callback3.WaitForResult(); EXPECT_EQ(3, rv); EXPECT_EQ("PROXY request3:80", results3.ToPacString()); + + // Ensure that PurgeMemory() reaches the wrapped resolver and happens on the + // right thread. + EXPECT_EQ(0, mock->purge_count()); + resolver->PurgeMemory(); + // There is no way to get a callback directly when PurgeMemory() completes, so + // we queue up a dummy request after the PurgeMemory() call and wait until it + // finishes to ensure PurgeMemory() has had a chance to run. + TestCompletionCallback dummy_callback; + rv = resolver->SetPacScriptByData("dummy", &dummy_callback); + EXPECT_EQ(OK, dummy_callback.WaitForResult()); + EXPECT_EQ(1, mock->purge_count()); } // Cancel a request which is in progress, and then cancel a request which |