Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/fetch/InternalRequest.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "InternalRequest.h"
8
9
#include "nsIContentPolicy.h"
10
#include "nsIDocument.h"
11
#include "nsStreamUtils.h"
12
13
#include "mozilla/ErrorResult.h"
14
#include "mozilla/dom/FetchTypes.h"
15
#include "mozilla/dom/ScriptSettings.h"
16
17
#include "mozilla/dom/WorkerCommon.h"
18
#include "mozilla/dom/WorkerPrivate.h"
19
20
namespace mozilla {
21
namespace dom {
22
// The global is used to extract the principal.
23
already_AddRefed<InternalRequest>
24
InternalRequest::GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult& aRv) const
25
0
{
26
0
  MOZ_RELEASE_ASSERT(!mURLList.IsEmpty(), "Internal Request's urlList should not be empty when copied from constructor.");
27
0
  RefPtr<InternalRequest> copy = new InternalRequest(mURLList.LastElement(),
28
0
                                                     mFragment);
29
0
  copy->SetMethod(mMethod);
30
0
  copy->mHeaders = new InternalHeaders(*mHeaders);
31
0
  copy->SetUnsafeRequest();
32
0
  copy->mBodyStream = mBodyStream;
33
0
  copy->mBodyLength = mBodyLength;
34
0
  copy->mForceOriginHeader = true;
35
0
  // The "client" is not stored in our implementation. Fetch API users should
36
0
  // use the appropriate window/document/principal and other Gecko security
37
0
  // mechanisms as appropriate.
38
0
  copy->mSameOriginDataURL = true;
39
0
  copy->mPreserveContentCodings = true;
40
0
  copy->mReferrer = mReferrer;
41
0
  copy->mReferrerPolicy = mReferrerPolicy;
42
0
  copy->mEnvironmentReferrerPolicy = mEnvironmentReferrerPolicy;
43
0
  copy->mIntegrity = mIntegrity;
44
0
  copy->mMozErrors = mMozErrors;
45
0
46
0
  copy->mContentPolicyType = mContentPolicyTypeOverridden ?
47
0
                             mContentPolicyType :
48
0
                             nsIContentPolicy::TYPE_FETCH;
49
0
  copy->mMode = mMode;
50
0
  copy->mCredentialsMode = mCredentialsMode;
51
0
  copy->mCacheMode = mCacheMode;
52
0
  copy->mRedirectMode = mRedirectMode;
53
0
  copy->mCreatedByFetchEvent = mCreatedByFetchEvent;
54
0
  copy->mContentPolicyTypeOverridden = mContentPolicyTypeOverridden;
55
0
56
0
  copy->mPreferredAlternativeDataType = mPreferredAlternativeDataType;
57
0
  return copy.forget();
58
0
}
59
60
already_AddRefed<InternalRequest>
61
InternalRequest::Clone()
62
0
{
63
0
  RefPtr<InternalRequest> clone = new InternalRequest(*this);
64
0
65
0
  if (!mBodyStream) {
66
0
    return clone.forget();
67
0
  }
68
0
69
0
  nsCOMPtr<nsIInputStream> clonedBody;
70
0
  nsCOMPtr<nsIInputStream> replacementBody;
71
0
72
0
  nsresult rv = NS_CloneInputStream(mBodyStream, getter_AddRefs(clonedBody),
73
0
                                    getter_AddRefs(replacementBody));
74
0
  if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; }
75
0
76
0
  clone->mBodyStream.swap(clonedBody);
77
0
  if (replacementBody) {
78
0
    mBodyStream.swap(replacementBody);
79
0
  }
80
0
  return clone.forget();
81
0
}
82
InternalRequest::InternalRequest(const nsACString& aURL,
83
                                 const nsACString& aFragment)
84
  : mMethod("GET")
85
  , mHeaders(new InternalHeaders(HeadersGuardEnum::None))
86
  , mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE)
87
  , mContentPolicyType(nsIContentPolicy::TYPE_FETCH)
88
  , mReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR))
89
  , mReferrerPolicy(ReferrerPolicy::_empty)
90
  , mEnvironmentReferrerPolicy(net::RP_Unset)
91
  , mMode(RequestMode::No_cors)
92
  , mCredentialsMode(RequestCredentials::Omit)
93
  , mResponseTainting(LoadTainting::Basic)
94
  , mCacheMode(RequestCache::Default)
