Web Inspector: optional arguments support for the frontend needs to be extended.
[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     bool canceled = error.isCancellation();
303     m_frontend->loadingFailed(requestId, currentTime(), error.localizedDescription(), canceled ? &canceled : 0);
304 }
305
306 void InspectorResourceAgent::didLoadResourceFromMemoryCache(DocumentLoader* loader, CachedResource* resource)
307 {
308     String loaderId = m_pageAgent->loaderId(loader);
309     String frameId = m_pageAgent->frameId(loader->frame());
310     unsigned long identifier = loader->frame()->page()->progress()->createUniqueIdentifier();
311     String requestId = IdentifiersFactory::requestId(identifier);
312     m_resourcesData->resourceCreated(requestId, loaderId);
313     m_resourcesData->addCachedResource(requestId, resource);
314     RefPtr<InspectorObject> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : 0);
315
316     m_frontend->requestServedFromMemoryCache(requestId, frameId, loaderId, loader->url().string(), currentTime(), initiatorObject, buildObjectForCachedResource(*resource));
317 }
318
319 void InspectorResourceAgent::setInitialScriptContent(unsigned long identifier, const String& sourceString)
320 {
321     m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString);
322 }
323
324 void InspectorResourceAgent::didReceiveScriptResponse(unsigned long identifier)
325 {
326     m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::ScriptResource);
327 }
328
329 void InspectorResourceAgent::setInitialXHRContent(unsigned long identifier, const String& sourceString)
330 {
331     m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString);
332 }
333
334 void InspectorResourceAgent::didReceiveXHRResponse(unsigned long identifier)
335 {
336     m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::XHRResource);
337 }
338
339 void InspectorResourceAgent::willLoadXHRSynchronously()
340 {
341     m_loadingXHRSynchronously = true;
342 }
343
344 void InspectorResourceAgent::didLoadXHRSynchronously()
345 {
346     m_loadingXHRSynchronously = false;
347 }
348
349 void InspectorResourceAgent::applyUserAgentOverride(String* userAgent)
350 {
351     if (!m_userAgentOverride.isEmpty())
352         *userAgent = m_userAgentOverride;
353 }
354
355 void InspectorResourceAgent::willRecalculateStyle()
356 {
357     m_isRecalculatingStyle = true;
358 }
359
360 void InspectorResourceAgent::didRecalculateStyle()
361 {
362     m_isRecalculatingStyle = false;
363     m_styleRecalculationInitiator = nullptr;
364 }
365
366 void InspectorResourceAgent::didScheduleStyleRecalculation(Document* document)
367 {
368     if (!m_styleRecalculationInitiator)
369         m_styleRecalculationInitiator = buildInitiatorObject(document);
370 }
371
372 PassRefPtr<InspectorObject> InspectorResourceAgent::buildInitiatorObject(Document* document)
373 {
374     RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
375     if (stackTrace && stackTrace->size() > 0) {
376         RefPtr<InspectorObject> initiatorObject = InspectorObject::create();
377         initiatorObject->setString("type", "script");
378         initiatorObject->setArray("stackTrace", stackTrace->buildInspectorArray());
379         return initiatorObject;
380     }
381
382     if (document && document->scriptableDocumentParser()) {
383         RefPtr<InspectorObject> initiatorObject = InspectorObject::create();
384         initiatorObject->setString("type", "parser");
385         initiatorObject->setString("url", document->url().string());
386         initiatorObject->setNumber("lineNumber", document->scriptableDocumentParser()->lineNumber().oneBasedInt());
387         return initiatorObject;
388     }
389
390     if (m_isRecalculatingStyle && m_styleRecalculationInitiator)
391         return m_styleRecalculationInitiator;
392
393     RefPtr<InspectorObject> initiatorObject = InspectorObject::create();
394     initiatorObject->setString("type", "other");
395     return initiatorObject;
396 }
397
398 #if ENABLE(WEB_SOCKETS)
399
400 // FIXME: More this into the front-end?
401 // Create human-readable binary representation, like "01:23:45:67:89:AB:CD:EF".
402 static String createReadableStringFromBinary(const unsigned char* value, size_t length)
403 {
404     ASSERT(length > 0);
405     StringBuilder builder;
406     builder.reserveCapacity(length * 3 - 1);
407     for (size_t i = 0; i < length; ++i) {
408         if (i > 0)
409             builder.append(':');
410         appendByteAsHex(value[i], builder);
411     }
412     return builder.toString();
413 }
414
415 void InspectorResourceAgent::didCreateWebSocket(unsigned long identifier, const KURL& requestURL)
416 {
417     m_frontend->webSocketCreated(IdentifiersFactory::requestId(identifier), requestURL.string());
418 }
419
420 void InspectorResourceAgent::willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest& request)
421 {
422     RefPtr<InspectorObject> requestObject = InspectorObject::create();
423     requestObject->setObject("headers", buildObjectForHeaders(request.headerFields()));
424     requestObject->setString("requestKey3", createReadableStringFromBinary(request.key3().value, sizeof(request.key3().value)));
425     m_frontend->webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), currentTime(), requestObject);
426 }
427
428 void InspectorResourceAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse& response)
429 {
430     RefPtr<InspectorObject> responseObject = InspectorObject::create();
431     responseObject->setNumber("status", response.statusCode());
432     responseObject->setString("statusText", response.statusText());
433     responseObject->setObject("headers", buildObjectForHeaders(response.headerFields()));
434     responseObject->setString("challengeResponse", createReadableStringFromBinary(response.challengeResponse().value, sizeof(response.challengeResponse().value)));
435     m_frontend->webSocketHandshakeResponseReceived(IdentifiersFactory::requestId(identifier), currentTime(), responseObject);
436 }
437
438 void InspectorResourceAgent::didCloseWebSocket(unsigned long identifier)
439 {
440     m_frontend->webSocketClosed(IdentifiersFactory::requestId(identifier), currentTime());
441 }
442 #endif // ENABLE(WEB_SOCKETS)
443
444 // called from Internals for layout test purposes.
445 void InspectorResourceAgent::setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize)
446 {
447     m_resourcesData->setResourcesDataSizeLimits(maximumResourcesContentSize, maximumSingleResourceContentSize);
448 }
449
450 void InspectorResourceAgent::enable(ErrorString*)
451 {
452     enable();
453 }
454
455 void InspectorResourceAgent::enable()
456 {
457     if (!m_frontend)
458         return;
459     m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, true);
460     m_instrumentingAgents->setInspectorResourceAgent(this);
461 }
462
463 void InspectorResourceAgent::disable(ErrorString*)
464 {
465     m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, false);
466     m_instrumentingAgents->setInspectorResourceAgent(0);
467     m_resourcesData->clear();
468 }
469
470 void InspectorResourceAgent::setUserAgentOverride(ErrorString*, const String& userAgent)
471 {
472     m_userAgentOverride = userAgent;
473 }
474
475 void InspectorResourceAgent::setExtraHTTPHeaders(ErrorString*, PassRefPtr<InspectorObject> headers)
476 {
477     m_state->setObject(ResourceAgentState::extraRequestHeaders, headers);
478 }
479
480 void InspectorResourceAgent::getResponseBody(ErrorString* errorString, const String& requestId, String* content, bool* base64Encoded)
481 {
482     NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
483     if (!resourceData) {
484         *errorString = "No resource with given identifier found";
485         return;
486     }
487
488     if (resourceData->hasContent()) {
489         *base64Encoded = false;
490         *content = resourceData->content();
491         return;
492     }
493
494     if (resourceData->buffer() && !resourceData->textEncodingName().isNull()) {
495         *base64Encoded = false;
496         if (InspectorPageAgent::sharedBufferContent(resourceData->buffer(), resourceData->textEncodingName(), *base64Encoded, content))
497             return;
498     }
499
500     if (resourceData->cachedResource()) {
501         if (InspectorPageAgent::cachedResourceContent(resourceData->cachedResource(), content, base64Encoded))
502             return;
503     }
504
505     *errorString = "No data found for resource with given identifier";
506 }
507
508 void InspectorResourceAgent::clearBrowserCache(ErrorString*)
509 {
510     m_client->clearBrowserCache();
511 }
512
513 void InspectorResourceAgent::clearBrowserCookies(ErrorString*)
514 {
515     m_client->clearBrowserCookies();
516 }
517
518 void InspectorResourceAgent::setCacheDisabled(ErrorString*, bool cacheDisabled)
519 {
520     m_state->setBoolean(ResourceAgentState::cacheDisabled, cacheDisabled);
521 }
522
523 void InspectorResourceAgent::mainFrameNavigated(DocumentLoader* loader)
524 {
525     if (m_state->getBoolean(ResourceAgentState::cacheDisabled))
526         memoryCache()->evictResources();
527
528     m_resourcesData->clear(m_pageAgent->loaderId(loader));
529 }
530
531 InspectorResourceAgent::InspectorResourceAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorClient* client, InspectorState* state)
532     : m_instrumentingAgents(instrumentingAgents)
533     , m_pageAgent(pageAgent)
534     , m_client(client)
535     , m_state(state)
536     , m_frontend(0)
537     , m_resourcesData(adoptPtr(new NetworkResourcesData()))
538     , m_loadingXHRSynchronously(false)
539     , m_isRecalculatingStyle(false)
540 {
541 }
542
543 } // namespace WebCore
544
545 #endif // ENABLE(INSPECTOR)