OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/proxy/sync_host_resolver_bridge.h" | 5 #include "net/proxy/sync_host_resolver_bridge.h" |
6 | 6 |
7 #include "base/threading/thread.h" | 7 #include "base/threading/thread.h" |
8 #include "base/synchronization/waitable_event.h" | 8 #include "base/synchronization/waitable_event.h" |
9 #include "net/base/address_list.h" | 9 #include "net/base/address_list.h" |
10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 | 76 |
77 // This implementation of ProxyResolver simply does a synchronous resolve | 77 // This implementation of ProxyResolver simply does a synchronous resolve |
78 // on |host_resolver| in response to GetProxyForURL(). | 78 // on |host_resolver| in response to GetProxyForURL(). |
79 class SyncProxyResolver : public ProxyResolver { | 79 class SyncProxyResolver : public ProxyResolver { |
80 public: | 80 public: |
81 explicit SyncProxyResolver(SyncHostResolverBridge* host_resolver) | 81 explicit SyncProxyResolver(SyncHostResolverBridge* host_resolver) |
82 : ProxyResolver(false), host_resolver_(host_resolver) {} | 82 : ProxyResolver(false), host_resolver_(host_resolver) {} |
83 | 83 |
84 virtual int GetProxyForURL(const GURL& url, | 84 virtual int GetProxyForURL(const GURL& url, |
85 ProxyInfo* results, | 85 ProxyInfo* results, |
86 OldCompletionCallback* callback, | 86 const CompletionCallback& callback, |
87 RequestHandle* request, | 87 RequestHandle* request, |
88 const BoundNetLog& net_log) { | 88 const BoundNetLog& net_log) { |
89 EXPECT_FALSE(callback); | 89 EXPECT_FALSE(!callback.is_null()); |
90 EXPECT_FALSE(request); | 90 EXPECT_FALSE(request); |
91 | 91 |
92 // Do a synchronous host resolve. | 92 // Do a synchronous host resolve. |
93 HostResolver::RequestInfo info(HostPortPair::FromURL(url)); | 93 HostResolver::RequestInfo info(HostPortPair::FromURL(url)); |
94 AddressList addresses; | 94 AddressList addresses; |
95 int rv = host_resolver_->Resolve(info, &addresses); | 95 int rv = host_resolver_->Resolve(info, &addresses); |
96 | 96 |
97 EXPECT_EQ(ERR_ABORTED, rv); | 97 EXPECT_EQ(ERR_ABORTED, rv); |
98 | 98 |
99 return rv; | 99 return rv; |
(...skipping 17 matching lines...) Expand all Loading... |
117 virtual void Shutdown() OVERRIDE { | 117 virtual void Shutdown() OVERRIDE { |
118 host_resolver_->Shutdown(); | 118 host_resolver_->Shutdown(); |
119 } | 119 } |
120 | 120 |
121 virtual void CancelSetPacScript() OVERRIDE { | 121 virtual void CancelSetPacScript() OVERRIDE { |
122 NOTREACHED(); | 122 NOTREACHED(); |
123 } | 123 } |
124 | 124 |
125 virtual int SetPacScript( | 125 virtual int SetPacScript( |
126 const scoped_refptr<ProxyResolverScriptData>& script_data, | 126 const scoped_refptr<ProxyResolverScriptData>& script_data, |
127 OldCompletionCallback* callback) OVERRIDE { | 127 const CompletionCallback& callback) OVERRIDE { |
128 return OK; | 128 return OK; |
129 } | 129 } |
130 | 130 |
131 private: | 131 private: |
132 SyncHostResolverBridge* const host_resolver_; | 132 SyncHostResolverBridge* const host_resolver_; |
133 }; | 133 }; |
134 | 134 |
135 class SyncProxyResolverFactory : public ProxyResolverFactory { | 135 class SyncProxyResolverFactory : public ProxyResolverFactory { |
136 public: | 136 public: |
137 // Takes ownership of |sync_host_resolver|. | 137 // Takes ownership of |sync_host_resolver|. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 // resolver on THIS thread. | 171 // resolver on THIS thread. |
172 SyncHostResolverBridge* sync_resolver = | 172 SyncHostResolverBridge* sync_resolver = |
173 new SyncHostResolverBridge(async_resolver_.get(), message_loop()); | 173 new SyncHostResolverBridge(async_resolver_.get(), message_loop()); |
174 | 174 |
175 proxy_resolver_.reset( | 175 proxy_resolver_.reset( |
176 new MultiThreadedProxyResolver( | 176 new MultiThreadedProxyResolver( |
177 new SyncProxyResolverFactory(sync_resolver), | 177 new SyncProxyResolverFactory(sync_resolver), |
178 1u)); | 178 1u)); |
179 | 179 |
180 // Initialize the resolver. | 180 // Initialize the resolver. |
181 TestOldCompletionCallback callback; | 181 TestCompletionCallback callback; |
182 proxy_resolver_->SetPacScript(ProxyResolverScriptData::FromURL(GURL()), | 182 proxy_resolver_->SetPacScript(ProxyResolverScriptData::FromURL(GURL()), |
183 &callback); | 183 callback.callback()); |
184 EXPECT_EQ(OK, callback.WaitForResult()); | 184 EXPECT_EQ(OK, callback.WaitForResult()); |
185 | 185 |
186 // Start an asynchronous request to the proxy resolver | 186 // Start an asynchronous request to the proxy resolver |
187 // (note that it will never complete). | 187 // (note that it will never complete). |
188 proxy_resolver_->GetProxyForURL(GURL("http://test/"), &results_, | 188 proxy_resolver_->GetProxyForURL( |
189 &callback_, &request_, BoundNetLog()); | 189 GURL("http://test/"), &results_, callback_.callback(), &request_, |
| 190 BoundNetLog()); |
190 } | 191 } |
191 | 192 |
192 virtual void CleanUp() OVERRIDE { | 193 virtual void CleanUp() OVERRIDE { |
193 // Cancel the outstanding request (note however that this will not | 194 // Cancel the outstanding request (note however that this will not |
194 // unblock the PAC thread though). | 195 // unblock the PAC thread though). |
195 proxy_resolver_->CancelRequest(request_); | 196 proxy_resolver_->CancelRequest(request_); |
196 | 197 |
197 // Delete the single threaded proxy resolver. | 198 // Delete the single threaded proxy resolver. |
198 proxy_resolver_.reset(); | 199 proxy_resolver_.reset(); |
199 | 200 |
200 // (There may have been a completion posted back to origin thread, avoid | 201 // (There may have been a completion posted back to origin thread, avoid |
201 // leaking it by running). | 202 // leaking it by running). |
202 MessageLoop::current()->RunAllPending(); | 203 MessageLoop::current()->RunAllPending(); |
203 | 204 |
204 // During the teardown sequence of the single threaded proxy resolver, | 205 // During the teardown sequence of the single threaded proxy resolver, |
205 // the outstanding host resolve should have been cancelled. | 206 // the outstanding host resolve should have been cancelled. |
206 EXPECT_TRUE(async_resolver_->was_request_cancelled()); | 207 EXPECT_TRUE(async_resolver_->was_request_cancelled()); |
207 } | 208 } |
208 | 209 |
209 private: | 210 private: |
210 // This (async) host resolver will outlive the thread that is operating it | 211 // This (async) host resolver will outlive the thread that is operating it |
211 // synchronously. | 212 // synchronously. |
212 scoped_ptr<BlockableHostResolver> async_resolver_; | 213 scoped_ptr<BlockableHostResolver> async_resolver_; |
213 | 214 |
214 scoped_ptr<ProxyResolver> proxy_resolver_; | 215 scoped_ptr<ProxyResolver> proxy_resolver_; |
215 | 216 |
216 // Data for the outstanding request to the single threaded proxy resolver. | 217 // Data for the outstanding request to the single threaded proxy resolver. |
217 TestOldCompletionCallback callback_; | 218 TestCompletionCallback callback_; |
218 ProxyInfo results_; | 219 ProxyInfo results_; |
219 ProxyResolver::RequestHandle request_; | 220 ProxyResolver::RequestHandle request_; |
220 }; | 221 }; |
221 | 222 |
222 // Test that a deadlock does not happen during shutdown when a host resolve | 223 // Test that a deadlock does not happen during shutdown when a host resolve |
223 // is outstanding on the SyncHostResolverBridge. | 224 // is outstanding on the SyncHostResolverBridge. |
224 // This is a regression test for http://crbug.com/41244. | 225 // This is a regression test for http://crbug.com/41244. |
225 TEST(MultiThreadedProxyResolverTest, ShutdownIsCalledBeforeThreadJoin) { | 226 TEST(MultiThreadedProxyResolverTest, ShutdownIsCalledBeforeThreadJoin) { |
226 IOThread io_thread; | 227 IOThread io_thread; |
227 base::Thread::Options options; | 228 base::Thread::Options options; |
228 options.message_loop_type = MessageLoop::TYPE_IO; | 229 options.message_loop_type = MessageLoop::TYPE_IO; |
229 ASSERT_TRUE(io_thread.StartWithOptions(options)); | 230 ASSERT_TRUE(io_thread.StartWithOptions(options)); |
230 | 231 |
231 io_thread.async_resolver()->WaitUntilRequestIsReceived(); | 232 io_thread.async_resolver()->WaitUntilRequestIsReceived(); |
232 | 233 |
233 // Now upon exitting this scope, the IOThread is destroyed -- this will | 234 // Now upon exitting this scope, the IOThread is destroyed -- this will |
234 // stop the IOThread, which will in turn delete the | 235 // stop the IOThread, which will in turn delete the |
235 // SingleThreadedProxyResolver, which in turn will stop its internal | 236 // SingleThreadedProxyResolver, which in turn will stop its internal |
236 // PAC thread (which is currently blocked waiting on the host resolve which | 237 // PAC thread (which is currently blocked waiting on the host resolve which |
237 // is running on IOThread). The IOThread::Cleanup() will verify that after | 238 // is running on IOThread). The IOThread::Cleanup() will verify that after |
238 // the PAC thread is stopped, it cancels the request on the HostResolver. | 239 // the PAC thread is stopped, it cancels the request on the HostResolver. |
239 } | 240 } |
240 | 241 |
241 } // namespace | 242 } // namespace |
242 | 243 |
243 } // namespace net | 244 } // namespace net |
OLD | NEW |