95
  , mRedirectMode(RequestRedirect::Follow)
96
  , mMozErrors(false)
97
  , mAuthenticationFlag(false)
98
  , mForceOriginHeader(false)
99
  , mPreserveContentCodings(false)
100
    // FIXME(nsm): This should be false by default, but will lead to the
101
    // algorithm never loading data: URLs right now. See Bug 1018872 about
102
    // how certain contexts will override it to set it to true. Fetch
103
    // specification does not handle this yet.
104
  , mSameOriginDataURL(true)
105
  , mSkipServiceWorker(false)
106
  , mSynchronous(false)
107
  , mUnsafeRequest(false)
108
  , mUseURLCredentials(false)
109
0
{
110
0
  MOZ_ASSERT(!aURL.IsEmpty());
111
0
  AddURL(aURL, aFragment);
112
0
}
113
InternalRequest::InternalRequest(const nsACString& aURL,
114
                                 const nsACString& aFragment,
115
                                 const nsACString& aMethod,
116
                                 already_AddRefed<InternalHeaders> aHeaders,
117
                                 RequestCache aCacheMode,
118
                                 RequestMode aMode,
119
                                 RequestRedirect aRequestRedirect,
120
                                 RequestCredentials aRequestCredentials,
121
                                 const nsAString& aReferrer,
122
                                 ReferrerPolicy aReferrerPolicy,
123
                                 nsContentPolicyType aContentPolicyType,
124
                                 const nsAString& aIntegrity)
125
  : mMethod(aMethod)
126
  , mHeaders(aHeaders)
127
  , mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE)
128
  , mContentPolicyType(aContentPolicyType)
129
  , mReferrer(aReferrer)
130
  , mReferrerPolicy(aReferrerPolicy)
131
  , mEnvironmentReferrerPolicy(net::RP_Unset)
132
  , mMode(aMode)
133
  , mCredentialsMode(aRequestCredentials)
134
  , mResponseTainting(LoadTainting::Basic)
135
  , mCacheMode(aCacheMode)
136
  , mRedirectMode(aRequestRedirect)
137
  , mIntegrity(aIntegrity)
138
  , mMozErrors(false)
139
  , mAuthenticationFlag(false)
140
  , mForceOriginHeader(false)
141
  , mPreserveContentCodings(false)
142
    // FIXME See the above comment in the default constructor.
143
  , mSameOriginDataURL(true)
144
  , mSkipServiceWorker(false)
145
  , mSynchronous(false)
146
  , mUnsafeRequest(false)
147
  , mUseURLCredentials(false)
148
0
{
149
0
  MOZ_ASSERT(!aURL.IsEmpty());
150
0
  AddURL(aURL, aFragment);
151
0
}
152
InternalRequest::InternalRequest(const InternalRequest& aOther)
153
  : mMethod(aOther.mMethod)
154
  , mURLList(aOther.mURLList)
155
  , mHeaders(new InternalHeaders(*aOther.mHeaders))
156
  , mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE)
157
  , mContentPolicyType(aOther.mContentPolicyType)
158
  , mReferrer(aOther.mReferrer)
159
  , mReferrerPolicy(aOther.mReferrerPolicy)
160
  , mEnvironmentReferrerPolicy(aOther.mEnvironmentReferrerPolicy)
161
  , mMode(aOther.mMode)
162
  , mCredentialsMode(aOther.mCredentialsMode)
163
  , mResponseTainting(aOther.mResponseTainting)
164
  , mCacheMode(aOther.mCacheMode)
165
  , mRedirectMode(aOther.mRedirectMode)
166
  , mIntegrity(aOther.mIntegrity)
167
  , mMozErrors(aOther.mMozErrors)
168
  , mFragment(aOther.mFragment)
169
  , mAuthenticationFlag(aOther.mAuthenticationFlag)
170
  , mForceOriginHeader(aOther.mForceOriginHeader)
171
  , mPreserveContentCodings(aOther.mPreserveContentCodings)
172
  , mSameOriginDataURL(aOther.mSameOriginDataURL)
173
  , mSkipServiceWorker(aOther.mSkipServiceWorker)
174
  , mSynchronous(aOther.mSynchronous)
175
  , mUnsafeRequest(aOther.mUnsafeRequest)
176
  , mUseURLCredentials(aOther.mUseURLCredentials)
