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