diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-18 16:08:51 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-18 16:08:51 +0000 |
commit | 97e6c4c6081444371405bb39c99b016a65a309b8 (patch) | |
tree | 01d5b996990212964f7a91ca5315ff41134bd317 /content | |
parent | a15fcb778a2c7d4c188ddbf44edcca8b6a526e16 (diff) | |
download | chromium_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/DEPS | 2 | ||||
-rw-r--r-- | content/browser/content_browser_client.cc | 3 | ||||
-rw-r--r-- | content/browser/content_browser_client.h | 6 | ||||
-rw-r--r-- | content/browser/plugin_process_host.cc | 44 | ||||
-rw-r--r-- | content/browser/plugin_process_host.h | 5 | ||||
-rw-r--r-- | content/browser/renderer_host/browser_render_process_host.cc | 2 | ||||
-rw-r--r-- | content/browser/resolve_proxy_msg_helper.cc | 120 | ||||
-rw-r--r-- | content/browser/resolve_proxy_msg_helper.h | 85 | ||||
-rw-r--r-- | content/browser/resolve_proxy_msg_helper_unittest.cc | 236 | ||||
-rw-r--r-- | content/common/plugin_messages.h | 8 | ||||
-rw-r--r-- | content/content_browser.gypi | 2 |
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', |