177
  , mCreatedByFetchEvent(aOther.mCreatedByFetchEvent)
178
  , mContentPolicyTypeOverridden(aOther.mContentPolicyTypeOverridden)
179
0
{
180
0
  // NOTE: does not copy body stream... use the fallible Clone() for that
181
0
}
182
183
InternalRequest::InternalRequest(const IPCInternalRequest& aIPCRequest)
184
  : mMethod(aIPCRequest.method())
185
  , mURLList(aIPCRequest.urls())
186
  , mHeaders(new InternalHeaders(aIPCRequest.headers(),
187
                                 aIPCRequest.headersGuard()))
188
  , mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE)
189
  , mContentPolicyType(aIPCRequest.contentPolicyType())
190
  , mReferrer(aIPCRequest.referrer())
191
  , mReferrerPolicy(aIPCRequest.referrerPolicy())
192
  , mEnvironmentReferrerPolicy(net::RP_Unset)
193
  , mMode(aIPCRequest.mode())
194
  , mCredentialsMode(aIPCRequest.credentials())
195
  , mCacheMode(aIPCRequest.requestCache())
196
  , mRedirectMode(aIPCRequest.requestRedirect())
197
  , mMozErrors(false)
198
0
{
199
0
  MOZ_ASSERT(!mURLList.IsEmpty());
200
0
}
201
202
InternalRequest::~InternalRequest()
203
0
{
204
0
}
205
206
void
207
InternalRequest::ToIPC(IPCInternalRequest* aIPCRequest)
208
0
{
209
0
  MOZ_ASSERT(aIPCRequest);
210
0
  MOZ_ASSERT(!mURLList.IsEmpty());
211
0
  aIPCRequest->urls() = mURLList;
212
0
  aIPCRequest->method() = mMethod;
213
0
214
0
  mHeaders->ToIPC(aIPCRequest->headers(), aIPCRequest->headersGuard());
215
0
216
0
  aIPCRequest->referrer() = mReferrer;
217
0
  aIPCRequest->referrerPolicy() = mReferrerPolicy;
218
0
  aIPCRequest->mode() = mMode;
219
0
  aIPCRequest->credentials() = mCredentialsMode;
220
0
  aIPCRequest->contentPolicyType() = mContentPolicyType;
221
0
  aIPCRequest->requestCache() = mCacheMode;
222
0
  aIPCRequest->requestRedirect() = mRedirectMode;
223
0
}
224
225
void
226
InternalRequest::SetContentPolicyType(nsContentPolicyType aContentPolicyType)
227
0
{
228
0
  mContentPolicyType = aContentPolicyType;
229
0
}
230
231
void
232
InternalRequest::OverrideContentPolicyType(nsContentPolicyType aContentPolicyType)
233
0
{
234
0
  SetContentPolicyType(aContentPolicyType);
235
0
  mContentPolicyTypeOverridden = true;
236
0
}
237
238
/* static */ RequestDestination
239
InternalRequest::MapContentPolicyTypeToRequestDestination(nsContentPolicyType aContentPolicyType)
240
0
{
241
0
  RequestDestination destination = RequestDestination::_empty;
242
0
  switch (aContentPolicyType) {
243
0
  case nsIContentPolicy::TYPE_OTHER:
244
0
    destination = RequestDestination::_empty;
245
0
    break;
246
0
  case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
247
0
  case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
248
0
  case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
249
0
  case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
250
0
  case nsIContentPolicy::TYPE_SCRIPT:
251
0
    destination = RequestDestination::Script;
252
0
    break;
253
0
  case nsIContentPolicy::TYPE_INTERNAL_WORKER:
254
0
    destination = RequestDestination::Worker;
255
0
    break;
256
0
  case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
257
0
    destination = RequestDestination::Sharedworker;
258
0
    break;
259
0
  case nsIContentPolicy::TYPE_IMAGESET:
260
0
  case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
261
0
  case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
262
0
  case nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON:
263
0
  case nsIContentPolicy::TYPE_IMAGE:
264
0
    destination = RequestDestination::Image;
265
0
    break;
266
0
  case nsIContentPolicy::TYPE_STYLESHEET:
267
0
  case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:
268
0
  case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD:
269
0
    destination = RequestDestination::Style;
270
0
    break;
271
0
  case nsIContentPolicy::TYPE_OBJECT:
272
0
  case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
273
0
    destination = RequestDestination::Object;
274
0
    break;
275
0
  case nsIContentPolicy::TYPE_INTERNAL_EMBED:
276
0
    destination = RequestDestination::Embed;
277
0
    break;
278
0
  case nsIContentPolicy::TYPE_DOCUMENT:
279
0
  case nsIContentPolicy::TYPE_SUBDOCUMENT:
280
0
  case nsIContentPolicy::TYPE_INTERNAL_IFRAME:
281
0
    destination = RequestDestination::Document;
282
0
    break;
283
0
  case nsIContentPolicy::TYPE_INTERNAL_FRAME:
284
0
    destination = RequestDestination::_empty;
285
0
    break;
286
0
  case nsIContentPolicy::TYPE_REFRESH:
287
0
    destination = RequestDestination::_empty;
288
0
    break;
289
0
  case nsIContentPolicy::TYPE_XBL:
290
0
    destination = RequestDestination::_empty;
291
0
    break;
292
0
  case nsIContentPolicy::TYPE_PING:
293
0
    destination = RequestDestination::_empty;
294
0
    break;
295
0
  case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
296
0
  case nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST:
297
0
    destination = RequestDestination::_empty;
298
0
    break;
299
0
  case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE:
300
0
    destination = RequestDestination::_empty;
301
0
    break;
302
0
  case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
303
0
    destination = RequestDestination::_empty;
304
0
    break;
305
0
  case nsIContentPolicy::TYPE_DTD:
306
0
    destination = RequestDestination::_empty;
307
0
    break;
308
0
  case nsIContentPolicy::TYPE_FONT:
309
0
    destination = RequestDestination::Font;
310
0
    break;
311
0
  case nsIContentPolicy::TYPE_MEDIA:
312
0
    destination = RequestDestination::_empty;
313
0
    break;
314
0
  case nsIContentPolicy::TYPE_INTERNAL_AUDIO:
315
0
    destination = RequestDestination::Audio;
316
0
    break;
317
0
  case nsIContentPolicy::TYPE_INTERNAL_VIDEO:
318
0
    destination = RequestDestination::Video;
319
0
    break;
320
0
  case nsIContentPolicy::TYPE_INTERNAL_TRACK:
321
0
    destination = RequestDestination::Track;
322
0
    break;
323
0
  case nsIContentPolicy::TYPE_WEBSOCKET:
324
0
    destination = RequestDestination::_empty;
325
0
    break;
326
0
  case nsIContentPolicy::TYPE_CSP_REPORT:
327
0
    destination = RequestDestination::_empty;
328
0
    break;
329
0
  case nsIContentPolicy::TYPE_XSLT:
330
0
    destination = RequestDestination::Xslt;
331
0
    break;
332
0
  case nsIContentPolicy::TYPE_BEACON:
333
0
    destination = RequestDestination::_empty;
334
0
    break;
335
0
  case nsIContentPolicy::TYPE_FETCH:
336
0
    destination = RequestDestination::_empty;
337
0
    break;
338
0
  case nsIContentPolicy::TYPE_WEB_MANIFEST:
339
0
    destination = RequestDestination::Manifest;
340
0
    break;
341
0
  case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD:
342
0
    destination = RequestDestination::_empty;
343
0
    break;
344
0
  case nsIContentPolicy::TYPE_SPECULATIVE:
345
0
    destination = RequestDestination::_empty;
346
0
    break;
347
0
  default:
348
0
    MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
349
0
    break;
350
0
  }
351
0
352
0
  return destination;
353
0
}
354
355
// static
356
bool
357
InternalRequest::IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType)
358
0
{
359
0
  // https://fetch.spec.whatwg.org/#navigation-request-context
360
0
  //
361
0
  // A navigation request context is one of "form", "frame", "hyperlink",
362
0
  // "iframe", "internal" (as long as context frame type is not "none"),
363
0
  // "location", "metarefresh", and "prerender".
364
0
  //
365
0
  // Note, all of these request types are effectively initiated by nsDocShell.
366
0
  //
367
0
  // The TYPE_REFRESH is used in some code paths for metarefresh, but will not
368
0
  // be seen during the actual load.  Instead the new load gets a normal
369
0
  // nsDocShell policy type.  We include it here in case this utility method
370
0
  // is called before the load starts.
371
0
  return aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
372
0
         aContentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
373
0
         aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
374
0
         aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
375
0
         aContentPolicyType == nsIContentPolicy::TYPE_REFRESH;
376
0
}
377
378
// static
379
bool
380
InternalRequest::IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType)
381
0
{
382
0
  // https://fetch.spec.whatwg.org/#worker-request-context
383
0
  //
384
0
  // A worker request context is one of "serviceworker", "sharedworker", and
385
0
  // "worker".
386
0
  //
387
0
  // Note, service workers are not included here because currently there is
388
0
  // no way to generate a Request with a "serviceworker" RequestDestination.
389
0
  // ServiceWorker scripts cannot be intercepted.
390
0
  return aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
391
0
         aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
392
0
}
393
394
bool
395
InternalRequest::IsNavigationRequest() const
396
0
{
397
0
  return IsNavigationContentPolicy(mContentPolicyType);
398
0
}
399
400
bool
401
InternalRequest::IsWorkerRequest() const
402
0
{
403
0
  return IsWorkerContentPolicy(mContentPolicyType);
404
0
}
405
406
bool
407
InternalRequest::IsClientRequest() const
408
0
{
409
0
  return IsNavigationRequest() || IsWorkerRequest();
410
0
}
411
412
// static
413
RequestMode
414
InternalRequest::MapChannelToRequestMode(nsIChannel* aChannel)
415
0
{
416
0
  MOZ_ASSERT(aChannel);
417
0
418
0
  nsCOMPtr<nsILoadInfo> loadInfo;
419
0
  MOZ_ALWAYS_SUCCEEDS(aChannel->GetLoadInfo(getter_AddRefs(loadInfo)));
420
0
421
0
  nsContentPolicyType contentPolicy = loadInfo->InternalContentPolicyType();
422
0
  if (IsNavigationContentPolicy(contentPolicy)) {
423
0
    return RequestMode::Navigate;
424
0
  }
425
0
426
0
  // TODO: remove the worker override once securityMode is fully implemented (bug 1189945)
427
0
  if (IsWorkerContentPolicy(contentPolicy)) {
428
0
    return RequestMode::Same_origin;
429
0
  }
430
0
431
0
  uint32_t securityMode = loadInfo->GetSecurityMode();
432
0
433
0
  switch(securityMode) {
434
0
    case nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS:
435
0
    case nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED:
436
0
      return RequestMode::Same_origin;
437
0
    case nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS:
438
0
    case nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL:
439
0
      return RequestMode::No_cors;
440
0
    case nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS:
441
0
      // TODO: Check additional flag force-preflight after bug 1199693 (bug 1189945)
442
0
      return RequestMode::Cors;
443
0
    default:
444
0
      MOZ_ASSERT_UNREACHABLE("Unexpected security mode!");
445
0
      return RequestMode::Same_origin;
446
0
  }
447
0
}
448
449
// static
450
RequestCredentials
451
InternalRequest::MapChannelToRequestCredentials(nsIChannel* aChannel)
452
0
{
453
0
  MOZ_ASSERT(aChannel);
454
0
455
0
  nsCOMPtr<nsILoadInfo> loadInfo;
456
0
  MOZ_ALWAYS_SUCCEEDS(aChannel->GetLoadInfo(getter_AddRefs(loadInfo)));
457
0
458
0
  uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
459
0
460
0
  if (cookiePolicy == nsILoadInfo::SEC_COOKIES_INCLUDE) {
461
0
    return RequestCredentials::Include;
462
0
  } else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_OMIT) {
463
0
    return RequestCredentials::Omit;
464
0
  } else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
465
0
    return RequestCredentials::Same_origin;
466
0
  }
467
0
468
0
  MOZ_ASSERT_UNREACHABLE("Unexpected cookie policy!");
469
0
  return RequestCredentials::Same_origin;
470
0
}
471
472
void
473
InternalRequest::MaybeSkipCacheIfPerformingRevalidation()
474
0
{
475
0
  if (mCacheMode == RequestCache::Default &&
476
0
      mHeaders->HasRevalidationHeaders()) {
477
0
    mCacheMode = RequestCache::No_store;
478
0
  }
479
0
}
480
481
void
482
InternalRequest::SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo)
483
0
{
484
0
  mPrincipalInfo = std::move(aPrincipalInfo);
485
0
}
486
487
} // namespace dom
488
} // namespace mozilla