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