Web Inspector: Remove recompileAllJSFunctions timer in ScriptDebugServer
[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
33 #if ENABLE(INSPECTOR)
34
35 #include "InspectorResourceAgent.h"
36
37 #include "CachedRawResource.h"
38 #include "CachedResource.h"
39 #include "CachedResourceLoader.h"
40 #include "Document.h"
41 #include "DocumentLoader.h"
42 #include "ExceptionCodePlaceholder.h"
43 #include "Frame.h"
44 #include "FrameLoader.h"
45 #include "HTTPHeaderMap.h"
46 #include "IconController.h"
47 #include "IdentifiersFactory.h"
48 #include "InspectorClient.h"
49 #include "InspectorPageAgent.h"
50 #include "InspectorWebFrontendDispatchers.h"
51 #include "InstrumentingAgents.h"
52 #include "MemoryCache.h"
53 #include "NetworkResourcesData.h"
54 #include "Page.h"
55 #include "ProgressTracker.h"
56 #include "ResourceBuffer.h"
57 #include "ResourceError.h"
58 #include "ResourceLoader.h"
59 #include "ResourceRequest.h"
60 #include "ResourceResponse.h"
61 #include "ScriptCallStack.h"
62 #include "ScriptCallStackFactory.h"
63 #include "ScriptableDocumentParser.h"
64 #include "Settings.h"
65 #include "SubresourceLoader.h"
66 #include "URL.h"
67 #include "WebSocketFrame.h"
68 #include "XMLHttpRequest.h"
69 #include <inspector/InspectorValues.h>
70 #include <wtf/CurrentTime.h>
71 #include <wtf/HexNumber.h>
72 #include <wtf/ListHashSet.h>
73 #include <wtf/RefPtr.h>
74 #include <wtf/text/StringBuilder.h>
75
76 using namespace Inspector;
77
78 namespace WebCore {
79
80 void InspectorResourceAgent::didCreateFrontendAndBackend(Inspector::InspectorFrontendChannel* frontendChannel, InspectorBackendDispatcher* backendDispatcher)
81 {
82     m_frontendDispatcher = std::make_unique<InspectorNetworkFrontendDispatcher>(frontendChannel);
83     m_backendDispatcher = InspectorNetworkBackendDispatcher::create(backendDispatcher, this);
84 }
85
86 void InspectorResourceAgent::willDestroyFrontendAndBackend(InspectorDisconnectReason)
87 {
88     m_frontendDispatcher = nullptr;
89     m_backendDispatcher.clear();
90
91     ErrorString error;
92     disable(&error);
93 }
94
95 static PassRefPtr<InspectorObject> buildObjectForHeaders(const HTTPHeaderMap& headers)
96 {
97     RefPtr<InspectorObject> headersObject = InspectorObject::create();
98     HTTPHeaderMap::const_iterator end = headers.end();
99     for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
100         headersObject->setString(it->key.string(), it->value);
101     return headersObject;
102 }
103
104 static PassRefPtr<Inspector::TypeBuilder::Network::ResourceTiming> buildObjectForTiming(const ResourceLoadTiming& timing, DocumentLoader* loader)
105 {
106     return Inspector::TypeBuilder::Network::ResourceTiming::create()
107         .setRequestTime(loader->timing()->monotonicTimeToPseudoWallTime(timing.convertResourceLoadTimeToMonotonicTime(0)))
108         .setProxyStart(timing.proxyStart)
109         .setProxyEnd(timing.proxyEnd)
110         .setDnsStart(timing.dnsStart)
111         .setDnsEnd(timing.dnsEnd)
112         .setConnectStart(timing.connectStart)
113         .setConnectEnd(timing.connectEnd)
114         .setSslStart(timing.sslStart)
115         .setSslEnd(timing.sslEnd)
116         .setSendStart(timing.sendStart)
117         .setSendEnd(timing.sendEnd)
118         .setReceiveHeadersEnd(timing.receiveHeadersEnd)
119         .release();
120 }
121
122 static PassRefPtr<Inspector::TypeBuilder::Network::Request> buildObjectForResourceRequest(const ResourceRequest& request)
123 {
124     RefPtr<Inspector::TypeBuilder::Network::Request> requestObject = Inspector::TypeBuilder::Network::Request::create()
125         .setUrl(request.url().string())
126         .setMethod(request.httpMethod())
127         .setHeaders(buildObjectForHeaders(request.httpHeaderFields()));
128     if (request.httpBody() && !request.httpBody()->isEmpty())
129         requestObject->setPostData(request.httpBody()->flattenToString());
130     return requestObject;
131 }
132
133 static PassRefPtr<Inspector::TypeBuilder::Network::Response> buildObjectForResourceResponse(const ResourceResponse& response, DocumentLoader* loader)
134 {
135     if (response.isNull())
136         return nullptr;
137
138     double status = response.httpStatusCode();
139     RefPtr<InspectorObject> headers = buildObjectForHeaders(response.httpHeaderFields());
140
141     RefPtr<Inspector::TypeBuilder::Network::Response> responseObject = Inspector::TypeBuilder::Network::Response::create()
142         .setUrl(response.url().string())
143         .setStatus(status)
144         .setStatusText(response.httpStatusText())
145         .setHeaders(headers)
146         .setMimeType(response.mimeType())
147         .setConnectionReused(response.connectionReused())
148         .setConnectionId(response.connectionID());
149
150     responseObject->setFromDiskCache(response.wasCached());
151     if (response.resourceLoadTiming())
152         responseObject->setTiming(buildObjectForTiming(*response.resourceLoadTiming(), loader));
153
154     return responseObject;
155 }
156
157 static PassRefPtr<Inspector::TypeBuilder::Network::CachedResource> buildObjectForCachedResource(CachedResource* cachedResource, DocumentLoader* loader)
158 {
159     RefPtr<Inspector::TypeBuilder::Network::CachedResource> resourceObject = Inspector::TypeBuilder::Network::CachedResource::create()
160         .setUrl(cachedResource->url())
161         .setType(InspectorPageAgent::cachedResourceTypeJson(*cachedResource))
162         .setBodySize(cachedResource->encodedSize());
163
164     RefPtr<Inspector::TypeBuilder::Network::Response> resourceResponse = buildObjectForResourceResponse(cachedResource->response(), loader);
165     if (resourceResponse)
166         resourceObject->setResponse(resourceResponse);
167
168     String sourceMappingURL = InspectorPageAgent::sourceMapURLForResource(cachedResource);
169     if (!sourceMappingURL.isEmpty())
170         resourceObject->setSourceMapURL(sourceMappingURL);
171
172     return resourceObject;
173 }
174
175 InspectorResourceAgent::~InspectorResourceAgent()
176 {
177     if (m_enabled) {
178         ErrorString error;
179         disable(&error);
180     }
181     ASSERT(!m_instrumentingAgents->inspectorResourceAgent());
182 }
183
184 void InspectorResourceAgent::willSendRequest(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
185 {
186     String requestId = IdentifiersFactory::requestId(identifier);
187     m_resourcesData->resourceCreated(requestId, m_pageAgent->loaderId(loader));
188
189     CachedResource* cachedResource = loader ? InspectorPageAgent::cachedResource(loader->frame(), request.url()) : nullptr;
190     InspectorPageAgent::ResourceType type = cachedResource ? InspectorPageAgent::cachedResourceType(*cachedResource) : m_resourcesData->resourceType(requestId);
191     if (type == InspectorPageAgent::OtherResource) {
192         if (m_loadingXHRSynchronously)
193             type = InspectorPageAgent::XHRResource;
194         else if (equalIgnoringFragmentIdentifier(request.url(), loader->frameLoader()->icon().url()))
195             type = InspectorPageAgent::ImageResource;
196         else if (equalIgnoringFragmentIdentifier(request.url(), loader->url()) && !loader->isCommitted())
197             type = InspectorPageAgent::DocumentResource;
198     }
199
200     m_resourcesData->setResourceType(requestId, type);
201
202     if (m_extraRequestHeaders) {
203         InspectorObject::const_iterator end = m_extraRequestHeaders->end();
204         for (InspectorObject::const_iterator it = m_extraRequestHeaders->begin(); it != end; ++it) {
205             String value;
206             if (it->value->asString(&value))
207                 request.setHTTPHeaderField(it->key, value);
208         }
209     }
210
211     request.setReportLoadTiming(true);
212     request.setReportRawHeaders(true);
213
214     if (m_cacheDisabled) {
215         request.setHTTPHeaderField("Pragma", "no-cache");
216         request.setCachePolicy(ReloadIgnoringCacheData);
217         request.setHTTPHeaderField("Cache-Control", "no-cache");
218     }
219
220     Inspector::TypeBuilder::Page::ResourceType::Enum resourceType = InspectorPageAgent::resourceTypeJson(type);
221
222     RefPtr<Inspector::TypeBuilder::Network::Initiator> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : nullptr);
223     m_frontendDispatcher->requestWillBeSent(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), loader->url().string(), buildObjectForResourceRequest(request), currentTime(), initiatorObject, buildObjectForResourceResponse(redirectResponse, loader), type != InspectorPageAgent::OtherResource ? &resourceType : nullptr);
224 }
225
226 void InspectorResourceAgent::markResourceAsCached(unsigned long identifier)
227 {
228     m_frontendDispatcher->requestServedFromCache(IdentifiersFactory::requestId(identifier));
229 }
230
231 void InspectorResourceAgent::didReceiveResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader)
232 {
233     String requestId = IdentifiersFactory::requestId(identifier);
234     RefPtr<Inspector::TypeBuilder::Network::Response> resourceResponse = buildObjectForResourceResponse(response, loader);
235
236     bool isNotModified = response.httpStatusCode() == 304;
237
238     CachedResource* cachedResource = nullptr;
239     if (resourceLoader && resourceLoader->isSubresourceLoader() && !isNotModified)
240         cachedResource = static_cast<SubresourceLoader*>(resourceLoader)->cachedResource();
241     if (!cachedResource)
242         cachedResource = InspectorPageAgent::cachedResource(loader->frame(), response.url());
243
244     if (cachedResource) {
245         // Use mime type from cached resource in case the one in response is empty.
246         if (resourceResponse && response.mimeType().isEmpty())
247             resourceResponse->setString(Inspector::TypeBuilder::Network::Response::MimeType, cachedResource->response().mimeType());
248         m_resourcesData->addCachedResource(requestId, cachedResource);
249     }
250
251     InspectorPageAgent::ResourceType type = m_resourcesData->resourceType(requestId);
252     InspectorPageAgent::ResourceType newType = cachedResource ? InspectorPageAgent::cachedResourceType(*cachedResource) : type;
253
254     // FIXME: XHRResource is returned for CachedResource::RawResource, it should be OtherResource unless it truly is an XHR.
255     // RawResource is used for loading worker scripts, and those should stay as ScriptResource and not change to XHRResource.
256     if (type != newType && newType != InspectorPageAgent::XHRResource && newType != InspectorPageAgent::OtherResource)
257         type = newType;
258
259     m_resourcesData->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), response);
260     m_resourcesData->setResourceType(requestId, type);
261
262     m_frontendDispatcher->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), currentTime(), InspectorPageAgent::resourceTypeJson(type), resourceResponse);
263
264     // If we revalidated the resource and got Not modified, send content length following didReceiveResponse
265     // as there will be no calls to didReceiveData from the network stack.
266     if (isNotModified && cachedResource && cachedResource->encodedSize())
267         didReceiveData(identifier, nullptr, cachedResource->encodedSize(), 0);
268 }
269
270 static bool isErrorStatusCode(int statusCode)
271 {
272     return statusCode >= 400;
273 }
274
275 void InspectorResourceAgent::didReceiveData(unsigned long identifier, const char* data, int dataLength, int encodedDataLength)
276 {
277     String requestId = IdentifiersFactory::requestId(identifier);
278
279     if (data) {
280         NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
281         if (resourceData && !m_loadingXHRSynchronously && (!resourceData->cachedResource() || resourceData->cachedResource()->dataBufferingPolicy() == DoNotBufferData || isErrorStatusCode(resourceData->httpStatusCode())))
282             m_resourcesData->maybeAddResourceData(requestId, data, dataLength);
283     }
284
285     m_frontendDispatcher->dataReceived(requestId, currentTime(), dataLength, encodedDataLength);
286 }
287
288 void InspectorResourceAgent::didFinishLoading(unsigned long identifier, DocumentLoader* loader, double finishTime)
289 {
290     String requestId = IdentifiersFactory::requestId(identifier);
291     if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) {
292         RefPtr<ResourceBuffer> buffer = loader->frameLoader()->documentLoader()->mainResourceData();
293         m_resourcesData->addResourceSharedBuffer(requestId, buffer ? buffer->sharedBuffer() : nullptr, loader->frame()->document()->inputEncoding());
294     }
295
296     m_resourcesData->maybeDecodeDataToContent(requestId);
297
298     // FIXME: The finishTime that is passed in is from the NetworkProcess and is more accurate.
299     // However, all other times passed to the Inspector are generated from the web process. Mixing
300     // times from different processes can cause the finish time to be earlier than the response
301     // received time due to inter-process communication lag.
302     finishTime = currentTime();
303
304     String sourceMappingURL;
305     NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
306     if (resourceData && resourceData->cachedResource())
307         sourceMappingURL = InspectorPageAgent::sourceMapURLForResource(resourceData->cachedResource());
308
309     m_frontendDispatcher->loadingFinished(requestId, finishTime, !sourceMappingURL.isEmpty() ? &sourceMappingURL : nullptr);
310 }
311
312 void InspectorResourceAgent::didFailLoading(unsigned long identifier, DocumentLoader* loader, const ResourceError& error)
313 {
314     String requestId = IdentifiersFactory::requestId(identifier);
315
316     if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) {
317         Frame* frame = loader ? loader->frame() : nullptr;
318         if (frame && frame->loader().documentLoader() && frame->document()) {
319             RefPtr<ResourceBuffer> buffer = frame->loader().documentLoader()->mainResourceData();
320             m_resourcesData->addResourceSharedBuffer(requestId, buffer ? buffer->sharedBuffer() : nullptr, frame->document()->inputEncoding());
321         }
322     }
323
324     bool canceled = error.isCancellation();
325     m_frontendDispatcher->loadingFailed(requestId, currentTime(), error.localizedDescription(), canceled ? &canceled : nullptr);
326 }
327
328 void InspectorResourceAgent::didLoadResourceFromMemoryCache(DocumentLoader* loader, CachedResource* resource)
329 {
330     String loaderId = m_pageAgent->loaderId(loader);
331     String frameId = m_pageAgent->frameId(loader->frame());
332     unsigned long identifier = loader->frame()->page()->progress().createUniqueIdentifier();
333     String requestId = IdentifiersFactory::requestId(identifier);
334     m_resourcesData->resourceCreated(requestId, loaderId);
335     m_resourcesData->addCachedResource(requestId, resource);
336     if (resource->type() == CachedResource::RawResource) {
337         CachedRawResource* rawResource = static_cast<CachedRawResource*>(resource);
338         String rawRequestId = IdentifiersFactory::requestId(rawResource->identifier());
339         m_resourcesData->reuseXHRReplayData(requestId, rawRequestId);
340     }
341
342     RefPtr<Inspector::TypeBuilder::Network::Initiator> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : nullptr);
343
344     m_frontendDispatcher->requestServedFromMemoryCache(requestId, frameId, loaderId, loader->url().string(), currentTime(), initiatorObject, buildObjectForCachedResource(resource, loader));
345 }
346
347 void InspectorResourceAgent::setInitialScriptContent(unsigned long identifier, const String& sourceString)
348 {
349     m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString);
350 }
351
352 void InspectorResourceAgent::didReceiveScriptResponse(unsigned long identifier)
353 {
354     m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::ScriptResource);
355 }
356
357 void InspectorResourceAgent::documentThreadableLoaderStartedLoadingForClient(unsigned long identifier, ThreadableLoaderClient* client)
358 {
359     if (!client)
360         return;
361
362     PendingXHRReplayDataMap::iterator it = m_pendingXHRReplayData.find(client);
363     if (it == m_pendingXHRReplayData.end())
364         return;
365
366     XHRReplayData* xhrReplayData = it->value.get();
367     String requestId = IdentifiersFactory::requestId(identifier);
368     m_resourcesData->setXHRReplayData(requestId, xhrReplayData);
369 }
370
371 void InspectorResourceAgent::willLoadXHR(ThreadableLoaderClient* client, const String& method, const URL& url, bool async, PassRefPtr<FormData> formData, const HTTPHeaderMap& headers, bool includeCredentials)
372 {
373     RefPtr<XHRReplayData> xhrReplayData = XHRReplayData::create(method, url, async, formData, includeCredentials);
374     HTTPHeaderMap::const_iterator end = headers.end();
375     for (HTTPHeaderMap::const_iterator it = headers.begin(); it!= end; ++it)
376         xhrReplayData->addHeader(it->key, it->value);
377     m_pendingXHRReplayData.set(client, xhrReplayData);
378 }
379
380 void InspectorResourceAgent::didFailXHRLoading(ThreadableLoaderClient* client)
381 {
382     m_pendingXHRReplayData.remove(client);
383 }
384
385 void InspectorResourceAgent::didFinishXHRLoading(ThreadableLoaderClient* client, unsigned long identifier, const String& sourceString)
386 {
387     // For Asynchronous XHRs, the inspector can grab the data directly off of the CachedResource. For sync XHRs, we need to
388     // provide the data here, since no CachedResource was involved.
389     if (m_loadingXHRSynchronously)
390         m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString);
391     m_pendingXHRReplayData.remove(client);
392 }
393
394 void InspectorResourceAgent::didReceiveXHRResponse(unsigned long identifier)
395 {
396     m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::XHRResource);
397 }
398
399 void InspectorResourceAgent::willLoadXHRSynchronously()
400 {
401     m_loadingXHRSynchronously = true;
402 }
403
404 void InspectorResourceAgent::didLoadXHRSynchronously()
405 {
406     m_loadingXHRSynchronously = false;
407 }
408
409 void InspectorResourceAgent::willDestroyCachedResource(CachedResource* cachedResource)
410 {
411     Vector<String> requestIds = m_resourcesData->removeCachedResource(cachedResource);
412     if (!requestIds.size())
413         return;
414
415     String content;
416     bool base64Encoded;
417     if (!InspectorPageAgent::cachedResourceContent(cachedResource, &content, &base64Encoded))
418         return;
419     Vector<String>::iterator end = requestIds.end();
420     for (Vector<String>::iterator it = requestIds.begin(); it != end; ++it)
421         m_resourcesData->setResourceContent(*it, content, base64Encoded);
422 }
423
424 void InspectorResourceAgent::willRecalculateStyle()
425 {
426     m_isRecalculatingStyle = true;
427 }
428
429 void InspectorResourceAgent::didRecalculateStyle()
430 {
431     m_isRecalculatingStyle = false;
432     m_styleRecalculationInitiator = nullptr;
433 }
434
435 void InspectorResourceAgent::didScheduleStyleRecalculation(Document* document)
436 {
437     if (!m_styleRecalculationInitiator)
438         m_styleRecalculationInitiator = buildInitiatorObject(document);
439 }
440
441 PassRefPtr<Inspector::TypeBuilder::Network::Initiator> InspectorResourceAgent::buildInitiatorObject(Document* document)
442 {
443     RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
444     if (stackTrace && stackTrace->size() > 0) {
445         RefPtr<Inspector::TypeBuilder::Network::Initiator> initiatorObject = Inspector::TypeBuilder::Network::Initiator::create()
446             .setType(Inspector::TypeBuilder::Network::Initiator::Type::Script);
447         initiatorObject->setStackTrace(stackTrace->buildInspectorArray());
448         return initiatorObject;
449     }
450
451     if (document && document->scriptableDocumentParser()) {
452         RefPtr<Inspector::TypeBuilder::Network::Initiator> initiatorObject = Inspector::TypeBuilder::Network::Initiator::create()
453             .setType(Inspector::TypeBuilder::Network::Initiator::Type::Parser);
454         initiatorObject->setUrl(document->url().string());
455         initiatorObject->setLineNumber(document->scriptableDocumentParser()->textPosition().m_line.oneBasedInt());
456         return initiatorObject;
457     }
458
459     if (m_isRecalculatingStyle && m_styleRecalculationInitiator)
460         return m_styleRecalculationInitiator;
461
462     return Inspector::TypeBuilder::Network::Initiator::create()
463         .setType(Inspector::TypeBuilder::Network::Initiator::Type::Other)
464         .release();
465 }
466
467 #if ENABLE(WEB_SOCKETS)
468
469 void InspectorResourceAgent::didCreateWebSocket(unsigned long identifier, const URL& requestURL)
470 {
471     m_frontendDispatcher->webSocketCreated(IdentifiersFactory::requestId(identifier), requestURL.string());
472 }
473
474 void InspectorResourceAgent::willSendWebSocketHandshakeRequest(unsigned long identifier, const ResourceRequest& request)
475 {
476     RefPtr<Inspector::TypeBuilder::Network::WebSocketRequest> requestObject = Inspector::TypeBuilder::Network::WebSocketRequest::create()
477         .setHeaders(buildObjectForHeaders(request.httpHeaderFields()));
478     m_frontendDispatcher->webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), currentTime(), requestObject);
479 }
480
481 void InspectorResourceAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const ResourceResponse& response)
482 {
483     RefPtr<Inspector::TypeBuilder::Network::WebSocketResponse> responseObject = Inspector::TypeBuilder::Network::WebSocketResponse::create()
484         .setStatus(response.httpStatusCode())
485         .setStatusText(response.httpStatusText())
486         .setHeaders(buildObjectForHeaders(response.httpHeaderFields()));
487     m_frontendDispatcher->webSocketHandshakeResponseReceived(IdentifiersFactory::requestId(identifier), currentTime(), responseObject);
488 }
489
490 void InspectorResourceAgent::didCloseWebSocket(unsigned long identifier)
491 {
492     m_frontendDispatcher->webSocketClosed(IdentifiersFactory::requestId(identifier), currentTime());
493 }
494
495 void InspectorResourceAgent::didReceiveWebSocketFrame(unsigned long identifier, const WebSocketFrame& frame)
496 {
497     RefPtr<Inspector::TypeBuilder::Network::WebSocketFrame> frameObject = Inspector::TypeBuilder::Network::WebSocketFrame::create()
498         .setOpcode(frame.opCode)
499         .setMask(frame.masked)
500         .setPayloadData(String(frame.payload, frame.payloadLength));
501     m_frontendDispatcher->webSocketFrameReceived(IdentifiersFactory::requestId(identifier), currentTime(), frameObject);
502 }
503
504 void InspectorResourceAgent::didSendWebSocketFrame(unsigned long identifier, const WebSocketFrame& frame)
505 {
506     RefPtr<Inspector::TypeBuilder::Network::WebSocketFrame> frameObject = Inspector::TypeBuilder::Network::WebSocketFrame::create()
507         .setOpcode(frame.opCode)
508         .setMask(frame.masked)
509         .setPayloadData(String(frame.payload, frame.payloadLength));
510     m_frontendDispatcher->webSocketFrameSent(IdentifiersFactory::requestId(identifier), currentTime(), frameObject);
511 }
512
513 void InspectorResourceAgent::didReceiveWebSocketFrameError(unsigned long identifier, const String& errorMessage)
514 {
515     m_frontendDispatcher->webSocketFrameError(IdentifiersFactory::requestId(identifier), currentTime(), errorMessage);
516 }
517
518 #endif // ENABLE(WEB_SOCKETS)
519
520 // called from Internals for layout test purposes.
521 void InspectorResourceAgent::setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize)
522 {
523     m_resourcesData->setResourcesDataSizeLimits(maximumResourcesContentSize, maximumSingleResourceContentSize);
524 }
525
526 void InspectorResourceAgent::enable(ErrorString*)
527 {
528     enable();
529 }
530
531 void InspectorResourceAgent::enable()
532 {
533     if (!m_frontendDispatcher)
534         return;
535     m_enabled = true;
536     m_instrumentingAgents->setInspectorResourceAgent(this);
537 }
538
539 void InspectorResourceAgent::disable(ErrorString*)
540 {
541     m_enabled = false;
542     m_instrumentingAgents->setInspectorResourceAgent(nullptr);
543     m_resourcesData->clear();
544     m_extraRequestHeaders.clear();
545 }
546
547 void InspectorResourceAgent::setExtraHTTPHeaders(ErrorString*, const RefPtr<InspectorObject>& headers)
548 {
549     m_extraRequestHeaders = headers;
550 }
551
552 void InspectorResourceAgent::getResponseBody(ErrorString* errorString, const String& requestId, String* content, bool* base64Encoded)
553 {
554     NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
555     if (!resourceData) {
556         *errorString = "No resource with given identifier found";
557         return;
558     }
559
560     if (resourceData->hasContent()) {
561         *base64Encoded = resourceData->base64Encoded();
562         *content = resourceData->content();
563         return;
564     }
565
566     if (resourceData->isContentEvicted()) {
567         *errorString = "Request content was evicted from inspector cache";
568         return;
569     }
570
571     if (resourceData->buffer() && !resourceData->textEncodingName().isNull()) {
572         *base64Encoded = false;
573         if (InspectorPageAgent::sharedBufferContent(resourceData->buffer(), resourceData->textEncodingName(), *base64Encoded, content))
574             return;
575     }
576
577     if (resourceData->cachedResource()) {
578         if (InspectorPageAgent::cachedResourceContent(resourceData->cachedResource(), content, base64Encoded))
579             return;
580     }
581
582     *errorString = "No data found for resource with given identifier";
583 }
584
585 void InspectorResourceAgent::replayXHR(ErrorString*, const String& requestId)
586 {
587     RefPtr<XMLHttpRequest> xhr = XMLHttpRequest::create(*m_pageAgent->mainFrame()->document());
588     String actualRequestId = requestId;
589
590     XHRReplayData* xhrReplayData = m_resourcesData->xhrReplayData(requestId);
591     if (!xhrReplayData)
592         return;
593
594     ResourceRequest request(xhrReplayData->url());
595 #if ENABLE(CACHE_PARTITIONING)
596     request.setCachePartition(m_pageAgent->mainFrame()->document()->topOrigin()->cachePartition());
597 #endif
598     CachedResource* cachedResource = memoryCache()->resourceForRequest(request);
599     if (cachedResource)
600         memoryCache()->remove(cachedResource);
601
602     xhr->open(xhrReplayData->method(), xhrReplayData->url(), xhrReplayData->async(), IGNORE_EXCEPTION);
603     HTTPHeaderMap::const_iterator end = xhrReplayData->headers().end();
604     for (HTTPHeaderMap::const_iterator it = xhrReplayData->headers().begin(); it!= end; ++it)
605         xhr->setRequestHeader(it->key, it->value, IGNORE_EXCEPTION);
606     xhr->sendFromInspector(xhrReplayData->formData(), IGNORE_EXCEPTION);
607 }
608
609 void InspectorResourceAgent::canClearBrowserCache(ErrorString*, bool* result)
610 {
611     *result = m_client->canClearBrowserCache();
612 }
613
614 void InspectorResourceAgent::clearBrowserCache(ErrorString*)
615 {
616     m_client->clearBrowserCache();
617 }
618
619 void InspectorResourceAgent::canClearBrowserCookies(ErrorString*, bool* result)
620 {
621     *result = m_client->canClearBrowserCookies();
622 }
623
624 void InspectorResourceAgent::clearBrowserCookies(ErrorString*)
625 {
626     m_client->clearBrowserCookies();
627 }
628
629 void InspectorResourceAgent::setCacheDisabled(ErrorString*, bool cacheDisabled)
630 {
631     m_cacheDisabled = cacheDisabled;
632     if (cacheDisabled)
633         memoryCache()->evictResources();
634 }
635
636 void InspectorResourceAgent::mainFrameNavigated(DocumentLoader* loader)
637 {
638     if (m_cacheDisabled)
639         memoryCache()->evictResources();
640
641     m_resourcesData->clear(m_pageAgent->loaderId(loader));
642 }
643
644 InspectorResourceAgent::InspectorResourceAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorClient* client)
645     : InspectorAgentBase(ASCIILiteral("Network"), instrumentingAgents)
646     , m_pageAgent(pageAgent)
647     , m_client(client)
648     , m_resourcesData(adoptPtr(new NetworkResourcesData()))
649     , m_enabled(false)
650     , m_cacheDisabled(false)
651     , m_loadingXHRSynchronously(false)
652     , m_isRecalculatingStyle(false)
653 {
654 }
655
656 } // namespace WebCore
657
658 #endif // ENABLE(INSPECTOR)