Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/cookie/CookieServiceParent.cpp
Line
Count
Source (jump to first uncovered line)
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/CookieServiceParent.h"
7
#include "mozilla/dom/PContentParent.h"
8
#include "mozilla/net/NeckoParent.h"
9
10
#include "mozilla/BasePrincipal.h"
11
#include "mozilla/ipc/URIUtils.h"
12
#include "nsArrayUtils.h"
13
#include "nsCookieService.h"
14
#include "nsIChannel.h"
15
#include "nsIEffectiveTLDService.h"
16
#include "nsIScriptSecurityManager.h"
17
#include "nsIPrivateBrowsingChannel.h"
18
#include "nsNetCID.h"
19
#include "nsPrintfCString.h"
20
21
using namespace mozilla::ipc;
22
using mozilla::BasePrincipal;
23
using mozilla::OriginAttributes;
24
using mozilla::dom::PContentParent;
25
using mozilla::net::NeckoParent;
26
27
namespace {
28
29
// Ignore failures from this function, as they only affect whether we do or
30
// don't show a dialog box in private browsing mode if the user sets a pref.
31
void
32
CreateDummyChannel(nsIURI* aHostURI, nsIURI* aChannelURI,
33
                   OriginAttributes& aAttrs, nsIChannel** aChannel)
34
0
{
35
0
  nsCOMPtr<nsIPrincipal> principal =
36
0
    BasePrincipal::CreateCodebasePrincipal(aHostURI, aAttrs);
37
0
  if (!principal) {
38
0
    return;
39
0
  }
40
0
41
0
  // The following channel is never openend, so it does not matter what
42
0
  // securityFlags we pass; let's follow the principle of least privilege.
43
0
  nsCOMPtr<nsIChannel> dummyChannel;
44
0
  NS_NewChannel(getter_AddRefs(dummyChannel), aChannelURI, principal,
45
0
                nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
46
0
                nsIContentPolicy::TYPE_INVALID);
47
0
  nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(dummyChannel);
48
0
  if (!pbChannel) {
49
0
    return;
50
0
  }
51
0
52
0
  pbChannel->SetPrivate(aAttrs.mPrivateBrowsingId > 0);
53
0
  dummyChannel.forget(aChannel);
54
0
}
55
56
}
57
58
namespace mozilla {
59
namespace net {
60
61
CookieServiceParent::CookieServiceParent()
62
0
{
63
0
  // Instantiate the cookieservice via the service manager, so it sticks around
64
0
  // until shutdown.
65
0
  nsCOMPtr<nsICookieService> cs = do_GetService(NS_COOKIESERVICE_CONTRACTID);
66
0
67
0
  // Get the nsCookieService instance directly, so we can call internal methods.
68
0
  mCookieService = nsCookieService::GetSingleton();
69
0
  NS_ASSERTION(mCookieService, "couldn't get nsICookieService");
70
0
  mProcessingCookie = false;
71
0
}
72
73
void
74
GetInfoFromCookie(nsCookie         *aCookie,
75
                  CookieStruct     &aCookieStruct)
76
0
{
77
0
  aCookieStruct.name() = aCookie->Name();
78
0
  aCookieStruct.value() = aCookie->Value();
79
0
  aCookieStruct.host() = aCookie->Host();
80
0
  aCookieStruct.path() = aCookie->Path();
81
0
  aCookieStruct.expiry() = aCookie->Expiry();
82
0
  aCookieStruct.lastAccessed() = aCookie->LastAccessed();
83
0
  aCookieStruct.creationTime() = aCookie->CreationTime();
84
0
  aCookieStruct.isSession() = aCookie->IsSession();
85
0
  aCookieStruct.isSecure() = aCookie->IsSecure();
86
0
  aCookieStruct.isHttpOnly() = aCookie->IsHttpOnly();
87
0
  aCookieStruct.sameSite() = aCookie->SameSite();
88
0
}
89
90
void
91
0
CookieServiceParent::RemoveBatchDeletedCookies(nsIArray *aCookieList) {
92
0
  uint32_t len = 0;
93
0
  aCookieList->GetLength(&len);
94
0
  OriginAttributes attrs;
95
0
  CookieStruct cookieStruct;
96
0
  nsTArray<CookieStruct> cookieStructList;
97
0
  nsTArray<OriginAttributes> attrsList;
98
0
  for (uint32_t i = 0; i < len; i++) {
99
0
    nsCOMPtr<nsICookie> xpcCookie = do_QueryElementAt(aCookieList, i);
100
0
    auto cookie = static_cast<nsCookie*>(xpcCookie.get());
101
0
    attrs = cookie->OriginAttributesRef();
102
0
    GetInfoFromCookie(cookie, cookieStruct);
103
0
    if (!cookie->IsHttpOnly()) {
104
0
      cookieStructList.AppendElement(cookieStruct);
105
0
      attrsList.AppendElement(attrs);
106
0
    }
107
0
  }
108
0
  Unused << SendRemoveBatchDeletedCookies(cookieStructList, attrsList);
109
0
}
110
111
void
112
CookieServiceParent::RemoveAll()
113
0
{
114
0
  Unused << SendRemoveAll();
115
0
}
116
117
void
118
CookieServiceParent::RemoveCookie(nsICookie *aCookie)
119
0
{
120
0
  auto cookie = static_cast<nsCookie*>(aCookie);
121
0
  OriginAttributes attrs = cookie->OriginAttributesRef();
122
0
  CookieStruct cookieStruct;
123
0
  GetInfoFromCookie(cookie, cookieStruct);
124
0
  if (!cookie->IsHttpOnly()) {
125
0
    Unused << SendRemoveCookie(cookieStruct, attrs);
126
0
  }
127
0
}
128
129
void
130
CookieServiceParent::AddCookie(nsICookie *aCookie)
131
0
{
132
0
  auto cookie = static_cast<nsCookie*>(aCookie);
133
0
  OriginAttributes attrs = cookie->OriginAttributesRef();
134
0
  CookieStruct cookieStruct;
135
0
  GetInfoFromCookie(cookie, cookieStruct);
136
0
  Unused << SendAddCookie(cookieStruct, attrs);
137
0
}
138
139
void
140
CookieServiceParent::TrackCookieLoad(nsIChannel *aChannel)
141
0
{
142
0
  nsCOMPtr<nsIURI> uri;
143
0
  aChannel->GetURI(getter_AddRefs(uri));
144
0
145
0
  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
146
0
  mozilla::OriginAttributes attrs;
147
0
  if (loadInfo) {
148
0
    attrs = loadInfo->GetOriginAttributes();
149
0
  }
150
0
  bool isSafeTopLevelNav = NS_IsSafeTopLevelNav(aChannel);
151
0
  bool aIsSameSiteForeign = NS_IsSameSiteForeign(aChannel, uri);
152
0
153
0
  // Send matching cookies to Child.
154
0
  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil;
155
0
  thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID);
156
0
  bool isForeign = true;
157
0
  thirdPartyUtil->IsThirdPartyChannel(aChannel, uri, &isForeign);
158
0
159
0
  bool isTrackingResource = false;
160
0
  bool storageAccessGranted = false;
161
0
  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
162
0
  if (httpChannel) {
163
0
    isTrackingResource = httpChannel->GetIsTrackingResource();
164
0
    // Check first-party storage access even for non-tracking resources, since
165
0
    // we will need the result when computing the access rights for the reject
166
0
    // foreign cookie behavior mode.
167
0
    if (isForeign &&
168
0
        AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(httpChannel,
169
0
                                                                uri,
170
0
                                                                nullptr)) {
171
0
      storageAccessGranted = true;
172
0
    }
173
0
  }
174
0
175
0
  nsTArray<nsCookie*> foundCookieList;
176
0
  mCookieService->GetCookiesForURI(uri, isForeign, isTrackingResource,
177
0
                                   storageAccessGranted, isSafeTopLevelNav,
178
0
                                   aIsSameSiteForeign, false, attrs,
179
0
                                   foundCookieList);
180
0
  nsTArray<CookieStruct> matchingCookiesList;
181
0
  SerialializeCookieList(foundCookieList, matchingCookiesList, uri);
182
0
  Unused << SendTrackCookiesLoad(matchingCookiesList, attrs);
183
0
}
184
185
void
186
CookieServiceParent::SerialializeCookieList(const nsTArray<nsCookie*> &aFoundCookieList,
187
                                            nsTArray<CookieStruct>    &aCookiesList,
188
                                            nsIURI                    *aHostURI)
189
0
{
190
0
  for (uint32_t i = 0; i < aFoundCookieList.Length(); i++) {
191
0
    nsCookie *cookie = aFoundCookieList.ElementAt(i);
192
0
    CookieStruct* cookieStruct = aCookiesList.AppendElement();
193
0
    cookieStruct->name() = cookie->Name();
194
0
    cookieStruct->value() = cookie->Value();
195
0
    cookieStruct->host() = cookie->Host();
196
0
    cookieStruct->path() = cookie->Path();
197
0
    cookieStruct->expiry() = cookie->Expiry();
198
0
    cookieStruct->lastAccessed() = cookie->LastAccessed();
199
0
    cookieStruct->creationTime() = cookie->CreationTime();
200
0
    cookieStruct->isSession() = cookie->IsSession();
201
0
    cookieStruct->isSecure() = cookie->IsSecure();
202
0
    cookieStruct->sameSite() = cookie->SameSite();
203
0
  }
204
0
}
205
206
mozilla::ipc::IPCResult
207
CookieServiceParent::RecvPrepareCookieList(const URIParams        &aHost,
208
                                           const bool             &aIsForeign,
209
                                           const bool             &aIsTrackingResource,
210
                                           const bool             &aFirstPartyStorageAccessGranted,
211
                                           const bool             &aIsSafeTopLevelNav,
212
                                           const bool             &aIsSameSiteForeign,
213
                                           const OriginAttributes &aAttrs)
214
0
{
215
0
  nsCOMPtr<nsIURI> hostURI = DeserializeURI(aHost);
216
0
217
0
  // Send matching cookies to Child.
218
0
  nsTArray<nsCookie*> foundCookieList;
219
0
  mCookieService->GetCookiesForURI(hostURI, aIsForeign, aIsTrackingResource,
220
0
                                   aFirstPartyStorageAccessGranted, aIsSafeTopLevelNav,
221
0
                                   aIsSameSiteForeign, false, aAttrs,
222
0
                                   foundCookieList);
223
0
  nsTArray<CookieStruct> matchingCookiesList;
224
0
  SerialializeCookieList(foundCookieList, matchingCookiesList, hostURI);
225
0
  Unused << SendTrackCookiesLoad(matchingCookiesList, aAttrs);
226
0
  return IPC_OK();
227
0
}
228
229
void
230
CookieServiceParent::ActorDestroy(ActorDestroyReason aWhy)
231
0
{
232
0
  // Nothing needed here. Called right before destructor since this is a
233
0
  // non-refcounted class.
234
0
}
235
236
mozilla::ipc::IPCResult
237
CookieServiceParent::RecvSetCookieString(const URIParams& aHost,
238
                                         const OptionalURIParams& aChannelURI,
239
                                         const bool& aIsForeign,
240
                                         const bool& aIsTrackingResource,
241
                                         const bool& aFirstPartyStorageAccessGranted,
242
                                         const nsCString& aCookieString,
243
                                         const nsCString& aServerTime,
244
                                         const OriginAttributes& aAttrs,
245
                                         const bool& aFromHttp)
246
0
{
247
0
  if (!mCookieService)
248
0
    return IPC_OK();
249
0
250
0
  // Deserialize URI. Having a host URI is mandatory and should always be
251
0
  // provided by the child; thus we consider failure fatal.
252
0
  nsCOMPtr<nsIURI> hostURI = DeserializeURI(aHost);
253
0
  if (!hostURI)
254
0
    return IPC_FAIL_NO_REASON(this);
255
0
256
0
  nsCOMPtr<nsIURI> channelURI = DeserializeURI(aChannelURI);
257
0
258
0
  // This is a gross hack. We've already computed everything we need to know
259
0
  // for whether to set this cookie or not, but we need to communicate all of
260
0
  // this information through to nsICookiePermission, which indirectly
261
0
  // computes the information from the channel. We only care about the
262
0
  // aIsPrivate argument as nsCookieService::SetCookieStringInternal deals
263
0
  // with aIsForeign before we have to worry about nsCookiePermission trying
264
0
  // to use the channel to inspect it.
265
0
  nsCOMPtr<nsIChannel> dummyChannel;
266
0
  CreateDummyChannel(hostURI, channelURI,
267
0
                     const_cast<OriginAttributes&>(aAttrs),
268
0
                     getter_AddRefs(dummyChannel));
269
0
270
0
  // NB: dummyChannel could be null if something failed in CreateDummyChannel.
271
0
  nsDependentCString cookieString(aCookieString, 0);
272
0
273
0
  // We set this to true while processing this cookie update, to make sure
274
0
  // we don't send it back to the same content process.
275
0
  mProcessingCookie = true;
276
0
  mCookieService->SetCookieStringInternal(hostURI, aIsForeign,
277
0
                                          aIsTrackingResource,
278
0
                                          aFirstPartyStorageAccessGranted,
279
0
                                          cookieString, aServerTime, aFromHttp,
280
0
                                          aAttrs, dummyChannel);
281
0
  mProcessingCookie = false;
282
0
  return IPC_OK();
283
0
}
284
285
} // namespace net
286
} // namespace mozilla
287