1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/loader/BeaconLoader.h"
#include "core/FetchInitiatorTypeNames.h"
#include "core/dom/Document.h"
#include "core/fetch/CrossOriginAccessControl.h"
#include "core/fetch/FetchContext.h"
#include "core/fileapi/File.h"
#include "core/frame/LocalFrame.h"
#include "core/html/DOMFormData.h"
#include "platform/network/FormData.h"
#include "platform/network/ParsedContentType.h"
#include "platform/network/ResourceRequest.h"
#include "wtf/ArrayBufferView.h"
namespace WebCore {
void BeaconLoader::prepareRequest(LocalFrame* frame, ResourceRequest& request)
{
// NOTE: do not distinguish Beacon by target type.
request.setTargetType(ResourceRequest::TargetIsPing);
request.setHTTPMethod("POST");
request.setHTTPHeaderField("Cache-Control", "max-age=0");
request.setAllowStoredCredentials(true);
frame->loader().fetchContext().addAdditionalRequestHeaders(frame->document(), request, FetchSubresource);
frame->loader().fetchContext().setFirstPartyForCookies(request);
}
void BeaconLoader::issueRequest(LocalFrame* frame, ResourceRequest& request)
{
FetchInitiatorInfo initiatorInfo;
initiatorInfo.name = FetchInitiatorTypeNames::beacon;
PingLoader::start(frame, request, initiatorInfo);
}
bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, const String& data, int& payloadLength)
{
ResourceRequest request(beaconURL);
prepareRequest(frame, request);
RefPtr<FormData> entityBody = FormData::create(data.utf8());
unsigned long long entitySize = entityBody->sizeInBytes();
if (allowance > 0 && static_cast<unsigned>(allowance) < entitySize)
return false;
request.setHTTPBody(entityBody);
request.setHTTPContentType("text/plain;charset=UTF-8");
issueRequest(frame, request);
payloadLength = entitySize;
return true;
}
bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtr<ArrayBufferView>& data, int& payloadLength)
{
ASSERT(data);
unsigned long long entitySize = data->byteLength();
if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
return false;
ResourceRequest request(beaconURL);
prepareRequest(frame, request);
RefPtr<FormData> entityBody = FormData::create(data->baseAddress(), data->byteLength());
request.setHTTPBody(entityBody.release());
// FIXME: a reasonable choice, but not in the spec; should it give a default?
AtomicString contentType = AtomicString("application/octet-stream");
request.setHTTPContentType(contentType);
issueRequest(frame, request);
payloadLength = entitySize;
return true;
}
bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtrWillBeRawPtr<Blob>& data, int& payloadLength)
{
ASSERT(data);
unsigned long long entitySize = data->size();
if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
return false;
ResourceRequest request(beaconURL);
prepareRequest(frame, request);
RefPtr<FormData> entityBody = FormData::create();
if (data->hasBackingFile())
entityBody->appendFile(toFile(data.get())->path());
else
entityBody->appendBlob(data->uuid(), data->blobDataHandle());
request.setHTTPBody(entityBody.release());
AtomicString contentType;
const String& blobType = data->type();
if (!blobType.isEmpty() && isValidContentType(blobType))
request.setHTTPContentType(AtomicString(contentType));
issueRequest(frame, request);
payloadLength = entitySize;
return true;
}
bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtrWillBeRawPtr<DOMFormData>& data, int& payloadLength)
{
ASSERT(data);
ResourceRequest request(beaconURL);
prepareRequest(frame, request);
RefPtr<FormData> entityBody = data->createMultiPartFormData();
unsigned long long entitySize = entityBody->sizeInBytes();
if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
return false;
AtomicString contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + entityBody->boundary().data();
request.setHTTPBody(entityBody.release());
request.setHTTPContentType(contentType);
issueRequest(frame, request);
payloadLength = entitySize;
return true;
}
} // namespace WebCore
|