77e5d6da5f5c813d1a2074f17073cf710ddd5c27
[WebKit-https.git] / Source / WebCore / inspector / InspectorResourceAgent.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "InspectorResourceAgent.h"
33
34 #if ENABLE(INSPECTOR)
35
36 #include "CachedResource.h"
37 #include "CachedResourceLoader.h"
38 #include "Document.h"
39 #include "DocumentLoader.h"
40 #include "Frame.h"
41 #include "FrameLoader.h"
42 #include "HTTPHeaderMap.h"
43 #include "IdentifiersFactory.h"
44 #include "InspectorClient.h"
45 #include "InspectorFrontend.h"
46 #include "InspectorPageAgent.h"
47 #include "InspectorState.h"
48 #include "InspectorValues.h"
49 #include "InstrumentingAgents.h"
50 #include "KURL.h"
51 #include "MemoryCache.h"
52 #include "NetworkResourcesData.h"
53 #include "Page.h"
54 #include "ProgressTracker.h"
55 #include "ResourceError.h"
56 #include "ResourceRequest.h"
57 #include "ResourceResponse.h"
58 #include "ScriptCallStack.h"
59 #include "ScriptCallStackFactory.h"
60 #include "ScriptableDocumentParser.h"
61 #include "WebSocketHandshakeRequest.h"
62 #include "WebSocketHandshakeResponse.h"
63
64 #include <wtf/CurrentTime.h>
65 #include <wtf/HexNumber.h>
66 #include <wtf/ListHashSet.h>
67 #include <wtf/RefPtr.h>
68 #include <wtf/text/StringBuilder.h>
69
70 namespace WebCore {
71
72 namespace ResourceAgentState {
73 static const char resourceAgentEnabled[] = "resourceAgentEnabled";
74 static const char extraRequestHeaders[] = "extraRequestHeaders";
75 static const char cacheDisabled[] = "cacheDisabled";
76 }
77
78 void InspectorResourceAgent::setFrontend(InspectorFrontend* frontend)
79 {
80     m_frontend = frontend->network();
81 }
82
83 void InspectorResourceAgent::clearFrontend()
84 {
85     m_frontend = 0;
86     ErrorString error;
87     disable(&error);
88     m_userAgentOverride = "";
89 }
90
91 void InspectorResourceAgent::restore()
92 {
93     if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled))
94         enable();
95 }
96
97 static PassRefPtr<InspectorObject> buildObjectForHeaders(const HTTPHeaderMap& headers)
98 {
99     RefPtr<InspectorObject> headersObject = InspectorObject::create();
100     HTTPHeaderMap::const_iterator end = headers.end();
101     for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
102         headersObject->setString(it->first.string(), it->second);
103     return headersObject;
104 }
105
106 static PassRefPtr<InspectorObject> buildObjectForTiming(const ResourceLoadTiming& timing)
107 {
108     RefPtr<InspectorObject> timingObject = InspectorObject::create();
109     timingObject->setNumber("requestTime", timing.requestTime);
110     timingObject->setNumber("proxyStart", timing.proxyStart);
111     timingObject->setNumber("proxyEnd", timing.proxyEnd);
112     timingObject->setNumber("dnsStart", timing.dnsStart);
113     timingObject->setNumber("dnsEnd", timing.dnsEnd);
114     timingObject->setNumber("connectStart", timing.connectStart);
115     timingObject->setNumber("connectEnd", timing.connectEnd);
116     timingObject->setNumber("sslStart", timing.sslStart);
117     timingObject->setNumber("sslEnd", timing.sslEnd);
118     timingObject->setNumber("sendStart", timing.sendStart);
119     timingObject->setNumber("sendEnd", timing.sendEnd);
120     timingObject->setNumber("receiveHeadersEnd", timing.receiveHeadersEnd);
121     return timingObject;
122 }
123
124 static PassRefPtr<InspectorObject> buildObjectForResourceRequest(const ResourceRequest& request)
125 {
126     RefPtr<InspectorObject> requestObject = InspectorObject::create();
127     requestObject->setString("url", request.url().string());
128     requestObject->setString("method", request.httpMethod());
129     requestObject->setObject("headers", buildObjectForHeaders(request.httpHeaderFields()));
130     if (request.httpBody() && !request.httpBody()->isEmpty())
131         requestObject->setString("postData", request.httpBody()->flattenToString());
132     return requestObject;
133 }
134
135 static PassRefPtr<InspectorObject> buildObjectForResourceResponse(const ResourceResponse& response)
136 {
137     if (response.isNull())
138         return 0;
139
140     RefPtr<InspectorObject> responseObject = InspectorObject::create();
141     responseObject->setString("url", response.url().string());
142     if (response.resourceLoadInfo() && response.resourceLoadInfo()->httpStatusCode) {
143         responseObject->setNumber("status", response.resourceLoadInfo()->httpStatusCode);
144         responseObject->setString("statusText", response.resourceLoadInfo()->httpStatusText);
145     } else {
146         responseObject->setNumber("status", response.httpStatusCode());
147         responseObject->setString("statusText", response.httpStatusText());
148     }
149
150     responseObject->setString("mimeType", response.mimeType());
151     responseObject->setBoolean("connectionReused", response.connectionReused());
152     responseObject->setNumber("connectionId", response.connectionID());
153     responseObject->setBoolean("fromDiskCache", response.wasCached());
154     if (response.resourceLoadTiming())
155         responseObject->setObject("timing", buildObjectForTiming(*response.resourceLoadTiming()));
156
157     if (response.resourceLoadInfo()) {
158         responseObject->setObject("headers", buildObjectForHeaders(response.resourceLoadInfo()->responseHeaders));
159         if (!response.resourceLoadInfo()->responseHeadersText.isEmpty())
160             responseObject->setString("headersText", response.resourceLoadInfo()->responseHeadersText);
161
162         responseObject->setObject("requestHeaders", buildObjectForHeaders(response.resourceLoadInfo()->requestHeaders));
163         if (!response.resourceLoadInfo()->requestHeadersText.isEmpty())
164             responseObject->setString("requestHeadersText", response.resourceLoadInfo()->requestHeadersText);
165     } else
166         responseObject->setObject("headers", buildObjectForHeaders(response.httpHeaderFields()));
167
168     return responseObject;
169 }
170
171 static PassRefPtr<InspectorObject> buildObjectForCachedResource(const CachedResource& cachedResource)
172 {
173     RefPtr<InspectorObject> resourceObject = InspectorObject::create();
174     resourceObject->setString("url", cachedResource.url());
175     resourceObject->setString("type", InspectorPageAgent::cachedResourceTypeString(cachedResource));
176     resourceObject->setNumber("bodySize", cachedResource.encodedSize());
177     RefPtr<InspectorObject> resourceResponse = buildObjectForResourceResponse(cachedResource.response());
178     if (resourceResponse)
179         resourceObject->setObject("response", resourceResponse);
180     return resourceObject;
181 }
182
183 InspectorResourceAgent::~InspectorResourceAgent()
184 {
185     if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled)) {
186         ErrorString error;
187         disable(&error);
188     }
189     ASSERT(!m_instrumentingAgents->inspectorResourceAgent());
190 }
191
192 void InspectorResourceAgent::willSendRequest(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
193 {
194     String requestId = IdentifiersFactory::requestId(identifier);
195     m_resourcesData->resourceCreated(requestId, m_pageAgent->loaderId(loader));
196
197     RefPtr<InspectorObject> headers = m_state->getObject(ResourceAgentState::extraRequestHeaders);
198
199     if (headers) {
200         InspectorObject::const_iterator end = headers->end();
201         for (InspectorObject::const_iterator it = headers->begin(); it != end; ++it) {
202             String value;
203             if (it->second->asString(&value))
204                 request.setHTTPHeaderField(it->first, value);
205         }
206     }
207
208     request.setReportLoadTiming(true);
209     request.setReportRawHeaders(true);
210
211     if (m_state->getBoolean(ResourceAgentState::cacheDisabled)) {
212         request.setCachePolicy(ReloadIgnoringCacheData);
213         request.setHTTPHeaderField("Pragma", "no-cache");
214         request.setHTTPHeaderField("Cache-Control", "no-cache");
215     }
216
217     RefPtr<ScriptCallStack> callStack = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
218     RefPtr<InspectorArray> callStackValue;
219     if (callStack)
220         callStackValue = callStack->buildInspectorArray();
221     else
222         callStackValue = InspectorArray::create();
223     RefPtr<InspectorObject> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : 0);
224     m_frontend->requestWillBeSent(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), loader->url().string(), buildObjectForResourceRequest(request), currentTime(), initiatorObject, callStackValue, buildObjectForResourceResponse(redirectResponse));
225 }
226
227 void InspectorResourceAgent::markResourceAsCached(unsigned long identifier)
228 {
229     m_frontend->requestServedFromCache(IdentifiersFactory::requestId(identifier));
230 }
231
232 void InspectorResourceAgent::didReceiveResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response)
233 {
234     String requestId = IdentifiersFactory::requestId(identifier);
235     RefPtr<InspectorObject> resourceResponse = buildObjectForResourceResponse(response);
236     InspectorPageAgent::ResourceType type = InspectorPageAgent::OtherResource;
237     long cachedResourceSize = 0;
238
239     if (loader) {
240         CachedResource* cachedResource = InspectorPageAgent::cachedResource(loader->frame(), response.url());
241         if (cachedResource) {
242             type = InspectorPageAgent::cachedResourceType(*cachedResource);
243             cachedResourceSize = cachedResource->encodedSize();
244             // Use mime type from cached resource in case the one in response is empty.
245             if (response.mimeType().isEmpty())
246                 resourceResponse->setString("mimeType", cachedResource->response().mimeType());
247
248             m_resourcesData->addCachedResource(requestId, cachedResource);
249         }
250         if (m_loadingXHRSynchronously || m_resourcesData->resourceType(requestId) == InspectorPageAgent::XHRResource)
251             type = InspectorPageAgent::XHRResource;
252         else if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::ScriptResource)
253             type = InspectorPageAgent::ScriptResource;
254         else if (equalIgnoringFragmentIdentifier(response.url(), loader->frameLoader()->icon()->url()))
255             type = InspectorPageAgent::ImageResource;
256         else if (equalIgnoringFragmentIdentifier(response.url(), loader->url()) && type == InspectorPageAgent::OtherResource)
257             type = InspectorPageAgent::DocumentResource;
258
259         m_resourcesData->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), response);
260     }
261     m_resourcesData->setResourceType(requestId, type);
262     m_frontend->responseReceived(requestId, currentTime(), InspectorPageAgent::resourceTypeString(type), resourceResponse);
263     // If we revalidated the resource and got Not modified, send content length following didReceiveResponse
264     // as there will be no calls to didReceiveData from the network stack.
265     if (cachedResourceSize && response.httpStatusCode() == 304)
266         didReceiveData(identifier, 0, cachedResourceSize, 0);
267 }
268
269 void InspectorResourceAgent::didReceiveData(unsigned long identifier, const char* data, int dataLength, int encodedDataLength)
270 {
271     String requestId = IdentifiersFactory::requestId(identifier);
272     if (data && m_resourcesData->resourceType(requestId) == InspectorPageAgent::OtherResource)
273         m_resourcesData->maybeAddResourceData(requestId, data, dataLength);
274
275     m_frontend->dataReceived(requestId, currentTime(), dataLength, encodedDataLength);
276 }
277
278 void InspectorResourceAgent::didFinishLoading(unsigned long identifier, DocumentLoader* loader, double finishTime)
279 {
280     String requestId = IdentifiersFactory::requestId(identifier);
281     if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource)
282         m_resourcesData->addResourceSharedBuffer(requestId, loader->frameLoader()->documentLoader()->mainResourceData(), loader->frame()->document()->inputEncoding());
283
284     m_resourcesData->maybeDecodeDataToContent(requestId);
285
286     if (!finishTime)
287         finishTime = currentTime();
288
289     m_frontend->loadingFinished(requestId, finishTime);
290 }
291
292 void InspectorResourceAgent::didFailLoading(unsigned long identifier, DocumentLoader* loader, const ResourceError& error)
293 {
294     String requestId = IdentifiersFactory::requestId(identifier);
295
296     if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) {
297         Frame* frame = loader ? loader->frame() : 0;
298         if (frame && frame->loader()->documentLoader() && frame->document())
299             m_resourcesData->addResourceSharedBuffer(requestId, frame->loader()->documentLoader()->mainResourceData(), frame->document()->inputEncoding());
300     }
301
302     m_frontend->loadingFailed(requestId, currentTime(), error.localizedDescription(), error.isCancellation());
303 }
304
305 void InspectorResourceAgent::didLoadResourceFromMemoryCache(DocumentLoader* loader, CachedResource* resource)
306 {
307     String loaderId = m_pageAgent->loaderId(loader);
308     String frameId = m_pageAgent->frameId(loader->frame());
309     unsigned long identifier = loader->frame()->page()->progress()->createUniqueIdentifier();
310     String requestId = IdentifiersFactory::requestId(identifier);
311     m_resourcesData->resourceCreated(requestId, loaderId);
312     m_resourcesData->addCachedResource(requestId, resource);
313     RefPtr<InspectorObject> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : 0);
314
315     m_frontend->requestServedFromMemoryCache(requestId, frameId, loaderId, loader->url().string(), currentTime(), initiatorObject, buildObjectForCachedResource(*resource));
316 }
317
318 void InspectorResourceAgent::setInitialScriptContent(unsigned long identifier, const String& sourceString)
319 {
320     m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString);
321 }
322
323 void InspectorResourceAgent::didReceiveScriptResponse(unsigned long identifier)
324 {
325     m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::ScriptResource);
326 }
327
328 void InspectorResourceAgent::setInitialXHRContent(unsigned long identifier, const String& sourceString)
329 {
330     m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString);
331 }
332
333 void InspectorResourceAgent::didReceiveXHRResponse(unsigned long identifier)
334 {
335     m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::XHRResource);
336 }
337
338 void InspectorResourceAgent::willLoadXHRSynchronously()
339 {
340     m_loadingXHRSynchronously = true;
341 }
342
343 void InspectorResourceAgent::didLoadXHRSynchronously()
344 {
345     m_loadingXHRSynchronously = false;
346 }
347
348 void InspectorResourceAgent::applyUserAgentOverride(String* userAgent)
349 {
350     if (!m_userAgentOverride.isEmpty())
351         *userAgent = m_userAgentOverride;
352 }
353
354 void InspectorResourceAgent::willRecalculateStyle()
355 {
356     m_isRecalculatingStyle = true;
357 }
358
359 void InspectorResourceAgent::didRecalculateStyle()
360 {
361     m_isRecalculatingStyle = false;
362     m_styleRecalculationInitiator = nullptr;
363 }
364
365 void InspectorResourceAgent::didScheduleStyleRecalculation(Document* document)
366 {
367     if (!m_styleRecalculationInitiator)
368         m_styleRecalculationInitiator = buildInitiatorObject(document);
369 }
370
371 PassRefPtr<InspectorObject> InspectorResourceAgent::buildInitiatorObject(Document* document)
372 {
373     RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
374     if (stackTrace && stackTrace->size() > 0) {
375         RefPtr<InspectorObject> initiatorObject = InspectorObject::create();
376         initiatorObject->setString("type", "script");
377         initiatorObject->setArray("stackTrace", stackTrace->buildInspectorArray());
378         return initiatorObject;
379     }
380
381     if (document && document->scriptableDocumentParser()) {
382         RefPtr<InspectorObject> initiatorObject = InspectorObject::create();
383         initiatorObject->setString("type", "parser");
384         initiatorObject->setString("url", document->url().string());
385         initiatorObject->setNumber("lineNumber", document->scriptableDocumentParser()->lineNumber().oneBasedInt());
386         return initiatorObject;
387     }
388
389     if (m_isRecalculatingStyle && m_styleRecalculationInitiator)
390         return m_styleRecalculationInitiator;
391
392     RefPtr<InspectorObject> initiatorObject = InspectorObject::create();
393     initiatorObject->setString("type", "other");
394     return initiatorObject;
395 }
396
397 #if ENABLE(WEB_SOCKETS)
398
399 // FIXME: More this into the front-end?
400 // Create human-readable binary representation, like "01:23:45:67:89:AB:CD:EF".
401 static String createReadableStringFromBinary(const unsigned char* value, size_t length)
402 {
403     ASSERT(length > 0);
404     StringBuilder builder;
405     builder.reserveCapacity(length * 3 - 1);
406     for (size_t i = 0; i < length; ++i) {
407         if (i > 0)
408             builder.append(':');
409         appendByteAsHex(value[i], builder);
410     }
411     return builder.toString();
412 }
413
414 void InspectorResourceAgent::didCreateWebSocket(unsigned long identifier, const KURL& requestURL)
415 {
416     m_frontend->webSocketCreated(IdentifiersFactory::requestId(identifier), requestURL.string());
417 }
418
419 void InspectorResourceAgent::willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest& request)
420 {
421     RefPtr<InspectorObject> requestObject = InspectorObject::create();
422     requestObject->setObject("headers", buildObjectForHeaders(request.headerFields()));
423     requestObject->setString("requestKey3", createReadableStringFromBinary(request.key3().value, sizeof(request.key3().value)));
424     m_frontend->webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), currentTime(), requestObject);
425 }
426
427 void InspectorResourceAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse& response)
428 {
429     RefPtr<InspectorObject> responseObject = InspectorObject::create();
430     responseObject->setNumber("status", response.statusCode());
431     responseObject->setString("statusText", response.statusText());
432     responseObject->setObject("headers", buildObjectForHeaders(response.headerFields()));
433     responseObject->setString("challengeResponse", createReadableStringFromBinary(response.challengeResponse().value, sizeof(response.challengeResponse().value)));
434     m_frontend->webSocketHandshakeResponseReceived(IdentifiersFactory::requestId(identifier), currentTime(), responseObject);
435 }
436
437 void InspectorResourceAgent::didCloseWebSocket(unsigned long identifier)
438 {
439     m_frontend->webSocketClosed(IdentifiersFactory::requestId(identifier), currentTime());
440 }
441 #endif // ENABLE(WEB_SOCKETS)
442
443 // called from Internals for layout test purposes.
444 void InspectorResourceAgent::setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize)
445 {
446     m_resourcesData->setResourcesDataSizeLimits(maximumResourcesContentSize, maximumSingleResourceContentSize);
447 }
448
449 void InspectorResourceAgent::enable(ErrorString*)
450 {
451     enable();
452 }
453
454 void InspectorResourceAgent::enable()
455 {
456     if (!m_frontend)
457         return;
458     m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, true);
459     m_instrumentingAgents->setInspectorResourceAgent(this);
460 }
461
462 void InspectorResourceAgent::disable(ErrorString*)
463 {
464     m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, false);
465     m_instrumentingAgents->setInspectorResourceAgent(0);
466     m_resourcesData->clear();
467 }
468
469 void InspectorResourceAgent::setUserAgentOverride(ErrorString*, const String& userAgent)
470 {
471     m_userAgentOverride = userAgent;
472 }
473
474 void InspectorResourceAgent::setExtraHTTPHeaders(ErrorString*, PassRefPtr<InspectorObject> headers)
475 {
476     m_state->setObject(ResourceAgentState::extraRequestHeaders, headers);
477 }
478
479 void InspectorResourceAgent::getResponseBody(ErrorString* errorString, const String& requestId, String* content, bool* base64Encoded)
480 {
481     NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
482     if (!resourceData) {
483         *errorString = "No resource with given identifier found";
484         return;
485     }
486
487     if (resourceData->hasContent()) {
488         *base64Encoded = false;
489         *content = resourceData->content();
490         return;
491     }
492
493     if (resourceData->buffer() && !resourceData->textEncodingName().isNull()) {
494         *base64Encoded = false;
495         if (InspectorPageAgent::sharedBufferContent(resourceData->buffer(), resourceData->textEncodingName(), *base64Encoded, content))
496             return;
497     }
498
499     if (resourceData->cachedResource()) {
500         if (InspectorPageAgent::cachedResourceContent(resourceData->cachedResource(), content, base64Encoded))
501             return;
502     }
503
504     *errorString = "No data found for resource with given identifier";
505 }
506
507 void InspectorResourceAgent::clearBrowserCache(ErrorString*)
508 {
509     m_client->clearBrowserCache();
510 }
511
512 void InspectorResourceAgent::clearBrowserCookies(ErrorString*)
513 {
514     m_client->clearBrowserCookies();
515 }
516
517 void InspectorResourceAgent::setCacheDisabled(ErrorString*, bool cacheDisabled)
518 {
519     m_state->setBoolean(ResourceAgentState::cacheDisabled, cacheDisabled);
520 }
521
522 void InspectorResourceAgent::mainFrameNavigated(DocumentLoader* loader)
523 {
524     if (m_state->getBoolean(ResourceAgentState::cacheDisabled))
525         memoryCache()->evictResources();
526
527     m_resourcesData->clear(m_pageAgent->loaderId(loader));
528 }
529
530 InspectorResourceAgent::InspectorResourceAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorClient* client, InspectorState* state)
531     : m_instrumentingAgents(instrumentingAgents)
532     , m_pageAgent(pageAgent)
533     , m_client(client)
534     , m_state(state)
535     , m_frontend(0)
536     , m_resourcesData(adoptPtr(new NetworkResourcesData()))
537     , m_loadingXHRSynchronously(false)
538     , m_isRecalculatingStyle(false)
539 {
540 }
541
542 } // namespace WebCore
543
544 #endif // ENABLE(INSPECTOR)