unsigned long long PerformanceTiming::resourceLoadTimeRelativeToAbsolute(int relativeMilliseconds) const { ASSERT(relativeMilliseconds >= 0); ResourceLoadTiming* resourceTiming = resourceLoadTiming(); ASSERT(resourceTiming); return monotonicTimeToIntegerMilliseconds(resourceTiming->convertResourceLoadTimeToMonotonicTime(relativeMilliseconds)); }
unsigned long long PerformanceTiming::requestStart() const { ResourceLoadTiming* timing = resourceLoadTiming(); if (!timing || timing->sendStart() == 0.0) return connectEnd(); return monotonicTimeToIntegerMilliseconds(timing->sendStart()); }
unsigned long long PerformanceTiming::responseStart() const { ResourceLoadTiming* timing = resourceLoadTiming(); if (!timing || timing->receiveHeadersEnd() == 0.0) return requestStart(); // FIXME: Response start needs to be the time of the first received byte. // However, the ResourceLoadTiming API currently only supports the time // the last header byte was received. For many responses with reasonable // sized cookies, the HTTP headers fit into a single packet so this time // is basically equivalent. But for some responses, particularly those with // headers larger than a single packet, this time will be too late. return monotonicTimeToIntegerMilliseconds(timing->receiveHeadersEnd()); }
unsigned long long PerformanceTiming::domainLookupEnd() const { ResourceLoadTiming* timing = resourceLoadTiming(); if (!timing) return domainLookupStart(); // This will be zero when a DNS request is not performed. Rather than // exposing a special value that indicates no DNS, we "backfill" with // domainLookupStart. double dnsEnd = timing->dnsEnd(); if (dnsEnd == 0.0) return domainLookupStart(); return monotonicTimeToIntegerMilliseconds(dnsEnd); }
void PerformanceBase::addResourceTiming(const ResourceTimingInfo& info) { if (isResourceTimingBufferFull() && !hasObserverFor(PerformanceEntry::Resource)) return; SecurityOrigin* securityOrigin = nullptr; ExecutionContext* context = getExecutionContext(); if (context) securityOrigin = context->getSecurityOrigin(); if (!securityOrigin) return; const ResourceResponse& finalResponse = info.finalResponse(); bool allowTimingDetails = passesTimingAllowCheck(finalResponse, *securityOrigin, info.originalTimingAllowOrigin(), context); double startTime = info.initialTime(); if (info.redirectChain().isEmpty()) { PerformanceEntry* entry = PerformanceResourceTiming::create( info, timeOrigin(), startTime, allowTimingDetails); notifyObserversOfEntry(*entry); if (!isResourceTimingBufferFull()) addResourceTimingBuffer(*entry); return; } const Vector<ResourceResponse>& redirectChain = info.redirectChain(); bool allowRedirectDetails = allowsTimingRedirect(redirectChain, finalResponse, *securityOrigin, context); if (!allowRedirectDetails) { ResourceLoadTiming* finalTiming = finalResponse.resourceLoadTiming(); ASSERT(finalTiming); if (finalTiming) startTime = finalTiming->requestTime(); } ResourceLoadTiming* lastRedirectTiming = redirectChain.back().resourceLoadTiming(); ASSERT(lastRedirectTiming); double lastRedirectEndTime = lastRedirectTiming->receiveHeadersEnd(); PerformanceEntry* entry = PerformanceResourceTiming::create( info, timeOrigin(), startTime, lastRedirectEndTime, allowTimingDetails, allowRedirectDetails); notifyObserversOfEntry(*entry); if (!isResourceTimingBufferFull()) addResourceTimingBuffer(*entry); }
unsigned long long PerformanceTiming::secureConnectionStart() const { DocumentLoader* loader = documentLoader(); if (!loader) return 0; ResourceLoadTiming* timing = loader->response().resourceLoadTiming(); if (!timing) return 0; double sslStart = timing->sslStart(); if (sslStart == 0.0) return 0; return monotonicTimeToIntegerMilliseconds(sslStart); }
unsigned long long PerformanceTiming::connectEnd() const { DocumentLoader* loader = documentLoader(); if (!loader) return connectStart(); ResourceLoadTiming* timing = loader->response().resourceLoadTiming(); if (!timing) return connectStart(); // connectEnd will be zero when a network request is not made. Rather than // exposing a special value that indicates no new connection, we "backfill" // with connectStart. double connectEnd = timing->connectEnd(); if (connectEnd == 0.0 || loader->response().connectionReused()) return connectStart(); return monotonicTimeToIntegerMilliseconds(connectEnd); }
unsigned long long PerformanceTiming::connectStart() const { DocumentLoader* loader = documentLoader(); if (!loader) return domainLookupEnd(); ResourceLoadTiming* timing = loader->response().resourceLoadTiming(); if (!timing) return domainLookupEnd(); // connectStart will be zero when a network request is not made. // Rather than exposing a special value that indicates no new connection, we "backfill" with domainLookupEnd. double connectStart = timing->connectStart(); if (connectStart == 0.0 || loader->response().connectionReused()) return domainLookupEnd(); // ResourceLoadTiming's connect phase includes DNS, however Navigation Timing's // connect phase should not. So if there is DNS time, trim it from the start. if (timing->dnsEnd() > 0.0 && timing->dnsEnd() > connectStart) connectStart = timing->dnsEnd(); return monotonicTimeToIntegerMilliseconds(connectStart); }
static PassRefPtr<TypeBuilder::Network::ResourceTiming> buildObjectForTiming(const ResourceLoadTiming& timing, DocumentLoader* loader) { return TypeBuilder::Network::ResourceTiming::create() .setRequestTime(timing.convertResourceLoadTimeToDocumentTime(loader->timing(), 0)) .setProxyStart(timing.proxyStart) .setProxyEnd(timing.proxyEnd) .setDnsStart(timing.dnsStart) .setDnsEnd(timing.dnsEnd) .setConnectStart(timing.connectStart) .setConnectEnd(timing.connectEnd) .setSslStart(timing.sslStart) .setSslEnd(timing.sslEnd) .setSendStart(timing.sendStart) .setSendEnd(timing.sendEnd) .setReceiveHeadersEnd(timing.receiveHeadersEnd); }
static PassRefPtr<InspectorObject> buildObjectForTiming(const ResourceLoadTiming& timing, DocumentLoader* loader) { RefPtr<InspectorObject> timingObject = InspectorObject::create(); timingObject->setNumber("requestTime", timing.convertResourceLoadTimeToDocumentTime(loader->timing(), 0)); timingObject->setNumber("proxyStart", timing.proxyStart); timingObject->setNumber("proxyEnd", timing.proxyEnd); timingObject->setNumber("dnsStart", timing.dnsStart); timingObject->setNumber("dnsEnd", timing.dnsEnd); timingObject->setNumber("connectStart", timing.connectStart); timingObject->setNumber("connectEnd", timing.connectEnd); timingObject->setNumber("sslStart", timing.sslStart); timingObject->setNumber("sslEnd", timing.sslEnd); timingObject->setNumber("sendStart", timing.sendStart); timingObject->setNumber("sendEnd", timing.sendEnd); timingObject->setNumber("receiveHeadersEnd", timing.receiveHeadersEnd); return timingObject; }