summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-31 01:34:20 +0000
committerericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-31 01:34:20 +0000
commit41b2780f0135d23196958816d3adcfd606b80f1e (patch)
tree306a00be7404dfc6d3ff9ef667d35827f87281a2 /chrome/browser
parent18a12354e6c3e1edf2f85e11cd7359127d2d3ce2 (diff)
downloadchromium_src-41b2780f0135d23196958816d3adcfd606b80f1e.zip
chromium_src-41b2780f0135d23196958816d3adcfd606b80f1e.tar.gz
chromium_src-41b2780f0135d23196958816d3adcfd606b80f1e.tar.bz2
Move proxy resolve requests out of plugin/renderer process, and into the browser.
Review URL: http://codereview.chromium.org/14142 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9006 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser.scons3
-rw-r--r--chrome/browser/browser.vcproj8
-rw-r--r--chrome/browser/net/resolve_proxy_msg_helper.cc89
-rw-r--r--chrome/browser/net/resolve_proxy_msg_helper.h104
-rw-r--r--chrome/browser/net/resolve_proxy_msg_helper_unittest.cc349
-rw-r--r--chrome/browser/plugin_process_host.cc67
-rw-r--r--chrome/browser/plugin_process_host.h16
-rw-r--r--chrome/browser/resource_message_filter.cc17
-rw-r--r--chrome/browser/resource_message_filter.h15
9 files changed, 603 insertions, 65 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons
index 5a56ec1..09ab7e5 100644
--- a/chrome/browser/browser.scons
+++ b/chrome/browser/browser.scons
@@ -432,6 +432,8 @@ input_files = ChromeFileList([
'net/dns_slave.h',
'net/referrer.cc',
'net/referrer.h',
+ 'net/resolve_proxy_msg_helper.cc',
+ 'net/resolve_proxy_msg_helper.h',
'net/sdch_dictionary_fetcher.cc',
'net/sdch_dictionary_fetcher.h',
'net/url_fetcher.cc',
@@ -746,6 +748,7 @@ if not env.Bit('windows'):
'net/dns_global.cc',
'net/dns_master.cc',
'net/dns_slave.cc',
+ 'net/resolve_proxy_msg_helper.cc',
'google_update.cc',
'password_manager/encryptor.cc',
'password_manager/ie7_password.cc',
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index b76a16f..253a164 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -1650,6 +1650,14 @@
>
</File>
<File
+ RelativePath=".\net\resolve_proxy_msg_helper.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\net\resolve_proxy_msg_helper.h"
+ >
+ </File>
+ <File
RelativePath=".\net\sdch_dictionary_fetcher.cc"
>
</File>
diff --git a/chrome/browser/net/resolve_proxy_msg_helper.cc b/chrome/browser/net/resolve_proxy_msg_helper.cc
new file mode 100644
index 0000000..dca5ad6
--- /dev/null
+++ b/chrome/browser/net/resolve_proxy_msg_helper.cc
@@ -0,0 +1,89 @@
+// 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.
+
+#include "chrome/browser/net/resolve_proxy_msg_helper.h"
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/profile.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request_context.h"
+
+ResolveProxyMsgHelper::ResolveProxyMsgHelper(Delegate* delegate,
+ net::ProxyService* proxy_service)
+ : proxy_service_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
+ this, &ResolveProxyMsgHelper::OnResolveProxyCompleted)),
+ delegate_(delegate),
+ proxy_service_override_(proxy_service) {
+}
+
+void ResolveProxyMsgHelper::Start(const GURL& url, IPC::Message* reply_msg) {
+ // Enqueue the pending request.
+ pending_requests_.push_back(PendingRequest(url, reply_msg));
+
+ // If nothing is in progress, start.
+ if (pending_requests_.size() == 1)
+ StartPendingRequest();
+}
+
+void ResolveProxyMsgHelper::OnResolveProxyCompleted(int result) {
+ CHECK(!pending_requests_.empty());
+
+ // Notify the delegate of completion.
+ const PendingRequest& completed_req = pending_requests_.front();
+ delegate_->OnResolveProxyCompleted(completed_req.reply_msg,
+ result,
+ proxy_info_.GetAnnotatedProxyList());
+
+ // Clear the current (completed) request.
+ pending_requests_.pop_front();
+ proxy_service_ = NULL;
+
+ // Start the next request.
+ if (!pending_requests_.empty())
+ StartPendingRequest();
+}
+
+void ResolveProxyMsgHelper::StartPendingRequest() {
+ PendingRequest& req = pending_requests_.front();
+
+ // Verify the request wasn't started yet.
+ DCHECK(NULL == req.pac_req);
+ DCHECK(NULL == proxy_service_);
+
+ // Start the request.
+ proxy_service_ = GetProxyService();
+ int result = proxy_service_->ResolveProxy(
+ req.url, &proxy_info_, &callback_, &req.pac_req);
+
+ // Completed synchronously.
+ if (result != net::ERR_IO_PENDING)
+ OnResolveProxyCompleted(result);
+}
+
+net::ProxyService* ResolveProxyMsgHelper::GetProxyService() const {
+ // Unit-tests specify their own proxy service to use.
+ if (proxy_service_override_)
+ return proxy_service_override_;
+
+ // Otherwise use the browser's global proxy service.
+ return Profile::GetDefaultRequestContext()->proxy_service();
+}
+
+ResolveProxyMsgHelper::~ResolveProxyMsgHelper() {
+ // Clear all pending requests.
+ if (!pending_requests_.empty()) {
+ PendingRequest req = pending_requests_.front();
+ proxy_service_->CancelPacRequest(req.pac_req);
+ }
+
+ for (PendingRequestList::iterator it = pending_requests_.begin();
+ it != pending_requests_.end();
+ ++it) {
+ delete it->reply_msg;
+ }
+
+ proxy_service_ = NULL;
+ pending_requests_.clear();
+}
diff --git a/chrome/browser/net/resolve_proxy_msg_helper.h b/chrome/browser/net/resolve_proxy_msg_helper.h
new file mode 100644
index 0000000..bf4c2f8
--- /dev/null
+++ b/chrome/browser/net/resolve_proxy_msg_helper.h
@@ -0,0 +1,104 @@
+// 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.
+
+#ifndef CHROME_BROWSER_NET_RESOLVE_PROXY_MSG_HELPER_
+#define CHROME_BROWSER_NET_RESOLVE_PROXY_MSG_HELPER_
+
+#include <deque>
+#include <string>
+
+#include "chrome/common/ipc_message.h"
+#include "net/base/completion_callback.h"
+#include "googleurl/src/gurl.h"
+#include "net/proxy/proxy_service.h"
+
+// This class holds the common logic used to respond to the messages:
+// {PluginProcessHostMsg_ResolveProxy, ViewHostMsg_ResolveProxy}.
+//
+// This involves kicking off a ProxyResolve request on the IO thread using
+// the specified proxy service.
+//
+// When the request completes, it calls the delegate's OnProxyResolveCompleted()
+// method, passing it the result (error code + proxy list), as well as the
+// IPC::Message pointer that had been stored.
+//
+// When an instance of ResolveProxyMsgHelper is destroyed, it cancels any
+// outstanding proxy resolve requests with the proxy service. It also deletes
+// the stored IPC::Message pointers for pending requests.
+//
+// This object is expected to live on the IO thread.
+class ResolveProxyMsgHelper {
+ public:
+ class Delegate {
+ public:
+ // Callback for when the proxy resolve request has completed.
+ // |reply_msg| -- The same pointer that the request was started with.
+ // |result| -- The network error code from ProxyService.
+ // |proxy_list| -- The PAC string result from ProxyService.
+ virtual void OnResolveProxyCompleted(IPC::Message* reply_msg,
+ int result,
+ const std::string& proxy_list) = 0;
+ virtual ~Delegate() {}
+ };
+
+ // Construct a ResolveProxyMsgHelper instance that notifies request
+ // completion to |delegate|. Note that |delegate| must be live throughout
+ // our lifespan. If |proxy_service| is NULL, then the current profile's
+ // proxy service will be used.
+ explicit ResolveProxyMsgHelper(Delegate* delegate,
+ net::ProxyService* proxy_service);
+
+ // Resolve proxies for |url|. Completion is notified through the delegate.
+ // If multiple requests are started at the same time, they will run in
+ // FIFO order, with only 1 being outstanding at a time.
+ void Start(const GURL& url, IPC::Message* reply_msg);
+
+ // Destruction cancels the current outstanding request, and clears the
+ // pending queue.
+ ~ResolveProxyMsgHelper();
+
+ private:
+ // Callback for the ProxyService (bound to |callback_|).
+ void OnResolveProxyCompleted(int result);
+
+ // Start the first pending request.
+ void StartPendingRequest();
+
+ // Get the proxy service instance to use.
+ net::ProxyService* GetProxyService() const;
+
+ // A PendingRequest is a resolve request that is in progress, or queued.
+ struct PendingRequest {
+ public:
+ PendingRequest(const GURL& url, IPC::Message* reply_msg) :
+ url(url), reply_msg(reply_msg), pac_req(NULL) { }
+
+ // The URL of the request.
+ GURL url;
+
+ // Data to pass back to the delegate on completion (we own it until then).
+ IPC::Message* reply_msg;
+
+ // Handle for cancelling the current request if it has started (else NULL).
+ net::ProxyService::PacRequest* pac_req;
+ };
+
+ // Members for the current outstanding proxy request.
+ net::ProxyService* proxy_service_;
+ net::CompletionCallbackImpl<ResolveProxyMsgHelper> callback_;
+ net::ProxyInfo proxy_info_;
+
+ // FIFO queue of pending requests. The first entry is always the current one.
+ typedef std::deque<PendingRequest> PendingRequestList;
+ PendingRequestList pending_requests_;
+
+ Delegate* delegate_;
+
+ // Specified by unit-tests, to use this proxy service in place of the
+ // global one.
+ net::ProxyService* proxy_service_override_;
+};
+
+#endif // CHROME_BROWSER_NET_RESOLVE_PROXY_MSG_HELPER_
+
diff --git a/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc b/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc
new file mode 100644
index 0000000..dd70713
--- /dev/null
+++ b/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc
@@ -0,0 +1,349 @@
+// 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.
+
+#include "chrome/browser/net/resolve_proxy_msg_helper.h"
+
+#include "base/waitable_event.h"
+#include "net/base/net_errors.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// This ProxyConfigService always returns "http://pac" as the PAC url to use.
+class MockProxyConfigService: public net::ProxyConfigService {
+ public:
+ virtual int GetProxyConfig(net::ProxyConfig* results) {
+ results->pac_url = GURL("http://pac");
+ return net::OK;
+ }
+};
+
+// This PAC resolver always returns the hostname of the query URL as the
+// proxy to use. The Block() method will make GetProxyForURL() hang until
+// Unblock() is called.
+class MockProxyResolver : public net::ProxyResolver {
+ public:
+ explicit MockProxyResolver() : event_(false, false), is_blocked_(false) {
+ }
+
+ virtual int GetProxyForURL(const GURL& query_url,
+ const GURL& /*pac_url*/,
+ net::ProxyInfo* results) {
+ if (is_blocked_)
+ event_.Wait();
+ results->UseNamedProxy(query_url.host());
+ return net::OK;
+ }
+
+ void Block() {
+ is_blocked_ = true;
+ event_.Reset();
+ }
+
+ void Unblock() {
+ is_blocked_ = false;
+ event_.Signal();
+ }
+
+ private:
+ base::WaitableEvent event_;
+ bool is_blocked_;
+};
+
+// This struct holds the values that were passed to
+// Delegate::OnResolveProxyCompleted(). The caller should use WaitUntilDone()
+// to block until the result has been populated.
+struct ResultFuture {
+ public:
+ ResultFuture()
+ : reply_msg(NULL),
+ error_code(0),
+ started_(false, false),
+ completed_(false, false) {
+ }
+
+ // Wait until the request has completed. In other words we have invoked:
+ // ResolveProxyMsgHelper::Delegate::OnResolveProxyCompleted.
+ void WaitUntilDone() {
+ completed_.Wait();
+ }
+
+ // Wait until the request has been sent to ResolveProxyMsgHelper.
+ void WaitUntilStarted() {
+ started_.Wait();
+ }
+
+ bool TimedWaitUntilDone(const base::TimeDelta& max_time) {
+ return completed_.TimedWait(max_time);
+ }
+
+ // These fields are only valid after returning from WaitUntilDone().
+ IPC::Message* reply_msg;
+ int error_code;
+ std::string proxy_list;
+
+ private:
+ friend class AsyncRequestRunner;
+ base::WaitableEvent started_;
+ base::WaitableEvent completed_;
+};
+
+// This class lives on the io thread. It starts async requests using the
+// class under test (ResolveProxyMsgHelper), and signals the result future on
+// completion.
+class AsyncRequestRunner : public ResolveProxyMsgHelper::Delegate {
+ public:
+ AsyncRequestRunner(net::ProxyService* proxy_service) {
+ resolve_proxy_msg_helper_.reset(
+ new ResolveProxyMsgHelper(this, proxy_service));
+ }
+
+ void Start(ResultFuture* future, const GURL& url, IPC::Message* reply_msg) {
+ futures_.push_back(future);
+ resolve_proxy_msg_helper_->Start(url, reply_msg);
+
+ // Notify of request start.
+ future->started_.Signal();
+ }
+
+ virtual void OnResolveProxyCompleted(IPC::Message* reply_msg,
+ int error_code,
+ const std::string& proxy_list) {
+ // Update the result future for this request (top of queue), and signal it.
+ ResultFuture* future = futures_.front();
+ futures_.pop_front();
+
+ future->reply_msg = reply_msg;
+ future->error_code = error_code;
+ future->proxy_list = proxy_list;
+
+ // Notify of request completion.
+ future->completed_.Signal();
+ }
+
+ private:
+ std::deque<ResultFuture*> futures_;
+ scoped_ptr<ResolveProxyMsgHelper> resolve_proxy_msg_helper_;
+};
+
+// Helper class to start async requests on an io thread, and return a
+// result future. The caller then uses ResultFuture::WaitUntilDone() to
+// get at the results. It "bridges" the originating thread with the helper
+// io thread.
+class RunnerBridge {
+ public:
+ RunnerBridge() : io_thread_("io_thread"), done_(true, false) {
+ // Start an io thread where we will run the async requests.
+ base::Thread::Options options;
+ options.message_loop_type = MessageLoop::TYPE_IO;
+ io_thread_.StartWithOptions(options);
+
+ // Construct the state that lives on io thread.
+ io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &RunnerBridge::DoConstruct));
+ done_.Wait();
+ }
+
+ // Start an async request on the io thread.
+ ResultFuture* Start(const GURL& url, IPC::Message* reply_msg) {
+ ResultFuture* future = new ResultFuture();
+
+ io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ async_runner_, &AsyncRequestRunner::Start, future, url, reply_msg));
+
+ return future;
+ }
+
+ void DestroyAsyncRunner() {
+ io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &RunnerBridge::DoDestroyAsyncRunner));
+ done_.Wait();
+ }
+
+ ~RunnerBridge() {
+ io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &RunnerBridge::DoDestroy));
+ done_.Wait();
+ }
+
+ MockProxyResolver* proxy_resolver() {
+ return proxy_resolver_;
+ }
+
+ // Called from io thread.
+ void DoConstruct() {
+ proxy_resolver_ = new MockProxyResolver();
+ proxy_service_ = new net::ProxyService(new MockProxyConfigService(),
+ proxy_resolver_);
+ async_runner_ = new AsyncRequestRunner(proxy_service_);
+ done_.Signal();
+ }
+
+ // Called from io thread.
+ void DoDestroy() {
+ delete async_runner_;
+ delete proxy_service_;
+ done_.Signal();
+ }
+
+ // Called from io thread.
+ void DoDestroyAsyncRunner() {
+ delete async_runner_;
+ async_runner_ = NULL;
+ done_.Signal();
+ }
+
+ private:
+ base::Thread io_thread_;
+ base::WaitableEvent done_;
+
+ net::ProxyService* proxy_service_;
+ MockProxyResolver* proxy_resolver_; // Owned by proxy_service_.
+
+ AsyncRequestRunner* async_runner_;
+};
+
+// Avoid the need to have an AddRef / Release
+template<>
+void RunnableMethodTraits<RunnerBridge>::RetainCallee(RunnerBridge*) {}
+template<>
+void RunnableMethodTraits<RunnerBridge>::ReleaseCallee(RunnerBridge*) {}
+
+template<>
+void RunnableMethodTraits<AsyncRequestRunner>::RetainCallee(AsyncRequestRunner*) {}
+template<>
+void RunnableMethodTraits<AsyncRequestRunner>::ReleaseCallee(AsyncRequestRunner*) {}
+
+
+// Issue three sequential requests -- each should succeed.
+TEST(ResolveProxyMsgHelperTest, Sequential) {
+ RunnerBridge runner;
+
+ GURL url1("http://www.google1.com/");
+ GURL url2("http://www.google2.com/");
+ GURL url3("http://www.google3.com/");
+
+ scoped_ptr<IPC::Message> msg1(new IPC::Message());
+ scoped_ptr<IPC::Message> msg2(new IPC::Message());
+ scoped_ptr<IPC::Message> msg3(new IPC::Message());
+
+ // Execute each request sequentially (so there are never 2 requests
+ // outstanding at the same time).
+
+ scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1.get()));
+ result1->WaitUntilDone();
+
+ scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2.get()));
+ result2->WaitUntilDone();
+
+ scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3.get()));
+ result3->WaitUntilDone();
+
+ // Check that each request gave the expected result.
+
+ EXPECT_EQ(msg1.get(), result1->reply_msg);
+ EXPECT_EQ(net::OK, result1->error_code);
+ EXPECT_EQ("PROXY www.google1.com", result1->proxy_list);
+
+ EXPECT_EQ(msg2.get(), result2->reply_msg);
+ EXPECT_EQ(net::OK, result2->error_code);
+ EXPECT_EQ("PROXY www.google2.com", result2->proxy_list);
+
+ EXPECT_EQ(msg3.get(), result3->reply_msg);
+ EXPECT_EQ(net::OK, result3->error_code);
+ EXPECT_EQ("PROXY www.google3.com", result3->proxy_list);
+}
+
+// Issue a request while one is already in progress -- should be queued.
+TEST(ResolveProxyMsgHelperTest, QueueRequests) {
+ RunnerBridge runner;
+
+ GURL url1("http://www.google1.com/");
+ GURL url2("http://www.google2.com/");
+ GURL url3("http://www.google3.com/");
+
+ scoped_ptr<IPC::Message> msg1(new IPC::Message());
+ scoped_ptr<IPC::Message> msg2(new IPC::Message());
+ scoped_ptr<IPC::Message> msg3(new IPC::Message());
+
+ // Make the proxy resolver hang on the next request.
+ runner.proxy_resolver()->Block();
+
+ // Start three requests. Since the proxy resolver is hung, the second two
+ // will be pending.
+
+ scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1.get()));
+ scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2.get()));
+ scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3.get()));
+
+ // Wait for the final request to have been scheduled. Otherwise we may rush
+ // to calling Unblock() without actually having blocked anything.
+ result3->WaitUntilStarted();
+
+ // Unblock the proxy service so requests 1-3 can complete.
+ runner.proxy_resolver()->Unblock();
+
+ // Wait for all the requests to finish (they run in FIFO order).
+ result3->WaitUntilDone();
+
+ // Check that each call invoked the callback with the right parameters.
+
+ EXPECT_EQ(msg1.get(), result1->reply_msg);
+ EXPECT_EQ(net::OK, result1->error_code);
+ EXPECT_EQ("PROXY www.google1.com", result1->proxy_list);
+
+ EXPECT_EQ(msg2.get(), result2->reply_msg);
+ EXPECT_EQ(net::OK, result2->error_code);
+ EXPECT_EQ("PROXY www.google2.com", result2->proxy_list);
+
+ EXPECT_EQ(msg3.get(), result3->reply_msg);
+ EXPECT_EQ(net::OK, result3->error_code);
+ EXPECT_EQ("PROXY www.google3.com", result3->proxy_list);
+}
+
+// Delete the helper while a request is in progress, and others are pending.
+TEST(ResolveProxyMsgHelperTest, CancelPendingRequests) {
+ RunnerBridge runner;
+
+ GURL url1("http://www.google1.com/");
+ GURL url2("http://www.google2.com/");
+ GURL url3("http://www.google3.com/");
+
+ // NOTE: these are not scoped ptr, since they will be deleted by the
+ // request's cancellation.
+ IPC::Message* msg1 = new IPC::Message();
+ IPC::Message* msg2 = new IPC::Message();
+ IPC::Message* msg3 = new IPC::Message();
+
+ // Make the next request block.
+ runner.proxy_resolver()->Block();
+
+ // Start three requests; since the first one blocked, the other two should
+ // be pending.
+
+ scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1));
+ scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2));
+ scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3));
+
+ result3->WaitUntilStarted();
+
+ // Delete the underlying ResolveProxyMsgHelper -- this should cancel all
+ // the requests which are outstanding.
+ runner.DestroyAsyncRunner();
+
+ // Unblocking the proxy resolver means the three requests can complete --
+ // however they should not try to notify the delegate since we have already
+ // deleted the helper.
+ runner.proxy_resolver()->Unblock();
+
+ // Check that none of the requests were sent to the delegate.
+ EXPECT_FALSE(
+ result1->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2)));
+ EXPECT_FALSE(
+ result2->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2)));
+ EXPECT_FALSE(
+ result3->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2)));
+
+ // It should also be the case that msg1, msg2, msg3 were deleted by the
+ // cancellation. (Else will show up as a leak in Purify).
+}
+
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc
index 0229d95..f071a7a 100644
--- a/chrome/browser/plugin_process_host.cc
+++ b/chrome/browser/plugin_process_host.cc
@@ -37,7 +37,6 @@
#include "chrome/common/win_util.h"
#include "net/base/cookie_monster.h"
#include "net/base/io_buffer.h"
-#include "net/proxy/proxy_service.h"
#include "net/url_request/url_request.h"
#include "sandbox/src/sandbox.h"
#include "webkit/glue/plugins/plugin_constants_win.h"
@@ -300,57 +299,6 @@ void PluginDownloadUrlHelper::DownloadCompletedHelper(bool success) {
delete this;
}
-// The following class is a helper to handle ProxyResolve IPC requests.
-// It is responsible for initiating an asynchronous proxy resolve request,
-// and will send out the IPC response on completion then delete itself.
-// Should the PluginProcessHost be destroyed while a proxy resolve request
-// is in progress, the request will not be canceled. However once it completes
-// it will see that it has been revoked and delete itself.
-// TODO(eroman): This could leak if ProxyService is deleted while request is
-// outstanding.
-class PluginResolveProxyHelper : RevocableStore::Revocable {
- public:
- // Create a helper that writes its response through |plugin_host|.
- PluginResolveProxyHelper(PluginProcessHost* plugin_host)
- : RevocableStore::Revocable(&plugin_host->revocable_store_),
- plugin_host_(plugin_host),
- reply_msg_(NULL),
- ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
- this, &PluginResolveProxyHelper::OnProxyResolveCompleted)) {
- }
-
- // Completion callback for ProxyService.
- void OnProxyResolveCompleted(int result) {
- if (!revoked()) {
- PluginProcessHostMsg_ResolveProxy::WriteReplyParams(
- reply_msg_, result, proxy_info_.GetAnnotatedProxyList());
- plugin_host_->Send(reply_msg_);
- }
-
- delete this;
- };
-
- // Resolve the proxy for |url| using |proxy_service|. Write the response
- // to |reply_msg|.
- void Start(net::ProxyService* proxy_service,
- const GURL& url,
- IPC::Message* reply_msg) {
- reply_msg_ = reply_msg;
- int rv = proxy_service->ResolveProxy(
- url, &proxy_info_, &callback_, NULL);
- if (rv != net::ERR_IO_PENDING)
- OnProxyResolveCompleted(rv);
- }
-
- private:
- // |plugin_host_| is only valid if !this->revoked().
- PluginProcessHost* plugin_host_;
- IPC::Message* reply_msg_;
- net::CompletionCallbackImpl<PluginResolveProxyHelper> callback_;
- net::ProxyInfo proxy_info_;
-};
-
-
// Sends the reply to the create window message on the IO thread.
class SendReplyTask : public Task {
public:
@@ -435,6 +383,7 @@ PluginProcessHost::PluginProcessHost(PluginService* plugin_service)
: process_(NULL),
opening_channel_(false),
resource_dispatcher_host_(plugin_service->resource_dispatcher_host()),
+ ALLOW_THIS_IN_INITIALIZER_LIST(resolve_proxy_msg_helper_(this, NULL)),
plugin_service_(plugin_service) {
DCHECK(resource_dispatcher_host_);
}
@@ -814,13 +763,15 @@ void PluginProcessHost::OnGetCookies(uint32 request_context,
void PluginProcessHost::OnResolveProxy(const GURL& url,
IPC::Message* reply_msg) {
- // Use the default profile's proxy service.
- net::ProxyService* proxy_service =
- Profile::GetDefaultRequestContext()->proxy_service();
+ resolve_proxy_msg_helper_.Start(url, reply_msg);
+}
- // Kick off a proxy resolve request; writes the response to |reply_msg|
- // on completion. The helper's storage will be deleted on completion.
- (new PluginResolveProxyHelper(this))->Start(proxy_service, url, reply_msg);
+void PluginProcessHost::OnResolveProxyCompleted(IPC::Message* reply_msg,
+ int result,
+ const std::string& proxy_list) {
+ PluginProcessHostMsg_ResolveProxy::WriteReplyParams(
+ reply_msg, result, proxy_list);
+ Send(reply_msg);
}
void PluginProcessHost::ReplyToRenderer(
diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h
index a4e390c..21adb90 100644
--- a/chrome/browser/plugin_process_host.h
+++ b/chrome/browser/plugin_process_host.h
@@ -15,6 +15,7 @@
#include "base/task.h"
#include "chrome/browser/resource_message_filter.h"
#include "chrome/common/ipc_channel_proxy.h"
+#include "chrome/browser/net/resolve_proxy_msg_helper.h"
#include "chrome/browser/resource_message_filter.h"
class PluginService;
@@ -34,7 +35,8 @@ class GURL;
// the renderer and plugin processes.
class PluginProcessHost : public IPC::Channel::Listener,
public IPC::Message::Sender,
- public base::ObjectWatcher::Delegate {
+ public base::ObjectWatcher::Delegate,
+ public ResolveProxyMsgHelper::Delegate {
public:
PluginProcessHost(PluginService* plugin_service);
~PluginProcessHost();
@@ -58,6 +60,11 @@ class PluginProcessHost : public IPC::Channel::Listener,
virtual void OnChannelConnected(int32 peer_pid);
virtual void OnChannelError();
+ // ResolveProxyMsgHelper::Delegate implementation:
+ virtual void OnResolveProxyCompleted(IPC::Message* reply_msg,
+ int result,
+ const std::string& proxy_list);
+
// Getter to the process, may return NULL if there is no connection.
HANDLE process() { return process_.handle(); }
@@ -157,10 +164,9 @@ class PluginProcessHost : public IPC::Channel::Listener,
ResourceDispatcherHost* resource_dispatcher_host_;
- // This RevocableStore prevents ResolveProxy completion callbacks from
- // accessing a deleted PluginProcessHost (since we do not cancel the
- // in-progress resolve requests during destruction).
- RevocableStore revocable_store_;
+ // Helper class for handling PluginProcessHost_ResolveProxy messages (manages
+ // the requests to the proxy service).
+ ResolveProxyMsgHelper resolve_proxy_msg_helper_;
DISALLOW_EVIL_CONSTRUCTORS(PluginProcessHost);
};
diff --git a/chrome/browser/resource_message_filter.cc b/chrome/browser/resource_message_filter.cc
index dd0dd5a..d1d9370 100644
--- a/chrome/browser/resource_message_filter.cc
+++ b/chrome/browser/resource_message_filter.cc
@@ -100,7 +100,8 @@ ResourceMessageFilter::ResourceMessageFilter(
request_context_(profile->GetRequestContext()),
profile_(profile),
render_widget_helper_(render_widget_helper),
- spellchecker_(spellchecker) {
+ spellchecker_(spellchecker),
+ ALLOW_THIS_IN_INITIALIZER_LIST(resolve_proxy_msg_helper_(this, NULL)) {
DCHECK(request_context_.get());
DCHECK(request_context_->cookie_store());
@@ -207,6 +208,7 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
OnGetCPBrowsingContext)
IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection)
IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceTypeStats, OnResourceTypeStats)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDefaultPrintSettings,
OnGetDefaultPrintSettings)
#if defined(OS_WIN)
@@ -572,6 +574,19 @@ void ResourceMessageFilter::OnResourceTypeStats(
static_cast<int>(stats.fonts.size / 1024));
}
+void ResourceMessageFilter::OnResolveProxy(const GURL& url,
+ IPC::Message* reply_msg) {
+ resolve_proxy_msg_helper_.Start(url, reply_msg);
+}
+
+void ResourceMessageFilter::OnResolveProxyCompleted(
+ IPC::Message* reply_msg,
+ int result,
+ const std::string& proxy_list) {
+ ViewHostMsg_ResolveProxy::WriteReplyParams(reply_msg, result, proxy_list);
+ Send(reply_msg);
+}
+
void ResourceMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
scoped_refptr<printing::PrinterQuery> printer_query;
print_job_manager_->PopPrinterQuery(0, &printer_query);
diff --git a/chrome/browser/resource_message_filter.h b/chrome/browser/resource_message_filter.h
index 026c232..48b4fb8 100644
--- a/chrome/browser/resource_message_filter.h
+++ b/chrome/browser/resource_message_filter.h
@@ -11,6 +11,7 @@
#include "base/gfx/native_widget_types.h"
#include "base/ref_counted.h"
#include "build/build_config.h"
+#include "chrome/browser/net/resolve_proxy_msg_helper.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/common/ipc_channel_proxy.h"
#include "chrome/common/notification_service.h"
@@ -43,7 +44,8 @@ struct ScreenInfo;
class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
public ResourceDispatcherHost::Receiver,
- public NotificationObserver {
+ public NotificationObserver,
+ public ResolveProxyMsgHelper::Delegate {
public:
// Create the filter.
// Note: because the lifecycle of the ResourceMessageFilter is not
@@ -157,6 +159,13 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
base::SharedMemoryHandle* browser_handle);
void OnResourceTypeStats(const CacheManager::ResourceTypeStats& stats);
+ void OnResolveProxy(const GURL& url, IPC::Message* reply_msg);
+
+ // ResolveProxyMsgHelper::Delegate implementation:
+ virtual void OnResolveProxyCompleted(IPC::Message* reply_msg,
+ int result,
+ const std::string& proxy_list);
+
// A javascript code requested to print the current page. This is done in two
// steps and this is the first step. Get the print setting right here
// synchronously. It will hang the I/O completely.
@@ -204,6 +213,10 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
// Our spellchecker object.
scoped_refptr<SpellChecker> spellchecker_;
+ // Helper class for handling PluginProcessHost_ResolveProxy messages (manages
+ // the requests to the proxy service).
+ ResolveProxyMsgHelper resolve_proxy_msg_helper_;
+
// Process handle of the renderer process.
base::ProcessHandle render_handle_;