This source file includes following definitions.
- buildObjectForHeaders
- m_statusCode
- didReceiveResponse
- didReceiveData
- didFinishLoading
- didFail
- didFailRedirectCheck
- didFailLoaderCreation
- setLoader
- dispose
- urlWithoutFragment
- setFrontend
- clearFrontend
- restore
- buildObjectForTiming
- buildObjectForResourceRequest
- buildObjectForResourceResponse
- willSendRequest
- markResourceAsCached
- didReceiveResourceResponse
- isErrorStatusCode
- didReceiveData
- didFinishLoading
- didReceiveCORSRedirectResponse
- didFailLoading
- scriptImported
- didReceiveScriptResponse
- documentThreadableLoaderStartedLoadingForClient
- willLoadXHR
- didFailXHRLoading
- didFinishXHRLoading
- willDestroyResource
- applyUserAgentOverride
- willRecalculateStyle
- didRecalculateStyle
- didScheduleStyleRecalculation
- buildInitiatorObject
- didCreateWebSocket
- willSendWebSocketHandshakeRequest
- didReceiveWebSocketHandshakeResponse
- didCloseWebSocket
- didReceiveWebSocketFrame
- didSendWebSocketFrame
- didReceiveWebSocketFrameError
- setResourcesDataSizeLimitsFromInternals
- enable
- enable
- disable
- setUserAgentOverride
- setExtraHTTPHeaders
- getResponseBody
- replayXHR
- canClearBrowserCache
- clearBrowserCache
- canClearBrowserCookies
- clearBrowserCookies
- setCacheDisabled
- loadResourceForFrontend
- didCommitLoad
- frameScheduledNavigation
- frameClearedScheduledNavigation
- fetchResourceContent
- m_isRecalculatingStyle
#include "config.h"
#include "core/inspector/InspectorResourceAgent.h"
#include "FetchInitiatorTypeNames.h"
#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "bindings/v8/ScriptCallStackFactory.h"
#include "core/dom/Document.h"
#include "core/dom/ScriptableDocumentParser.h"
#include "core/fetch/FetchInitiatorInfo.h"
#include "core/fetch/MemoryCache.h"
#include "core/fetch/Resource.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/fetch/ResourceLoader.h"
#include "core/frame/LocalFrame.h"
#include "core/inspector/IdentifiersFactory.h"
#include "core/inspector/InspectorClient.h"
#include "core/inspector/InspectorOverlay.h"
#include "core/inspector/InspectorPageAgent.h"
#include "core/inspector/InspectorState.h"
#include "core/inspector/InstrumentingAgents.h"
#include "core/inspector/NetworkResourcesData.h"
#include "core/inspector/ScriptCallStack.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/DocumentThreadableLoader.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/ThreadableLoader.h"
#include "core/loader/ThreadableLoaderClient.h"
#include "core/page/Page.h"
#include "core/xml/XMLHttpRequest.h"
#include "platform/JSONValues.h"
#include "platform/network/HTTPHeaderMap.h"
#include "platform/network/ResourceError.h"
#include "platform/network/ResourceRequest.h"
#include "platform/network/ResourceResponse.h"
#include "platform/network/WebSocketHandshakeRequest.h"
#include "platform/network/WebSocketHandshakeResponse.h"
#include "platform/weborigin/KURL.h"
#include "wtf/CurrentTime.h"
#include "wtf/RefPtr.h"
typedef WebCore::InspectorBackendDispatcher::NetworkCommandHandler::LoadResourceForFrontendCallback LoadResourceForFrontendCallback;
namespace WebCore {
namespace ResourceAgentState {
static const char resourceAgentEnabled[] = "resourceAgentEnabled";
static const char extraRequestHeaders[] = "extraRequestHeaders";
static const char cacheDisabled[] = "cacheDisabled";
static const char userAgentOverride[] = "userAgentOverride";
}
namespace {
static PassRefPtr<JSONObject> buildObjectForHeaders(const HTTPHeaderMap& headers)
{
RefPtr<JSONObject> headersObject = JSONObject::create();
HTTPHeaderMap::const_iterator end = headers.end();
for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
headersObject->setString(it->key.string(), it->value);
return headersObject;
}
class InspectorThreadableLoaderClient FINAL : public ThreadableLoaderClient {
WTF_MAKE_NONCOPYABLE(InspectorThreadableLoaderClient);
public:
InspectorThreadableLoaderClient(PassRefPtr<LoadResourceForFrontendCallback> callback)
: m_callback(callback)
, m_statusCode(0) { }
virtual ~InspectorThreadableLoaderClient() { }
virtual void didReceiveResponse(unsigned long identifier, const ResourceResponse& response) OVERRIDE
{
WTF::TextEncoding textEncoding(response.textEncodingName());
bool useDetector = false;
if (!textEncoding.isValid()) {
textEncoding = UTF8Encoding();
useDetector = true;
}
m_decoder = TextResourceDecoder::create("text/plain", textEncoding, useDetector);
m_statusCode = response.httpStatusCode();
m_responseHeaders = response.httpHeaderFields();
}
virtual void didReceiveData(const char* data, int dataLength) OVERRIDE
{
if (!dataLength)
return;
if (dataLength == -1)
dataLength = strlen(data);
m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, dataLength));
}
virtual void didFinishLoading(unsigned long , double ) OVERRIDE
{
if (m_decoder)
m_responseText = m_responseText.concatenateWith(m_decoder->flush());
m_callback->sendSuccess(m_statusCode, buildObjectForHeaders(m_responseHeaders), m_responseText.flattenToString());
dispose();
}
virtual void didFail(const ResourceError&) OVERRIDE
{
m_callback->sendFailure("Loading resource for inspector failed");
dispose();
}
virtual void didFailRedirectCheck() OVERRIDE
{
m_callback->sendFailure("Loading resource for inspector failed redirect check");
dispose();
}
void didFailLoaderCreation()
{
m_callback->sendFailure("Couldn't create a loader");
dispose();
}
void setLoader(PassRefPtr<ThreadableLoader> loader)
{
m_loader = loader;
}
private:
void dispose()
{
m_loader = nullptr;
delete this;
}
RefPtr<LoadResourceForFrontendCallback> m_callback;
RefPtr<ThreadableLoader> m_loader;
OwnPtr<TextResourceDecoder> m_decoder;
ScriptString m_responseText;
int m_statusCode;
HTTPHeaderMap m_responseHeaders;
};
KURL urlWithoutFragment(const KURL& url)
{
KURL result = url;
result.removeFragmentIdentifier();
return result;
}
}
void InspectorResourceAgent::setFrontend(InspectorFrontend* frontend)
{
m_frontend = frontend->network();
}
void InspectorResourceAgent::clearFrontend()
{
m_frontend = 0;
ErrorString error;
disable(&error);
}
void InspectorResourceAgent::restore()
{
if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled))
enable();
}
static PassRefPtr<TypeBuilder::Network::ResourceTiming> buildObjectForTiming(const ResourceLoadTiming& timing, DocumentLoader* loader)
{
return TypeBuilder::Network::ResourceTiming::create()
.setRequestTime(loader->timing()->monotonicTimeToPseudoWallTime(timing.requestTime))
.setProxyStart(timing.calculateMillisecondDelta(timing.proxyStart))
.setProxyEnd(timing.calculateMillisecondDelta(timing.proxyEnd))
.setDnsStart(timing.calculateMillisecondDelta(timing.dnsStart))
.setDnsEnd(timing.calculateMillisecondDelta(timing.dnsEnd))
.setConnectStart(timing.calculateMillisecondDelta(timing.connectStart))
.setConnectEnd(timing.calculateMillisecondDelta(timing.connectEnd))
.setSslStart(timing.calculateMillisecondDelta(timing.sslStart))
.setSslEnd(timing.calculateMillisecondDelta(timing.sslEnd))
.setSendStart(timing.calculateMillisecondDelta(timing.sendStart))
.setSendEnd(timing.calculateMillisecondDelta(timing.sendEnd))
.setReceiveHeadersEnd(timing.calculateMillisecondDelta(timing.receiveHeadersEnd))
.release();
}
static PassRefPtr<TypeBuilder::Network::Request> buildObjectForResourceRequest(const ResourceRequest& request)
{
RefPtr<TypeBuilder::Network::Request> requestObject = TypeBuilder::Network::Request::create()
.setUrl(urlWithoutFragment(request.url()).string())
.setMethod(request.httpMethod())
.setHeaders(buildObjectForHeaders(request.httpHeaderFields()));
if (request.httpBody() && !request.httpBody()->isEmpty()) {
Vector<char> bytes;
request.httpBody()->flatten(bytes);
requestObject->setPostData(String::fromUTF8WithLatin1Fallback(bytes.data(), bytes.size()));
}
return requestObject;
}
static PassRefPtr<TypeBuilder::Network::Response> buildObjectForResourceResponse(const ResourceResponse& response, DocumentLoader* loader)
{
if (response.isNull())
return nullptr;
double status;
String statusText;
if (response.resourceLoadInfo() && response.resourceLoadInfo()->httpStatusCode) {
status = response.resourceLoadInfo()->httpStatusCode;
statusText = response.resourceLoadInfo()->httpStatusText;
} else {
status = response.httpStatusCode();
statusText = response.httpStatusText();
}
RefPtr<JSONObject> headers;
if (response.resourceLoadInfo())
headers = buildObjectForHeaders(response.resourceLoadInfo()->responseHeaders);
else
headers = buildObjectForHeaders(response.httpHeaderFields());
int64_t encodedDataLength = response.resourceLoadInfo() ? response.resourceLoadInfo()->encodedDataLength : -1;
RefPtr<TypeBuilder::Network::Response> responseObject = TypeBuilder::Network::Response::create()
.setUrl(urlWithoutFragment(response.url()).string())
.setStatus(status)
.setStatusText(statusText)
.setHeaders(headers)
.setMimeType(response.mimeType())
.setConnectionReused(response.connectionReused())
.setConnectionId(response.connectionID())
.setEncodedDataLength(encodedDataLength);
responseObject->setFromDiskCache(response.wasCached());
if (response.resourceLoadTiming())
responseObject->setTiming(buildObjectForTiming(*response.resourceLoadTiming(), loader));
if (response.resourceLoadInfo()) {
if (!response.resourceLoadInfo()->responseHeadersText.isEmpty())
responseObject->setHeadersText(response.resourceLoadInfo()->responseHeadersText);
responseObject->setRequestHeaders(buildObjectForHeaders(response.resourceLoadInfo()->requestHeaders));
if (!response.resourceLoadInfo()->requestHeadersText.isEmpty())
responseObject->setRequestHeadersText(response.resourceLoadInfo()->requestHeadersText);
}
AtomicString remoteIPAddress = response.remoteIPAddress();
if (!remoteIPAddress.isEmpty()) {
responseObject->setRemoteIPAddress(remoteIPAddress);
responseObject->setRemotePort(response.remotePort());
}
return responseObject;
}
InspectorResourceAgent::~InspectorResourceAgent()
{
if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled)) {
ErrorString error;
disable(&error);
}
ASSERT(!m_instrumentingAgents->inspectorResourceAgent());
}
void InspectorResourceAgent::willSendRequest(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse, const FetchInitiatorInfo& initiatorInfo)
{
if (initiatorInfo.name == FetchInitiatorTypeNames::internal)
return;
String requestId = IdentifiersFactory::requestId(identifier);
m_resourcesData->resourceCreated(requestId, m_pageAgent->loaderId(loader));
RefPtr<JSONObject> headers = m_state->getObject(ResourceAgentState::extraRequestHeaders);
if (headers) {
JSONObject::const_iterator end = headers->end();
for (JSONObject::const_iterator it = headers->begin(); it != end; ++it) {
String value;
if (it->value->asString(&value))
request.setHTTPHeaderField(AtomicString(it->key), AtomicString(value));
}
}
request.setReportLoadTiming(true);
request.setReportRawHeaders(true);
if (m_state->getBoolean(ResourceAgentState::cacheDisabled)) {
request.setHTTPHeaderField("Pragma", "no-cache");
request.setCachePolicy(ReloadIgnoringCacheData);
request.setHTTPHeaderField("Cache-Control", "no-cache");
}
String frameId = m_pageAgent->frameId(loader->frame());
RefPtr<TypeBuilder::Network::Initiator> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : 0, initiatorInfo);
if (initiatorInfo.name == FetchInitiatorTypeNames::document) {
FrameNavigationInitiatorMap::iterator it = m_frameNavigationInitiatorMap.find(frameId);
if (it != m_frameNavigationInitiatorMap.end())
initiatorObject = it->value;
}
m_frontend->requestWillBeSent(requestId, frameId, m_pageAgent->loaderId(loader), urlWithoutFragment(loader->url()).string(), buildObjectForResourceRequest(request), currentTime(), initiatorObject, buildObjectForResourceResponse(redirectResponse, loader));
}
void InspectorResourceAgent::markResourceAsCached(unsigned long identifier)
{
m_frontend->requestServedFromCache(IdentifiersFactory::requestId(identifier));
}
void InspectorResourceAgent::didReceiveResourceResponse(LocalFrame* frame, unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader)
{
if (!loader)
return;
String requestId = IdentifiersFactory::requestId(identifier);
RefPtr<TypeBuilder::Network::Response> resourceResponse = buildObjectForResourceResponse(response, loader);
bool isNotModified = response.httpStatusCode() == 304;
Resource* cachedResource = 0;
if (resourceLoader && !isNotModified)
cachedResource = resourceLoader->cachedResource();
if (!cachedResource || cachedResource->type() == Resource::MainResource)
cachedResource = InspectorPageAgent::cachedResource(loader->frame(), response.url());
if (cachedResource) {
if (resourceResponse && response.mimeType().isEmpty())
resourceResponse->setString(TypeBuilder::Network::Response::MimeType, cachedResource->response().mimeType());
m_resourcesData->addResource(requestId, cachedResource);
}
InspectorPageAgent::ResourceType type = cachedResource ? InspectorPageAgent::cachedResourceType(*cachedResource) : InspectorPageAgent::OtherResource;
if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::ScriptResource)
type = InspectorPageAgent::ScriptResource;
if (equalIgnoringFragmentIdentifier(response.url(), loader->url()) && !loader->isCommitted())
type = InspectorPageAgent::DocumentResource;
m_resourcesData->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), response);
m_resourcesData->setResourceType(requestId, type);
m_frontend->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), currentTime(), InspectorPageAgent::resourceTypeJson(type), resourceResponse);
if (isNotModified && cachedResource && cachedResource->encodedSize())
didReceiveData(frame, identifier, 0, cachedResource->encodedSize(), 0);
}
static bool isErrorStatusCode(int statusCode)
{
return statusCode >= 400;
}
void InspectorResourceAgent::didReceiveData(LocalFrame*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength)
{
String requestId = IdentifiersFactory::requestId(identifier);
if (data) {
NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
if (resourceData && (!resourceData->cachedResource() || resourceData->cachedResource()->dataBufferingPolicy() == DoNotBufferData || isErrorStatusCode(resourceData->httpStatusCode())))
m_resourcesData->maybeAddResourceData(requestId, data, dataLength);
}
m_frontend->dataReceived(requestId, currentTime(), dataLength, encodedDataLength);
}
void InspectorResourceAgent::didFinishLoading(unsigned long identifier, DocumentLoader* loader, double monotonicFinishTime, int64_t encodedDataLength)
{
double finishTime = 0.0;
if (monotonicFinishTime)
finishTime = loader->timing()->monotonicTimeToPseudoWallTime(monotonicFinishTime);
String requestId = IdentifiersFactory::requestId(identifier);
m_resourcesData->maybeDecodeDataToContent(requestId);
if (!finishTime)
finishTime = currentTime();
m_frontend->loadingFinished(requestId, finishTime, encodedDataLength);
}
void InspectorResourceAgent::didReceiveCORSRedirectResponse(LocalFrame* frame, unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader)
{
didReceiveResourceResponse(frame, identifier, loader, response, resourceLoader);
didFinishLoading(identifier, loader, 0, blink::WebURLLoaderClient::kUnknownEncodedDataLength);
}
void InspectorResourceAgent::didFailLoading(unsigned long identifier, const ResourceError& error)
{
String requestId = IdentifiersFactory::requestId(identifier);
bool canceled = error.isCancellation();
m_frontend->loadingFailed(requestId, currentTime(), error.localizedDescription(), canceled ? &canceled : 0);
}
void InspectorResourceAgent::scriptImported(unsigned long identifier, const String& sourceString)
{
m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString);
}
void InspectorResourceAgent::didReceiveScriptResponse(unsigned long identifier)
{
m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::ScriptResource);
}
void InspectorResourceAgent::documentThreadableLoaderStartedLoadingForClient(unsigned long identifier, ThreadableLoaderClient* client)
{
if (!client)
return;
PendingXHRReplayDataMap::iterator it = m_pendingXHRReplayData.find(client);
if (it == m_pendingXHRReplayData.end())
return;
XHRReplayData* xhrReplayData = it->value.get();
String requestId = IdentifiersFactory::requestId(identifier);
m_resourcesData->setXHRReplayData(requestId, xhrReplayData);
}
void InspectorResourceAgent::willLoadXHR(XMLHttpRequest* xhr, ThreadableLoaderClient* client, const AtomicString& method, const KURL& url, bool async, FormData* formData, const HTTPHeaderMap& headers, bool includeCredentials)
{
ASSERT(xhr);
RefPtr<XHRReplayData> xhrReplayData = XHRReplayData::create(xhr->executionContext(), method, urlWithoutFragment(url), async, formData, includeCredentials);
HTTPHeaderMap::const_iterator end = headers.end();
for (HTTPHeaderMap::const_iterator it = headers.begin(); it!= end; ++it)
xhrReplayData->addHeader(it->key, it->value);
m_pendingXHRReplayData.set(client, xhrReplayData);
}
void InspectorResourceAgent::didFailXHRLoading(XMLHttpRequest*, ThreadableLoaderClient* client)
{
m_pendingXHRReplayData.remove(client);
}
void InspectorResourceAgent::didFinishXHRLoading(XMLHttpRequest*, ThreadableLoaderClient* client, unsigned long identifier, ScriptString sourceString, const AtomicString&, const String&, const String&, unsigned)
{
m_pendingXHRReplayData.remove(client);
}
void InspectorResourceAgent::willDestroyResource(Resource* cachedResource)
{
Vector<String> requestIds = m_resourcesData->removeResource(cachedResource);
if (!requestIds.size())
return;
String content;
bool base64Encoded;
if (!InspectorPageAgent::cachedResourceContent(cachedResource, &content, &base64Encoded))
return;
Vector<String>::iterator end = requestIds.end();
for (Vector<String>::iterator it = requestIds.begin(); it != end; ++it)
m_resourcesData->setResourceContent(*it, content, base64Encoded);
}
void InspectorResourceAgent::applyUserAgentOverride(String* userAgent)
{
String userAgentOverride = m_state->getString(ResourceAgentState::userAgentOverride);
if (!userAgentOverride.isEmpty())
*userAgent = userAgentOverride;
}
void InspectorResourceAgent::willRecalculateStyle(Document*)
{
m_isRecalculatingStyle = true;
}
void InspectorResourceAgent::didRecalculateStyle()
{
m_isRecalculatingStyle = false;
m_styleRecalculationInitiator = nullptr;
}
void InspectorResourceAgent::didScheduleStyleRecalculation(Document* document)
{
if (!m_styleRecalculationInitiator)
m_styleRecalculationInitiator = buildInitiatorObject(document, FetchInitiatorInfo());
}
PassRefPtr<TypeBuilder::Network::Initiator> InspectorResourceAgent::buildInitiatorObject(Document* document, const FetchInitiatorInfo& initiatorInfo)
{
RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
if (stackTrace && stackTrace->size() > 0) {
RefPtr<TypeBuilder::Network::Initiator> initiatorObject = TypeBuilder::Network::Initiator::create()
.setType(TypeBuilder::Network::Initiator::Type::Script);
initiatorObject->setStackTrace(stackTrace->buildInspectorArray());
return initiatorObject;
}
if (document && document->scriptableDocumentParser()) {
RefPtr<TypeBuilder::Network::Initiator> initiatorObject = TypeBuilder::Network::Initiator::create()
.setType(TypeBuilder::Network::Initiator::Type::Parser);
initiatorObject->setUrl(urlWithoutFragment(document->url()).string());
if (TextPosition::belowRangePosition() != initiatorInfo.position)
initiatorObject->setLineNumber(initiatorInfo.position.m_line.oneBasedInt());
else
initiatorObject->setLineNumber(document->scriptableDocumentParser()->lineNumber().oneBasedInt());
return initiatorObject;
}
if (m_isRecalculatingStyle && m_styleRecalculationInitiator)
return m_styleRecalculationInitiator;
return TypeBuilder::Network::Initiator::create()
.setType(TypeBuilder::Network::Initiator::Type::Other)
.release();
}
void InspectorResourceAgent::didCreateWebSocket(Document*, unsigned long identifier, const KURL& requestURL, const String&)
{
m_frontend->webSocketCreated(IdentifiersFactory::requestId(identifier), urlWithoutFragment(requestURL).string());
}
void InspectorResourceAgent::willSendWebSocketHandshakeRequest(Document*, unsigned long identifier, const WebSocketHandshakeRequest* request)
{
ASSERT(request);
RefPtr<TypeBuilder::Network::WebSocketRequest> requestObject = TypeBuilder::Network::WebSocketRequest::create()
.setHeaders(buildObjectForHeaders(request->headerFields()));
m_frontend->webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), currentTime(), requestObject);
}
void InspectorResourceAgent::didReceiveWebSocketHandshakeResponse(Document*, unsigned long identifier, const WebSocketHandshakeRequest* request, const WebSocketHandshakeResponse* response)
{
ASSERT(response);
RefPtr<TypeBuilder::Network::WebSocketResponse> responseObject = TypeBuilder::Network::WebSocketResponse::create()
.setStatus(response->statusCode())
.setStatusText(response->statusText())
.setHeaders(buildObjectForHeaders(response->headerFields()));
if (!response->headersText().isEmpty())
responseObject->setHeadersText(response->headersText());
if (request) {
responseObject->setRequestHeaders(buildObjectForHeaders(request->headerFields()));
if (!request->headersText().isEmpty())
responseObject->setRequestHeadersText(request->headersText());
}
m_frontend->webSocketHandshakeResponseReceived(IdentifiersFactory::requestId(identifier), currentTime(), responseObject);
}
void InspectorResourceAgent::didCloseWebSocket(Document*, unsigned long identifier)
{
m_frontend->webSocketClosed(IdentifiersFactory::requestId(identifier), currentTime());
}
void InspectorResourceAgent::didReceiveWebSocketFrame(unsigned long identifier, int opCode, bool masked, const char* payload, size_t payloadLength)
{
RefPtr<TypeBuilder::Network::WebSocketFrame> frameObject = TypeBuilder::Network::WebSocketFrame::create()
.setOpcode(opCode)
.setMask(masked)
.setPayloadData(String(payload, payloadLength));
m_frontend->webSocketFrameReceived(IdentifiersFactory::requestId(identifier), currentTime(), frameObject);
}
void InspectorResourceAgent::didSendWebSocketFrame(unsigned long identifier, int opCode, bool masked, const char* payload, size_t payloadLength)
{
RefPtr<TypeBuilder::Network::WebSocketFrame> frameObject = TypeBuilder::Network::WebSocketFrame::create()
.setOpcode(opCode)
.setMask(masked)
.setPayloadData(String(payload, payloadLength));
m_frontend->webSocketFrameSent(IdentifiersFactory::requestId(identifier), currentTime(), frameObject);
}
void InspectorResourceAgent::didReceiveWebSocketFrameError(unsigned long identifier, const String& errorMessage)
{
m_frontend->webSocketFrameError(IdentifiersFactory::requestId(identifier), currentTime(), errorMessage);
}
void InspectorResourceAgent::setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize)
{
m_resourcesData->setResourcesDataSizeLimits(maximumResourcesContentSize, maximumSingleResourceContentSize);
}
void InspectorResourceAgent::enable(ErrorString*)
{
enable();
}
void InspectorResourceAgent::enable()
{
if (!m_frontend)
return;
m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, true);
m_instrumentingAgents->setInspectorResourceAgent(this);
}
void InspectorResourceAgent::disable(ErrorString*)
{
m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, false);
m_state->setString(ResourceAgentState::userAgentOverride, "");
m_instrumentingAgents->setInspectorResourceAgent(0);
m_resourcesData->clear();
}
void InspectorResourceAgent::setUserAgentOverride(ErrorString*, const String& userAgent)
{
m_state->setString(ResourceAgentState::userAgentOverride, userAgent);
}
void InspectorResourceAgent::setExtraHTTPHeaders(ErrorString*, const RefPtr<JSONObject>& headers)
{
m_state->setObject(ResourceAgentState::extraRequestHeaders, headers);
}
void InspectorResourceAgent::getResponseBody(ErrorString* errorString, const String& requestId, String* content, bool* base64Encoded)
{
NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
if (!resourceData) {
*errorString = "No resource with given identifier found";
return;
}
if (resourceData->hasContent()) {
*base64Encoded = resourceData->base64Encoded();
*content = resourceData->content();
return;
}
if (resourceData->isContentEvicted()) {
*errorString = "Request content was evicted from inspector cache";
return;
}
if (resourceData->buffer() && !resourceData->textEncodingName().isNull()) {
*base64Encoded = false;
if (InspectorPageAgent::sharedBufferContent(resourceData->buffer(), resourceData->textEncodingName(), *base64Encoded, content))
return;
}
if (resourceData->cachedResource()) {
if (InspectorPageAgent::cachedResourceContent(resourceData->cachedResource(), content, base64Encoded))
return;
}
*errorString = "No data found for resource with given identifier";
}
void InspectorResourceAgent::replayXHR(ErrorString*, const String& requestId)
{
String actualRequestId = requestId;
XHRReplayData* xhrReplayData = m_resourcesData->xhrReplayData(requestId);
if (!xhrReplayData)
return;
ExecutionContext* executionContext = xhrReplayData->executionContext();
if (!executionContext) {
m_resourcesData->setXHRReplayData(requestId, 0);
return;
}
RefPtrWillBeRawPtr<XMLHttpRequest> xhr = XMLHttpRequest::create(executionContext);
Resource* cachedResource = memoryCache()->resourceForURL(xhrReplayData->url());
if (cachedResource)
memoryCache()->remove(cachedResource);
xhr->open(xhrReplayData->method(), xhrReplayData->url(), xhrReplayData->async(), IGNORE_EXCEPTION);
HTTPHeaderMap::const_iterator end = xhrReplayData->headers().end();
for (HTTPHeaderMap::const_iterator it = xhrReplayData->headers().begin(); it!= end; ++it)
xhr->setRequestHeader(it->key, it->value, IGNORE_EXCEPTION);
xhr->sendForInspectorXHRReplay(xhrReplayData->formData(), IGNORE_EXCEPTION);
}
void InspectorResourceAgent::canClearBrowserCache(ErrorString*, bool* result)
{
*result = true;
}
void InspectorResourceAgent::clearBrowserCache(ErrorString*)
{
m_client->clearBrowserCache();
}
void InspectorResourceAgent::canClearBrowserCookies(ErrorString*, bool* result)
{
*result = true;
}
void InspectorResourceAgent::clearBrowserCookies(ErrorString*)
{
m_client->clearBrowserCookies();
}
void InspectorResourceAgent::setCacheDisabled(ErrorString*, bool cacheDisabled)
{
m_state->setBoolean(ResourceAgentState::cacheDisabled, cacheDisabled);
if (cacheDisabled)
memoryCache()->evictResources();
for (LocalFrame* frame = m_pageAgent->mainFrame(); frame; frame = frame->tree().traverseNext())
frame->document()->fetcher()->garbageCollectDocumentResources();
}
void InspectorResourceAgent::loadResourceForFrontend(ErrorString* errorString, const String& frameId, const String& url, const RefPtr<JSONObject>* requestHeaders, PassRefPtr<LoadResourceForFrontendCallback> prpCallback)
{
RefPtr<LoadResourceForFrontendCallback> callback = prpCallback;
LocalFrame* frame = m_pageAgent->assertFrame(errorString, frameId);
if (!frame)
return;
Document* document = frame->document();
if (!document) {
*errorString = "No Document instance for the specified frame";
return;
}
ResourceRequest request(url);
request.setHTTPMethod("GET");
request.setCachePolicy(ReloadIgnoringCacheData);
if (requestHeaders) {
for (JSONObject::iterator it = (*requestHeaders)->begin(); it != (*requestHeaders)->end(); ++it) {
String value;
bool success = it->value->asString(&value);
if (!success) {
*errorString = "Request header \"" + it->key + "\" value is not a string";
return;
}
request.addHTTPHeaderField(AtomicString(it->key), AtomicString(value));
}
}
ThreadableLoaderOptions options;
options.allowCredentials = AllowStoredCredentials;
options.crossOriginRequestPolicy = AllowCrossOriginRequests;
InspectorThreadableLoaderClient* inspectorThreadableLoaderClient = new InspectorThreadableLoaderClient(callback);
RefPtr<DocumentThreadableLoader> loader = DocumentThreadableLoader::create(document, inspectorThreadableLoaderClient, request, options);
if (!loader) {
inspectorThreadableLoaderClient->didFailLoaderCreation();
return;
}
loader->setDefersLoading(false);
if (!callback->isActive())
return;
inspectorThreadableLoaderClient->setLoader(loader.release());
}
void InspectorResourceAgent::didCommitLoad(LocalFrame* frame, DocumentLoader* loader)
{
if (loader->frame() != frame->page()->mainFrame())
return;
if (m_state->getBoolean(ResourceAgentState::cacheDisabled))
memoryCache()->evictResources();
m_resourcesData->clear(m_pageAgent->loaderId(loader));
}
void InspectorResourceAgent::frameScheduledNavigation(LocalFrame* frame, double)
{
RefPtr<TypeBuilder::Network::Initiator> initiator = buildInitiatorObject(frame->document(), FetchInitiatorInfo());
m_frameNavigationInitiatorMap.set(m_pageAgent->frameId(frame), initiator);
}
void InspectorResourceAgent::frameClearedScheduledNavigation(LocalFrame* frame)
{
m_frameNavigationInitiatorMap.remove(m_pageAgent->frameId(frame));
}
bool InspectorResourceAgent::fetchResourceContent(LocalFrame* frame, const KURL& url, String* content, bool* base64Encoded)
{
Resource* cachedResource = frame->document()->fetcher()->cachedResource(url);
if (!cachedResource)
cachedResource = memoryCache()->resourceForURL(url);
if (cachedResource && InspectorPageAgent::cachedResourceContent(cachedResource, content, base64Encoded))
return true;
Vector<NetworkResourcesData::ResourceData*> resources = m_resourcesData->resources();
for (Vector<NetworkResourcesData::ResourceData*>::iterator it = resources.begin(); it != resources.end(); ++it) {
if ((*it)->url() == url) {
*content = (*it)->content();
*base64Encoded = (*it)->base64Encoded();
return true;
}
}
return false;
}
InspectorResourceAgent::InspectorResourceAgent(InspectorPageAgent* pageAgent, InspectorClient* client)
: InspectorBaseAgent<InspectorResourceAgent>("Network")
, m_pageAgent(pageAgent)
, m_client(client)
, m_frontend(0)
, m_resourcesData(adoptPtr(new NetworkResourcesData()))
, m_isRecalculatingStyle(false)
{
}
}