Commit d3ac1c7a authored by sunjian's avatar sunjian Committed by Commit bot

nav timing 2 redirect allow opt-in

BUG=665160

Review-Url: https://codereview.chromium.org/2550883003
Cr-Commit-Position: refs/heads/master@{#438052}
parent 196ee3b6
...@@ -50,6 +50,16 @@ ...@@ -50,6 +50,16 @@
namespace blink { namespace blink {
namespace {
SecurityOrigin* getSecurityOrigin(ExecutionContext* context) {
if (context)
return context->getSecurityOrigin();
return nullptr;
}
} // namespace
using PerformanceObserverVector = HeapVector<Member<PerformanceObserver>>; using PerformanceObserverVector = HeapVector<Member<PerformanceObserver>>;
static const size_t defaultResourceTimingBufferSize = 150; static const size_t defaultResourceTimingBufferSize = 150;
...@@ -225,7 +235,7 @@ void PerformanceBase::setFrameTimingBufferSize(unsigned size) { ...@@ -225,7 +235,7 @@ void PerformanceBase::setFrameTimingBufferSize(unsigned size) {
dispatchEvent(Event::create(EventTypeNames::frametimingbufferfull)); dispatchEvent(Event::create(EventTypeNames::frametimingbufferfull));
} }
static bool passesTimingAllowCheck( bool PerformanceBase::passesTimingAllowCheck(
const ResourceResponse& response, const ResourceResponse& response,
const SecurityOrigin& initiatorSecurityOrigin, const SecurityOrigin& initiatorSecurityOrigin,
const AtomicString& originalTimingAllowOrigin, const AtomicString& originalTimingAllowOrigin,
...@@ -263,10 +273,11 @@ static bool passesTimingAllowCheck( ...@@ -263,10 +273,11 @@ static bool passesTimingAllowCheck(
return false; return false;
} }
static bool allowsTimingRedirect(const Vector<ResourceResponse>& redirectChain, bool PerformanceBase::allowsTimingRedirect(
const ResourceResponse& finalResponse, const Vector<ResourceResponse>& redirectChain,
const SecurityOrigin& initiatorSecurityOrigin, const ResourceResponse& finalResponse,
ExecutionContext* context) { const SecurityOrigin& initiatorSecurityOrigin,
ExecutionContext* context) {
if (!passesTimingAllowCheck(finalResponse, initiatorSecurityOrigin, if (!passesTimingAllowCheck(finalResponse, initiatorSecurityOrigin,
AtomicString(), context)) AtomicString(), context))
return false; return false;
...@@ -284,10 +295,8 @@ void PerformanceBase::addResourceTiming(const ResourceTimingInfo& info) { ...@@ -284,10 +295,8 @@ void PerformanceBase::addResourceTiming(const ResourceTimingInfo& info) {
if (isResourceTimingBufferFull() && if (isResourceTimingBufferFull() &&
!hasObserverFor(PerformanceEntry::Resource)) !hasObserverFor(PerformanceEntry::Resource))
return; return;
SecurityOrigin* securityOrigin = nullptr;
ExecutionContext* context = getExecutionContext(); ExecutionContext* context = getExecutionContext();
if (context) SecurityOrigin* securityOrigin = getSecurityOrigin(context);
securityOrigin = context->getSecurityOrigin();
if (!securityOrigin) if (!securityOrigin)
return; return;
...@@ -357,6 +366,15 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) { ...@@ -357,6 +366,15 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) {
double lastRedirectEndTime = documentLoadTiming.redirectEnd(); double lastRedirectEndTime = documentLoadTiming.redirectEnd();
double finishTime = documentLoadTiming.loadEventEnd(); double finishTime = documentLoadTiming.loadEventEnd();
ExecutionContext* context = getExecutionContext();
SecurityOrigin* securityOrigin = getSecurityOrigin(context);
if (!securityOrigin)
return;
bool allowRedirectDetails =
allowsTimingRedirect(navigationTimingInfo->redirectChain(), finalResponse,
*securityOrigin, context);
unsigned long long transferSize = navigationTimingInfo->transferSize(); unsigned long long transferSize = navigationTimingInfo->transferSize();
unsigned long long encodedBodyLength = finalResponse.encodedBodyLength(); unsigned long long encodedBodyLength = finalResponse.encodedBodyLength();
unsigned long long decodedBodyLength = finalResponse.decodedBodyLength(); unsigned long long decodedBodyLength = finalResponse.decodedBodyLength();
...@@ -374,7 +392,7 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) { ...@@ -374,7 +392,7 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) {
documentTiming ? documentTiming->domComplete() : 0, type, documentTiming ? documentTiming->domComplete() : 0, type,
documentLoadTiming.redirectStart(), documentLoadTiming.redirectEnd(), documentLoadTiming.redirectStart(), documentLoadTiming.redirectEnd(),
documentLoadTiming.fetchStart(), documentLoadTiming.responseEnd(), documentLoadTiming.fetchStart(), documentLoadTiming.responseEnd(),
documentLoadTiming.hasCrossOriginRedirect(), allowRedirectDetails,
documentLoadTiming.hasSameOriginAsPreviousDocument(), resourceLoadTiming, documentLoadTiming.hasSameOriginAsPreviousDocument(), resourceLoadTiming,
lastRedirectEndTime, finishTime, transferSize, encodedBodyLength, lastRedirectEndTime, finishTime, transferSize, encodedBodyLength,
decodedBodyLength, didReuseConnection); decodedBodyLength, didReuseConnection);
......
...@@ -132,6 +132,16 @@ class CORE_EXPORT PerformanceBase : public EventTargetWithInlineData { ...@@ -132,6 +132,16 @@ class CORE_EXPORT PerformanceBase : public EventTargetWithInlineData {
NavigationType, NavigationType,
const Document*); const Document*);
static bool allowsTimingRedirect(const Vector<ResourceResponse>&,
const ResourceResponse&,
const SecurityOrigin&,
ExecutionContext*);
static bool passesTimingAllowCheck(const ResourceResponse&,
const SecurityOrigin&,
const AtomicString&,
ExecutionContext*);
protected: protected:
explicit PerformanceBase(double timeOrigin); explicit PerformanceBase(double timeOrigin);
......
...@@ -7,10 +7,12 @@ ...@@ -7,10 +7,12 @@
#include "bindings/core/v8/PerformanceObserverCallback.h" #include "bindings/core/v8/PerformanceObserverCallback.h"
#include "bindings/core/v8/V8BindingForTesting.h" #include "bindings/core/v8/V8BindingForTesting.h"
#include "core/testing/DummyPageHolder.h" #include "core/testing/DummyPageHolder.h"
#include "core/testing/NullExecutionContext.h"
#include "core/timing/PerformanceBase.h" #include "core/timing/PerformanceBase.h"
#include "core/timing/PerformanceLongTaskTiming.h" #include "core/timing/PerformanceLongTaskTiming.h"
#include "core/timing/PerformanceObserver.h" #include "core/timing/PerformanceObserver.h"
#include "core/timing/PerformanceObserverInit.h" #include "core/timing/PerformanceObserverInit.h"
#include "platform/network/ResourceResponse.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace blink { namespace blink {
...@@ -46,8 +48,11 @@ class PerformanceBaseTest : public ::testing::Test { ...@@ -46,8 +48,11 @@ class PerformanceBaseTest : public ::testing::Test {
void SetUp() override { void SetUp() override {
m_pageHolder = DummyPageHolder::create(IntSize(800, 600)); m_pageHolder = DummyPageHolder::create(IntSize(800, 600));
m_executionContext = new NullExecutionContext();
} }
ExecutionContext* getExecutionContext() { return m_executionContext.get(); }
int numPerformanceEntriesInObserver() { int numPerformanceEntriesInObserver() {
return m_observer->m_performanceEntries.size(); return m_observer->m_performanceEntries.size();
} }
...@@ -58,7 +63,17 @@ class PerformanceBaseTest : public ::testing::Test { ...@@ -58,7 +63,17 @@ class PerformanceBaseTest : public ::testing::Test {
return PerformanceBase::getNavigationType(type, document); return PerformanceBase::getNavigationType(type, document);
} }
static bool allowsTimingRedirect(
const Vector<ResourceResponse>& redirectChain,
const ResourceResponse& finalResponse,
const SecurityOrigin& initiatorSecurityOrigin,
ExecutionContext* context) {
return PerformanceBase::allowsTimingRedirect(
redirectChain, finalResponse, initiatorSecurityOrigin, context);
}
Persistent<TestPerformanceBase> m_base; Persistent<TestPerformanceBase> m_base;
Persistent<ExecutionContext> m_executionContext;
Persistent<PerformanceObserver> m_observer; Persistent<PerformanceObserver> m_observer;
std::unique_ptr<DummyPageHolder> m_pageHolder; std::unique_ptr<DummyPageHolder> m_pageHolder;
Persistent<PerformanceObserverCallback> m_cb; Persistent<PerformanceObserverCallback> m_cb;
...@@ -144,4 +159,40 @@ TEST_F(PerformanceBaseTest, GetNavigationType) { ...@@ -144,4 +159,40 @@ TEST_F(PerformanceBaseTest, GetNavigationType) {
EXPECT_EQ(returnedType, EXPECT_EQ(returnedType,
PerformanceNavigationTiming::NavigationType::Navigate); PerformanceNavigationTiming::NavigationType::Navigate);
} }
TEST_F(PerformanceBaseTest, AllowsTimingRedirect) {
// When there are no cross-origin redirects.
AtomicString originDomain = "http://127.0.0.1:8000";
Vector<ResourceResponse> redirectChain;
KURL url(ParsedURLString, originDomain + "/foo.html");
ResourceResponse finalResponse;
finalResponse.setURL(url);
ResourceResponse redirectResponse1;
redirectResponse1.setURL(url);
ResourceResponse redirectResponse2;
redirectResponse2.setURL(url);
redirectChain.append(redirectResponse1);
redirectChain.append(redirectResponse2);
RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(url);
EXPECT_TRUE(allowsTimingRedirect(redirectChain, finalResponse,
*securityOrigin.get(),
getExecutionContext()));
// When there exist cross-origin redirects.
AtomicString crossOriginDomain = "http://126.0.0.1:8000";
KURL redirectUrl(ParsedURLString, crossOriginDomain + "/bar.html");
ResourceResponse redirectResponse3;
redirectResponse3.setURL(redirectUrl);
redirectChain.append(redirectResponse3);
EXPECT_FALSE(allowsTimingRedirect(redirectChain, finalResponse,
*securityOrigin.get(),
getExecutionContext()));
// When cross-origin redirect opts in.
redirectChain.back().setHTTPHeaderField(HTTPNames::Timing_Allow_Origin,
originDomain);
EXPECT_TRUE(allowsTimingRedirect(redirectChain, finalResponse,
*securityOrigin.get(),
getExecutionContext()));
}
} // namespace blink } // namespace blink
...@@ -36,7 +36,7 @@ PerformanceNavigationTiming::PerformanceNavigationTiming( ...@@ -36,7 +36,7 @@ PerformanceNavigationTiming::PerformanceNavigationTiming(
double redirectEnd, double redirectEnd,
double fetchStart, double fetchStart,
double responseEnd, double responseEnd,
bool hasCrossOriginRedirect, bool allowRedirectDetails,
bool hasSameOriginAsPreviousDocument, bool hasSameOriginAsPreviousDocument,
ResourceLoadTiming* timing, ResourceLoadTiming* timing,
double lastRedirectEndTime, double lastRedirectEndTime,
...@@ -57,7 +57,7 @@ PerformanceNavigationTiming::PerformanceNavigationTiming( ...@@ -57,7 +57,7 @@ PerformanceNavigationTiming::PerformanceNavigationTiming(
true /*allowTimingDetails*/, // TODO(sunjian): true /*allowTimingDetails*/, // TODO(sunjian):
// Create an enum // Create an enum
// for this. // for this.
!hasCrossOriginRedirect, allowRedirectDetails,
"document", "document",
"navigation", "navigation",
timeOrigin), timeOrigin),
...@@ -76,19 +76,19 @@ PerformanceNavigationTiming::PerformanceNavigationTiming( ...@@ -76,19 +76,19 @@ PerformanceNavigationTiming::PerformanceNavigationTiming(
m_redirectEnd(redirectEnd), m_redirectEnd(redirectEnd),
m_fetchStart(fetchStart), m_fetchStart(fetchStart),
m_responseEnd(responseEnd), m_responseEnd(responseEnd),
m_hasCrossOriginRedirect(hasCrossOriginRedirect), m_allowRedirectDetails(allowRedirectDetails),
m_hasSameOriginAsPreviousDocument(hasSameOriginAsPreviousDocument) {} m_hasSameOriginAsPreviousDocument(hasSameOriginAsPreviousDocument) {}
PerformanceNavigationTiming::~PerformanceNavigationTiming() {} PerformanceNavigationTiming::~PerformanceNavigationTiming() {}
double PerformanceNavigationTiming::unloadEventStart() const { double PerformanceNavigationTiming::unloadEventStart() const {
if (m_hasCrossOriginRedirect || !m_hasSameOriginAsPreviousDocument) if (!m_allowRedirectDetails || !m_hasSameOriginAsPreviousDocument)
return 0; return 0;
return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_unloadEventStart); return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_unloadEventStart);
} }
double PerformanceNavigationTiming::unloadEventEnd() const { double PerformanceNavigationTiming::unloadEventEnd() const {
if (m_hasCrossOriginRedirect || !m_hasSameOriginAsPreviousDocument) if (!m_allowRedirectDetails || !m_hasSameOriginAsPreviousDocument)
return 0; return 0;
return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_unloadEventEnd); return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_unloadEventEnd);
...@@ -136,8 +136,7 @@ AtomicString PerformanceNavigationTiming::type() const { ...@@ -136,8 +136,7 @@ AtomicString PerformanceNavigationTiming::type() const {
} }
unsigned short PerformanceNavigationTiming::redirectCount() const { unsigned short PerformanceNavigationTiming::redirectCount() const {
// TODO(sunjian): Also check response headers to allow opt-in crbugs/665160 if (!m_allowRedirectDetails)
if (m_hasCrossOriginRedirect)
return 0; return 0;
return m_redirectCount; return m_redirectCount;
} }
...@@ -147,13 +146,13 @@ double PerformanceNavigationTiming::fetchStart() const { ...@@ -147,13 +146,13 @@ double PerformanceNavigationTiming::fetchStart() const {
} }
double PerformanceNavigationTiming::redirectStart() const { double PerformanceNavigationTiming::redirectStart() const {
if (m_hasCrossOriginRedirect) if (!m_allowRedirectDetails)
return 0; return 0;
return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_redirectStart); return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_redirectStart);
} }
double PerformanceNavigationTiming::redirectEnd() const { double PerformanceNavigationTiming::redirectEnd() const {
if (m_hasCrossOriginRedirect) if (!m_allowRedirectDetails)
return 0; return 0;
return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_redirectEnd); return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_redirectEnd);
} }
......
...@@ -32,7 +32,7 @@ class CORE_EXPORT PerformanceNavigationTiming final ...@@ -32,7 +32,7 @@ class CORE_EXPORT PerformanceNavigationTiming final
double redirectEnd, double redirectEnd,
double fetchStart, double fetchStart,
double responseEnd, double responseEnd,
bool hasCrossOriginRedirect, bool allowRedirectDetails,
bool hasSameOriginAsPreviousDocument, bool hasSameOriginAsPreviousDocument,
ResourceLoadTiming*, ResourceLoadTiming*,
double lastRedirectEndTime, double lastRedirectEndTime,
...@@ -80,7 +80,7 @@ class CORE_EXPORT PerformanceNavigationTiming final ...@@ -80,7 +80,7 @@ class CORE_EXPORT PerformanceNavigationTiming final
double m_redirectEnd; double m_redirectEnd;
double m_fetchStart; double m_fetchStart;
double m_responseEnd; double m_responseEnd;
bool m_hasCrossOriginRedirect; bool m_allowRedirectDetails;
bool m_hasSameOriginAsPreviousDocument; bool m_hasSameOriginAsPreviousDocument;
}; };
} // namespace blink } // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment