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