| Index: third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
 | 
| diff --git a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
 | 
| index 7a1abafb002f56cdfc0163b912222f53e521d509..f9df40ffb2c628cfc4a517144742edaa0b4a32d4 100644
 | 
| --- a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
 | 
| +++ b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
 | 
| @@ -5,127 +5,184 @@
 | 
|  #include "core/timing/PerformanceNavigationTiming.h"
 | 
|  
 | 
|  #include "bindings/core/v8/V8ObjectBuilder.h"
 | 
| +#include "core/dom/Document.h"
 | 
| +#include "core/dom/DocumentTiming.h"
 | 
| +#include "core/frame/LocalFrame.h"
 | 
| +#include "core/loader/DocumentLoadTiming.h"
 | 
| +#include "core/loader/DocumentLoader.h"
 | 
|  #include "core/timing/PerformanceBase.h"
 | 
| +#include "platform/loader/fetch/ResourceTimingInfo.h"
 | 
|  
 | 
|  namespace blink {
 | 
|  
 | 
|  PerformanceNavigationTiming::PerformanceNavigationTiming(
 | 
| -    double timeOrigin,
 | 
| -    const String& requestedUrl,
 | 
| -    double unloadEventStart,
 | 
| -    double unloadEventEnd,
 | 
| -    double loadEventStart,
 | 
| -    double loadEventEnd,
 | 
| -    unsigned short redirectCount,
 | 
| -    double domInteractive,
 | 
| -    double domContentLoadedEventStart,
 | 
| -    double domContentLoadedEventEnd,
 | 
| -    double domComplete,
 | 
| -    NavigationType type,
 | 
| -    double redirectStart,
 | 
| -    double redirectEnd,
 | 
| -    double fetchStart,
 | 
| -    double responseEnd,
 | 
| -    bool allowRedirectDetails,
 | 
| -    bool hasSameOriginAsPreviousDocument,
 | 
| -    ResourceLoadTiming* timing,
 | 
| -    double lastRedirectEndTime,
 | 
| -    double finishTime,
 | 
| -    unsigned long long transferSize,
 | 
| -    unsigned long long encodedBodyLength,
 | 
| -    unsigned long long decodedBodyLength,
 | 
| -    bool didReuseConnection)
 | 
| -    : PerformanceResourceTiming("navigation",
 | 
| -                                timeOrigin,
 | 
| -                                timing,
 | 
| -                                lastRedirectEndTime,
 | 
| -                                finishTime,
 | 
| -                                transferSize,
 | 
| -                                encodedBodyLength,
 | 
| -                                decodedBodyLength,
 | 
| -                                didReuseConnection,
 | 
| -                                true /*allowTimingDetails*/,  // TODO(sunjian):
 | 
| -                                                              // Create an enum
 | 
| -                                                              // for this.
 | 
| -                                allowRedirectDetails,
 | 
| -                                requestedUrl,
 | 
| +    LocalFrame* frame,
 | 
| +    ResourceTimingInfo* info,
 | 
| +    double timeOrigin)
 | 
| +    : PerformanceResourceTiming(info ? info->initialURL().getString() : "",
 | 
|                                  "navigation",
 | 
| -                                timeOrigin),
 | 
| +                                0.0,
 | 
| +                                0.0),
 | 
|        m_timeOrigin(timeOrigin),
 | 
| -      m_unloadEventStart(unloadEventStart),
 | 
| -      m_unloadEventEnd(unloadEventEnd),
 | 
| -      m_loadEventStart(loadEventStart),
 | 
| -      m_loadEventEnd(loadEventEnd),
 | 
| -      m_redirectCount(redirectCount),
 | 
| -      m_domInteractive(domInteractive),
 | 
| -      m_domContentLoadedEventStart(domContentLoadedEventStart),
 | 
| -      m_domContentLoadedEventEnd(domContentLoadedEventEnd),
 | 
| -      m_domComplete(domComplete),
 | 
| -      m_type(type),
 | 
| -      m_redirectStart(redirectStart),
 | 
| -      m_redirectEnd(redirectEnd),
 | 
| -      m_fetchStart(fetchStart),
 | 
| -      m_responseEnd(responseEnd),
 | 
| -      m_allowRedirectDetails(allowRedirectDetails),
 | 
| -      m_hasSameOriginAsPreviousDocument(hasSameOriginAsPreviousDocument) {}
 | 
| +      m_resourceTimingInfo(info),
 | 
| +      m_frame(frame) {
 | 
| +  DCHECK(frame);
 | 
| +  DCHECK(info);
 | 
| +}
 | 
|  
 | 
|  PerformanceNavigationTiming::~PerformanceNavigationTiming() {}
 | 
|  
 | 
| +DEFINE_TRACE(PerformanceNavigationTiming) {
 | 
| +  visitor->trace(m_frame);
 | 
| +  PerformanceEntry::trace(visitor);
 | 
| +}
 | 
| +
 | 
