Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: net/proxy/proxy_resolver_mac.cc

Issue 2094373002: Synchronize events of CFNetworkExecuteProxyAutoConfigurationURL (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Misha's comments Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/proxy_resolver_mac.h" 5 #include "net/proxy/proxy_resolver_mac.h"
6 6
7 #include <CoreFoundation/CoreFoundation.h> 7 #include <CoreFoundation/CoreFoundation.h>
8 8
9 #include "base/lazy_instance.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "base/mac/foundation_util.h" 11 #include "base/mac/foundation_util.h"
11 #include "base/mac/scoped_cftyperef.h" 12 #include "base/mac/scoped_cftyperef.h"
12 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
13 #include "base/strings/sys_string_conversions.h" 14 #include "base/strings/sys_string_conversions.h"
15 #include "base/synchronization/lock.h"
16 #include "base/threading/thread_checker.h"
14 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
15 #include "net/proxy/proxy_info.h" 18 #include "net/proxy/proxy_info.h"
16 #include "net/proxy/proxy_resolver.h" 19 #include "net/proxy/proxy_resolver.h"
17 #include "net/proxy/proxy_server.h" 20 #include "net/proxy/proxy_server.h"
18 21
19 #if defined(OS_IOS) 22 #if defined(OS_IOS)
20 #include <CFNetwork/CFProxySupport.h> 23 #include <CFNetwork/CFProxySupport.h>
21 #else 24 #else
22 #include <CoreServices/CoreServices.h> 25 #include <CoreServices/CoreServices.h>
23 #endif 26 #endif
24 27
25 namespace net { 28 namespace net {
26 29
27 namespace { 30 namespace {
28 31
32 // A lock shared by all ProxyResolverMac instances. It is used to synchronize
33 // the events of multiple CFNetworkExecuteProxyAutoConfigurationURL run loop
34 // sources. These events are:
35 // 1. Adding the source to the run loop.
36 // 2. Handling the source result.
37 // 3. Removing the source from the run loop.
38 static base::LazyInstance<base::Lock>::Leaky g_cfnetwork_pac_runloop_lock =
39 LAZY_INSTANCE_INITIALIZER;
40
41 // Forward declaration of the callback function used by the
42 // SynchronizedRunLoopObserver class.
43 void RunLoopObserverCallBackFunc(CFRunLoopObserverRef observer,
44 CFRunLoopActivity activity,
45 void* info);
46
29 // Utility function to map a CFProxyType to a ProxyServer::Scheme. 47 // Utility function to map a CFProxyType to a ProxyServer::Scheme.
30 // If the type is unknown, returns ProxyServer::SCHEME_INVALID. 48 // If the type is unknown, returns ProxyServer::SCHEME_INVALID.
31 ProxyServer::Scheme GetProxyServerScheme(CFStringRef proxy_type) { 49 ProxyServer::Scheme GetProxyServerScheme(CFStringRef proxy_type) {
32 if (CFEqual(proxy_type, kCFProxyTypeNone)) 50 if (CFEqual(proxy_type, kCFProxyTypeNone))
33 return ProxyServer::SCHEME_DIRECT; 51 return ProxyServer::SCHEME_DIRECT;
34 if (CFEqual(proxy_type, kCFProxyTypeHTTP)) 52 if (CFEqual(proxy_type, kCFProxyTypeHTTP))
35 return ProxyServer::SCHEME_HTTP; 53 return ProxyServer::SCHEME_HTTP;
36 if (CFEqual(proxy_type, kCFProxyTypeHTTPS)) { 54 if (CFEqual(proxy_type, kCFProxyTypeHTTPS)) {
37 // The "HTTPS" on the Mac side here means "proxy applies to https://" URLs; 55 // The "HTTPS" on the Mac side here means "proxy applies to https://" URLs;
38 // the proxy itself is still expected to be an HTTP proxy. 56 // the proxy itself is still expected to be an HTTP proxy.
(...skipping 17 matching lines...) Expand all
56 DCHECK(*result_ptr == NULL); 74 DCHECK(*result_ptr == NULL);
57 75
58 if (error != NULL) { 76 if (error != NULL) {
59 *result_ptr = CFRetain(error); 77 *result_ptr = CFRetain(error);
60 } else { 78 } else {
61 *result_ptr = CFRetain(proxies); 79 *result_ptr = CFRetain(proxies);
62 } 80 }
63 CFRunLoopStop(CFRunLoopGetCurrent()); 81 CFRunLoopStop(CFRunLoopGetCurrent());
64 } 82 }
65 83
84 #pragma mark - SynchronizedRunLoopObserver
85 // A run loop observer that guarantees that no any two run loop sources
eroman 2016/06/30 19:02:02 "no any two" --> "no two"
86 // protected by the same lock will be fired concurrently in different threads.
87 // The observer does not prevent the parallel execution of the sources but only
88 // synchronizes the run loop events associated with the sources. In the context
89 // of proxy resolver, the observer is used to synchronize the execution of the
90 // callbacks function that handles the result of
91 // CFNetworkExecuteProxyAutoConfigurationURL execution.
92 class SynchronizedRunLoopObserver final {
93 public:
94 // Creates the instance of an observer that will synchronize the sources
95 // using a given |lock|.
96 SynchronizedRunLoopObserver(base::Lock& lock);
97 // Destructor.
98 ~SynchronizedRunLoopObserver();
99 // Adds the observer to the current run loop for a given run loop mode.
100 // This method should always be paired with |RemoveFromCurrentRunLoop|.
101 void AddToCurrentRunLoop(const CFStringRef mode);
102 // Removes the observer from the current run loop for a given run loop mode.
103 // This method should always be paired with |AddToCurrentRunLoop|.
104 void RemoveFromCurrentRunLoop(const CFStringRef mode);
105 // Callback function that is called when an observable run loop event occurs.
106 void RunLoopObserverCallBack(CFRunLoopObserverRef observer,
107 CFRunLoopActivity activity);
108
109 private:
110 // Lock to use to synchronize the run loop sources.
111 base::Lock& lock_;
112 // Indicates whether the current observer holds the lock. It is used to
113 // avoid double locking and releasing.
114 bool lock_acquired_;
115 // The underlying CFRunLoopObserverRef structure wrapped by this instance.
116 base::ScopedCFTypeRef<CFRunLoopObserverRef> observer_;
117 // Validates that all methods of this class are executed on the same thread.
118 base::ThreadChecker thread_checker_;
119 DISALLOW_COPY_AND_ASSIGN(SynchronizedRunLoopObserver);
120 };
121
122 SynchronizedRunLoopObserver::SynchronizedRunLoopObserver(base::Lock& lock)
123 : lock_(lock), lock_acquired_(false) {
124 CFRunLoopObserverContext observer_context = {0, this, NULL, NULL, NULL};
125 observer_.reset(CFRunLoopObserverCreate(
126 kCFAllocatorDefault,
127 kCFRunLoopBeforeSources | kCFRunLoopBeforeWaiting | kCFRunLoopExit, true,
128 0, RunLoopObserverCallBackFunc, &observer_context));
129 }
130
131 SynchronizedRunLoopObserver::~SynchronizedRunLoopObserver() {
132 DCHECK(thread_checker_.CalledOnValidThread());
133 DCHECK(!lock_acquired_);
134 }
135
136 void SynchronizedRunLoopObserver::AddToCurrentRunLoop(const CFStringRef mode) {
137 DCHECK(thread_checker_.CalledOnValidThread());
138 CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer_.get(), mode);
139 }
140
141 void SynchronizedRunLoopObserver::RemoveFromCurrentRunLoop(
142 const CFStringRef mode) {
143 DCHECK(thread_checker_.CalledOnValidThread());
144 CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), observer_.get(), mode);
145 }
146
147 void SynchronizedRunLoopObserver::RunLoopObserverCallBack(
148 CFRunLoopObserverRef observer,
149 CFRunLoopActivity activity) {
150 DCHECK(thread_checker_.CalledOnValidThread());
151 // Acquire the lock when a source has been signaled and going to be fired.
152 // In the context of the proxy resolver that happens when the proxy for a
153 // given URL has been resolved and the callback function that handles the
154 // result is going to be fired.
155 // Release the lock when all source events have been handled.
156 switch (activity) {
157 case kCFRunLoopBeforeSources:
158 if (!lock_acquired_) {
159 lock_.Acquire();
160 lock_acquired_ = true;
161 }
162 break;
163 case kCFRunLoopBeforeWaiting:
164 case kCFRunLoopExit:
165 if (lock_acquired_) {
166 lock_acquired_ = false;
167 lock_.Release();
168 }
169 break;
170 }
171 }
172
173 void RunLoopObserverCallBackFunc(CFRunLoopObserverRef observer,
174 CFRunLoopActivity activity,
175 void* info) {
176 // Forward the call to the instance of SynchronizedRunLoopObserver
177 // that is associated with the current CF run loop observer.
178 SynchronizedRunLoopObserver* observerInstance =
179 (SynchronizedRunLoopObserver*)info;
180 observerInstance->RunLoopObserverCallBack(observer, activity);
181 }
182
183 #pragma mark - ProxyResolverMac
66 class ProxyResolverMac : public ProxyResolver { 184 class ProxyResolverMac : public ProxyResolver {
67 public: 185 public:
68 explicit ProxyResolverMac( 186 explicit ProxyResolverMac(
69 const scoped_refptr<ProxyResolverScriptData>& script_data); 187 const scoped_refptr<ProxyResolverScriptData>& script_data);
70 ~ProxyResolverMac() override; 188 ~ProxyResolverMac() override;
71 189
72 // ProxyResolver methods: 190 // ProxyResolver methods:
73 int GetProxyForURL(const GURL& url, 191 int GetProxyForURL(const GURL& url,
74 ProxyInfo* results, 192 ProxyInfo* results,
75 const CompletionCallback& callback, 193 const CompletionCallback& callback,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 CFStreamClientContext context = { 0, &result, NULL, NULL, NULL }; 251 CFStreamClientContext context = { 0, &result, NULL, NULL, NULL };
134 base::ScopedCFTypeRef<CFRunLoopSourceRef> runloop_source( 252 base::ScopedCFTypeRef<CFRunLoopSourceRef> runloop_source(
135 CFNetworkExecuteProxyAutoConfigurationURL( 253 CFNetworkExecuteProxyAutoConfigurationURL(
136 pac_url_ref.get(), query_url_ref.get(), ResultCallback, &context)); 254 pac_url_ref.get(), query_url_ref.get(), ResultCallback, &context));
137 if (!runloop_source) 255 if (!runloop_source)
138 return ERR_FAILED; 256 return ERR_FAILED;
139 257
140 const CFStringRef private_runloop_mode = 258 const CFStringRef private_runloop_mode =
141 CFSTR("org.chromium.ProxyResolverMac"); 259 CFSTR("org.chromium.ProxyResolverMac");
142 260
143 CFRunLoopAddSource(CFRunLoopGetCurrent(), runloop_source.get(), 261 // Add the run loop observer to synchronize events of
144 private_runloop_mode); 262 // CFNetworkExecuteProxyAutoConfigurationURL sources. See the definition of
263 // |g_cfnetwork_pac_runloop_lock|.
264 SynchronizedRunLoopObserver observer(g_cfnetwork_pac_runloop_lock.Get());
265 observer.AddToCurrentRunLoop(private_runloop_mode);
266
267 // Make sure that no CFNetworkExecuteProxyAutoConfigurationURL sources
268 // are added to the run loop concurrently.
269 {
270 base::AutoLock lock(g_cfnetwork_pac_runloop_lock.Get());
271 CFRunLoopAddSource(CFRunLoopGetCurrent(), runloop_source.get(),
272 private_runloop_mode);
273 }
274
145 CFRunLoopRunInMode(private_runloop_mode, DBL_MAX, false); 275 CFRunLoopRunInMode(private_runloop_mode, DBL_MAX, false);
146 CFRunLoopSourceInvalidate(runloop_source.get()); 276
277 // Make sure that no CFNetworkExecuteProxyAutoConfigurationURL sources
278 // are removed from the run loop concurrently.
279 {
280 base::AutoLock lock(g_cfnetwork_pac_runloop_lock.Get());
281 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runloop_source.get(),
282 private_runloop_mode);
283 }
284 observer.RemoveFromCurrentRunLoop(private_runloop_mode);
285
147 DCHECK(result != NULL); 286 DCHECK(result != NULL);
148 287
149 if (CFGetTypeID(result) == CFErrorGetTypeID()) { 288 if (CFGetTypeID(result) == CFErrorGetTypeID()) {
150 // TODO(avi): do something better than this 289 // TODO(avi): do something better than this
151 CFRelease(result); 290 CFRelease(result);
152 return ERR_FAILED; 291 return ERR_FAILED;
153 } 292 }
154 base::ScopedCFTypeRef<CFArrayRef> proxy_array_ref( 293 base::ScopedCFTypeRef<CFArrayRef> proxy_array_ref(
155 base::mac::CFCastStrict<CFArrayRef>(result)); 294 base::mac::CFCastStrict<CFArrayRef>(result));
156 DCHECK(proxy_array_ref != NULL); 295 DCHECK(proxy_array_ref != NULL);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 int ProxyResolverFactoryMac::CreateProxyResolver( 360 int ProxyResolverFactoryMac::CreateProxyResolver(
222 const scoped_refptr<ProxyResolverScriptData>& pac_script, 361 const scoped_refptr<ProxyResolverScriptData>& pac_script,
223 std::unique_ptr<ProxyResolver>* resolver, 362 std::unique_ptr<ProxyResolver>* resolver,
224 const CompletionCallback& callback, 363 const CompletionCallback& callback,
225 std::unique_ptr<Request>* request) { 364 std::unique_ptr<Request>* request) {
226 resolver->reset(new ProxyResolverMac(pac_script)); 365 resolver->reset(new ProxyResolverMac(pac_script));
227 return OK; 366 return OK;
228 } 367 }
229 368
230 } // namespace net 369 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698