1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "mozilla/net/CookieServiceChild.h"
7 #include "mozilla/LoadInfo.h"
8 #include "mozilla/BasePrincipal.h"
9 #include "mozilla/ipc/URIUtils.h"
10 #include "mozilla/net/NeckoChild.h"
11 #include "nsIChannel.h"
12 #include "nsIURI.h"
13 #include "nsIPrefService.h"
14 #include "nsIPrefBranch.h"
15 #include "nsServiceManagerUtils.h"
16 
17 using namespace mozilla::ipc;
18 
19 namespace mozilla {
20 namespace net {
21 
22 // Pref string constants
23 static const char kPrefCookieBehavior[] = "network.cookie.cookieBehavior";
24 static const char kPrefThirdPartySession[] =
25   "network.cookie.thirdparty.sessionOnly";
26 
27 static CookieServiceChild *gCookieService;
28 
29 CookieServiceChild*
GetSingleton()30 CookieServiceChild::GetSingleton()
31 {
32   if (!gCookieService)
33     gCookieService = new CookieServiceChild();
34 
35   NS_ADDREF(gCookieService);
36   return gCookieService;
37 }
38 
NS_IMPL_ISUPPORTS(CookieServiceChild,nsICookieService,nsIObserver,nsISupportsWeakReference)39 NS_IMPL_ISUPPORTS(CookieServiceChild,
40                   nsICookieService,
41                   nsIObserver,
42                   nsISupportsWeakReference)
43 
44 CookieServiceChild::CookieServiceChild()
45   : mCookieBehavior(nsICookieService::BEHAVIOR_ACCEPT)
46   , mThirdPartySession(false)
47 {
48   NS_ASSERTION(IsNeckoChild(), "not a child process");
49 
50   // This corresponds to Release() in DeallocPCookieService.
51   NS_ADDREF_THIS();
52 
53   // Create a child PCookieService actor.
54   NeckoChild::InitNeckoChild();
55   gNeckoChild->SendPCookieServiceConstructor(this);
56 
57   // Init our prefs and observer.
58   nsCOMPtr<nsIPrefBranch> prefBranch =
59     do_GetService(NS_PREFSERVICE_CONTRACTID);
60   NS_WARNING_ASSERTION(prefBranch, "no prefservice");
61   if (prefBranch) {
62     prefBranch->AddObserver(kPrefCookieBehavior, this, true);
63     prefBranch->AddObserver(kPrefThirdPartySession, this, true);
64     PrefChanged(prefBranch);
65   }
66 }
67 
~CookieServiceChild()68 CookieServiceChild::~CookieServiceChild()
69 {
70   gCookieService = nullptr;
71 }
72 
73 void
PrefChanged(nsIPrefBranch * aPrefBranch)74 CookieServiceChild::PrefChanged(nsIPrefBranch *aPrefBranch)
75 {
76   int32_t val;
77   if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefCookieBehavior, &val)))
78     mCookieBehavior =
79       val >= nsICookieService::BEHAVIOR_ACCEPT &&
80       val <= nsICookieService::BEHAVIOR_LIMIT_FOREIGN
81         ? val : nsICookieService::BEHAVIOR_ACCEPT;
82 
83   bool boolval;
84   if (NS_SUCCEEDED(aPrefBranch->GetBoolPref(kPrefThirdPartySession, &boolval)))
85     mThirdPartySession = !!boolval;
86 
87   if (!mThirdPartyUtil && RequireThirdPartyCheck()) {
88     mThirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID);
89     NS_ASSERTION(mThirdPartyUtil, "require ThirdPartyUtil service");
90   }
91 }
92 
93 bool
RequireThirdPartyCheck()94 CookieServiceChild::RequireThirdPartyCheck()
95 {
96   return mCookieBehavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
97     mCookieBehavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN ||
98     mThirdPartySession;
99 }
100 
101 nsresult
GetCookieStringInternal(nsIURI * aHostURI,nsIChannel * aChannel,char ** aCookieString,bool aFromHttp)102 CookieServiceChild::GetCookieStringInternal(nsIURI *aHostURI,
103                                             nsIChannel *aChannel,
104                                             char **aCookieString,
105                                             bool aFromHttp)
106 {
107   NS_ENSURE_ARG(aHostURI);
108   NS_ENSURE_ARG_POINTER(aCookieString);
109 
110   *aCookieString = nullptr;
111 
112   // Fast past: don't bother sending IPC messages about nullprincipal'd
113   // documents.
114   nsAutoCString scheme;
115   aHostURI->GetScheme(scheme);
116   if (scheme.EqualsLiteral("moz-nullprincipal"))
117     return NS_OK;
118 
119   // Determine whether the request is foreign. Failure is acceptable.
120   bool isForeign = true;
121   if (RequireThirdPartyCheck())
122     mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
123 
124   URIParams uriParams;
125   SerializeURI(aHostURI, uriParams);
126 
127   mozilla::NeckoOriginAttributes attrs;
128   if (aChannel) {
129     nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
130     if (loadInfo) {
131       attrs = loadInfo->GetOriginAttributes();
132     }
133   }
134 
135   // Synchronously call the parent.
136   nsAutoCString result;
137   SendGetCookieString(uriParams, !!isForeign, aFromHttp, attrs, &result);
138   if (!result.IsEmpty())
139     *aCookieString = ToNewCString(result);
140 
141   return NS_OK;
142 }
143 
144 nsresult
SetCookieStringInternal(nsIURI * aHostURI,nsIChannel * aChannel,const char * aCookieString,const char * aServerTime,bool aFromHttp)145 CookieServiceChild::SetCookieStringInternal(nsIURI *aHostURI,
146                                             nsIChannel *aChannel,
147                                             const char *aCookieString,
148                                             const char *aServerTime,
149                                             bool aFromHttp)
150 {
151   NS_ENSURE_ARG(aHostURI);
152   NS_ENSURE_ARG_POINTER(aCookieString);
153 
154   // Fast past: don't bother sending IPC messages about nullprincipal'd
155   // documents.
156   nsAutoCString scheme;
157   aHostURI->GetScheme(scheme);
158   if (scheme.EqualsLiteral("moz-nullprincipal"))
159     return NS_OK;
160 
161   // Determine whether the request is foreign. Failure is acceptable.
162   bool isForeign = true;
163   if (RequireThirdPartyCheck())
164     mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
165 
166   nsDependentCString cookieString(aCookieString);
167   nsDependentCString serverTime;
168   if (aServerTime)
169     serverTime.Rebind(aServerTime);
170 
171   URIParams uriParams;
172   SerializeURI(aHostURI, uriParams);
173 
174   mozilla::NeckoOriginAttributes attrs;
175   if (aChannel) {
176     nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
177     if (loadInfo) {
178       attrs = loadInfo->GetOriginAttributes();
179     }
180   }
181 
182   // Synchronously call the parent.
183   SendSetCookieString(uriParams, !!isForeign, cookieString, serverTime,
184                       aFromHttp, attrs);
185   return NS_OK;
186 }
187 
188 NS_IMETHODIMP
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aData)189 CookieServiceChild::Observe(nsISupports     *aSubject,
190                             const char      *aTopic,
191                             const char16_t *aData)
192 {
193   NS_ASSERTION(strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0,
194                "not a pref change topic!");
195 
196   nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(aSubject);
197   if (prefBranch)
198     PrefChanged(prefBranch);
199   return NS_OK;
200 }
201 
202 NS_IMETHODIMP
GetCookieString(nsIURI * aHostURI,nsIChannel * aChannel,char ** aCookieString)203 CookieServiceChild::GetCookieString(nsIURI *aHostURI,
204                                     nsIChannel *aChannel,
205                                     char **aCookieString)
206 {
207   return GetCookieStringInternal(aHostURI, aChannel, aCookieString, false);
208 }
209 
210 NS_IMETHODIMP
GetCookieStringFromHttp(nsIURI * aHostURI,nsIURI * aFirstURI,nsIChannel * aChannel,char ** aCookieString)211 CookieServiceChild::GetCookieStringFromHttp(nsIURI *aHostURI,
212                                             nsIURI *aFirstURI,
213                                             nsIChannel *aChannel,
214                                             char **aCookieString)
215 {
216   return GetCookieStringInternal(aHostURI, aChannel, aCookieString, true);
217 }
218 
219 NS_IMETHODIMP
SetCookieString(nsIURI * aHostURI,nsIPrompt * aPrompt,const char * aCookieString,nsIChannel * aChannel)220 CookieServiceChild::SetCookieString(nsIURI *aHostURI,
221                                     nsIPrompt *aPrompt,
222                                     const char *aCookieString,
223                                     nsIChannel *aChannel)
224 {
225   return SetCookieStringInternal(aHostURI, aChannel, aCookieString,
226                                  nullptr, false);
227 }
228 
229 NS_IMETHODIMP
SetCookieStringFromHttp(nsIURI * aHostURI,nsIURI * aFirstURI,nsIPrompt * aPrompt,const char * aCookieString,const char * aServerTime,nsIChannel * aChannel)230 CookieServiceChild::SetCookieStringFromHttp(nsIURI     *aHostURI,
231                                             nsIURI     *aFirstURI,
232                                             nsIPrompt  *aPrompt,
233                                             const char *aCookieString,
234                                             const char *aServerTime,
235                                             nsIChannel *aChannel)
236 {
237   return SetCookieStringInternal(aHostURI, aChannel, aCookieString,
238                                  aServerTime, true);
239 }
240 
241 } // namespace net
242 } // namespace mozilla
243 
244