summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-18 16:08:51 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-18 16:08:51 +0000
commit97e6c4c6081444371405bb39c99b016a65a309b8 (patch)
tree01d5b996990212964f7a91ca5315ff41134bd317 /content
parenta15fcb778a2c7d4c188ddbf44edcca8b6a526e16 (diff)
downloadchromium_src-97e6c4c6081444371405bb39c99b016a65a309b8.zip
chromium_src-97e6c4c6081444371405bb39c99b016a65a309b8.tar.gz
chromium_src-97e6c4c6081444371405bb39c99b016a65a309b8.tar.bz2
Get rid of chrome dependencies from PluginProcessHost by moving dispatching of chrome specific messages to a chrome IPC filter.
Review URL: http://codereview.chromium.org/7036025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85767 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/DEPS2
-rw-r--r--content/browser/content_browser_client.cc3
-rw-r--r--content/browser/content_browser_client.h6
-rw-r--r--content/browser/plugin_process_host.cc44
-rw-r--r--content/browser/plugin_process_host.h5
-rw-r--r--content/browser/renderer_host/browser_render_process_host.cc2
-rw-r--r--content/browser/resolve_proxy_msg_helper.cc120
-rw-r--r--content/browser/resolve_proxy_msg_helper.h85
-rw-r--r--content/browser/resolve_proxy_msg_helper_unittest.cc236
-rw-r--r--content/common/plugin_messages.h8
-rw-r--r--content/content_browser.gypi2
11 files changed, 461 insertions, 52 deletions
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 41ae24c..437eb28 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -46,7 +46,6 @@ include_rules = [
"+chrome/browser/net/load_timing_observer.h",
"+chrome/browser/net/predictor_api.h",
- "+chrome/browser/net/resolve_proxy_msg_helper.h",
"+chrome/browser/net/url_request_tracking.h",
"+chrome/browser/notifications/desktop_notification_service.h",
@@ -55,7 +54,6 @@ include_rules = [
"+chrome/browser/platform_util.h",
- "+chrome/browser/plugin_download_helper.h",
"+chrome/browser/plugin_observer.h",
"+chrome/common/default_plugin.h",
diff --git a/content/browser/content_browser_client.cc b/content/browser/content_browser_client.cc
index 901097e..47d55e4 100644
--- a/content/browser/content_browser_client.cc
+++ b/content/browser/content_browser_client.cc
@@ -18,6 +18,9 @@ void ContentBrowserClient::BrowserRenderProcessHostCreated(
BrowserRenderProcessHost* host) {
}
+void ContentBrowserClient::PluginProcessHostCreated(PluginProcessHost* host) {
+}
+
void ContentBrowserClient::WorkerProcessHostCreated(WorkerProcessHost* host) {
}
diff --git a/content/browser/content_browser_client.h b/content/browser/content_browser_client.h
index 6395d9a..70932b6 100644
--- a/content/browser/content_browser_client.h
+++ b/content/browser/content_browser_client.h
@@ -13,6 +13,7 @@
class BrowserRenderProcessHost;
class CommandLine;
class GURL;
+class PluginProcessHost;
class Profile;
class RenderViewHost;
class TabContents;
@@ -39,6 +40,11 @@ class ContentBrowserClient {
// embedder's IPC filters have priority.
virtual void BrowserRenderProcessHostCreated(BrowserRenderProcessHost* host);
+ // Notifies that a PluginProcessHost has been created. This is called
+ // before the content layer adds its own message filters, so that the
+ // embedder's IPC filters have priority.
+ virtual void PluginProcessHostCreated(PluginProcessHost* host);
+
// Notifies that a WorkerProcessHost has been created. This is called
// before the content layer adds its own message filters, so that the
// embedder's IPC filters have priority.
diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc
index a543200..2e72f31 100644
--- a/content/browser/plugin_process_host.cc
+++ b/content/browser/plugin_process_host.cc
@@ -19,26 +19,18 @@
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/net/resolve_proxy_msg_helper.h"
-#include "chrome/browser/net/url_request_tracking.h"
-#include "chrome/browser/plugin_download_helper.h"
-#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
-#include "chrome/common/render_messages.h"
#include "content/browser/browser_thread.h"
+#include "content/browser/content_browser_client.h"
+#include "content/browser/resolve_proxy_msg_helper.h"
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/resource_dispatcher_host.h"
#include "content/browser/renderer_host/resource_message_filter.h"
#include "content/common/plugin_messages.h"
#include "content/common/resource_messages.h"
#include "ipc/ipc_switches.h"
-#include "net/base/io_buffer.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/gl/gl_switches.h"
@@ -53,9 +45,6 @@
#include "ui/gfx/rect.h"
#endif
-static const char kDefaultPluginFinderURL[] =
- "https://dl-ssl.google.com/edgedl/chrome/plugins/plugins2.xml";
-
#if defined(OS_WIN)
void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) {
// The window is destroyed at this point, we just care about its parent, which
@@ -69,15 +58,6 @@ void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) {
PostMessage(parent, WM_CLOSE, 0, 0);
}
-void PluginProcessHost::OnDownloadUrl(const std::string& url,
- int source_pid,
- gfx::NativeWindow caller_window) {
- PluginDownloadUrlHelper* download_url_helper =
- new PluginDownloadUrlHelper(url, source_pid, caller_window, NULL);
- download_url_helper->InitiateDownload(
- Profile::GetDefaultRequestContext()->GetURLRequestContext());
-}
-
void PluginProcessHost::AddWindow(HWND window) {
plugin_parent_windows_set_.insert(window);
}
@@ -241,6 +221,7 @@ bool PluginProcessHost::Init(const webkit::npapi::WebPluginInfo& info,
#endif
cmd_line);
+ content::GetContentClient()->browser()->PluginProcessHostCreated(this);
AddFilter(new ResolveProxyMsgHelper(NULL));
return true;
@@ -256,12 +237,9 @@ bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PluginProcessHost, msg)
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ChannelCreated, OnChannelCreated)
- IPC_MESSAGE_HANDLER(PluginProcessHostMsg_GetPluginFinderUrl,
- OnGetPluginFinderUrl)
#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed,
OnPluginWindowDestroyed)
- IPC_MESSAGE_HANDLER(PluginProcessHostMsg_DownloadUrl, OnDownloadUrl)
#endif
#if defined(TOOLKIT_USES_GTK)
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_MapNativeViewId,
@@ -350,19 +328,3 @@ void PluginProcessHost::OnChannelCreated(
client->OnChannelOpened(channel_handle);
sent_requests_.pop();
}
-
-void PluginProcessHost::OnGetPluginFinderUrl(std::string* plugin_finder_url) {
- // TODO(bauerb): Move this method to MessageFilter.
- if (!plugin_finder_url) {
- NOTREACHED();
- return;
- }
-
- if (!g_browser_process->plugin_finder_disabled()) {
- // TODO(iyengar): Add the plumbing to retrieve the default
- // plugin finder URL.
- *plugin_finder_url = kDefaultPluginFinderURL;
- } else {
- plugin_finder_url->clear();
- }
-}
diff --git a/content/browser/plugin_process_host.h b/content/browser/plugin_process_host.h
index 68cd738..f33027d 100644
--- a/content/browser/plugin_process_host.h
+++ b/content/browser/plugin_process_host.h
@@ -16,8 +16,8 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "content/browser/browser_child_process_host.h"
-#include "ui/gfx/native_widget_types.h"
#include "webkit/plugins/npapi/webplugininfo.h"
+#include "ui/gfx/native_widget_types.h"
namespace gfx {
class Rect;
@@ -99,12 +99,9 @@ class PluginProcessHost : public BrowserChildProcessHost {
// Message handlers.
void OnChannelCreated(const IPC::ChannelHandle& channel_handle);
- void OnGetPluginFinderUrl(std::string* plugin_finder_url);
#if defined(OS_WIN)
void OnPluginWindowDestroyed(HWND window, HWND parent);
- void OnDownloadUrl(const std::string& url, int source_child_unique_id,
- gfx::NativeWindow caller_window);
#endif
#if defined(USE_X11)
diff --git a/content/browser/renderer_host/browser_render_process_host.cc b/content/browser/renderer_host/browser_render_process_host.cc
index ef8d040..282ef9a 100644
--- a/content/browser/renderer_host/browser_render_process_host.cc
+++ b/content/browser/renderer_host/browser_render_process_host.cc
@@ -28,7 +28,6 @@
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/history/history.h"
-#include "chrome/browser/net/resolve_proxy_msg_helper.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_host/web_cache_manager.h"
@@ -48,6 +47,7 @@
#include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h"
#include "content/browser/file_system/file_system_dispatcher_host.h"
#include "content/browser/mime_registry_message_filter.h"
+#include "content/browser/resolve_proxy_msg_helper.h"
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/audio_input_renderer_host.h"
#include "content/browser/renderer_host/audio_renderer_host.h"
diff --git a/content/browser/resolve_proxy_msg_helper.cc b/content/browser/resolve_proxy_msg_helper.cc
new file mode 100644
index 0000000..edacad9
--- /dev/null
+++ b/content/browser/resolve_proxy_msg_helper.cc
@@ -0,0 +1,120 @@
+// Copyright (c) 2011 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 "content/browser/resolve_proxy_msg_helper.h"
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/common/child_process_messages.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+
+ResolveProxyMsgHelper::ResolveProxyMsgHelper(net::ProxyService* proxy_service)
+ : proxy_service_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
+ this, &ResolveProxyMsgHelper::OnResolveProxyCompleted)),
+ proxy_service_override_(proxy_service) {
+}
+
+bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(ResolveProxyMsgHelper, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ChildProcessHostMsg_ResolveProxy,
+ OnResolveProxy)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void ResolveProxyMsgHelper::OnResolveProxy(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());
+
+ const PendingRequest& completed_req = pending_requests_.front();
+ ChildProcessHostMsg_ResolveProxy::WriteReplyParams(
+ completed_req.reply_msg, result, proxy_info_.ToPacString());
+ Send(completed_req.reply_msg);
+
+ // 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.
+ bool ok = GetProxyService(&proxy_service_);
+
+ if (!ok) {
+ // During shutdown, there may be no ProxyService to use, because the
+ // default ChromeURLRequestContext has already been NULL-ed out.
+ LOG(WARNING) << "Failed getting default URLRequestContext";
+ OnResolveProxyCompleted(net::ERR_FAILED);
+ return;
+ }
+
+ int result = proxy_service_->ResolveProxy(
+ req.url, &proxy_info_, &callback_, &req.pac_req, net::BoundNetLog());
+
+ // Completed synchronously.
+ if (result != net::ERR_IO_PENDING)
+ OnResolveProxyCompleted(result);
+}
+
+bool ResolveProxyMsgHelper::GetProxyService(net::ProxyService** out) const {
+ // Unit-tests specify their own proxy service to use.
+ if (proxy_service_override_) {
+ *out = proxy_service_override_;
+ return true;
+ }
+
+ // If there is no default request context (say during shut down).
+ net::URLRequestContextGetter* context_getter =
+ Profile::GetDefaultRequestContext();
+ if (!context_getter)
+ return false;
+
+ // Otherwise use the browser's global proxy service.
+ *out = context_getter->GetURLRequestContext()->proxy_service();
+ return true;
+}
+
+ResolveProxyMsgHelper::~ResolveProxyMsgHelper() {
+ // Clear all pending requests if the ProxyService is still alive (if we have a
+ // default request context or override).
+ if (!pending_requests_.empty() &&
+ (Profile::GetDefaultRequestContext() || proxy_service_override_)) {
+ 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/content/browser/resolve_proxy_msg_helper.h b/content/browser/resolve_proxy_msg_helper.h
new file mode 100644
index 0000000..5032687
--- /dev/null
+++ b/content/browser/resolve_proxy_msg_helper.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_RESOLVE_PROXY_MSG_HELPER_H_
+#define CONTENT_BROWSER_RESOLVE_PROXY_MSG_HELPER_H_
+#pragma once
+
+#include <deque>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "content/browser/browser_message_filter.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/completion_callback.h"
+#include "net/proxy/proxy_service.h"
+
+// Responds to ChildProcessHostMsg_ResolveProxy, kicking off a ProxyResolve
+// request on the IO thread using the specified proxy service. 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.
+//
+// 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 BrowserMessageFilter {
+ public:
+ // If |proxy_service| is NULL, then the main profile's proxy service will
+ // be used.
+ explicit ResolveProxyMsgHelper(net::ProxyService* proxy_service);
+
+ // Destruction cancels the current outstanding request, and clears the
+ // pending queue.
+ ~ResolveProxyMsgHelper();
+
+ // BrowserMessageFilter implementation
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok);
+
+ void OnResolveProxy(const GURL& url, IPC::Message* reply_msg);
+
+ private:
+ // Callback for the ProxyService (bound to |callback_|).
+ void OnResolveProxyCompleted(int result);
+
+ // Starts the first pending request.
+ void StartPendingRequest();
+
+ // Get the proxy service instance to use. On success returns true and
+ // sets |*out|. Otherwise returns false.
+ bool GetProxyService(net::ProxyService** out) 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_;
+
+ // Specified by unit-tests, to use this proxy service in place of the
+ // global one.
+ net::ProxyService* proxy_service_override_;
+};
+
+#endif // CONTENT_BROWSER_RESOLVE_PROXY_MSG_HELPER_H_
diff --git a/content/browser/resolve_proxy_msg_helper_unittest.cc b/content/browser/resolve_proxy_msg_helper_unittest.cc
new file mode 100644
index 0000000..763736c
--- /dev/null
+++ b/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -0,0 +1,236 @@
+// Copyright (c) 2011 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 "content/browser/resolve_proxy_msg_helper.h"
+
+#include "content/common/child_process_messages.h"
+#include "ipc/ipc_test_sink.h"
+#include "net/base/net_errors.h"
+#include "net/proxy/mock_proxy_resolver.h"
+#include "net/proxy/proxy_config_service.h"
+#include "net/proxy/proxy_service.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 void AddObserver(Observer* observer) {}
+ virtual void RemoveObserver(Observer* observer) {}
+ virtual ConfigAvailability GetLatestProxyConfig(net::ProxyConfig* results) {
+ *results = net::ProxyConfig::CreateFromCustomPacURL(GURL("http://pac"));
+ return CONFIG_VALID;
+ }
+};
+
+class ResolveProxyMsgHelperTest : public testing::Test,
+ public IPC::Channel::Listener {
+ public:
+ struct PendingResult {
+ PendingResult(int error_code,
+ const std::string& proxy_list)
+ : error_code(error_code), proxy_list(proxy_list) {
+ }
+
+ int error_code;
+ std::string proxy_list;
+ };
+
+ ResolveProxyMsgHelperTest()
+ : resolver_(new net::MockAsyncProxyResolver),
+ service_(new net::ProxyService(
+ new MockProxyConfigService, resolver_, NULL)),
+ helper_(new ResolveProxyMsgHelper(service_.get())),
+ message_loop_(MessageLoop::TYPE_IO),
+ io_thread_(BrowserThread::IO, &message_loop_) {
+ test_sink_.AddFilter(this);
+ helper_->OnFilterAdded(&test_sink_);
+ }
+
+ protected:
+ const PendingResult* pending_result() const { return pending_result_.get(); }
+
+ void clear_pending_result() {
+ pending_result_.reset();
+ }
+
+ IPC::Message* GenerateReply() {
+ int temp_int;
+ std::string temp_string;
+ ChildProcessHostMsg_ResolveProxy message(GURL(), &temp_int, &temp_string);
+ return IPC::SyncMessage::GenerateReply(&message);
+ }
+
+ net::MockAsyncProxyResolver* resolver_;
+ scoped_ptr<net::ProxyService> service_;
+ scoped_refptr<ResolveProxyMsgHelper> helper_;
+ scoped_ptr<PendingResult> pending_result_;
+
+ private:
+ virtual bool OnMessageReceived(const IPC::Message& msg) {
+ TupleTypes<ChildProcessHostMsg_ResolveProxy::ReplyParam>::ValueTuple
+ reply_data;
+ EXPECT_TRUE(
+ ChildProcessHostMsg_ResolveProxy::ReadReplyParam(&msg, &reply_data));
+ DCHECK(!pending_result_.get());
+ pending_result_.reset(new PendingResult(reply_data.a, reply_data.b));
+ test_sink_.ClearMessages();
+ return true;
+ }
+
+ MessageLoop message_loop_;
+ BrowserThread io_thread_;
+ IPC::TestSink test_sink_;
+};
+
+// Issue three sequential requests -- each should succeed.
+TEST_F(ResolveProxyMsgHelperTest, Sequential) {
+ GURL url1("http://www.google1.com/");
+ GURL url2("http://www.google2.com/");
+ GURL url3("http://www.google3.com/");
+
+ // Messages are deleted by the sink.
+ IPC::Message* msg1 = GenerateReply();
+ IPC::Message* msg2 = GenerateReply();
+ IPC::Message* msg3 = GenerateReply();
+
+ // Execute each request sequentially (so there are never 2 requests
+ // outstanding at the same time).
+
+ helper_->OnResolveProxy(url1, msg1);
+
+ // Finish ProxyService's initialization.
+ resolver_->pending_set_pac_script_request()->CompleteNow(net::OK);
+
+ ASSERT_EQ(1u, resolver_->pending_requests().size());
+ EXPECT_EQ(url1, resolver_->pending_requests()[0]->url());
+ resolver_->pending_requests()[0]->results()->UseNamedProxy("result1:80");
+ resolver_->pending_requests()[0]->CompleteNow(net::OK);
+
+ // Check result.
+ EXPECT_EQ(net::OK, pending_result()->error_code);
+ EXPECT_EQ("PROXY result1:80", pending_result()->proxy_list);
+ clear_pending_result();
+
+ helper_->OnResolveProxy(url2, msg2);
+
+ ASSERT_EQ(1u, resolver_->pending_requests().size());
+ EXPECT_EQ(url2, resolver_->pending_requests()[0]->url());
+ resolver_->pending_requests()[0]->results()->UseNamedProxy("result2:80");
+ resolver_->pending_requests()[0]->CompleteNow(net::OK);
+
+ // Check result.
+ EXPECT_EQ(net::OK, pending_result()->error_code);
+ EXPECT_EQ("PROXY result2:80", pending_result()->proxy_list);
+ clear_pending_result();
+
+ helper_->OnResolveProxy(url3, msg3);
+
+ ASSERT_EQ(1u, resolver_->pending_requests().size());
+ EXPECT_EQ(url3, resolver_->pending_requests()[0]->url());
+ resolver_->pending_requests()[0]->results()->UseNamedProxy("result3:80");
+ resolver_->pending_requests()[0]->CompleteNow(net::OK);
+
+ // Check result.
+ EXPECT_EQ(net::OK, pending_result()->error_code);
+ EXPECT_EQ("PROXY result3:80", pending_result()->proxy_list);
+ clear_pending_result();
+}
+
+// Issue a request while one is already in progress -- should be queued.
+TEST_F(ResolveProxyMsgHelperTest, QueueRequests) {
+ GURL url1("http://www.google1.com/");
+ GURL url2("http://www.google2.com/");
+ GURL url3("http://www.google3.com/");
+
+ IPC::Message* msg1 = GenerateReply();
+ IPC::Message* msg2 = GenerateReply();
+ IPC::Message* msg3 = GenerateReply();
+
+ // Start three requests. Since the proxy resolver is async, all the
+ // requests will be pending.
+
+ helper_->OnResolveProxy(url1, msg1);
+
+ // Finish ProxyService's initialization.
+ resolver_->pending_set_pac_script_request()->CompleteNow(net::OK);
+
+ helper_->OnResolveProxy(url2, msg2);
+ helper_->OnResolveProxy(url3, msg3);
+
+ // ResolveProxyHelper only keeps 1 request outstanding in ProxyService
+ // at a time.
+ ASSERT_EQ(1u, resolver_->pending_requests().size());
+ EXPECT_EQ(url1, resolver_->pending_requests()[0]->url());
+
+ resolver_->pending_requests()[0]->results()->UseNamedProxy("result1:80");
+ resolver_->pending_requests()[0]->CompleteNow(net::OK);
+
+ // Check result.
+ EXPECT_EQ(net::OK, pending_result()->error_code);
+ EXPECT_EQ("PROXY result1:80", pending_result()->proxy_list);
+ clear_pending_result();
+
+ ASSERT_EQ(1u, resolver_->pending_requests().size());
+ EXPECT_EQ(url2, resolver_->pending_requests()[0]->url());
+
+ resolver_->pending_requests()[0]->results()->UseNamedProxy("result2:80");
+ resolver_->pending_requests()[0]->CompleteNow(net::OK);
+
+ // Check result.
+ EXPECT_EQ(net::OK, pending_result()->error_code);
+ EXPECT_EQ("PROXY result2:80", pending_result()->proxy_list);
+ clear_pending_result();
+
+ ASSERT_EQ(1u, resolver_->pending_requests().size());
+ EXPECT_EQ(url3, resolver_->pending_requests()[0]->url());
+
+ resolver_->pending_requests()[0]->results()->UseNamedProxy("result3:80");
+ resolver_->pending_requests()[0]->CompleteNow(net::OK);
+
+ // Check result.
+ EXPECT_EQ(net::OK, pending_result()->error_code);
+ EXPECT_EQ("PROXY result3:80", pending_result()->proxy_list);
+ clear_pending_result();
+}
+
+// Delete the helper while a request is in progress, and others are pending.
+TEST_F(ResolveProxyMsgHelperTest, CancelPendingRequests) {
+ GURL url1("http://www.google1.com/");
+ GURL url2("http://www.google2.com/");
+ GURL url3("http://www.google3.com/");
+
+ // They will be deleted by the request's cancellation.
+ IPC::Message* msg1 = GenerateReply();
+ IPC::Message* msg2 = GenerateReply();
+ IPC::Message* msg3 = GenerateReply();
+
+ // Start three requests. Since the proxy resolver is async, all the
+ // requests will be pending.
+
+ helper_->OnResolveProxy(url1, msg1);
+
+ // Finish ProxyService's initialization.
+ resolver_->pending_set_pac_script_request()->CompleteNow(net::OK);
+
+ helper_->OnResolveProxy(url2, msg2);
+ helper_->OnResolveProxy(url3, msg3);
+
+ // ResolveProxyHelper only keeps 1 request outstanding in ProxyService
+ // at a time.
+ ASSERT_EQ(1u, resolver_->pending_requests().size());
+ EXPECT_EQ(url1, resolver_->pending_requests()[0]->url());
+
+ // Delete the underlying ResolveProxyMsgHelper -- this should cancel all
+ // the requests which are outstanding.
+ helper_ = NULL;
+
+ // The pending requests sent to the proxy resolver should have been cancelled.
+
+ EXPECT_EQ(0u, resolver_->pending_requests().size());
+
+ EXPECT_TRUE(pending_result() == NULL);
+
+ // It should also be the case that msg1, msg2, msg3 were deleted by the
+ // cancellation. (Else will show up as a leak in Purify/Valgrind).
+}
diff --git a/content/common/plugin_messages.h b/content/common/plugin_messages.h
index 813d8bb..d34e0d1 100644
--- a/content/common/plugin_messages.h
+++ b/content/common/plugin_messages.h
@@ -98,10 +98,10 @@ IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginWindowDestroyed,
HWND /* window */,
HWND /* parent */)
-IPC_MESSAGE_ROUTED3(PluginProcessHostMsg_DownloadUrl,
- std::string /* URL */,
- int /* process id */,
- HWND /* caller window */)
+IPC_MESSAGE_CONTROL3(PluginProcessHostMsg_DownloadUrl,
+ std::string /* URL */,
+ int /* process id */,
+ HWND /* caller window */)
#endif
#if defined(USE_X11)
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 6ba0c08..0b26790 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -272,6 +272,8 @@
'browser/renderer_host/sync_resource_handler.h',
'browser/renderer_host/x509_user_cert_resource_handler.cc',
'browser/renderer_host/x509_user_cert_resource_handler.h',
+ 'browser/resolve_proxy_msg_helper.cc',
+ 'browser/resolve_proxy_msg_helper.h',
'browser/resource_context.cc',
'browser/resource_context.h',
'browser/site_instance.cc',