michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/net/CookieServiceChild.h" michael@0: #include "mozilla/ipc/URIUtils.h" michael@0: #include "mozilla/net/NeckoChild.h" michael@0: #include "nsIURI.h" michael@0: #include "nsIPrefService.h" michael@0: #include "nsIPrefBranch.h" michael@0: #include "nsNetUtil.h" michael@0: #include "SerializedLoadContext.h" michael@0: michael@0: using namespace mozilla::ipc; michael@0: michael@0: namespace mozilla { michael@0: namespace net { michael@0: michael@0: // Behavior pref constants michael@0: static const int32_t BEHAVIOR_ACCEPT = 0; michael@0: static const int32_t BEHAVIOR_REJECTFOREIGN = 1; michael@0: // static const int32_t BEHAVIOR_REJECT = 2; michael@0: static const int32_t BEHAVIOR_LIMITFOREIGN = 3; michael@0: michael@0: // Pref string constants michael@0: static const char kPrefCookieBehavior[] = "network.cookie.cookieBehavior"; michael@0: static const char kPrefThirdPartySession[] = michael@0: "network.cookie.thirdparty.sessionOnly"; michael@0: michael@0: static CookieServiceChild *gCookieService; michael@0: michael@0: CookieServiceChild* michael@0: CookieServiceChild::GetSingleton() michael@0: { michael@0: if (!gCookieService) michael@0: gCookieService = new CookieServiceChild(); michael@0: michael@0: NS_ADDREF(gCookieService); michael@0: return gCookieService; michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(CookieServiceChild, michael@0: nsICookieService, michael@0: nsIObserver, michael@0: nsISupportsWeakReference) michael@0: michael@0: CookieServiceChild::CookieServiceChild() michael@0: : mCookieBehavior(BEHAVIOR_ACCEPT) michael@0: , mThirdPartySession(false) michael@0: { michael@0: NS_ASSERTION(IsNeckoChild(), "not a child process"); michael@0: michael@0: // This corresponds to Release() in DeallocPCookieService. michael@0: NS_ADDREF_THIS(); michael@0: michael@0: // Create a child PCookieService actor. michael@0: NeckoChild::InitNeckoChild(); michael@0: gNeckoChild->SendPCookieServiceConstructor(this); michael@0: michael@0: // Init our prefs and observer. michael@0: nsCOMPtr prefBranch = michael@0: do_GetService(NS_PREFSERVICE_CONTRACTID); michael@0: NS_WARN_IF_FALSE(prefBranch, "no prefservice"); michael@0: if (prefBranch) { michael@0: prefBranch->AddObserver(kPrefCookieBehavior, this, true); michael@0: prefBranch->AddObserver(kPrefThirdPartySession, this, true); michael@0: PrefChanged(prefBranch); michael@0: } michael@0: } michael@0: michael@0: CookieServiceChild::~CookieServiceChild() michael@0: { michael@0: gCookieService = nullptr; michael@0: } michael@0: michael@0: void michael@0: CookieServiceChild::PrefChanged(nsIPrefBranch *aPrefBranch) michael@0: { michael@0: int32_t val; michael@0: if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefCookieBehavior, &val))) michael@0: mCookieBehavior = michael@0: val >= BEHAVIOR_ACCEPT && val <= BEHAVIOR_LIMITFOREIGN ? val : BEHAVIOR_ACCEPT; michael@0: michael@0: bool boolval; michael@0: if (NS_SUCCEEDED(aPrefBranch->GetBoolPref(kPrefThirdPartySession, &boolval))) michael@0: mThirdPartySession = !!boolval; michael@0: michael@0: if (!mThirdPartyUtil && RequireThirdPartyCheck()) { michael@0: mThirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID); michael@0: NS_ASSERTION(mThirdPartyUtil, "require ThirdPartyUtil service"); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: CookieServiceChild::RequireThirdPartyCheck() michael@0: { michael@0: return mCookieBehavior == BEHAVIOR_REJECTFOREIGN || mCookieBehavior == BEHAVIOR_LIMITFOREIGN || mThirdPartySession; michael@0: } michael@0: michael@0: nsresult michael@0: CookieServiceChild::GetCookieStringInternal(nsIURI *aHostURI, michael@0: nsIChannel *aChannel, michael@0: char **aCookieString, michael@0: bool aFromHttp) michael@0: { michael@0: NS_ENSURE_ARG(aHostURI); michael@0: NS_ENSURE_ARG_POINTER(aCookieString); michael@0: michael@0: *aCookieString = nullptr; michael@0: michael@0: // Determine whether the request is foreign. Failure is acceptable. michael@0: bool isForeign = true; michael@0: if (RequireThirdPartyCheck()) michael@0: mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign); michael@0: michael@0: URIParams uriParams; michael@0: SerializeURI(aHostURI, uriParams); michael@0: michael@0: // Synchronously call the parent. michael@0: nsAutoCString result; michael@0: SendGetCookieString(uriParams, !!isForeign, aFromHttp, michael@0: IPC::SerializedLoadContext(aChannel), &result); michael@0: if (!result.IsEmpty()) michael@0: *aCookieString = ToNewCString(result); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: CookieServiceChild::SetCookieStringInternal(nsIURI *aHostURI, michael@0: nsIChannel *aChannel, michael@0: const char *aCookieString, michael@0: const char *aServerTime, michael@0: bool aFromHttp) michael@0: { michael@0: NS_ENSURE_ARG(aHostURI); michael@0: NS_ENSURE_ARG_POINTER(aCookieString); michael@0: michael@0: // Determine whether the request is foreign. Failure is acceptable. michael@0: bool isForeign = true; michael@0: if (RequireThirdPartyCheck()) michael@0: mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign); michael@0: michael@0: nsDependentCString cookieString(aCookieString); michael@0: nsDependentCString serverTime; michael@0: if (aServerTime) michael@0: serverTime.Rebind(aServerTime); michael@0: michael@0: URIParams uriParams; michael@0: SerializeURI(aHostURI, uriParams); michael@0: michael@0: // Synchronously call the parent. michael@0: SendSetCookieString(uriParams, !!isForeign, cookieString, serverTime, michael@0: aFromHttp, IPC::SerializedLoadContext(aChannel)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CookieServiceChild::Observe(nsISupports *aSubject, michael@0: const char *aTopic, michael@0: const char16_t *aData) michael@0: { michael@0: NS_ASSERTION(strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0, michael@0: "not a pref change topic!"); michael@0: michael@0: nsCOMPtr prefBranch = do_QueryInterface(aSubject); michael@0: if (prefBranch) michael@0: PrefChanged(prefBranch); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CookieServiceChild::GetCookieString(nsIURI *aHostURI, michael@0: nsIChannel *aChannel, michael@0: char **aCookieString) michael@0: { michael@0: return GetCookieStringInternal(aHostURI, aChannel, aCookieString, false); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CookieServiceChild::GetCookieStringFromHttp(nsIURI *aHostURI, michael@0: nsIURI *aFirstURI, michael@0: nsIChannel *aChannel, michael@0: char **aCookieString) michael@0: { michael@0: return GetCookieStringInternal(aHostURI, aChannel, aCookieString, true); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CookieServiceChild::SetCookieString(nsIURI *aHostURI, michael@0: nsIPrompt *aPrompt, michael@0: const char *aCookieString, michael@0: nsIChannel *aChannel) michael@0: { michael@0: return SetCookieStringInternal(aHostURI, aChannel, aCookieString, michael@0: nullptr, false); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: CookieServiceChild::SetCookieStringFromHttp(nsIURI *aHostURI, michael@0: nsIURI *aFirstURI, michael@0: nsIPrompt *aPrompt, michael@0: const char *aCookieString, michael@0: const char *aServerTime, michael@0: nsIChannel *aChannel) michael@0: { michael@0: return SetCookieStringInternal(aHostURI, aChannel, aCookieString, michael@0: aServerTime, true); michael@0: } michael@0: michael@0: } michael@0: } michael@0: