1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/compiler_specific.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/weak_ptr.h"
139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/path_service.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_paths.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/test/browser_test_utils.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/load_timing_info.h"
25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/spawned_test_server/spawned_test_server.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_request_file_job.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_request_filter.h"
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/url_request/url_request_interceptor.h"
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file tests that net::LoadTimingInfo is correctly hooked up to the
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// NavigationTiming API.  It depends on behavior in a large number of files
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// spread across multiple projects, so is somewhat arbitrarily put in
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// chrome/browser/net.
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using content::BrowserThread;
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kTestDomain[] = "test.com";
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kTestUrl[] = "http://test.com/";
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Relative times need to be used because:
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 1)  ExecuteScriptAndExtractInt does not support 64-bit integers.
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 2)  Times for tests are set before the request has been started, but need to
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//     be set relative to the start time.
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Since some tests need to test negative time deltas (preconnected sockets)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// and others need to test NULL times (events that don't apply), this class has
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to be able to handle all cases:  positive deltas, negative deltas, no
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// delta, and null times.
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class RelativeTime {
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Constructor for null RelativeTimes.
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime() : is_null_(true) {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Constructor for non-null RelativeTimes.
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit RelativeTime(int delta_ms)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : is_null_(false),
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        delta_(base::TimeDelta::FromMilliseconds(delta_ms)) {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Given a base time, returns the TimeTicks |this| identifies.
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeTicks ToTimeTicks(base::TimeTicks base_time) const {
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (is_null_)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return base::TimeTicks();
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return base_time + delta_;
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool is_null() const { return is_null_; }
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeDelta GetDelta() const {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This allows tests to compare times that shouldn't be null without
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // explicitly null-testing them all first.
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_FALSE(is_null_);
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return delta_;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool is_null_;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Must be 0 when |is_null| is true.
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeDelta delta_;
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This class is copyable and assignable.
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Structure used for both setting the LoadTimingInfo used by mock requests
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// and for times retrieved from the renderer process.
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Times used for mock requests are all expressed as TimeDeltas relative to
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// when the Job starts.  Null RelativeTimes correspond to null TimeTicks().
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Times read from the renderer are expressed relative to fetchStart (Which is
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// not the same as request_start).  Null RelativeTimes correspond to times that
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// either cannot be retrieved (proxy times, send end) or times that are 0 (SSL
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// time when no new SSL connection was established).
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct TimingDeltas {
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime proxy_resolve_start;
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime proxy_resolve_end;
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime dns_start;
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime dns_end;
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime connect_start;
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime ssl_start;
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime connect_end;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime send_start;
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime send_end;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Must be non-negative and greater than all other times.  May only be null if
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // all other times are as well.
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime receive_headers_end;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Mock UrlRequestJob that returns the contents of a specified file and
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// provides the specified load timing information when queried.
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockUrlRequestJobWithTiming : public net::URLRequestFileJob {
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockUrlRequestJobWithTiming(net::URLRequest* request,
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              net::NetworkDelegate* network_delegate,
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              const base::FilePath& path,
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              const TimingDeltas& load_timing_deltas)
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      : net::URLRequestFileJob(
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            request, network_delegate, path,
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            content::BrowserThread::GetBlockingPool()->
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                GetTaskRunnerWithShutdownBehavior(
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        load_timing_deltas_(load_timing_deltas),
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        weak_factory_(this) {}
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // net::URLRequestFileJob implementation:
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void Start() OVERRIDE {
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::TimeDelta time_to_wait;
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    start_time_ = base::TimeTicks::Now();
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!load_timing_deltas_.receive_headers_end.is_null()) {
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Need to delay starting until the largest of the times has elapsed.
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Wait a little longer than necessary, to be on the safe side.
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      time_to_wait = load_timing_deltas_.receive_headers_end.GetDelta() +
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         base::TimeDelta::FromMilliseconds(100);
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FROM_HERE,
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&MockUrlRequestJobWithTiming::DelayedStart,
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   weak_factory_.GetWeakPtr()),
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        time_to_wait);
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void GetLoadTimingInfo(
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::LoadTimingInfo* load_timing_info) const OVERRIDE {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Make sure enough time has elapsed since start was called.  If this
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // fails, the test fixture itself is flaky.
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!load_timing_deltas_.receive_headers_end.is_null()) {
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      EXPECT_LE(
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          start_time_ + load_timing_deltas_.receive_headers_end.GetDelta(),
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::TimeTicks::Now());
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // If there are no connect times, but there is a receive headers end time,
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // then assume the socket is reused.  This shouldn't affect the load timing
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // information the test checks, just done for completeness.
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->socket_reused = false;
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (load_timing_deltas_.connect_start.is_null() &&
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !load_timing_deltas_.receive_headers_end.is_null()) {
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      load_timing_info->socket_reused = true;
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->proxy_resolve_start =
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.proxy_resolve_start.ToTimeTicks(start_time_);
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->proxy_resolve_end =
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.proxy_resolve_end.ToTimeTicks(start_time_);
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->connect_timing.dns_start =
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.dns_start.ToTimeTicks(start_time_);
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->connect_timing.dns_end =
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.dns_end.ToTimeTicks(start_time_);
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->connect_timing.connect_start =
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.connect_start.ToTimeTicks(start_time_);
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->connect_timing.ssl_start =
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.ssl_start.ToTimeTicks(start_time_);
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->connect_timing.connect_end =
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.connect_end.ToTimeTicks(start_time_);
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // If there's an SSL start time, use connect end as the SSL end time.
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The NavigationTiming API does not have a corresponding field, and there's
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // no need to test the case when the values are both non-NULL and different.
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!load_timing_deltas_.ssl_start.is_null()) {
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      load_timing_info->connect_timing.ssl_end =
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          load_timing_info->connect_timing.connect_end;
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->send_start =
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.send_start.ToTimeTicks(start_time_);
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->send_end=
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.send_end.ToTimeTicks(start_time_);
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    load_timing_info->receive_headers_end =
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        load_timing_deltas_.receive_headers_end.ToTimeTicks(start_time_);
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Parent class is reference counted, so need to have a private destructor.
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~MockUrlRequestJobWithTiming() {}
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void DelayedStart() {
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    net::URLRequestFileJob::Start();
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Load times to use, relative to |start_time_|.
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const TimingDeltas load_timing_deltas_;
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::TimeTicks start_time_;
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WeakPtrFactory<MockUrlRequestJobWithTiming> weak_factory_;
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MockUrlRequestJobWithTiming);
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// AURLRequestInterceptor that returns mock URLRequestJobs that return the
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// specified file with the given timings.  Constructed on the UI thread, but
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// after that, lives and is destroyed on the IO thread.
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class TestInterceptor : public net::URLRequestInterceptor {
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  TestInterceptor(const base::FilePath& path,
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                  const TimingDeltas& load_timing_deltas)
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : path_(path), load_timing_deltas_(load_timing_deltas) {
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~TestInterceptor() {
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Registers |this| with the URLRequestFilter, which takes ownership of it.
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Register() {
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        "http", kTestDomain, scoped_ptr<net::URLRequestInterceptor>(this));
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Unregisters |this| with the URLRequestFilter, which should then delete
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |this|.
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Unregister() {
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "http", kTestDomain);
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // net::URLRequestJobFactory::ProtocolHandler implementation:
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual net::URLRequestJob* MaybeInterceptRequest(
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::URLRequest* request,
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::NetworkDelegate* network_delegate) const OVERRIDE {
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return new MockUrlRequestJobWithTiming(request, network_delegate, path_,
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           load_timing_deltas_);
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Path of the file to use as the response body.
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::FilePath path_;
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Load times for each request to use, relative to when the Job starts.
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const TimingDeltas load_timing_deltas_;
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestInterceptor);
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class LoadTimingBrowserTest : public InProcessBrowserTest {
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LoadTimingBrowserTest() {
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~LoadTimingBrowserTest() {
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Navigates to |url| and writes the resulting navigation timings to
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |navigation_deltas|.
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RunTestWithUrl(const GURL& url, TimingDeltas* navigation_deltas) {
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ui_test_utils::NavigateToURL(browser(), url);
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetResultDeltas(navigation_deltas);
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Navigates to a url that returns the timings indicated by
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |load_timing_deltas| and writes the resulting navigation timings to
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |navigation_deltas|.  Uses a generic test page.
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RunTest(const TimingDeltas& load_timing_deltas,
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               TimingDeltas* navigation_deltas) {
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // None of the tests care about the contents of the test page.  Just do
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // this here because PathService has thread restrictions on some platforms.
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::FilePath path;
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PathService::Get(chrome::DIR_TEST_DATA, &path);
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    path = path.AppendASCII("title1.html");
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Create and register request interceptor.
29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    TestInterceptor* test_interceptor =
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        new TestInterceptor(path, load_timing_deltas);
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            base::Bind(&TestInterceptor::Register,
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       base::Unretained(test_interceptor)));
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Navigate to the page.
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RunTestWithUrl(GURL(kTestUrl), navigation_deltas);
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Once navigation is complete, unregister the protocol handler.
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            base::Bind(&TestInterceptor::Unregister,
30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                        base::Unretained(test_interceptor)));
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Reads applicable times from performance.timing and writes them to
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |navigation_deltas|.  Proxy times and send end cannot be read from the
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Navigation Timing API, so those are all left as null.
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void GetResultDeltas(TimingDeltas* navigation_deltas) {
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *navigation_deltas = TimingDeltas();
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    navigation_deltas->dns_start = GetResultDelta("domainLookupStart");
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    navigation_deltas->dns_end = GetResultDelta("domainLookupEnd");
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    navigation_deltas->connect_start = GetResultDelta("connectStart");
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    navigation_deltas->connect_end = GetResultDelta("connectEnd");
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    navigation_deltas->send_start = GetResultDelta("requestStart");
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    navigation_deltas->receive_headers_end = GetResultDelta("responseStart");
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Unlike the above times, secureConnectionStart will be zero when not
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // applicable.  In that case, leave ssl_start as null.
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool ssl_start_zero = false;
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    browser()->tab_strip_model()->GetActiveWebContents(),
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    "window.domAutomationController.send("
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        "performance.timing.secureConnectionStart == 0);",
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    &ssl_start_zero));
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!ssl_start_zero)
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      navigation_deltas->ssl_start = GetResultDelta("secureConnectionStart");
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Simple sanity checks.  Make sure times that correspond to LoadTimingInfo
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // occur between fetchStart and loadEventEnd.  Relationships between
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // intervening times are handled by the test bodies.
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RelativeTime fetch_start = GetResultDelta("fetchStart");
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // While the input dns_start is sometimes null, when read from the
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // NavigationTiming API, it's always non-null.
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_LE(fetch_start.GetDelta(), navigation_deltas->dns_start.GetDelta());
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RelativeTime load_event_end = GetResultDelta("loadEventEnd");
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_LE(navigation_deltas->receive_headers_end.GetDelta(),
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              load_event_end.GetDelta());
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Returns the time between performance.timing.fetchStart and the time with
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the specified name.  This time must be non-negative.
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RelativeTime GetResultDelta(const std::string& name) {
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int time_ms = 0;
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string command(base::StringPrintf(
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "window.domAutomationController.send("
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            "performance.timing.%s - performance.timing.fetchStart);",
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        name.c_str()));
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    browser()->tab_strip_model()->GetActiveWebContents(),
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    command.c_str(),
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    &time_ms));
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Basic sanity check.
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_GE(time_ms, 0);
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return RelativeTime(time_ms);
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Test case when no times are given, except the request start times.  This
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// happens with FTP, cached responses, responses handled by something other than
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the network stack, RedirectJobs, HSTs, etc.
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, NoTimes) {
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas load_timing_deltas;
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas navigation_deltas;
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunTest(load_timing_deltas, &navigation_deltas);
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // When there are no times, all read times should be the same as fetchStart,
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // except SSL start, which should be 0.
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_start.GetDelta());
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_end.GetDelta());
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_start.GetDelta());
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_end.GetDelta());
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(), navigation_deltas.send_start.GetDelta());
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(),
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Standard case - new socket, no PAC, no preconnect, no SSL.
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Basic) {
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas load_timing_deltas;
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.dns_start = RelativeTime(0);
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.dns_end = RelativeTime(100);
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.connect_start = RelativeTime(200);
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.connect_end = RelativeTime(300);
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_start = RelativeTime(400);
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_end = RelativeTime(500);
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.receive_headers_end = RelativeTime(600);
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas navigation_deltas;
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunTest(load_timing_deltas, &navigation_deltas);
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Due to potential roundoff issues, never check exact differences.
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.dns_start.GetDelta(),
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.dns_end.GetDelta());
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.dns_end.GetDelta(),
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_start.GetDelta());
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.connect_start.GetDelta(),
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_end.GetDelta());
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.connect_end.GetDelta(),
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.send_start.GetDelta());
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.send_start.GetDelta(),
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Basic SSL case.
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Ssl) {
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas load_timing_deltas;
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.dns_start = RelativeTime(0);
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.dns_end = RelativeTime(100);
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.connect_start = RelativeTime(200);
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.ssl_start = RelativeTime(300);
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.connect_end = RelativeTime(400);
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_start = RelativeTime(500);
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_end = RelativeTime(600);
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.receive_headers_end = RelativeTime(700);
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas navigation_deltas;
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunTest(load_timing_deltas, &navigation_deltas);
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Due to potential roundoff issues, never check exact differences.
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.dns_start.GetDelta(),
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.dns_end.GetDelta());
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.dns_end.GetDelta(),
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_start.GetDelta());
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.connect_start.GetDelta(),
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.ssl_start.GetDelta());
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.ssl_start.GetDelta(),
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_end.GetDelta());
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.connect_end.GetDelta(),
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.send_start.GetDelta());
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.send_start.GetDelta(),
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// All times are the same.
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, EverythingAtOnce) {
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas load_timing_deltas;
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.dns_start = RelativeTime(100);
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.dns_end = RelativeTime(100);
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.connect_start = RelativeTime(100);
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.ssl_start = RelativeTime(100);
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.connect_end = RelativeTime(100);
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_start = RelativeTime(100);
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_end = RelativeTime(100);
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.receive_headers_end = RelativeTime(100);
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas navigation_deltas;
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunTest(load_timing_deltas, &navigation_deltas);
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.dns_end.GetDelta());
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_end.GetDelta(),
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_start.GetDelta());
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.connect_start.GetDelta(),
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.ssl_start.GetDelta());
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.ssl_start.GetDelta(),
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_end.GetDelta());
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.connect_end.GetDelta(),
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.send_start.GetDelta());
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.send_start.GetDelta(),
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Reuse case.
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, ReuseSocket) {
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas load_timing_deltas;
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_start = RelativeTime(0);
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_end = RelativeTime(100);
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.receive_headers_end = RelativeTime(200);
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas navigation_deltas;
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunTest(load_timing_deltas, &navigation_deltas);
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Connect times should all be the same as fetchStart.
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_start.GetDelta());
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(), navigation_deltas.dns_end.GetDelta());
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_start.GetDelta());
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(base::TimeDelta(), navigation_deltas.connect_end.GetDelta());
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Connect end may be less than send start, since connect end defaults to
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // fetchStart, which is often less than request_start.
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LE(navigation_deltas.connect_end.GetDelta(),
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.send_start.GetDelta());
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.send_start.GetDelta(),
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Preconnect case.  Connect times are all before the request was started.
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Preconnect) {
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas load_timing_deltas;
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  load_timing_deltas.dns_start = RelativeTime(-1000300);
50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  load_timing_deltas.dns_end = RelativeTime(-1000200);
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  load_timing_deltas.connect_start = RelativeTime(-1000100);
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  load_timing_deltas.connect_end = RelativeTime(-1000000);
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_start = RelativeTime(0);
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_end = RelativeTime(100);
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.receive_headers_end = RelativeTime(200);
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas navigation_deltas;
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunTest(load_timing_deltas, &navigation_deltas);
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Connect times should all be the same as request_start.
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.dns_end.GetDelta());
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_start.GetDelta());
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_end.GetDelta());
52590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
52690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_LE(navigation_deltas.dns_start.GetDelta(),
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.send_start.GetDelta());
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.send_start.GetDelta(),
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.send_start.GetDelta(),
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Preconnect case with a proxy.  Connect times are all before the proxy lookup
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// finished (Or at the same time).
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, PreconnectProxySsl) {
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas load_timing_deltas;
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.proxy_resolve_start = RelativeTime(0);
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.proxy_resolve_end = RelativeTime(100);
54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  load_timing_deltas.dns_start = RelativeTime(-3000000);
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  load_timing_deltas.dns_end = RelativeTime(-2000000);
54590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  load_timing_deltas.connect_start = RelativeTime(-1000000);
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.ssl_start = RelativeTime(0);
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.connect_end = RelativeTime(100);
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_start = RelativeTime(100);
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.send_end = RelativeTime(200);
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  load_timing_deltas.receive_headers_end = RelativeTime(300);
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas navigation_deltas;
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunTest(load_timing_deltas, &navigation_deltas);
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Connect times should all be the same as proxy_end, which is also the
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // same as send_start.
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.dns_end.GetDelta());
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_start.GetDelta());
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.ssl_start.GetDelta());
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_end.GetDelta());
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(navigation_deltas.dns_start.GetDelta(),
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.send_start.GetDelta());
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.send_start.GetDelta(),
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.send_start.GetDelta(),
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Integration test with a real network response.
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, Integration) {
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TimingDeltas navigation_deltas;
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunTestWithUrl(test_server()->GetURL("chunked?waitBeforeHeaders=100"),
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 &navigation_deltas);
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Due to potential roundoff issues, never check exact differences.
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LE(navigation_deltas.dns_start.GetDelta(),
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.dns_end.GetDelta());
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LE(navigation_deltas.dns_end.GetDelta(),
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_start.GetDelta());
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LE(navigation_deltas.connect_start.GetDelta(),
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.connect_end.GetDelta());
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LE(navigation_deltas.connect_end.GetDelta(),
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.send_start.GetDelta());
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The only times that are guaranteed to be distinct are send_start and
59190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // received_headers_end.
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_LT(navigation_deltas.send_start.GetDelta(),
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            navigation_deltas.receive_headers_end.GetDelta());
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(navigation_deltas.ssl_start.is_null());
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
599