Home | History | Annotate | Download | only in inspector
      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 
     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 
    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 
    113 void InspectorResourceAgent::restore()
    114 {
    115     if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled))
    116         enable();
    117 }
    118 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    334 void InspectorResourceAgent::markResourceAsCached(unsigned long identifier)
    335 {
    336     m_frontend->resourceMarkedAsCached(static_cast<int>(identifier));
    337 }
    338 
    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 
    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 
    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 
    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 
    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 
    389 void InspectorResourceAgent::setInitialScriptContent(unsigned long identifier, const String& sourceString)
    390 {
    391     m_frontend->initialContentSet(static_cast<int>(identifier), sourceString, ResourceType::script);
    392 }
    393 
    394 void InspectorResourceAgent::setInitialXHRContent(unsigned long identifier, const String& sourceString)
    395 {
    396     m_frontend->initialContentSet(static_cast<int>(identifier), sourceString, ResourceType::xhr);
    397 }
    398 
    399 void InspectorResourceAgent::domContentEventFired()
    400 {
    401     m_frontend->domContentEventFired(currentTime());
    402 }
    403 
    404 void InspectorResourceAgent::loadEventFired()
    405 {
    406     m_frontend->loadEventFired(currentTime());
    407 }
    408 
    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 
    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 
    455 void InspectorResourceAgent::didCommitLoad(DocumentLoader* loader)
    456 {
    457     m_frontend->frameNavigated(buildObjectForFrame(loader->frame()), pointerAsId(loader));
    458 }
    459 
    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".
    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 
    482 void InspectorResourceAgent::didCreateWebSocket(unsigned long identifier, const KURL& requestURL)
    483 {
    484     m_frontend->webSocketCreated(static_cast<int>(identifier), requestURL.string());
    485 }
    486 
    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 
    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 
    505 void InspectorResourceAgent::didCloseWebSocket(unsigned long identifier)
    506 {
    507     m_frontend->webSocketClosed(static_cast<int>(identifier), currentTime());
    508 }
    509 #endif // ENABLE(WEB_SOCKETS)
    510 
    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 
    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 
    529 void InspectorResourceAgent::enable(ErrorString*)
    530 {
    531     enable();
    532 }
    533 
    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 
    542 void InspectorResourceAgent::disable(ErrorString*)
    543 {
    544     m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, false);
    545     m_instrumentingAgents->setInspectorResourceAgent(0);
    546 }
    547 
    548 void InspectorResourceAgent::getCachedResources(ErrorString*, RefPtr<InspectorObject>* object)
    549 {
    550     *object = buildObjectForFrameTree(m_page->mainFrame());
    551 }
    552 
    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 
    566 void InspectorResourceAgent::setExtraHeaders(ErrorString*, PassRefPtr<InspectorObject> headers)
    567 {
    568     m_state->setObject(ResourceAgentState::extraRequestHeaders, headers);
    569 }
    570 
    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