| +DocumentLoadTiming* PerformanceNavigationTiming::documentLoadTiming() const {
 | 
| +  DocumentLoader* loader = documentLoader();
 | 
| +  if (!loader)
 | 
| +    return nullptr;
 | 
| +
 | 
| +  return &loader->timing();
 | 
| +}
 | 
| +
 | 
| +DocumentLoader* PerformanceNavigationTiming::documentLoader() const {
 | 
| +  return m_frame->loader().documentLoader();
 | 
| +}
 | 
| +
 | 
| +const DocumentTiming* PerformanceNavigationTiming::documentTiming() const {
 | 
| +  Document* document = m_frame->document();
 | 
| +  if (!document)
 | 
| +    return nullptr;
 | 
| +
 | 
| +  return &document->timing();
 | 
| +}
 | 
| +
 | 
| +ResourceLoadTiming* PerformanceNavigationTiming::resourceLoadTiming() const {
 | 
| +  return m_resourceTimingInfo->finalResponse().resourceLoadTiming();
 | 
| +}
 | 
| +
 | 
| +bool PerformanceNavigationTiming::allowTimingDetails() const {
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +bool PerformanceNavigationTiming::didReuseConnection() const {
 | 
| +  return m_resourceTimingInfo->finalResponse().connectionReused();
 | 
| +}
 | 
| +
 | 
| +unsigned long long PerformanceNavigationTiming::getTransferSize() const {
 | 
| +  return m_resourceTimingInfo->transferSize();
 | 
| +}
 | 
| +
 | 
| +unsigned long long PerformanceNavigationTiming::getEncodedBodySize() const {
 | 
| +  return m_resourceTimingInfo->finalResponse().encodedBodyLength();
 | 
| +}
 | 
| +
 | 
| +unsigned long long PerformanceNavigationTiming::getDecodedBodySize() const {
 | 
| +  return m_resourceTimingInfo->finalResponse().decodedBodyLength();
 | 
| +}
 | 
| +
 | 
| +AtomicString PerformanceNavigationTiming::initiatorType() const {
 | 
| +  return "navigation";
 | 
| +}
 | 
| +
 | 
| +bool PerformanceNavigationTiming::getAllowRedirectDetails() const {
 | 
| +  ExecutionContext* context = m_frame->document();
 | 
| +  SecurityOrigin* securityOrigin = nullptr;
 | 
| +  if (context)
 | 
| +    securityOrigin = context->getSecurityOrigin();
 | 
| +  if (!securityOrigin)
 | 
| +    return false;
 | 
| +  // TODO(sunjian): Think about how to make this flag deterministic.
 | 
| +  // crbug/693183.
 | 
| +  return PerformanceBase::allowsTimingRedirect(
 | 
| +      m_resourceTimingInfo->redirectChain(),
 | 
| +      m_resourceTimingInfo->finalResponse(), *securityOrigin, context);
 | 
| +}
 | 
| +
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventStart() const {
 | 
| -  if (!m_allowRedirectDetails || !m_hasSameOriginAsPreviousDocument)
 | 
| +  bool allowRedirectDetails = getAllowRedirectDetails();
 | 
| +  DocumentLoadTiming* timing = documentLoadTiming();
 | 
| +
 | 
| +  if (!allowRedirectDetails || !timing ||
 | 
| +      !timing->hasSameOriginAsPreviousDocument())
 | 
|      return 0;
 | 
|    return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| -      m_timeOrigin, m_unloadEventStart);
 | 
| +      m_timeOrigin, timing->unloadEventStart());
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventEnd() const {
 | 
| -  if (!m_allowRedirectDetails || !m_hasSameOriginAsPreviousDocument)
 | 
| -    return 0;
 | 
| +  bool allowRedirectDetails = getAllowRedirectDetails();
 | 
| +  DocumentLoadTiming* timing = documentLoadTiming();
 | 
|  
 | 
| -  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
 | 
| -                                                             m_unloadEventEnd);
 | 
| +  if (!allowRedirectDetails || !timing ||
 | 
| +      !timing->hasSameOriginAsPreviousDocument())
 | 
| +    return 0;
 | 
| +  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| +      m_timeOrigin, timing->unloadEventEnd());
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::domInteractive() const {
 | 
| -  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
 | 
| -                                                             m_domInteractive);
 | 
| +  const DocumentTiming* timing = documentTiming();
 | 
| +  if (!timing)
 | 
| +    return 0.0;
 | 
| +  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| +      m_timeOrigin, timing->domInteractive());
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventStart()
 | 
|      const {
 | 
| +  const DocumentTiming* timing = documentTiming();
 | 
| +  if (!timing)
 | 
| +    return 0.0;
 | 
|    return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| -      m_timeOrigin, m_domContentLoadedEventStart);
 | 
| +      m_timeOrigin, timing->domContentLoadedEventStart());
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventEnd()
 | 
|      const {
 | 
| +  const DocumentTiming* timing = documentTiming();
 | 
| +  if (!timing)
 | 
| +    return 0.0;
 | 
|    return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| -      m_timeOrigin, m_domContentLoadedEventEnd);
 | 
