1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file.
4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/devtools/devtools_network_interceptor.h"
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include <limits>
86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/time/time.h"
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/devtools/devtools_network_conditions.h"
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/devtools/devtools_network_transaction.h"
126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "net/base/load_timing_info.h"
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)int64_t kPacketSize = 1500;
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)DevToolsNetworkInterceptor::DevToolsNetworkInterceptor()
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : conditions_(new DevToolsNetworkConditions()),
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      weak_ptr_factory_(this) {
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)DevToolsNetworkInterceptor::~DevToolsNetworkInterceptor() {
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)base::WeakPtr<DevToolsNetworkInterceptor>
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)DevToolsNetworkInterceptor::GetWeakPtr() {
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return weak_ptr_factory_.GetWeakPtr();
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DevToolsNetworkInterceptor::AddTransaction(
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DevToolsNetworkTransaction* transaction) {
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(transactions_.find(transaction) == transactions_.end());
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  transactions_.insert(transaction);
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DevToolsNetworkInterceptor::RemoveTransaction(
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DevToolsNetworkTransaction* transaction) {
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(transactions_.find(transaction) != transactions_.end());
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  transactions_.erase(transaction);
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!conditions_->IsThrottling())
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UpdateThrottledTransactions(now);
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  throttled_transactions_.erase(std::remove(throttled_transactions_.begin(),
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      throttled_transactions_.end(), transaction),
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      throttled_transactions_.end());
526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SuspendedTransactions::iterator it = suspended_transactions_.begin();
546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (; it != suspended_transactions_.end(); ++it) {
556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (it->first == transaction) {
566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      suspended_transactions_.erase(it);
576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      break;
586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ArmTimer(now);
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DevToolsNetworkInterceptor::UpdateConditions(
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<DevToolsNetworkConditions> conditions) {
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(conditions);
676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (conditions_->IsThrottling())
696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    UpdateThrottledTransactions(now);
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  conditions_ = conditions.Pass();
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (conditions_->offline()) {
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    timer_.Stop();
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    throttled_transactions_.clear();
766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    suspended_transactions_.clear();
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Transactions old_transactions(transactions_);
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Transactions::iterator it = old_transactions.begin();
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (;it != old_transactions.end(); ++it) {
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (transactions_.find(*it) == transactions_.end())
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        continue;
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (!(*it)->request() || (*it)->failed())
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        continue;
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (ShouldFail(*it))
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        (*it)->Fail();
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (conditions_->IsThrottling()) {
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK(conditions_->download_throughput() != 0);
926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    offset_ = now;
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    last_tick_ = 0;
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int64_t us_tick_length =
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        (1000000L * kPacketSize) / conditions_->download_throughput();
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(us_tick_length != 0);
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (us_tick_length == 0)
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      us_tick_length = 1;
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    tick_length_ = base::TimeDelta::FromMicroseconds(us_tick_length);
1006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    latency_length_ = base::TimeDelta();
1016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    double latency = conditions_->latency();
1026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (latency > 0)
1036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      latency_length_ = base::TimeDelta::FromMillisecondsD(latency);
1046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    ArmTimer(now);
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    timer_.Stop();
1076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    std::vector<DevToolsNetworkTransaction*> throttled_transactions;
1096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    throttled_transactions.swap(throttled_transactions_);
1106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    size_t throttle_count = throttled_transactions.size();
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (size_t i = 0; i < throttle_count; ++i)
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      FireThrottledCallback(throttled_transactions[i]);
1136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    SuspendedTransactions suspended_transactions;
1156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    suspended_transactions_.swap(suspended_transactions_);
1166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    size_t suspend_count = suspended_transactions.size();
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (size_t i = 0; i < suspend_count; ++i)
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      FireThrottledCallback(suspended_transactions[i].first);
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid DevToolsNetworkInterceptor::FireThrottledCallback(
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DevToolsNetworkTransaction* transaction) {
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (transactions_.find(transaction) != transactions_.end())
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    transaction->FireThrottledCallback();
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DevToolsNetworkInterceptor::UpdateThrottledTransactions(
1296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::TimeTicks now) {
1306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  int64_t last_tick = (now - offset_) / tick_length_;
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int64_t ticks = last_tick - last_tick_;
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  last_tick_ = last_tick;
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int64_t length = throttled_transactions_.size();
1356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!length) {
1366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    UpdateSuspendedTransactions(now);
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
1386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int64_t shift = ticks % length;
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (int64_t i = 0; i < length; ++i) {
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    throttled_transactions_[i]->DecreaseThrottledByteCount(
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        (ticks / length) * kPacketSize + (i < shift ? kPacketSize : 0));
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::rotate(throttled_transactions_.begin(),
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      throttled_transactions_.begin() + shift, throttled_transactions_.end());
1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UpdateSuspendedTransactions(now);
1496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
1506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DevToolsNetworkInterceptor::UpdateSuspendedTransactions(
1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::TimeTicks now) {
1536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  int64_t activation_baseline =
1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      (now - latency_length_ - base::TimeTicks()).InMicroseconds();
1556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SuspendedTransactions suspended_transactions;
1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SuspendedTransactions::iterator it = suspended_transactions_.begin();
1576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (; it != suspended_transactions_.end(); ++it) {
1586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (it->second <= activation_baseline)
1596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      throttled_transactions_.push_back(it->first);
1606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    else
1616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      suspended_transactions.push_back(*it);
1626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
1636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  suspended_transactions_.swap(suspended_transactions);
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DevToolsNetworkInterceptor::OnTimer() {
1676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
1686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UpdateThrottledTransactions(now);
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::vector<DevToolsNetworkTransaction*> active_transactions;
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::vector<DevToolsNetworkTransaction*> finished_transactions;
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t length = throttled_transactions_.size();
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < length; ++i) {
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (throttled_transactions_[i]->throttled_byte_count() < 0)
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      finished_transactions.push_back(throttled_transactions_[i]);
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    else
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      active_transactions.push_back(throttled_transactions_[i]);
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  throttled_transactions_.swap(active_transactions);
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  length = finished_transactions.size();
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < length; ++i)
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    FireThrottledCallback(finished_transactions[i]);
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ArmTimer(now);
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DevToolsNetworkInterceptor::ArmTimer(base::TimeTicks now) {
1896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  size_t throttle_count = throttled_transactions_.size();
1906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  size_t suspend_count = suspended_transactions_.size();
1916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!throttle_count && !suspend_count)
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int64_t min_ticks_left = 0x10000L;
1946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (size_t i = 0; i < throttle_count; ++i) {
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int64_t packets_left = (throttled_transactions_[i]->throttled_byte_count() +
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        kPacketSize - 1) / kPacketSize;
1976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    int64_t ticks_left = (i + 1) + throttle_count * (packets_left - 1);
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (i == 0 || ticks_left < min_ticks_left)
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      min_ticks_left = ticks_left;
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::TimeTicks desired_time =
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      offset_ + tick_length_ * (last_tick_ + min_ticks_left);
2036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  int64_t min_baseline = std::numeric_limits<int64>::max();
2056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (size_t i = 0; i < suspend_count; ++i) {
2066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (suspended_transactions_[i].second < min_baseline)
2076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      min_baseline = suspended_transactions_[i].second;
2086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (suspend_count) {
2106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::TimeTicks activation_time = base::TimeTicks() +
2116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        base::TimeDelta::FromMicroseconds(min_baseline) + latency_length_;
2126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (activation_time < desired_time)
2136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      desired_time = activation_time;
2146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  timer_.Start(
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      FROM_HERE,
2186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      desired_time - now,
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::Bind(
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          &DevToolsNetworkInterceptor::OnTimer,
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          base::Unretained(this)));
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DevToolsNetworkInterceptor::ThrottleTransaction(
2256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    DevToolsNetworkTransaction* transaction, bool start) {
2266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
2276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UpdateThrottledTransactions(now);
2286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (start && latency_length_ != base::TimeDelta()) {
2296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    net::LoadTimingInfo load_timing_info;
2306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::TimeTicks send_end;
2316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (transaction->GetLoadTimingInfo(&load_timing_info))
2326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      send_end = load_timing_info.send_end;
2336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (send_end.is_null())
2346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      send_end = now;
2356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    int64_t us_send_end = (send_end - base::TimeTicks()).InMicroseconds();
2366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    suspended_transactions_.push_back(
2376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        SuspendedTransaction(transaction, us_send_end));
2386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    UpdateSuspendedTransactions(now);
2396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  } else {
2406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    throttled_transactions_.push_back(transaction);
2416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ArmTimer(now);
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool DevToolsNetworkInterceptor::ShouldFail(
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const DevToolsNetworkTransaction* transaction) {
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!conditions_->offline())
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!transaction->request_initiator().empty())
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool DevToolsNetworkInterceptor::ShouldThrottle(
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const DevToolsNetworkTransaction* transaction) {
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!conditions_->IsThrottling())
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!transaction->request_initiator().empty())
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
266