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

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: 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/logging.h" 9 #include "base/logging.h"
10 #include "base/mac/foundation_util.h" 10 #include "base/mac/foundation_util.h"
11 #include "base/mac/scoped_cftyperef.h" 11 #include "base/mac/scoped_cftyperef.h"
12 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/strings/sys_string_conversions.h" 13 #include "base/strings/sys_string_conversions.h"
14 #include "base/synchronization/lock.h"
14 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
15 #include "net/proxy/proxy_info.h" 16 #include "net/proxy/proxy_info.h"
16 #include "net/proxy/proxy_resolver.h" 17 #include "net/proxy/proxy_resolver.h"
17 #include "net/proxy/proxy_server.h" 18 #include "net/proxy/proxy_server.h"
18 19
19 #if defined(OS_IOS) 20 #if defined(OS_IOS)
20 #include <CFNetwork/CFProxySupport.h> 21 #include <CFNetwork/CFProxySupport.h>
21 #else 22 #else
22 #include <CoreServices/CoreServices.h> 23 #include <CoreServices/CoreServices.h>
23 #endif 24 #endif
24 25
25 namespace net { 26 namespace net {
26 27
27 namespace { 28 namespace {
28 29
30 // Forward declaration of the callback function used by the
31 // SynchronizedRunLoopObserver class.
32 void RunLoopObserverCallBackFunc(CFRunLoopObserverRef observer,
33 CFRunLoopActivity activity,
34 void* info);
35
29 // Utility function to map a CFProxyType to a ProxyServer::Scheme. 36 // Utility function to map a CFProxyType to a ProxyServer::Scheme.
30 // If the type is unknown, returns ProxyServer::SCHEME_INVALID. 37 // If the type is unknown, returns ProxyServer::SCHEME_INVALID.
31 ProxyServer::Scheme GetProxyServerScheme(CFStringRef proxy_type) { 38 ProxyServer::Scheme GetProxyServerScheme(CFStringRef proxy_type) {
32 if (CFEqual(proxy_type, kCFProxyTypeNone)) 39 if (CFEqual(proxy_type, kCFProxyTypeNone))
33 return ProxyServer::SCHEME_DIRECT; 40 return ProxyServer::SCHEME_DIRECT;
34 if (CFEqual(proxy_type, kCFProxyTypeHTTP)) 41 if (CFEqual(proxy_type, kCFProxyTypeHTTP))
35 return ProxyServer::SCHEME_HTTP; 42 return ProxyServer::SCHEME_HTTP;
36 if (CFEqual(proxy_type, kCFProxyTypeHTTPS)) { 43 if (CFEqual(proxy_type, kCFProxyTypeHTTPS)) {
37 // The "HTTPS" on the Mac side here means "proxy applies to https://" URLs; 44 // 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. 45 // the proxy itself is still expected to be an HTTP proxy.
(...skipping 17 matching lines...) Expand all
56 DCHECK(*result_ptr == NULL); 63 DCHECK(*result_ptr == NULL);
57 64
58 if (error != NULL) { 65 if (error != NULL) {
59 *result_ptr = CFRetain(error); 66 *result_ptr = CFRetain(error);
60 } else { 67 } else {
61 *result_ptr = CFRetain(proxies); 68 *result_ptr = CFRetain(proxies);
62 } 69 }
63 CFRunLoopStop(CFRunLoopGetCurrent()); 70 CFRunLoopStop(CFRunLoopGetCurrent());
64 } 71 }
65 72
73 #pragma mark - SynchronizedRunLoopObserver
74 // A run loop observer that guarantees that no any two run loop sources
75 // protected by the same lock will be fired concurrently in different threads.
76 // The observer does not prevent the parallel execution of the sources but only
77 // synchronizes the run loop events associated with the sources. In the context
78 // of proxy resolver, the observer is used to synchronize the execution of the
79 // callbacks function that handles the result of
80 // CFNetworkExecuteProxyAutoConfigurationURL execution.
81 class SynchronizedRunLoopObserver {
82 public:
83 // Creates the instance of an observer that will synchronize the sources
84 // using a given |lock|.
85 SynchronizedRunLoopObserver(base::Lock& lock);
mef 2016/06/28 19:41:06 add destructor with DCHECK(!lock_acquired_);
kapishnikov 2016/06/28 21:31:04 Done.
86 // Adds the observer to the current run loop for a given run loop mode.
87 // This method should always be paired with |RemoveObserver|.
88 void AddObserver(const CFStringRef mode);
89 // Removes the observer from the current run loop for a given run loop mode.
90 // This method should always be paired with |AddObserver|.
91 void RemoveObserver(const CFStringRef mode);
92 // Callback function that is called when an observable run loop event occurs.
93 void RunLoopObserverCallBack(CFRunLoopObserverRef observer,
94 CFRunLoopActivity activity);
95
96 private:
97 // Lock to use to synchronize the run loop sources.
98 base::Lock& lock_;
99 // Indicates whether the current observer holds the lock. It is used to
100 // avoid double locking and releasing.
101 bool lock_acquired_;
102 // The underlying CFRunLoopObserverRef structure wrapped by this instance.
103 base::ScopedCFTypeRef<CFRunLoopObserverRef> observer_;
104 };
105
106 SynchronizedRunLoopObserver::SynchronizedRunLoopObserver(base::Lock& lock)
107 : lock_(lock), lock_acquired_(false) {
108 CFRunLoopObserverContext observer_context = {0, this, NULL, NULL, NULL};
109 observer_.reset(CFRunLoopObserverCreate(
110 kCFAllocatorDefault,
111 kCFRunLoopBeforeSources | kCFRunLoopBeforeWaiting | kCFRunLoopExit, true,
112 0, RunLoopObserverCallBackFunc, &observer_context));
113 }
114
115 void SynchronizedRunLoopObserver::AddObserver(const CFStringRef mode) {
mef 2016/06/28 19:41:06 Rename into AddToCurrentRunLoop().
kapishnikov 2016/06/28 21:31:04 Done.
116 CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer_.get(), mode);
117 }
118
119 void SynchronizedRunLoopObserver::RemoveObserver(const CFStringRef mode) {
mef 2016/06/28 19:41:06 Rename into RemoveFromCurrentRunLoop().
kapishnikov 2016/06/28 21:31:04 Done.
120 CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), observer_.get(), mode);
121 }
122
123 void SynchronizedRunLoopObserver::RunLoopObserverCallBack(
124 CFRunLoopObserverRef observer,
125 CFRunLoopActivity activity) {
126 // Acquire the lock when a source has been signaled and going to be fired.
127 // In the context of the proxy resolver that happens when the proxy for a
128 // given URL has been resolved and the callback function that handles the
129 // result is going to be fired.
130 // Release the lock when all source events have been handled.
131 switch (activity) {
132 case kCFRunLoopBeforeSources:
133 if (!lock_acquired_) {
mef 2016/06/28 16:59:51 Having |lock_acquired_| flag and checking it outsi
kapishnikov 2016/06/28 18:51:20 A SynchronizedRunLoopObservers instance is always
134 lock_.Acquire();
135 lock_acquired_ = true;
136 }
137 break;
138 case kCFRunLoopBeforeWaiting:
139 case kCFRunLoopExit:
140 if (lock_acquired_) {
141 lock_acquired_ = false;
142 lock_.Release();
143 }
144 break;
145 }
146 }
147
148 void RunLoopObserverCallBackFunc(CFRunLoopObserverRef observer,
149 CFRunLoopActivity activity,
150 void* info) {
151 // Forward the call to the instance of SynchronizedRunLoopObserver
152 // that is associated with the current CF run loop observer.
153 SynchronizedRunLoopObserver* observerInstance =
154 (SynchronizedRunLoopObserver*)info;
155 observerInstance->RunLoopObserverCallBack(observer, activity);
156 }
157
158 #pragma mark - ProxyResolverMac
66 class ProxyResolverMac : public ProxyResolver { 159 class ProxyResolverMac : public ProxyResolver {
67 public: 160 public:
68 explicit ProxyResolverMac( 161 explicit ProxyResolverMac(
69 const scoped_refptr<ProxyResolverScriptData>& script_data); 162 const scoped_refptr<ProxyResolverScriptData>& script_data);
70 ~ProxyResolverMac() override; 163 ~ProxyResolverMac() override;
71 164
72 // ProxyResolver methods: 165 // ProxyResolver methods:
73 int GetProxyForURL(const GURL& url, 166 int GetProxyForURL(const GURL& url,
74 ProxyInfo* results, 167 ProxyInfo* results,
75 const CompletionCallback& callback, 168 const CompletionCallback& callback,
(...skipping 15 matching lines...) Expand all
91 184
92 ProxyResolverMac::~ProxyResolverMac() {} 185 ProxyResolverMac::~ProxyResolverMac() {}
93 186
94 // Gets the proxy information for a query URL from a PAC. Implementation 187 // Gets the proxy information for a query URL from a PAC. Implementation
95 // inspired by http://developer.apple.com/samplecode/CFProxySupportTool/ 188 // inspired by http://developer.apple.com/samplecode/CFProxySupportTool/
96 int ProxyResolverMac::GetProxyForURL(const GURL& query_url, 189 int ProxyResolverMac::GetProxyForURL(const GURL& query_url,
97 ProxyInfo* results, 190 ProxyInfo* results,
98 const CompletionCallback& /*callback*/, 191 const CompletionCallback& /*callback*/,
99 RequestHandle* /*request*/, 192 RequestHandle* /*request*/,
100 const BoundNetLog& net_log) { 193 const BoundNetLog& net_log) {
194 // A lock shared by all ProxyResolverMac instances. It is used to synchronize
195 // the events of multiple CFNetworkExecuteProxyAutoConfigurationURL run loop
196 // sources. These events are:
197 // 1. Adding the source to the run loop.
198 // 2. Handling the source result.
199 // 3. Removing the source from the run loop.
200 CR_DEFINE_STATIC_LOCAL(base::Lock, lock, ());
mef 2016/06/28 16:59:52 Would it make sense to make lock a static member o
kapishnikov 2016/06/28 18:51:20 The lock is used in this method to synchronize 'ad
mef 2016/06/28 19:41:07 Use base/lazy_instance.h instead, rename into 'cfn
kapishnikov 2016/06/28 21:31:04 Done & Done
201
101 base::ScopedCFTypeRef<CFStringRef> query_ref( 202 base::ScopedCFTypeRef<CFStringRef> query_ref(
102 base::SysUTF8ToCFStringRef(query_url.spec())); 203 base::SysUTF8ToCFStringRef(query_url.spec()));
103 base::ScopedCFTypeRef<CFURLRef> query_url_ref( 204 base::ScopedCFTypeRef<CFURLRef> query_url_ref(
104 CFURLCreateWithString(kCFAllocatorDefault, query_ref.get(), NULL)); 205 CFURLCreateWithString(kCFAllocatorDefault, query_ref.get(), NULL));
105 if (!query_url_ref.get()) 206 if (!query_url_ref.get())
106 return ERR_FAILED; 207 return ERR_FAILED;
107 base::ScopedCFTypeRef<CFStringRef> pac_ref(base::SysUTF8ToCFStringRef( 208 base::ScopedCFTypeRef<CFStringRef> pac_ref(base::SysUTF8ToCFStringRef(
108 script_data_->type() == ProxyResolverScriptData::TYPE_AUTO_DETECT 209 script_data_->type() == ProxyResolverScriptData::TYPE_AUTO_DETECT
109 ? std::string() 210 ? std::string()
110 : script_data_->url().spec())); 211 : script_data_->url().spec()));
(...skipping 22 matching lines...) Expand all
133 CFStreamClientContext context = { 0, &result, NULL, NULL, NULL }; 234 CFStreamClientContext context = { 0, &result, NULL, NULL, NULL };
134 base::ScopedCFTypeRef<CFRunLoopSourceRef> runloop_source( 235 base::ScopedCFTypeRef<CFRunLoopSourceRef> runloop_source(
135 CFNetworkExecuteProxyAutoConfigurationURL( 236 CFNetworkExecuteProxyAutoConfigurationURL(
136 pac_url_ref.get(), query_url_ref.get(), ResultCallback, &context)); 237 pac_url_ref.get(), query_url_ref.get(), ResultCallback, &context));
137 if (!runloop_source) 238 if (!runloop_source)
138 return ERR_FAILED; 239 return ERR_FAILED;
139 240
140 const CFStringRef private_runloop_mode = 241 const CFStringRef private_runloop_mode =
141 CFSTR("org.chromium.ProxyResolverMac"); 242 CFSTR("org.chromium.ProxyResolverMac");
142 243
244 // Add the run loop observer to synchronize events of
245 // CFNetworkExecuteProxyAutoConfigurationURL sources. See the definition of
246 // |lock| above.
247 std::unique_ptr<SynchronizedRunLoopObserver> observer(
mef 2016/06/28 19:41:07 drop unique_ptr.
kapishnikov 2016/06/28 21:31:04 Done.
248 new SynchronizedRunLoopObserver(lock));
249 observer->AddObserver(private_runloop_mode);
250
251 // Make sure that no CFNetworkExecuteProxyAutoConfigurationURL sources
252 // are added to the run loop concurrently.
253 lock.Acquire();
143 CFRunLoopAddSource(CFRunLoopGetCurrent(), runloop_source.get(), 254 CFRunLoopAddSource(CFRunLoopGetCurrent(), runloop_source.get(),
144 private_runloop_mode); 255 private_runloop_mode);
256 lock.Release();
145 CFRunLoopRunInMode(private_runloop_mode, DBL_MAX, false); 257 CFRunLoopRunInMode(private_runloop_mode, DBL_MAX, false);
146 CFRunLoopSourceInvalidate(runloop_source.get()); 258 // Make sure that no CFNetworkExecuteProxyAutoConfigurationURL sources
259 // are removed from the run loop concurrently.
260 lock.Acquire();
mef 2016/06/28 19:41:06 Consider AutoLock
kapishnikov 2016/06/28 21:31:04 Done.
261 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runloop_source.get(),
262 private_runloop_mode);
263 lock.Release();
264
265 observer->RemoveObserver(private_runloop_mode);
266
147 DCHECK(result != NULL); 267 DCHECK(result != NULL);
148 268
149 if (CFGetTypeID(result) == CFErrorGetTypeID()) { 269 if (CFGetTypeID(result) == CFErrorGetTypeID()) {
150 // TODO(avi): do something better than this 270 // TODO(avi): do something better than this
151 CFRelease(result); 271 CFRelease(result);
152 return ERR_FAILED; 272 return ERR_FAILED;
153 } 273 }
154 base::ScopedCFTypeRef<CFArrayRef> proxy_array_ref( 274 base::ScopedCFTypeRef<CFArrayRef> proxy_array_ref(
155 base::mac::CFCastStrict<CFArrayRef>(result)); 275 base::mac::CFCastStrict<CFArrayRef>(result));
156 DCHECK(proxy_array_ref != NULL); 276 DCHECK(proxy_array_ref != NULL);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 int ProxyResolverFactoryMac::CreateProxyResolver( 341 int ProxyResolverFactoryMac::CreateProxyResolver(
222 const scoped_refptr<ProxyResolverScriptData>& pac_script, 342 const scoped_refptr<ProxyResolverScriptData>& pac_script,
223 std::unique_ptr<ProxyResolver>* resolver, 343 std::unique_ptr<ProxyResolver>* resolver,
224 const CompletionCallback& callback, 344 const CompletionCallback& callback,
225 std::unique_ptr<Request>* request) { 345 std::unique_ptr<Request>* request) {
226 resolver->reset(new ProxyResolverMac(pac_script)); 346 resolver->reset(new ProxyResolverMac(pac_script));
227 return OK; 347 return OK;
228 } 348 }
229 349
230 } // namespace net 350 } // 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