toolkit/system/osxproxy/nsOSXSystemProxySettings.mm

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #import <Cocoa/Cocoa.h>
michael@0 8 #import <SystemConfiguration/SystemConfiguration.h>
michael@0 9
michael@0 10 #include "nsISystemProxySettings.h"
michael@0 11 #include "mozilla/ModuleUtils.h"
michael@0 12 #include "nsIServiceManager.h"
michael@0 13 #include "nsPrintfCString.h"
michael@0 14 #include "nsNetUtil.h"
michael@0 15 #include "nsISupportsPrimitives.h"
michael@0 16 #include "nsIURI.h"
michael@0 17 #include "nsObjCExceptions.h"
michael@0 18 #include "mozilla/Attributes.h"
michael@0 19
michael@0 20 class nsOSXSystemProxySettings MOZ_FINAL : public nsISystemProxySettings {
michael@0 21 public:
michael@0 22 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 23 NS_DECL_NSISYSTEMPROXYSETTINGS
michael@0 24
michael@0 25 nsOSXSystemProxySettings();
michael@0 26 nsresult Init();
michael@0 27
michael@0 28 // called by OSX when the proxy settings have changed
michael@0 29 void ProxyHasChanged();
michael@0 30
michael@0 31 // is there a PAC url specified in the system configuration
michael@0 32 bool IsAutoconfigEnabled() const;
michael@0 33 // retrieve the pac url
michael@0 34 nsresult GetAutoconfigURL(nsAutoCString& aResult) const;
michael@0 35
michael@0 36 // Find the SystemConfiguration proxy & port for a given URI
michael@0 37 nsresult FindSCProxyPort(const nsACString &aScheme, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy);
michael@0 38
michael@0 39 // is host:port on the proxy exception list?
michael@0 40 bool IsInExceptionList(const nsACString& aHost) const;
michael@0 41
michael@0 42 private:
michael@0 43 ~nsOSXSystemProxySettings();
michael@0 44
michael@0 45 SCDynamicStoreContext mContext;
michael@0 46 SCDynamicStoreRef mSystemDynamicStore;
michael@0 47 NSDictionary* mProxyDict;
michael@0 48
michael@0 49
michael@0 50 // Mapping of URI schemes to SystemConfiguration keys
michael@0 51 struct SchemeMapping {
michael@0 52 const char* mScheme;
michael@0 53 CFStringRef mEnabled;
michael@0 54 CFStringRef mHost;
michael@0 55 CFStringRef mPort;
michael@0 56 bool mIsSocksProxy;
michael@0 57 };
michael@0 58 static const SchemeMapping gSchemeMappingList[];
michael@0 59 };
michael@0 60
michael@0 61 NS_IMPL_ISUPPORTS(nsOSXSystemProxySettings, nsISystemProxySettings)
michael@0 62
michael@0 63 NS_IMETHODIMP
michael@0 64 nsOSXSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
michael@0 65 {
michael@0 66 *aMainThreadOnly = true;
michael@0 67 return NS_OK;
michael@0 68 }
michael@0 69
michael@0 70 // Mapping of URI schemes to SystemConfiguration keys
michael@0 71 const nsOSXSystemProxySettings::SchemeMapping nsOSXSystemProxySettings::gSchemeMappingList[] = {
michael@0 72 {"http", kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort, false},
michael@0 73 {"https", kSCPropNetProxiesHTTPSEnable, kSCPropNetProxiesHTTPSProxy, kSCPropNetProxiesHTTPSPort, false},
michael@0 74 {"ftp", kSCPropNetProxiesFTPEnable, kSCPropNetProxiesFTPProxy, kSCPropNetProxiesFTPPort, false},
michael@0 75 {"socks", kSCPropNetProxiesSOCKSEnable, kSCPropNetProxiesSOCKSProxy, kSCPropNetProxiesSOCKSPort, true},
michael@0 76 {NULL, NULL, NULL, NULL, false},
michael@0 77 };
michael@0 78
michael@0 79 static void
michael@0 80 ProxyHasChangedWrapper(SCDynamicStoreRef aStore, CFArrayRef aChangedKeys, void* aInfo)
michael@0 81 {
michael@0 82 static_cast<nsOSXSystemProxySettings*>(aInfo)->ProxyHasChanged();
michael@0 83 }
michael@0 84
michael@0 85
michael@0 86 nsOSXSystemProxySettings::nsOSXSystemProxySettings()
michael@0 87 : mSystemDynamicStore(NULL), mProxyDict(NULL)
michael@0 88 {
michael@0 89 mContext = (SCDynamicStoreContext){0, this, NULL, NULL, NULL};
michael@0 90 }
michael@0 91
michael@0 92 nsresult
michael@0 93 nsOSXSystemProxySettings::Init()
michael@0 94 {
michael@0 95 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
michael@0 96
michael@0 97 // Register for notification of proxy setting changes
michael@0 98 // See: http://developer.apple.com/documentation/Networking/Conceptual/CFNetwork/CFStreamTasks/chapter_4_section_5.html
michael@0 99 mSystemDynamicStore = SCDynamicStoreCreate(NULL, CFSTR("Mozilla"), ProxyHasChangedWrapper, &mContext);
michael@0 100 if (!mSystemDynamicStore)
michael@0 101 return NS_ERROR_FAILURE;
michael@0 102
michael@0 103 // Set up the store to monitor any changes to the proxies
michael@0 104 CFStringRef proxiesKey = SCDynamicStoreKeyCreateProxies(NULL);
michael@0 105 if (!proxiesKey)
michael@0 106 return NS_ERROR_FAILURE;
michael@0 107
michael@0 108 CFArrayRef keyArray = CFArrayCreate(NULL, (const void**)(&proxiesKey), 1, &kCFTypeArrayCallBacks);
michael@0 109 CFRelease(proxiesKey);
michael@0 110 if (!keyArray)
michael@0 111 return NS_ERROR_FAILURE;
michael@0 112
michael@0 113 SCDynamicStoreSetNotificationKeys(mSystemDynamicStore, keyArray, NULL);
michael@0 114 CFRelease(keyArray);
michael@0 115
michael@0 116 // Add the dynamic store to the run loop
michael@0 117 CFRunLoopSourceRef storeRLSource = SCDynamicStoreCreateRunLoopSource(NULL, mSystemDynamicStore, 0);
michael@0 118 if (!storeRLSource)
michael@0 119 return NS_ERROR_FAILURE;
michael@0 120 CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRLSource, kCFRunLoopCommonModes);
michael@0 121 CFRelease(storeRLSource);
michael@0 122
michael@0 123 // Load the initial copy of proxy info
michael@0 124 mProxyDict = (NSDictionary*)SCDynamicStoreCopyProxies(mSystemDynamicStore);
michael@0 125 if (!mProxyDict)
michael@0 126 return NS_ERROR_FAILURE;
michael@0 127
michael@0 128 return NS_OK;
michael@0 129
michael@0 130 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
michael@0 131 }
michael@0 132
michael@0 133 nsOSXSystemProxySettings::~nsOSXSystemProxySettings()
michael@0 134 {
michael@0 135 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
michael@0 136
michael@0 137 [mProxyDict release];
michael@0 138
michael@0 139 if (mSystemDynamicStore) {
michael@0 140 // Invalidate the dynamic store's run loop source
michael@0 141 // to get the store out of the run loop
michael@0 142 CFRunLoopSourceRef rls = SCDynamicStoreCreateRunLoopSource(NULL, mSystemDynamicStore, 0);
michael@0 143 if (rls) {
michael@0 144 CFRunLoopSourceInvalidate(rls);
michael@0 145 CFRelease(rls);
michael@0 146 }
michael@0 147 CFRelease(mSystemDynamicStore);
michael@0 148 }
michael@0 149
michael@0 150 NS_OBJC_END_TRY_ABORT_BLOCK;
michael@0 151 }
michael@0 152
michael@0 153
michael@0 154 void
michael@0 155 nsOSXSystemProxySettings::ProxyHasChanged()
michael@0 156 {
michael@0 157 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
michael@0 158
michael@0 159 [mProxyDict release];
michael@0 160 mProxyDict = (NSDictionary*)SCDynamicStoreCopyProxies(mSystemDynamicStore);
michael@0 161
michael@0 162 NS_OBJC_END_TRY_ABORT_BLOCK;
michael@0 163 }
michael@0 164
michael@0 165 nsresult
michael@0 166 nsOSXSystemProxySettings::FindSCProxyPort(const nsACString &aScheme, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy)
michael@0 167 {
michael@0 168 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
michael@0 169
michael@0 170 NS_ENSURE_TRUE(mProxyDict != NULL, NS_ERROR_FAILURE);
michael@0 171
michael@0 172 for (const SchemeMapping* keys = gSchemeMappingList; keys->mScheme != NULL; ++keys) {
michael@0 173 // Check for matching scheme (when appropriate)
michael@0 174 if (strcasecmp(keys->mScheme, PromiseFlatCString(aScheme).get()) &&
michael@0 175 !keys->mIsSocksProxy)
michael@0 176 continue;
michael@0 177
michael@0 178 // Check the proxy is enabled
michael@0 179 NSNumber* enabled = [mProxyDict objectForKey:(NSString*)keys->mEnabled];
michael@0 180 NS_ENSURE_TRUE(enabled == NULL || [enabled isKindOfClass:[NSNumber class]], NS_ERROR_FAILURE);
michael@0 181 if ([enabled intValue] == 0)
michael@0 182 continue;
michael@0 183
michael@0 184 // Get the proxy host
michael@0 185 NSString* host = [mProxyDict objectForKey:(NSString*)keys->mHost];
michael@0 186 if (host == NULL)
michael@0 187 break;
michael@0 188 NS_ENSURE_TRUE([host isKindOfClass:[NSString class]], NS_ERROR_FAILURE);
michael@0 189 aResultHost.Assign([host UTF8String]);
michael@0 190
michael@0 191 // Get the proxy port
michael@0 192 NSNumber* port = [mProxyDict objectForKey:(NSString*)keys->mPort];
michael@0 193 NS_ENSURE_TRUE([port isKindOfClass:[NSNumber class]], NS_ERROR_FAILURE);
michael@0 194 aResultPort = [port intValue];
michael@0 195
michael@0 196 aResultSocksProxy = keys->mIsSocksProxy;
michael@0 197
michael@0 198 return NS_OK;
michael@0 199 }
michael@0 200
michael@0 201 return NS_ERROR_FAILURE;
michael@0 202
michael@0 203 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
michael@0 204 }
michael@0 205
michael@0 206 bool
michael@0 207 nsOSXSystemProxySettings::IsAutoconfigEnabled() const
michael@0 208 {
michael@0 209 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
michael@0 210
michael@0 211 NSNumber* value = [mProxyDict objectForKey:(NSString*)kSCPropNetProxiesProxyAutoConfigEnable];
michael@0 212 NS_ENSURE_TRUE(value == NULL || [value isKindOfClass:[NSNumber class]], false);
michael@0 213 return ([value intValue] != 0);
michael@0 214
michael@0 215 NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
michael@0 216 }
michael@0 217
michael@0 218 nsresult
michael@0 219 nsOSXSystemProxySettings::GetAutoconfigURL(nsAutoCString& aResult) const
michael@0 220 {
michael@0 221 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
michael@0 222
michael@0 223 NSString* value = [mProxyDict objectForKey:(NSString*)kSCPropNetProxiesProxyAutoConfigURLString];
michael@0 224 if (value != NULL) {
michael@0 225 NS_ENSURE_TRUE([value isKindOfClass:[NSString class]], NS_ERROR_FAILURE);
michael@0 226 aResult.Assign([value UTF8String]);
michael@0 227 return NS_OK;
michael@0 228 }
michael@0 229
michael@0 230 return NS_ERROR_FAILURE;
michael@0 231
michael@0 232 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
michael@0 233 }
michael@0 234
michael@0 235 static bool
michael@0 236 IsHostProxyEntry(const nsACString& aHost, const nsACString& aOverride)
michael@0 237 {
michael@0 238 nsAutoCString host(aHost);
michael@0 239 nsAutoCString override(aOverride);
michael@0 240
michael@0 241 int32_t overrideLength = override.Length();
michael@0 242 int32_t tokenStart = 0;
michael@0 243 int32_t offset = 0;
michael@0 244 bool star = false;
michael@0 245
michael@0 246 while (tokenStart < overrideLength) {
michael@0 247 int32_t tokenEnd = override.FindChar('*', tokenStart);
michael@0 248 if (tokenEnd == tokenStart) {
michael@0 249 // Star is the first character in the token.
michael@0 250 star = true;
michael@0 251 tokenStart++;
michael@0 252 // If the character following the '*' is a '.' character then skip
michael@0 253 // it so that "*.foo.com" allows "foo.com".
michael@0 254 if (override.FindChar('.', tokenStart) == tokenStart)
michael@0 255 tokenStart++;
michael@0 256 } else {
michael@0 257 if (tokenEnd == -1)
michael@0 258 tokenEnd = overrideLength; // no '*' char, match rest of string
michael@0 259 nsAutoCString token(Substring(override, tokenStart, tokenEnd - tokenStart));
michael@0 260 offset = host.Find(token, offset);
michael@0 261 if (offset == -1 || (!star && offset))
michael@0 262 return false;
michael@0 263 star = false;
michael@0 264 tokenStart = tokenEnd;
michael@0 265 offset += token.Length();
michael@0 266 }
michael@0 267 }
michael@0 268
michael@0 269 return (star || (offset == static_cast<int32_t>(host.Length())));
michael@0 270 }
michael@0 271
michael@0 272 bool
michael@0 273 nsOSXSystemProxySettings::IsInExceptionList(const nsACString& aHost) const
michael@0 274 {
michael@0 275 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
michael@0 276
michael@0 277 NS_ENSURE_TRUE(mProxyDict != NULL, false);
michael@0 278
michael@0 279 NSArray* exceptionList = [mProxyDict objectForKey:(NSString*)kSCPropNetProxiesExceptionsList];
michael@0 280 NS_ENSURE_TRUE(exceptionList == NULL || [exceptionList isKindOfClass:[NSArray class]], false);
michael@0 281
michael@0 282 NSEnumerator* exceptionEnumerator = [exceptionList objectEnumerator];
michael@0 283 NSString* currentValue = NULL;
michael@0 284 while ((currentValue = [exceptionEnumerator nextObject])) {
michael@0 285 NS_ENSURE_TRUE([currentValue isKindOfClass:[NSString class]], false);
michael@0 286 nsAutoCString overrideStr([currentValue UTF8String]);
michael@0 287 if (IsHostProxyEntry(aHost, overrideStr))
michael@0 288 return true;
michael@0 289 }
michael@0 290
michael@0 291 NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
michael@0 292 }
michael@0 293
michael@0 294 nsresult
michael@0 295 nsOSXSystemProxySettings::GetPACURI(nsACString& aResult)
michael@0 296 {
michael@0 297 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
michael@0 298
michael@0 299 NS_ENSURE_TRUE(mProxyDict != NULL, NS_ERROR_FAILURE);
michael@0 300
michael@0 301 nsAutoCString pacUrl;
michael@0 302 if (IsAutoconfigEnabled() && NS_SUCCEEDED(GetAutoconfigURL(pacUrl))) {
michael@0 303 aResult.Assign(pacUrl);
michael@0 304 return NS_OK;
michael@0 305 }
michael@0 306
michael@0 307 return NS_ERROR_FAILURE;
michael@0 308
michael@0 309 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
michael@0 310 }
michael@0 311
michael@0 312 nsresult
michael@0 313 nsOSXSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
michael@0 314 const nsACString & aScheme,
michael@0 315 const nsACString & aHost,
michael@0 316 const int32_t aPort,
michael@0 317 nsACString & aResult)
michael@0 318 {
michael@0 319 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
michael@0 320
michael@0 321 int32_t proxyPort;
michael@0 322 nsAutoCString proxyHost;
michael@0 323 bool proxySocks;
michael@0 324 nsresult rv = FindSCProxyPort(aScheme, proxyHost, proxyPort, proxySocks);
michael@0 325
michael@0 326 if (NS_FAILED(rv) || IsInExceptionList(aHost)) {
michael@0 327 aResult.AssignLiteral("DIRECT");
michael@0 328 } else if (proxySocks) {
michael@0 329 aResult.Assign(NS_LITERAL_CSTRING("SOCKS ") + proxyHost + nsPrintfCString(":%d", proxyPort));
michael@0 330 } else {
michael@0 331 aResult.Assign(NS_LITERAL_CSTRING("PROXY ") + proxyHost + nsPrintfCString(":%d", proxyPort));
michael@0 332 }
michael@0 333
michael@0 334 return NS_OK;
michael@0 335
michael@0 336 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
michael@0 337 }
michael@0 338
michael@0 339 #define NS_OSXSYSTEMPROXYSERVICE_CID /* 9afcd4b8-2e0f-41f4-8f1f-3bf0d3cf67de */\
michael@0 340 { 0x9afcd4b8, 0x2e0f, 0x41f4, \
michael@0 341 { 0x8f, 0x1f, 0x3b, 0xf0, 0xd3, 0xcf, 0x67, 0xde } }
michael@0 342
michael@0 343 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsOSXSystemProxySettings, Init);
michael@0 344 NS_DEFINE_NAMED_CID(NS_OSXSYSTEMPROXYSERVICE_CID);
michael@0 345
michael@0 346 static const mozilla::Module::CIDEntry kOSXSysProxyCIDs[] = {
michael@0 347 { &kNS_OSXSYSTEMPROXYSERVICE_CID, false, NULL, nsOSXSystemProxySettingsConstructor },
michael@0 348 { NULL }
michael@0 349 };
michael@0 350
michael@0 351 static const mozilla::Module::ContractIDEntry kOSXSysProxyContracts[] = {
michael@0 352 { NS_SYSTEMPROXYSETTINGS_CONTRACTID, &kNS_OSXSYSTEMPROXYSERVICE_CID },
michael@0 353 { NULL }
michael@0 354 };
michael@0 355
michael@0 356 static const mozilla::Module kOSXSysProxyModule = {
michael@0 357 mozilla::Module::kVersion,
michael@0 358 kOSXSysProxyCIDs,
michael@0 359 kOSXSysProxyContracts
michael@0 360 };
michael@0 361
michael@0 362 NSMODULE_DEFN(nsOSXProxyModule) = &kOSXSysProxyModule;

mercurial