• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Base64.h"
37 #include "CachedResource.h"
38 #include "CachedResourceLoader.h"
39 #include "Document.h"
40 #include "DocumentLoader.h"
41 #include "EventsCollector.h"
42 #include "Frame.h"
43 #include "FrameLoader.h"
44 #include "HTMLFrameOwnerElement.h"
45 #include "HTMLNames.h"
46 #include "HTTPHeaderMap.h"
47 #include "InspectorFrontend.h"
48 #include "InspectorFrontendChannel.h"
49 #include "InspectorFrontendProxy.h"
50 #include "InspectorState.h"
51 #include "InspectorValues.h"
52 #include "InstrumentingAgents.h"
53 #include "KURL.h"
54 #include "MemoryCache.h"
55 #include "Page.h"
56 #include "ProgressTracker.h"
57 #include "ResourceError.h"
58 #include "ResourceRequest.h"
59 #include "ResourceResponse.h"
60 #include "ScriptCallStack.h"
61 #include "ScriptCallStackFactory.h"
62 #include "SharedBuffer.h"
63 #include "TextEncoding.h"
64 #include "WebSocketHandshakeRequest.h"
65 #include "WebSocketHandshakeResponse.h"
66 
67 #include <wtf/CurrentTime.h>
68 #include <wtf/HexNumber.h>
69 #include <wtf/ListHashSet.h>
70 #include <wtf/RefPtr.h>
71 #include <wtf/text/StringBuilder.h>
72 
73 namespace WebCore {
74 
75 namespace ResourceAgentState {
76 static const char resourceAgentEnabled[] = "resourceAgentEnabled";
77 static const char extraRequestHeaders[] = "extraRequestHeaders";
78 }
79 
80 namespace ResourceType {
81 static const char document[] = "Document";
82 static const char stylesheet[] = "Stylesheet";
83 static const char image[] = "Image";
84 static const char font[] = "Font";
85 static const char script[] = "Script";
86 static const char xhr[] = "XHR";
87 static const char websocket[] = "WebSocket";
88 static const char other[] = "Other";
89 }
90 
setFrontend(InspectorFrontend * frontend)91 void InspectorResourceAgent::setFrontend(InspectorFrontend* frontend)
92 {
93     m_frontend = frontend->network();
94     if (backgroundEventsCollectionEnabled()) {
95         // Insert Message Proxy in receiver chain.
96         InspectorFrontendChannel* client = m_frontend->getInspectorFrontendChannel();
97         m_inspectorFrontendProxy->setInspectorFrontendChannel(client);
98         m_frontend->setInspectorFrontendChannel(m_inspectorFrontendProxy.get());
99         m_eventsCollector->sendCollectedEvents(client);
100     }
101 }
102 
clearFrontend()103 void InspectorResourceAgent::clearFrontend()
104 {
105     if (backgroundEventsCollectionEnabled()) {
106         m_inspectorFrontendProxy->setInspectorFrontendChannel(0);
107         m_frontend = m_mockFrontend.get();
108     } else
109         m_frontend = 0;
110     disable(0);
111 }
112 
restore()113 void InspectorResourceAgent::restore()
114 {
115     if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled))
116         enable();
117 }
118 
resourceContent(ErrorString * errorString,Frame * frame,const KURL & url,String * result)119 void InspectorResourceAgent::resourceContent(ErrorString* errorString, Frame* frame, const KURL& url, String* result)
120 {
121     if (!frame) {
122         *errorString = "No frame to get resource content for";
123         return;
124     }
125 
126     String textEncodingName;
127     RefPtr<SharedBuffer> buffer = InspectorResourceAgent::resourceData(frame, url, &textEncodingName);
128 
129     if (buffer) {
130         TextEncoding encoding(textEncodingName);
131         if (!encoding.isValid())
132             encoding = WindowsLatin1Encoding();
133         *result = encoding.decode(buffer->data(), buffer->size());
134         return;
135     }
136     *errorString = "No resource with given URL found";
137 }
138 
resourceContentBase64(ErrorString * errorString,Frame * frame,const KURL & url,String * result)139 void InspectorResourceAgent::resourceContentBase64(ErrorString* errorString, Frame* frame, const KURL& url, String* result)
140 {
141     String textEncodingName;
142     RefPtr<SharedBuffer> data = InspectorResourceAgent::resourceData(frame, url, &textEncodingName);
143     if (!data) {
144         *result = String();
145         *errorString = "No resource with given URL found";
146         return;
147     }
148 
149     *result = base64Encode(data->data(), data->size());
150 }
151 
resourceData(Frame * frame,const KURL & url,String * textEncodingName)152 PassRefPtr<SharedBuffer> InspectorResourceAgent::resourceData(Frame* frame, const KURL& url, String* textEncodingName)
153 {
154     FrameLoader* frameLoader = frame->loader();
155     DocumentLoader* loader = frameLoader->documentLoader();
156     if (equalIgnoringFragmentIdentifier(url, loader->url())) {
157         *textEncodingName = frame->document()->inputEncoding();
158         return frameLoader->documentLoader()->mainResourceData();
159     }
160 
161     CachedResource* cachedResource = InspectorResourceAgent::cachedResource(frame, url);
162     if (!cachedResource)
163         return 0;
164 
165     // Zero-sized resources don't have data at all -- so fake the empty buffer, insted of indicating error by returning 0.
166     if (!cachedResource->encodedSize())
167         return SharedBuffer::create();
168 
169     if (cachedResource->isPurgeable()) {
170         // If the resource is purgeable then make it unpurgeable to get
171         // get its data. This might fail, in which case we return an
172         // empty String.
173         // FIXME: should we do something else in the case of a purged
174         // resource that informs the user why there is no data in the
175         // inspector?
176         if (!cachedResource->makePurgeable(false))
177             return 0;
178     }
179 
180     *textEncodingName = cachedResource->encoding();
181     return cachedResource->data();
182 }
183 
cachedResource(Frame * frame,const KURL & url)184 CachedResource* InspectorResourceAgent::cachedResource(Frame* frame, const KURL& url)
185 {
186     CachedResource* cachedResource = frame->document()->cachedResourceLoader()->cachedResource(url);
187     if (!cachedResource)
188         cachedResource = memoryCache()->resourceForURL(url);
189     return cachedResource;
190 }
191 
buildObjectForHeaders(const HTTPHeaderMap & headers)192 static PassRefPtr<InspectorObject> buildObjectForHeaders(const HTTPHeaderMap& headers)
193 {
194     RefPtr<InspectorObject> headersObject = InspectorObject::create();
195     HTTPHeaderMap::const_iterator end = headers.end();
196     for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
197         headersObject->setString(it->first.string(), it->second);
198     return headersObject;
199 }
200 
buildObjectForTiming(const ResourceLoadTiming & timing)201 static PassRefPtr<InspectorObject> buildObjectForTiming(const ResourceLoadTiming& timing)
202 {
203     RefPtr<InspectorObject> timingObject = InspectorObject::create();
204     timingObject->setNumber("requestTime", timing.requestTime);
205     timingObject->setNumber("proxyStart", timing.proxyStart);
206     timingObject->setNumber("proxyEnd", timing.proxyEnd);
207     timingObject->setNumber("dnsStart", timing.dnsStart);
208     timingObject->setNumber("dnsEnd", timing.dnsEnd);
209     timingObject->setNumber("connectStart", timing.connectStart);
210     timingObject->setNumber("connectEnd", timing.connectEnd);
211     timingObject->setNumber("sslStart", timing.sslStart);
212     timingObject->setNumber("sslEnd", timing.sslEnd);
213     timingObject->setNumber("sendStart", timing.sendStart);
214     timingObject->setNumber("sendEnd", timing.sendEnd);
215     timingObject->setNumber("receiveHeadersEnd", timing.receiveHeadersEnd);
216     return timingObject;
217 }
218 
buildObjectForResourceRequest(const ResourceRequest & request)219 static PassRefPtr<InspectorObject> buildObjectForResourceRequest(const ResourceRequest& request)
220 {
221     RefPtr<InspectorObject> requestObject = InspectorObject::create();
222     requestObject->setString("url", request.url().string());
223     requestObject->setString("method", request.httpMethod());
224     requestObject->setObject("headers", buildObjectForHeaders(request.httpHeaderFields()));
225     if (request.httpBody() && !request.httpBody()->isEmpty())
226         requestObject->setString("postData", request.httpBody()->flattenToString());
227     return requestObject;
228 }
229 
buildObjectForResourceResponse(const ResourceResponse & response)230 static PassRefPtr<InspectorObject> buildObjectForResourceResponse(const ResourceResponse& response)
231 {
232     if (response.isNull())
233         return 0;
234 
235     RefPtr<InspectorObject> responseObject = InspectorObject::create();
236     responseObject->setNumber("status", response.resourceLoadInfo() ? response.resourceLoadInfo()->httpStatusCode : response.httpStatusCode());
237     responseObject->setString("statusText", response.resourceLoadInfo() ? response.resourceLoadInfo()->httpStatusText : response.httpStatusText());
238 
239     responseObject->setString("mimeType", response.mimeType());
240     responseObject->setBoolean("connectionReused", response.connectionReused());
241     responseObject->setNumber("connectionID", response.connectionID());
242     responseObject->setBoolean("fromDiskCache", response.wasCached());
243     if (response.resourceLoadTiming())
244         responseObject->setObject("timing", buildObjectForTiming(*response.resourceLoadTiming()));
245 
246     if (response.resourceLoadInfo()) {
247         responseObject->setObject("headers", buildObjectForHeaders(response.resourceLoadInfo()->responseHeaders));
248         if (!response.resourceLoadInfo()->responseHeadersText.isEmpty())
249             responseObject->setString("headersText", response.resourceLoadInfo()->responseHeadersText);
250 
251         responseObject->setObject("requestHeaders", buildObjectForHeaders(response.resourceLoadInfo()->requestHeaders));
252         if (!response.resourceLoadInfo()->requestHeadersText.isEmpty())
253             responseObject->setString("requestHeadersText", response.resourceLoadInfo()->requestHeadersText);
254     } else
255         responseObject->setObject("headers", buildObjectForHeaders(response.httpHeaderFields()));
256 
257     return responseObject;
258 }
259 
pointerAsId(void * pointer)260 static String pointerAsId(void* pointer)
261 {
262     unsigned long long address = reinterpret_cast<uintptr_t>(pointer);
263     // We want 0 to be "", so that JavaScript checks for if (frameId) worked.
264     return String::format("%.0llX", address);
265 }
266 
cachedResourceTypeString(const CachedResource & cachedResource)267 static String cachedResourceTypeString(const CachedResource& cachedResource)
268 {
269     switch (cachedResource.type()) {
270     case CachedResource::ImageResource:
271         return ResourceType::image;
272     case CachedResource::FontResource:
273         return ResourceType::font;
274     case CachedResource::CSSStyleSheet:
275         // Fall through.
276 #if ENABLE(XSLT)
277     case CachedResource::XSLStyleSheet:
278 #endif
279         return ResourceType::stylesheet;
280     case CachedResource::Script:
281         return ResourceType::script;
282     default:
283         break;
284     }
285     return ResourceType::other;
286 }
287 
buildObjectForCachedResource(const CachedResource & cachedResource)288 static PassRefPtr<InspectorObject> buildObjectForCachedResource(const CachedResource& cachedResource)
289 {
290     RefPtr<InspectorObject> resourceObject = InspectorObject::create();
291     resourceObject->setString("url", cachedResource.url());
292     resourceObject->setString("type", cachedResourceTypeString(cachedResource));
293     resourceObject->setNumber("bodySize", cachedResource.encodedSize());
294     RefPtr<InspectorObject> resourceResponse = buildObjectForResourceResponse(cachedResource.response());
295     if (resourceResponse)
296         resourceObject->setObject("response", resourceResponse);
297     return resourceObject;
298 }
299 
~InspectorResourceAgent()300 InspectorResourceAgent::~InspectorResourceAgent()
301 {
302     if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled)) {
303         ErrorString error;
304         disable(&error);
305     }
306     ASSERT(!m_instrumentingAgents->inspectorResourceAgent());
307 }
308 
willSendRequest(unsigned long identifier,DocumentLoader * loader,ResourceRequest & request,const ResourceResponse & redirectResponse)309 void InspectorResourceAgent::willSendRequest(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
310 {
311     RefPtr<InspectorObject> headers = m_state->getObject(ResourceAgentState::extraRequestHeaders);
312 
313     if (headers) {
314         InspectorObject::const_iterator end = headers->end();
315         for (InspectorObject::const_iterator it = headers->begin(); it != end; ++it) {
316             String value;
317             if (it->second->asString(&value))
318                 request.setHTTPHeaderField(it->first, value);
319         }
320     }
321 
322     request.setReportLoadTiming(true);
323     request.setReportRawHeaders(true);
324 
325     RefPtr<ScriptCallStack> callStack = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
326     RefPtr<InspectorArray> callStackValue;
327     if (callStack)
328         callStackValue = callStack->buildInspectorArray();
329     else
330         callStackValue = InspectorArray::create();
331     m_frontend->requestWillBeSent(static_cast<int>(identifier), pointerAsId(loader->frame()), pointerAsId(loader), loader->url().string(), buildObjectForResourceRequest(request), currentTime(), callStackValue, buildObjectForResourceResponse(redirectResponse));
332 }
333 
markResourceAsCached(unsigned long identifier)334 void InspectorResourceAgent::markResourceAsCached(unsigned long identifier)
335 {
336     m_frontend->resourceMarkedAsCached(static_cast<int>(identifier));
337 }
338 
didReceiveResponse(unsigned long identifier,DocumentLoader * loader,const ResourceResponse & response)339 void InspectorResourceAgent::didReceiveResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response)
340 {
341     RefPtr<InspectorObject> resourceResponse = buildObjectForResourceResponse(response);
342     String type = "Other";
343     long cachedResourceSize = 0;
344 
345     if (loader) {
346         CachedResource* cachedResource = InspectorResourceAgent::cachedResource(loader->frame(), response.url());
347         if (cachedResource) {
348             type = cachedResourceTypeString(*cachedResource);
349             cachedResourceSize = cachedResource->encodedSize();
350             // Use mime type from cached resource in case the one in response is empty.
351             if (response.mimeType().isEmpty())
352                 resourceResponse->setString("mimeType", cachedResource->response().mimeType());
353         }
354         if (equalIgnoringFragmentIdentifier(response.url(), loader->frameLoader()->iconURL()))
355             type = ResourceType::image;
356         else if (equalIgnoringFragmentIdentifier(response.url(), loader->url()) && type == "Other")
357             type = ResourceType::document;
358     }
359     m_frontend->responseReceived(static_cast<int>(identifier), currentTime(), type, resourceResponse);
360     // If we revalidated the resource and got Not modified, send content length following didReceiveResponse
361     // as there will be no calls to didReceiveContentLength from the network stack.
362     if (cachedResourceSize && response.httpStatusCode() == 304)
363         didReceiveContentLength(identifier, cachedResourceSize, 0);
364 }
365 
didReceiveContentLength(unsigned long identifier,int dataLength,int encodedDataLength)366 void InspectorResourceAgent::didReceiveContentLength(unsigned long identifier, int dataLength, int encodedDataLength)
367 {
368     m_frontend->dataReceived(static_cast<int>(identifier), currentTime(), dataLength, encodedDataLength);
369 }
370 
didFinishLoading(unsigned long identifier,double finishTime)371 void InspectorResourceAgent::didFinishLoading(unsigned long identifier, double finishTime)
372 {
373     if (!finishTime)
374         finishTime = currentTime();
375 
376     m_frontend->loadingFinished(static_cast<int>(identifier), finishTime);
377 }
378 
didFailLoading(unsigned long identifier,const ResourceError & error)379 void InspectorResourceAgent::didFailLoading(unsigned long identifier, const ResourceError& error)
380 {
381     m_frontend->loadingFailed(static_cast<int>(identifier), currentTime(), error.localizedDescription(), error.isCancellation());
382 }
383 
didLoadResourceFromMemoryCache(DocumentLoader * loader,const CachedResource * resource)384 void InspectorResourceAgent::didLoadResourceFromMemoryCache(DocumentLoader* loader, const CachedResource* resource)
385 {
386     m_frontend->resourceLoadedFromMemoryCache(pointerAsId(loader->frame()), pointerAsId(loader), loader->url().string(), currentTime(), buildObjectForCachedResource(*resource));
387 }
388 
setInitialScriptContent(unsigned long identifier,const String & sourceString)389 void InspectorResourceAgent::setInitialScriptContent(unsigned long identifier, const String& sourceString)
390 {
391     m_frontend->initialContentSet(static_cast<int>(identifier), sourceString, ResourceType::script);
392 }
393 
setInitialXHRContent(unsigned long identifier,const String & sourceString)394 void InspectorResourceAgent::setInitialXHRContent(unsigned long identifier, const String& sourceString)
395 {
396     m_frontend->initialContentSet(static_cast<int>(identifier), sourceString, ResourceType::xhr);
397 }
398 
domContentEventFired()399 void InspectorResourceAgent::domContentEventFired()
400 {
401     m_frontend->domContentEventFired(currentTime());
402 }
403 
loadEventFired()404 void InspectorResourceAgent::loadEventFired()
405 {
406     m_frontend->loadEventFired(currentTime());
407 }
408 
buildObjectForFrame(Frame * frame)409 static PassRefPtr<InspectorObject> buildObjectForFrame(Frame* frame)
410 {
411     RefPtr<InspectorObject> frameObject = InspectorObject::create();
412     frameObject->setString("id", pointerAsId(frame));
413     frameObject->setString("parentId", pointerAsId(frame->tree()->parent()));
414     if (frame->ownerElement()) {
415         String name = frame->ownerElement()->getAttribute(HTMLNames::nameAttr);
416         if (name.isEmpty())
417             name = frame->ownerElement()->getAttribute(HTMLNames::idAttr);
418         frameObject->setString("name", name);
419     }
420     frameObject->setString("url", frame->document()->url().string());
421     frameObject->setString("loaderId", pointerAsId(frame->loader()->documentLoader()));
422 
423     return frameObject;
424 }
425 
buildObjectForFrameTree(Frame * frame)426 static PassRefPtr<InspectorObject> buildObjectForFrameTree(Frame* frame)
427 {
428     RefPtr<InspectorObject> result = InspectorObject::create();
429     RefPtr<InspectorObject> frameObject = buildObjectForFrame(frame);
430     result->setObject("frame", frameObject);
431 
432     RefPtr<InspectorArray> subresources = InspectorArray::create();
433     result->setArray("resources", subresources);
434     const CachedResourceLoader::DocumentResourceMap& allResources = frame->document()->cachedResourceLoader()->allCachedResources();
435     CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
436     for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) {
437         CachedResource* cachedResource = it->second.get();
438         RefPtr<InspectorObject> resourceObject = InspectorObject::create();
439         resourceObject->setString("url", cachedResource->url());
440         resourceObject->setString("type", cachedResourceTypeString(*cachedResource));
441         subresources->pushValue(resourceObject);
442     }
443 
444     RefPtr<InspectorArray> childrenArray;
445     for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
446         if (!childrenArray) {
447             childrenArray = InspectorArray::create();
448             result->setArray("childFrames", childrenArray);
449         }
450         childrenArray->pushObject(buildObjectForFrameTree(child));
451     }
452     return result;
453 }
454 
didCommitLoad(DocumentLoader * loader)455 void InspectorResourceAgent::didCommitLoad(DocumentLoader* loader)
456 {
457     m_frontend->frameNavigated(buildObjectForFrame(loader->frame()), pointerAsId(loader));
458 }
459 
frameDetachedFromParent(Frame * frame)460 void InspectorResourceAgent::frameDetachedFromParent(Frame* frame)
461 {
462     m_frontend->frameDetached(pointerAsId(frame));
463 }
464 
465 #if ENABLE(WEB_SOCKETS)
466 
467 // FIXME: More this into the front-end?
468 // Create human-readable binary representation, like "01:23:45:67:89:AB:CD:EF".
createReadableStringFromBinary(const unsigned char * value,size_t length)469 static String createReadableStringFromBinary(const unsigned char* value, size_t length)
470 {
471     ASSERT(length > 0);
472     StringBuilder builder;
473     builder.reserveCapacity(length * 3 - 1);
474     for (size_t i = 0; i < length; ++i) {
475         if (i > 0)
476             builder.append(':');
477         appendByteAsHex(value[i], builder);
478     }
479     return builder.toString();
480 }
481 
didCreateWebSocket(unsigned long identifier,const KURL & requestURL)482 void InspectorResourceAgent::didCreateWebSocket(unsigned long identifier, const KURL& requestURL)
483 {
484     m_frontend->webSocketCreated(static_cast<int>(identifier), requestURL.string());
485 }
486 
willSendWebSocketHandshakeRequest(unsigned long identifier,const WebSocketHandshakeRequest & request)487 void InspectorResourceAgent::willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest& request)
488 {
489     RefPtr<InspectorObject> requestObject = InspectorObject::create();
490     requestObject->setObject("headers", buildObjectForHeaders(request.headerFields()));
491     requestObject->setString("requestKey3", createReadableStringFromBinary(request.key3().value, sizeof(request.key3().value)));
492     m_frontend->webSocketWillSendHandshakeRequest(static_cast<int>(identifier), currentTime(), requestObject);
493 }
494 
didReceiveWebSocketHandshakeResponse(unsigned long identifier,const WebSocketHandshakeResponse & response)495 void InspectorResourceAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse& response)
496 {
497     RefPtr<InspectorObject> responseObject = InspectorObject::create();
498     responseObject->setNumber("status", response.statusCode());
499     responseObject->setString("statusText", response.statusText());
500     responseObject->setObject("headers", buildObjectForHeaders(response.headerFields()));
501     responseObject->setString("challengeResponse", createReadableStringFromBinary(response.challengeResponse().value, sizeof(response.challengeResponse().value)));
502     m_frontend->webSocketHandshakeResponseReceived(static_cast<int>(identifier), currentTime(), responseObject);
503 }
504 
didCloseWebSocket(unsigned long identifier)505 void InspectorResourceAgent::didCloseWebSocket(unsigned long identifier)
506 {
507     m_frontend->webSocketClosed(static_cast<int>(identifier), currentTime());
508 }
509 #endif // ENABLE(WEB_SOCKETS)
510 
frameForId(const String & frameId)511 Frame* InspectorResourceAgent::frameForId(const String& frameId)
512 {
513     Frame* mainFrame = m_page->mainFrame();
514     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext(mainFrame)) {
515         if (pointerAsId(frame) == frameId)
516             return frame;
517     }
518     return 0;
519 }
520 
backgroundEventsCollectionEnabled()521 bool InspectorResourceAgent::backgroundEventsCollectionEnabled()
522 {
523     // FIXME (https://bugs.webkit.org/show_bug.cgi?id=58652)
524     // Add here condition to enable background events collection.
525     // Now this function is disable.
526     return false;
527 }
528 
enable(ErrorString *)529 void InspectorResourceAgent::enable(ErrorString*)
530 {
531     enable();
532 }
533 
enable()534 void InspectorResourceAgent::enable()
535 {
536     if (!m_frontend)
537         return;
538     m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, true);
539     m_instrumentingAgents->setInspectorResourceAgent(this);
540 }
541 
disable(ErrorString *)542 void InspectorResourceAgent::disable(ErrorString*)
543 {
544     m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, false);
545     m_instrumentingAgents->setInspectorResourceAgent(0);
546 }
547 
getCachedResources(ErrorString *,RefPtr<InspectorObject> * object)548 void InspectorResourceAgent::getCachedResources(ErrorString*, RefPtr<InspectorObject>* object)
549 {
550     *object = buildObjectForFrameTree(m_page->mainFrame());
551 }
552 
getResourceContent(ErrorString * errorString,const String & frameId,const String & url,const bool * const optionalBase64Encode,String * content)553 void InspectorResourceAgent::getResourceContent(ErrorString* errorString, const String& frameId, const String& url, const bool* const optionalBase64Encode, String* content)
554 {
555     Frame* frame = frameForId(frameId);
556     if (!frame) {
557         *errorString = "No frame for given id found";
558         return;
559     }
560     if (optionalBase64Encode ? *optionalBase64Encode : false)
561         InspectorResourceAgent::resourceContentBase64(errorString, frame, KURL(ParsedURLString, url), content);
562     else
563         InspectorResourceAgent::resourceContent(errorString, frame, KURL(ParsedURLString, url), content);
564 }
565 
setExtraHeaders(ErrorString *,PassRefPtr<InspectorObject> headers)566 void InspectorResourceAgent::setExtraHeaders(ErrorString*, PassRefPtr<InspectorObject> headers)
567 {
568     m_state->setObject(ResourceAgentState::extraRequestHeaders, headers);
569 }
570 
InspectorResourceAgent(InstrumentingAgents * instrumentingAgents,Page * page,InspectorState * state)571 InspectorResourceAgent::InspectorResourceAgent(InstrumentingAgents* instrumentingAgents, Page* page, InspectorState* state)
572     : m_instrumentingAgents(instrumentingAgents)
573     , m_page(page)
574     , m_state(state)
575 {
576     if (backgroundEventsCollectionEnabled()) {
577         m_eventsCollector = new EventsCollector();
578         m_inspectorFrontendProxy = new InspectorFrontendProxy(m_eventsCollector.get());
579         // Create mock frontend, so we can collect network events.
580         m_mockFrontend = new InspectorFrontend::Network(m_inspectorFrontendProxy.get());
581         m_frontend = m_mockFrontend.get();
582         enable();
583     } else
584         m_frontend = 0;
585 }
586 
587 } // namespace WebCore
588 
589 #endif // ENABLE(INSPECTOR)
590