| +      m_timeOrigin, timing->domContentLoadedEventEnd());
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::domComplete() const {
 | 
| -  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
 | 
| -                                                             m_domComplete);
 | 
| +  const DocumentTiming* timing = documentTiming();
 | 
| +  if (!timing)
 | 
| +    return 0.0;
 | 
| +  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| +      m_timeOrigin, timing->domComplete());
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::loadEventStart() const {
 | 
| -  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
 | 
| -                                                             m_loadEventStart);
 | 
| +  DocumentLoadTiming* timing = documentLoadTiming();
 | 
| +  if (!timing)
 | 
| +    return 0.0;
 | 
| +  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| +      m_timeOrigin, timing->loadEventStart());
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::loadEventEnd() const {
 | 
| -  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
 | 
| -                                                             m_loadEventEnd);
 | 
| +  DocumentLoadTiming* timing = documentLoadTiming();
 | 
| +  if (!timing)
 | 
| +    return 0.0;
 | 
| +  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| +      m_timeOrigin, timing->loadEventEnd());
 | 
|  }
 | 
|  
 | 
|  AtomicString PerformanceNavigationTiming::type() const {
 | 
| -  switch (m_type) {
 | 
| +  DocumentLoader* loader = documentLoader();
 | 
| +  DCHECK(loader);
 | 
| +  Document* document = m_frame->document();
 | 
| +  switch (PerformanceBase::getNavigationType(loader->getNavigationType(),
 | 
| +                                             document)) {
 | 
| +    case NavigationType::Prerender:
 | 
| +      return "prerender";
 | 
|      case NavigationType::Reload:
 | 
|        return "reload";
 | 
|      case NavigationType::BackForward:
 | 
|        return "back_forward";
 | 
| -    case NavigationType::Prerender:
 | 
| -      return "prerender";
 | 
|      case NavigationType::Navigate:
 | 
|        return "navigate";
 | 
|    }
 | 
| @@ -134,33 +191,50 @@ AtomicString PerformanceNavigationTiming::type() const {
 | 
|  }
 | 
|  
 | 
|  unsigned short PerformanceNavigationTiming::redirectCount() const {
 | 
| -  if (!m_allowRedirectDetails)
 | 
| +  bool allowRedirectDetails = getAllowRedirectDetails();
 | 
| +  DocumentLoadTiming* timing = documentLoadTiming();
 | 
| +  if (!allowRedirectDetails || !timing)
 | 
|      return 0;
 | 
| -  return m_redirectCount;
 | 
| -}
 | 
| -
 | 
| -DOMHighResTimeStamp PerformanceNavigationTiming::fetchStart() const {
 | 
| -  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
 | 
| -                                                             m_fetchStart);
 | 
| +  return timing->redirectCount();
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::redirectStart() const {
 | 
| -  if (!m_allowRedirectDetails)
 | 
| +  bool allowRedirectDetails = getAllowRedirectDetails();
 | 
| +  DocumentLoadTiming* timing = documentLoadTiming();
 | 
| +  if (!allowRedirectDetails || !timing)
 | 
|      return 0;
 | 
| -  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
 | 
| -                                                             m_redirectStart);
 | 
| +  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| +      m_timeOrigin, timing->redirectStart());
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::redirectEnd() const {
 | 
| -  if (!m_allowRedirectDetails)
 | 
| +  bool allowRedirectDetails = getAllowRedirectDetails();
 | 
| +  DocumentLoadTiming* timing = documentLoadTiming();
 | 
| +  if (!allowRedirectDetails || !timing)
 | 
|      return 0;
 | 
| -  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
 | 
| -                                                             m_redirectEnd);
 | 
| +  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| +      m_timeOrigin, timing->redirectEnd());
 | 
| +}
 | 
| +
 | 
| +DOMHighResTimeStamp PerformanceNavigationTiming::fetchStart() const {
 | 
| +  DocumentLoadTiming* timing = documentLoadTiming();
 | 
| +  if (!timing)
 | 
| +    return 0.0;
 | 
| +  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| +      m_timeOrigin, timing->fetchStart());
 | 
|  }
 | 
|  
 | 
|  DOMHighResTimeStamp PerformanceNavigationTiming::responseEnd() const {
 | 
| -  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
 | 
| -                                                             m_responseEnd);
 | 
| +  DocumentLoadTiming* timing = documentLoadTiming();
 | 
| +  if (!timing)
 | 
| +    return 0.0;
 | 
| +  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
 | 
| +      m_timeOrigin, timing->responseEnd());
 | 
| +}
 | 
| +
 | 
| +// Overriding PerformanceEntry's attributes.
 | 
| +DOMHighResTimeStamp PerformanceNavigationTiming::duration() const {
 | 
| +  return loadEventEnd();
 | 
|  }
 | 
|  
 | 
|  void PerformanceNavigationTiming::buildJSONValue(
 | 
| 
 |