Sat, 03 Jan 2015 20:18:00 +0100
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; |