This source file includes following definitions.
- create
- addHeader
- m_includeCredentials
- m_cachedResource
- setContent
- contentSizeInBytes
- removeContent
- evictContent
- dataLength
- appendData
- decodeDataToContent
- m_maximumSingleResourceContentSize
- resourceCreated
- createOtherResourceTextDecoder
- responseReceived
- setResourceType
- resourceType
- setResourceContent
- maybeAddResourceData
- maybeDecodeDataToContent
- addResource
- addResourceSharedBuffer
- data
- xhrReplayData
- setXHRReplayData
- reuseXHRReplayData
- resources
- removeResource
- clear
- setResourcesDataSizeLimits
- resourceDataForRequestId
- ensureNoDataForRequestId
- ensureFreeSpace
#include "config.h"
#include "core/inspector/NetworkResourcesData.h"
#include "core/dom/DOMImplementation.h"
#include "core/fetch/Resource.h"
#include "platform/MIMETypeRegistry.h"
#include "platform/SharedBuffer.h"
#include "platform/network/ResourceResponse.h"
namespace {
static size_t maximumResourcesContentSize = 100 * 1000 * 1000;
static size_t maximumSingleResourceContentSize = 10 * 1000 * 1000;
}
namespace WebCore {
PassRefPtr<XHRReplayData> XHRReplayData::create(ExecutionContext* executionContext, const AtomicString& method, const KURL& url, bool async, PassRefPtr<FormData> formData, bool includeCredentials)
{
return adoptRef(new XHRReplayData(executionContext, method, url, async, formData, includeCredentials));
}
void XHRReplayData::addHeader(const AtomicString& key, const AtomicString& value)
{
m_headers.set(key, value);
}
XHRReplayData::XHRReplayData(ExecutionContext* executionContext, const AtomicString& method, const KURL& url, bool async, PassRefPtr<FormData> formData, bool includeCredentials)
: ContextLifecycleObserver(executionContext)
, m_method(method)
, m_url(url)
, m_async(async)
, m_formData(formData)
, m_includeCredentials(includeCredentials)
{
}
NetworkResourcesData::ResourceData::ResourceData(const String& requestId, const String& loaderId)
: m_requestId(requestId)
, m_loaderId(loaderId)
, m_base64Encoded(false)
, m_isContentEvicted(false)
, m_type(InspectorPageAgent::OtherResource)
, m_cachedResource(0)
{
}
void NetworkResourcesData::ResourceData::setContent(const String& content, bool base64Encoded)
{
ASSERT(!hasData());
ASSERT(!hasContent());
m_content = content;
m_base64Encoded = base64Encoded;
}
static size_t contentSizeInBytes(const String& content)
{
return content.isNull() ? 0 : content.impl()->sizeInBytes();
}
unsigned NetworkResourcesData::ResourceData::removeContent()
{
unsigned result = 0;
if (hasData()) {
ASSERT(!hasContent());
result = m_dataBuffer->size();
m_dataBuffer = nullptr;
}
if (hasContent()) {
ASSERT(!hasData());
result = contentSizeInBytes(m_content);
m_content = String();
}
return result;
}
unsigned NetworkResourcesData::ResourceData::evictContent()
{
m_isContentEvicted = true;
return removeContent();
}
size_t NetworkResourcesData::ResourceData::dataLength() const
{
return m_dataBuffer ? m_dataBuffer->size() : 0;
}
void NetworkResourcesData::ResourceData::appendData(const char* data, size_t dataLength)
{
ASSERT(!hasContent());
if (!m_dataBuffer)
m_dataBuffer = SharedBuffer::create(data, dataLength);
else
m_dataBuffer->append(data, dataLength);
}
size_t NetworkResourcesData::ResourceData::decodeDataToContent()
{
ASSERT(!hasContent());
size_t dataLength = m_dataBuffer->size();
m_content = m_decoder->decode(m_dataBuffer->data(), m_dataBuffer->size());
m_content = m_content + m_decoder->flush();
m_dataBuffer = nullptr;
return contentSizeInBytes(m_content) - dataLength;
}
NetworkResourcesData::NetworkResourcesData()
: m_contentSize(0)
, m_maximumResourcesContentSize(maximumResourcesContentSize)
, m_maximumSingleResourceContentSize(maximumSingleResourceContentSize)
{
}
NetworkResourcesData::~NetworkResourcesData()
{
clear();
}
void NetworkResourcesData::resourceCreated(const String& requestId, const String& loaderId)
{
ensureNoDataForRequestId(requestId);
m_requestIdToResourceDataMap.set(requestId, new ResourceData(requestId, loaderId));
}
static PassOwnPtr<TextResourceDecoder> createOtherResourceTextDecoder(const String& mimeType, const String& textEncodingName)
{
OwnPtr<TextResourceDecoder> decoder;
if (!textEncodingName.isEmpty()) {
decoder = TextResourceDecoder::create("text/plain", textEncodingName);
} else if (DOMImplementation::isXMLMIMEType(mimeType)) {
decoder = TextResourceDecoder::create("application/xml");
decoder->useLenientXMLDecoding();
} else if (equalIgnoringCase(mimeType, "text/html")) {
decoder = TextResourceDecoder::create("text/html", "UTF-8");
} else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType) || DOMImplementation::isJSONMIMEType(mimeType)) {
decoder = TextResourceDecoder::create("text/plain", "UTF-8");
} else if (DOMImplementation::isTextMIMEType(mimeType)) {
decoder = TextResourceDecoder::create("text/plain", "ISO-8859-1");
}
return decoder.release();
}
void NetworkResourcesData::responseReceived(const String& requestId, const String& frameId, const ResourceResponse& response)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return;
resourceData->setFrameId(frameId);
resourceData->setUrl(response.url());
resourceData->setDecoder(createOtherResourceTextDecoder(response.mimeType(), response.textEncodingName()));
resourceData->setHTTPStatusCode(response.httpStatusCode());
}
void NetworkResourcesData::setResourceType(const String& requestId, InspectorPageAgent::ResourceType type)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return;
resourceData->setType(type);
}
InspectorPageAgent::ResourceType NetworkResourcesData::resourceType(const String& requestId)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return InspectorPageAgent::OtherResource;
return resourceData->type();
}
void NetworkResourcesData::setResourceContent(const String& requestId, const String& content, bool base64Encoded)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return;
size_t dataLength = contentSizeInBytes(content);
if (dataLength > m_maximumSingleResourceContentSize)
return;
if (resourceData->isContentEvicted())
return;
if (ensureFreeSpace(dataLength) && !resourceData->isContentEvicted()) {
if (resourceData->hasContent())
m_contentSize -= resourceData->removeContent();
m_requestIdsDeque.append(requestId);
resourceData->setContent(content, base64Encoded);
m_contentSize += dataLength;
}
}
void NetworkResourcesData::maybeAddResourceData(const String& requestId, const char* data, size_t dataLength)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return;
if (!resourceData->decoder())
return;
if (resourceData->dataLength() + dataLength > m_maximumSingleResourceContentSize)
m_contentSize -= resourceData->evictContent();
if (resourceData->isContentEvicted())
return;
if (ensureFreeSpace(dataLength) && !resourceData->isContentEvicted()) {
m_requestIdsDeque.append(requestId);
resourceData->appendData(data, dataLength);
m_contentSize += dataLength;
}
}
void NetworkResourcesData::maybeDecodeDataToContent(const String& requestId)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return;
if (!resourceData->hasData())
return;
m_contentSize += resourceData->decodeDataToContent();
size_t dataLength = contentSizeInBytes(resourceData->content());
if (dataLength > m_maximumSingleResourceContentSize)
m_contentSize -= resourceData->evictContent();
}
void NetworkResourcesData::addResource(const String& requestId, Resource* cachedResource)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return;
resourceData->setResource(cachedResource);
}
void NetworkResourcesData::addResourceSharedBuffer(const String& requestId, PassRefPtr<SharedBuffer> buffer, const String& textEncodingName)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return;
resourceData->setBuffer(buffer);
resourceData->setTextEncodingName(textEncodingName);
}
NetworkResourcesData::ResourceData const* NetworkResourcesData::data(const String& requestId)
{
return resourceDataForRequestId(requestId);
}
XHRReplayData* NetworkResourcesData::xhrReplayData(const String& requestId)
{
if (m_reusedXHRReplayDataRequestIds.contains(requestId))
return xhrReplayData(m_reusedXHRReplayDataRequestIds.get(requestId));
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return 0;
return resourceData->xhrReplayData();
}
void NetworkResourcesData::setXHRReplayData(const String& requestId, XHRReplayData* xhrReplayData)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData) {
Vector<String> result;
ReusedRequestIds::iterator it;
ReusedRequestIds::iterator end = m_reusedXHRReplayDataRequestIds.end();
for (it = m_reusedXHRReplayDataRequestIds.begin(); it != end; ++it) {
if (it->value == requestId)
setXHRReplayData(it->key, xhrReplayData);
}
return;
}
resourceData->setXHRReplayData(xhrReplayData);
}
void NetworkResourcesData::reuseXHRReplayData(const String& requestId, const String& reusedRequestId)
{
ResourceData* reusedResourceData = resourceDataForRequestId(reusedRequestId);
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!reusedResourceData || !resourceData) {
m_reusedXHRReplayDataRequestIds.set(requestId, reusedRequestId);
return;
}
resourceData->setXHRReplayData(reusedResourceData->xhrReplayData());
}
Vector<NetworkResourcesData::ResourceData*> NetworkResourcesData::resources()
{
Vector<ResourceData*> result;
for (ResourceDataMap::iterator it = m_requestIdToResourceDataMap.begin(); it != m_requestIdToResourceDataMap.end(); ++it)
result.append(it->value);
return result;
}
Vector<String> NetworkResourcesData::removeResource(Resource* cachedResource)
{
Vector<String> result;
ResourceDataMap::iterator it;
ResourceDataMap::iterator end = m_requestIdToResourceDataMap.end();
for (it = m_requestIdToResourceDataMap.begin(); it != end; ++it) {
ResourceData* resourceData = it->value;
if (resourceData->cachedResource() == cachedResource) {
resourceData->setResource(0);
result.append(it->key);
}
}
return result;
}
void NetworkResourcesData::clear(const String& preservedLoaderId)
{
m_requestIdsDeque.clear();
m_contentSize = 0;
ResourceDataMap preservedMap;
ResourceDataMap::iterator it;
ResourceDataMap::iterator end = m_requestIdToResourceDataMap.end();
for (it = m_requestIdToResourceDataMap.begin(); it != end; ++it) {
ResourceData* resourceData = it->value;
if (!preservedLoaderId.isNull() && resourceData->loaderId() == preservedLoaderId)
preservedMap.set(it->key, it->value);
else
delete resourceData;
}
m_requestIdToResourceDataMap.swap(preservedMap);
m_reusedXHRReplayDataRequestIds.clear();
}
void NetworkResourcesData::setResourcesDataSizeLimits(size_t maximumResourcesContentSize, size_t maximumSingleResourceContentSize)
{
clear();
m_maximumResourcesContentSize = maximumResourcesContentSize;
m_maximumSingleResourceContentSize = maximumSingleResourceContentSize;
}
NetworkResourcesData::ResourceData* NetworkResourcesData::resourceDataForRequestId(const String& requestId)
{
if (requestId.isNull())
return 0;
return m_requestIdToResourceDataMap.get(requestId);
}
void NetworkResourcesData::ensureNoDataForRequestId(const String& requestId)
{
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (!resourceData)
return;
if (resourceData->hasContent() || resourceData->hasData())
m_contentSize -= resourceData->evictContent();
delete resourceData;
m_requestIdToResourceDataMap.remove(requestId);
}
bool NetworkResourcesData::ensureFreeSpace(size_t size)
{
if (size > m_maximumResourcesContentSize)
return false;
while (size > m_maximumResourcesContentSize - m_contentSize) {
String requestId = m_requestIdsDeque.takeFirst();
ResourceData* resourceData = resourceDataForRequestId(requestId);
if (resourceData)
m_contentSize -= resourceData->evictContent();
}
return true;
}
}