2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "NetworkResourcesData.h"
35 #include "DOMImplementation.h"
36 #include "SharedBuffer.h"
37 #include "TextResourceDecoder.h"
41 static size_t maximumResourcesContentSize = 100 * 1000 * 1000;
44 static size_t maximumSingleResourceContentSize = 10 * 1000 * 1000;
51 NetworkResourcesData::ResourceData::ResourceData(const String& requestId, const String& loaderId)
52 : m_requestId(requestId)
53 , m_loaderId(loaderId)
54 , m_base64Encoded(false)
55 , m_isContentPurged(false)
56 , m_type(InspectorPageAgent::OtherResource)
61 void NetworkResourcesData::ResourceData::setContent(const String& content, bool base64Encoded)
64 ASSERT(!hasContent());
66 m_base64Encoded = base64Encoded;
69 unsigned NetworkResourcesData::ResourceData::removeContent()
73 ASSERT(!hasContent());
74 result = m_dataBuffer->size();
75 m_dataBuffer = nullptr;
80 result = 2 * m_content.length();
86 unsigned NetworkResourcesData::ResourceData::purgeContent()
88 m_isContentPurged = true;
89 return removeContent();
92 size_t NetworkResourcesData::ResourceData::dataLength() const
94 return m_dataBuffer ? m_dataBuffer->size() : 0;
97 void NetworkResourcesData::ResourceData::appendData(const char* data, size_t dataLength)
99 ASSERT(!hasContent());
101 m_dataBuffer = SharedBuffer::create(data, dataLength);
103 m_dataBuffer->append(data, dataLength);
106 size_t NetworkResourcesData::ResourceData::decodeDataToContent()
108 ASSERT(!hasContent());
109 size_t dataLength = m_dataBuffer->size();
110 m_content = m_decoder->decode(m_dataBuffer->data(), m_dataBuffer->size());
111 m_content += m_decoder->flush();
112 m_dataBuffer = nullptr;
113 return 2 * m_content.length() - dataLength;
116 // NetworkResourcesData
117 NetworkResourcesData::NetworkResourcesData()
119 , m_maximumResourcesContentSize(maximumResourcesContentSize)
120 , m_maximumSingleResourceContentSize(maximumSingleResourceContentSize)
124 NetworkResourcesData::~NetworkResourcesData()
129 void NetworkResourcesData::resourceCreated(const String& requestId, const String& loaderId)
131 ensureNoDataForRequestId(requestId);
132 m_requestIdToResourceDataMap.set(requestId, new ResourceData(requestId, loaderId));
135 static PassRefPtr<TextResourceDecoder> createOtherResourceTextDecoder(const String& mimeType, const String& textEncodingName)
137 RefPtr<TextResourceDecoder> decoder;
138 if (!textEncodingName.isEmpty())
139 decoder = TextResourceDecoder::create("text/plain", textEncodingName);
140 else if (DOMImplementation::isXMLMIMEType(mimeType.lower())) {
141 decoder = TextResourceDecoder::create("application/xml");
142 decoder->useLenientXMLDecoding();
143 } else if (equalIgnoringCase(mimeType, "text/html"))
144 decoder = TextResourceDecoder::create("text/html", "UTF-8");
145 else if (mimeType == "text/plain")
146 decoder = TextResourceDecoder::create("text/plain", "ISO-8859-1");
150 void NetworkResourcesData::responseReceived(const String& requestId, const String& frameId, const ResourceResponse& response)
152 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
155 resourceData->setFrameId(frameId);
156 resourceData->setUrl(response.url());
157 resourceData->setDecoder(createOtherResourceTextDecoder(response.mimeType(), response.textEncodingName()));
158 resourceData->setHTTPStatusCode(response.httpStatusCode());
161 void NetworkResourcesData::setResourceType(const String& requestId, InspectorPageAgent::ResourceType type)
163 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
166 resourceData->setType(type);
169 InspectorPageAgent::ResourceType NetworkResourcesData::resourceType(const String& requestId)
171 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
173 return InspectorPageAgent::OtherResource;
174 return resourceData->type();
177 void NetworkResourcesData::setResourceContent(const String& requestId, const String& content, bool base64Encoded)
179 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
182 size_t dataLength = 2 * content.length();
183 if (dataLength > m_maximumSingleResourceContentSize)
185 if (resourceData->isContentPurged())
187 if (ensureFreeSpace(dataLength) && !resourceData->isContentPurged()) {
188 // We can not be sure that we didn't try to save this request data while it was loading, so remove it, if any.
189 if (resourceData->hasContent())
190 m_contentSize -= resourceData->removeContent();
191 m_requestIdsDeque.append(requestId);
192 resourceData->setContent(content, base64Encoded);
193 m_contentSize += dataLength;
197 void NetworkResourcesData::maybeAddResourceData(const String& requestId, const char* data, size_t dataLength)
199 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
202 if (!resourceData->decoder())
204 if (resourceData->dataLength() + dataLength > m_maximumSingleResourceContentSize)
205 m_contentSize -= resourceData->purgeContent();
206 if (resourceData->isContentPurged())
208 if (ensureFreeSpace(dataLength) && !resourceData->isContentPurged()) {
209 m_requestIdsDeque.append(requestId);
210 resourceData->appendData(data, dataLength);
211 m_contentSize += dataLength;
215 void NetworkResourcesData::maybeDecodeDataToContent(const String& requestId)
217 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
220 if (!resourceData->hasData())
222 m_contentSize += resourceData->decodeDataToContent();
223 size_t dataLength = 2 * resourceData->content().length();
224 if (dataLength > m_maximumSingleResourceContentSize)
225 m_contentSize -= resourceData->purgeContent();
228 void NetworkResourcesData::addCachedResource(const String& requestId, CachedResource* cachedResource)
230 if (!m_requestIdToResourceDataMap.contains(requestId))
232 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
234 resourceData->setCachedResource(cachedResource);
237 void NetworkResourcesData::addResourceSharedBuffer(const String& requestId, PassRefPtr<SharedBuffer> buffer, const String& textEncodingName)
239 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
242 resourceData->setBuffer(buffer);
243 resourceData->setTextEncodingName(textEncodingName);
246 NetworkResourcesData::ResourceData const* NetworkResourcesData::data(const String& requestId)
248 return m_requestIdToResourceDataMap.get(requestId);
251 Vector<String> NetworkResourcesData::removeCachedResource(CachedResource* cachedResource)
253 Vector<String> result;
254 ResourceDataMap::iterator it;
255 ResourceDataMap::iterator end = m_requestIdToResourceDataMap.end();
256 for (it = m_requestIdToResourceDataMap.begin(); it != end; ++it) {
257 ResourceData* resourceData = it->second;
258 if (resourceData->cachedResource() == cachedResource) {
259 resourceData->setCachedResource(0);
260 result.append(it->first);
267 void NetworkResourcesData::clear(const String& preservedLoaderId)
269 m_requestIdsDeque.clear();
272 ResourceDataMap preservedMap;
274 ResourceDataMap::iterator it;
275 ResourceDataMap::iterator end = m_requestIdToResourceDataMap.end();
276 for (it = m_requestIdToResourceDataMap.begin(); it != end; ++it) {
277 ResourceData* resourceData = it->second;
278 if (!preservedLoaderId.isNull() && resourceData->loaderId() == preservedLoaderId)
279 preservedMap.set(it->first, it->second);
283 m_requestIdToResourceDataMap.swap(preservedMap);
286 void NetworkResourcesData::setResourcesDataSizeLimits(size_t maximumResourcesContentSize, size_t maximumSingleResourceContentSize)
289 m_maximumResourcesContentSize = maximumResourcesContentSize;
290 m_maximumSingleResourceContentSize = maximumSingleResourceContentSize;
294 void NetworkResourcesData::ensureNoDataForRequestId(const String& requestId)
296 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
298 if (resourceData->hasContent() || resourceData->hasData())
299 m_contentSize -= resourceData->purgeContent();
301 m_requestIdToResourceDataMap.remove(requestId);
305 bool NetworkResourcesData::ensureFreeSpace(size_t size)
307 if (size > m_maximumResourcesContentSize)
310 while (size > m_maximumResourcesContentSize - m_contentSize) {
311 String requestId = m_requestIdsDeque.takeFirst();
312 ResourceData* resourceData = m_requestIdToResourceDataMap.get(requestId);
314 m_contentSize -= resourceData->purgeContent();
319 } // namespace WebCore
321 #endif // ENABLE(INSPECTOR)