This source file includes following definitions.
- delta_
- ToTimeTicks
- is_null
- GetDelta
- weak_factory_
- Start
- GetLoadTimingInfo
- DelayedStart
- load_timing_deltas_
- Register
- Unregister
- MaybeCreateJob
- RunTestWithUrl
- RunTest
- GetResultDeltas
- GetResultDelta
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
#include <string>
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test_utils.h"
#include "net/base/load_timing_info.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_job_factory.h"
#include "url/gurl.h"
using content::BrowserThread;
namespace {
const char kTestDomain[] = "test.com";
const char kTestUrl[] = "http://test.com/";
class RelativeTime {
public:
RelativeTime() : is_null_(true) {
}
explicit RelativeTime(int delta_ms)
: is_null_(false),
delta_(base::TimeDelta::FromMilliseconds(delta_ms)) {
}
base::TimeTicks ToTimeTicks(base::TimeTicks base_time) const {
if (is_null_)
return base::TimeTicks();
return base_time + delta_;
}
bool is_null() const { return is_null_; }
base::TimeDelta GetDelta() const {
EXPECT_FALSE(is_null_);
return delta_;
}
private:
bool is_null_;
base::TimeDelta delta_;
};
struct TimingDeltas {
RelativeTime proxy_resolve_start;
RelativeTime proxy_resolve_end;
RelativeTime dns_start;
RelativeTime dns_end;
RelativeTime connect_start;
RelativeTime ssl_start;
RelativeTime connect_end;
RelativeTime send_start;
RelativeTime send_end;
RelativeTime receive_headers_end;
};
class MockUrlRequestJobWithTiming : public net::URLRequestFileJob {
public:
MockUrlRequestJobWithTiming(net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const base::FilePath& path,
const TimingDeltas& load_timing_deltas)
: net::URLRequestFileJob(
request, network_delegate, path,
content::BrowserThread::GetBlockingPool()->
GetTaskRunnerWithShutdownBehavior(
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
load_timing_deltas_(load_timing_deltas),
weak_factory_(this) {}
virtual void Start() OVERRIDE {
base::TimeDelta time_to_wait;
start_time_ = base::TimeTicks::Now();
if (!load_timing_deltas_.receive_headers_end.is_null()) {
time_to_wait = load_timing_deltas_.receive_headers_end.GetDelta() +
base::TimeDelta::FromMilliseconds(100);
}
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&MockUrlRequestJobWithTiming::DelayedStart,
weak_factory_.GetWeakPtr()),
time_to_wait);
}
virtual void GetLoadTimingInfo(
net::LoadTimingInfo* load_timing_info) const OVERRIDE {
if (!load_timing_deltas_.receive_headers_end.is_null()) {
EXPECT_LE(
start_time_ + load_timing_deltas_.receive_headers_end.GetDelta(),
base::TimeTicks::Now());
}
load_timing_info->socket_reused = false;
if (load_timing_deltas_.connect_start.is_null() &&
!load_timing_deltas_.receive_headers_end.is_null()) {
load_timing_info->socket_reused = true;
}
load_timing_info->proxy_resolve_start =
load_timing_deltas_.proxy_resolve_start.ToTimeTicks(start_time_);
load_timing_info->proxy_resolve_end =
load_timing_deltas_.proxy_resolve_end.ToTimeTicks(start_time_);
load_timing_info->connect_timing.dns_start =
load_timing_deltas_.dns_start.ToTimeTicks(start_time_);
load_timing_info->connect_timing.dns_end =
load_timing_deltas_.dns_end.ToTimeTicks(start_time_);
load_timing_info->connect_timing.connect_start =
load_timing_deltas_.connect_start.ToTimeTicks(start_time_);
load_timing_info->connect_timing.ssl_start =
load_timing_deltas_.ssl_start.ToTimeTicks(start_time_);
load_timing_info->connect_timing.connect_end =
load_timing_deltas_.connect_end.ToTimeTicks(start_time_);
if (!load_timing_deltas_.ssl_start.is_null()) {
load_timing_info->connect_timing.ssl_end =
load_timing_info->connect_timing.connect_end;
}
load_timing_info->send_start =
load_timing_deltas_.send_start.ToTimeTicks(start_time_);
load_timing_info->send_end=
load_timing_deltas_.send_end.ToTimeTicks(start_time_);
load_timing_info->receive_headers_end =
load_timing_deltas_.receive_headers_end.ToTimeTicks(start_time_);
}
private:
virtual ~MockUrlRequestJobWithTiming() {}
void DelayedStart() {
net::URLRequestFileJob::Start();
}
const TimingDeltas load_timing_deltas_;
base::TimeTicks start_time_;
base::WeakPtrFactory<MockUrlRequestJobWithTiming> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MockUrlRequestJobWithTiming);
};
class TestProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
public:
TestProtocolHandler(const base::FilePath& path,
const TimingDeltas& load_timing_deltas)
: path_(path), load_timing_deltas_(load_timing_deltas) {
EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
virtual ~TestProtocolHandler() {
EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
void Register() {
EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
net::URLRequestFilter::GetInstance()->AddHostnameProtocolHandler(
"http", kTestDomain,
scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(this));
}
void Unregister() {
EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(
"http", kTestDomain);
}
virtual net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const OVERRIDE {
EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
return new MockUrlRequestJobWithTiming(request, network_delegate, path_,
load_timing_deltas_);
}
private:
const base::FilePath path_;
const TimingDeltas load_timing_deltas_;
DISALLOW_COPY_AND_ASSIGN(TestProtocolHandler);
};
class LoadTimingBrowserTest : public InProcessBrowserTest {
public:
LoadTimingBrowserTest() {
}
virtual ~LoadTimingBrowserTest() {
}
void RunTestWithUrl(const GURL& url, TimingDeltas* navigation_deltas) {
ui_test_utils::NavigateToURL(browser(), url);
GetResultDeltas(navigation_deltas);
}
void RunTest(const TimingDeltas& load_timing_deltas,
TimingDeltas* navigation_deltas) {
base::FilePath path;
PathService::Get(chrome::DIR_TEST_DATA, &path);
path = path.AppendASCII("title1.html");
TestProtocolHandler* protocol_handler =
new TestProtocolHandler(path, load_timing_deltas);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&TestProtocolHandler::Register,
base::Unretained(protocol_handler)));
RunTestWithUrl(GURL(kTestUrl), navigation_deltas);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&TestProtocolHandler::Unregister,
base::Unretained(protocol_handler)));
}
private:
void GetResultDeltas(TimingDeltas* navigation_deltas) {
*navigation_deltas = TimingDeltas();
navigation_deltas->dns_start = GetResultDelta("domainLookupStart");
navigation_deltas->dns_end = GetResultDelta("domainLookupEnd");
navigation_deltas->connect_start = GetResultDelta("connectStart");
navigation_deltas->connect_end = GetResultDelta("connectEnd");
navigation_deltas->send_start = GetResultDelta("requestStart");
navigation_deltas->receive_headers_end = GetResultDelta("responseStart");
bool ssl_start_zero = false;
ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
browser()->tab_strip_model()->GetActiveWebContents(),
"window.domAutomationController.send("
"performance.timing.secureConnectionStart == 0);",
&ssl_start_zero));
if (!ssl_start_zero)
navigation_deltas->ssl_start = GetResultDelta("secureConnectionStart");
RelativeTime fetch_start = GetResultDelta("fetchStart");
EXPECT_LE(fetch_start.GetDelta(), navigation_deltas->dns_start.GetDelta());
RelativeTime load_event_end = GetResultDelta("loadEventEnd");
EXPECT_LE(navigation_deltas->receive_headers_end.GetDelta(),
load_event_end.GetDelta());
}
RelativeTime GetResultDelta(const std::string& name) {
int time_ms = 0;
std::string command(base::StringPrintf(
"window.domAutomationController.send("
"performance.timing.%s - performance.timing.fetchStart);",
name.c_str()));
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
browser()->tab_strip_model()->GetActiveWebContents(),
command.c_str(),
&time_ms));
EXPECT_GE(time_ms, 0);
return RelativeTime(time_ms);
}
};
IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, NoTimes) {
TimingDeltas load_timing_deltas;
TimingDeltas navigation_deltas;
RunTest(load_timing_deltas, &navigation_deltas);
EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_start.GetDelta());
EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_end.GetDelta());
EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_start.GetDelta());
EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_end.GetDelta());
EXPECT_EQ(base::TimeDelta(), navigation_deltas.send_start.GetDelta());
EXPECT_EQ(base::TimeDelta(),
navigation_deltas.receive_headers_end.GetDelta());
EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
}
IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Basic) {
TimingDeltas load_timing_deltas;
load_timing_deltas.dns_start = RelativeTime(0);
load_timing_deltas.dns_end = RelativeTime(100);
load_timing_deltas.connect_start = RelativeTime(200);
load_timing_deltas.connect_end = RelativeTime(300);
load_timing_deltas.send_start = RelativeTime(400);
load_timing_deltas.send_end = RelativeTime(500);
load_timing_deltas.receive_headers_end = RelativeTime(600);
TimingDeltas navigation_deltas;
RunTest(load_timing_deltas, &navigation_deltas);
EXPECT_LT(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.dns_end.GetDelta());
EXPECT_LT(navigation_deltas.dns_end.GetDelta(),
navigation_deltas.connect_start.GetDelta());
EXPECT_LT(navigation_deltas.connect_start.GetDelta(),
navigation_deltas.connect_end.GetDelta());
EXPECT_LT(navigation_deltas.connect_end.GetDelta(),
navigation_deltas.send_start.GetDelta());
EXPECT_LT(navigation_deltas.send_start.GetDelta(),
navigation_deltas.receive_headers_end.GetDelta());
EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
}
IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Ssl) {
TimingDeltas load_timing_deltas;
load_timing_deltas.dns_start = RelativeTime(0);
load_timing_deltas.dns_end = RelativeTime(100);
load_timing_deltas.connect_start = RelativeTime(200);
load_timing_deltas.ssl_start = RelativeTime(300);
load_timing_deltas.connect_end = RelativeTime(400);
load_timing_deltas.send_start = RelativeTime(500);
load_timing_deltas.send_end = RelativeTime(600);
load_timing_deltas.receive_headers_end = RelativeTime(700);
TimingDeltas navigation_deltas;
RunTest(load_timing_deltas, &navigation_deltas);
EXPECT_LT(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.dns_end.GetDelta());
EXPECT_LT(navigation_deltas.dns_end.GetDelta(),
navigation_deltas.connect_start.GetDelta());
EXPECT_LT(navigation_deltas.connect_start.GetDelta(),
navigation_deltas.ssl_start.GetDelta());
EXPECT_LT(navigation_deltas.ssl_start.GetDelta(),
navigation_deltas.connect_end.GetDelta());
EXPECT_LT(navigation_deltas.connect_end.GetDelta(),
navigation_deltas.send_start.GetDelta());
EXPECT_LT(navigation_deltas.send_start.GetDelta(),
navigation_deltas.receive_headers_end.GetDelta());
}
IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, EverythingAtOnce) {
TimingDeltas load_timing_deltas;
load_timing_deltas.dns_start = RelativeTime(100);
load_timing_deltas.dns_end = RelativeTime(100);
load_timing_deltas.connect_start = RelativeTime(100);
load_timing_deltas.ssl_start = RelativeTime(100);
load_timing_deltas.connect_end = RelativeTime(100);
load_timing_deltas.send_start = RelativeTime(100);
load_timing_deltas.send_end = RelativeTime(100);
load_timing_deltas.receive_headers_end = RelativeTime(100);
TimingDeltas navigation_deltas;
RunTest(load_timing_deltas, &navigation_deltas);
EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.dns_end.GetDelta());
EXPECT_EQ(navigation_deltas.dns_end.GetDelta(),
navigation_deltas.connect_start.GetDelta());
EXPECT_EQ(navigation_deltas.connect_start.GetDelta(),
navigation_deltas.ssl_start.GetDelta());
EXPECT_EQ(navigation_deltas.ssl_start.GetDelta(),
navigation_deltas.connect_end.GetDelta());
EXPECT_EQ(navigation_deltas.connect_end.GetDelta(),
navigation_deltas.send_start.GetDelta());
EXPECT_EQ(navigation_deltas.send_start.GetDelta(),
navigation_deltas.receive_headers_end.GetDelta());
}
IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, ReuseSocket) {
TimingDeltas load_timing_deltas;
load_timing_deltas.send_start = RelativeTime(0);
load_timing_deltas.send_end = RelativeTime(100);
load_timing_deltas.receive_headers_end = RelativeTime(200);
TimingDeltas navigation_deltas;
RunTest(load_timing_deltas, &navigation_deltas);
EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_start.GetDelta());
EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_end.GetDelta());
EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_start.GetDelta());
EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_end.GetDelta());
EXPECT_LE(navigation_deltas.connect_end.GetDelta(),
navigation_deltas.send_start.GetDelta());
EXPECT_LT(navigation_deltas.send_start.GetDelta(),
navigation_deltas.receive_headers_end.GetDelta());
EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
}
IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Preconnect) {
TimingDeltas load_timing_deltas;
load_timing_deltas.dns_start = RelativeTime(-1000300);
load_timing_deltas.dns_end = RelativeTime(-1000200);
load_timing_deltas.connect_start = RelativeTime(-1000100);
load_timing_deltas.connect_end = RelativeTime(-1000000);
load_timing_deltas.send_start = RelativeTime(0);
load_timing_deltas.send_end = RelativeTime(100);
load_timing_deltas.receive_headers_end = RelativeTime(200);
TimingDeltas navigation_deltas;
RunTest(load_timing_deltas, &navigation_deltas);
EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.dns_end.GetDelta());
EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.connect_start.GetDelta());
EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.connect_end.GetDelta());
EXPECT_LE(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.send_start.GetDelta());
EXPECT_LT(navigation_deltas.send_start.GetDelta(),
navigation_deltas.receive_headers_end.GetDelta());
EXPECT_LT(navigation_deltas.send_start.GetDelta(),
navigation_deltas.receive_headers_end.GetDelta());
EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
}
IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, PreconnectProxySsl) {
TimingDeltas load_timing_deltas;
load_timing_deltas.proxy_resolve_start = RelativeTime(0);
load_timing_deltas.proxy_resolve_end = RelativeTime(100);
load_timing_deltas.dns_start = RelativeTime(-3000000);
load_timing_deltas.dns_end = RelativeTime(-2000000);
load_timing_deltas.connect_start = RelativeTime(-1000000);
load_timing_deltas.ssl_start = RelativeTime(0);
load_timing_deltas.connect_end = RelativeTime(100);
load_timing_deltas.send_start = RelativeTime(100);
load_timing_deltas.send_end = RelativeTime(200);
load_timing_deltas.receive_headers_end = RelativeTime(300);
TimingDeltas navigation_deltas;
RunTest(load_timing_deltas, &navigation_deltas);
EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.dns_end.GetDelta());
EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.connect_start.GetDelta());
EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.ssl_start.GetDelta());
EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.connect_end.GetDelta());
EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.send_start.GetDelta());
EXPECT_LT(navigation_deltas.send_start.GetDelta(),
navigation_deltas.receive_headers_end.GetDelta());
EXPECT_LT(navigation_deltas.send_start.GetDelta(),
navigation_deltas.receive_headers_end.GetDelta());
}
IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Integration) {
ASSERT_TRUE(test_server()->Start());
TimingDeltas navigation_deltas;
RunTestWithUrl(test_server()->GetURL("chunked?waitBeforeHeaders=100"),
&navigation_deltas);
EXPECT_LE(navigation_deltas.dns_start.GetDelta(),
navigation_deltas.dns_end.GetDelta());
EXPECT_LE(navigation_deltas.dns_end.GetDelta(),
navigation_deltas.connect_start.GetDelta());
EXPECT_LE(navigation_deltas.connect_start.GetDelta(),
navigation_deltas.connect_end.GetDelta());
EXPECT_LE(navigation_deltas.connect_end.GetDelta(),
navigation_deltas.send_start.GetDelta());
EXPECT_LT(navigation_deltas.send_start.GetDelta(),
navigation_deltas.receive_headers_end.GetDelta());
EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
}
}