summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/proxy/proxy_resolver.h7
-rw-r--r--net/proxy/proxy_resolver_v8.cc14
-rw-r--r--net/proxy/proxy_resolver_v8.h1
-rw-r--r--net/proxy/proxy_resolver_v8_unittest.cc7
-rw-r--r--net/proxy/proxy_service.cc5
-rw-r--r--net/proxy/proxy_service.h5
-rw-r--r--net/proxy/single_threaded_proxy_resolver.cc20
-rw-r--r--net/proxy/single_threaded_proxy_resolver.h2
-rw-r--r--net/proxy/single_threaded_proxy_resolver_unittest.cc21
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