summaryrefslogtreecommitdiffstats
path: root/chrome/browser/devtools/devtools_network_interceptor.cc
diff options
context:
space:
mode:
authoreustas@chromium.org <eustas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-18 17:05:36 +0000
committereustas@chromium.org <eustas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-18 17:05:36 +0000
commit60c5dad3c730ceb8cf227e63cd9877712d11a5d5 (patch)
tree068f9d1a1cf0bd60fb8f9b0d7f708679f884296c /chrome/browser/devtools/devtools_network_interceptor.cc
parent01db472d7320e72ea8464b92f6c725644d7b88b0 (diff)
downloadchromium_src-60c5dad3c730ceb8cf227e63cd9877712d11a5d5.zip
chromium_src-60c5dad3c730ceb8cf227e63cd9877712d11a5d5.tar.gz
chromium_src-60c5dad3c730ceb8cf227e63cd9877712d11a5d5.tar.bz2
DevTools: make network conditions emulation scoped (browser)
Currently network conditions are applied browser-wide. To restrict conditions to one tab requests are marked with specific headers. Those specific headers are removed before sending headers to network. BUG=245436 Review URL: https://codereview.chromium.org/342473004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278109 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/devtools/devtools_network_interceptor.cc')
-rw-r--r--chrome/browser/devtools/devtools_network_interceptor.cc183
1 files changed, 183 insertions, 0 deletions
diff --git a/chrome/browser/devtools/devtools_network_interceptor.cc b/chrome/browser/devtools/devtools_network_interceptor.cc
new file mode 100644
index 0000000..0399b8d
--- /dev/null
+++ b/chrome/browser/devtools/devtools_network_interceptor.cc
@@ -0,0 +1,183 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/devtools/devtools_network_interceptor.h"
+
+#include "base/time/time.h"
+#include "chrome/browser/devtools/devtools_network_conditions.h"
+#include "chrome/browser/devtools/devtools_network_transaction.h"
+
+namespace {
+
+int64_t kPacketSize = 1500;
+
+} // namespace
+
+DevToolsNetworkInterceptor::DevToolsNetworkInterceptor()
+ : conditions_(new DevToolsNetworkConditions()),
+ weak_ptr_factory_(this) {
+}
+
+DevToolsNetworkInterceptor::~DevToolsNetworkInterceptor() {
+}
+
+base::WeakPtr<DevToolsNetworkInterceptor>
+DevToolsNetworkInterceptor::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+void DevToolsNetworkInterceptor::AddTransaction(
+ DevToolsNetworkTransaction* transaction) {
+ DCHECK(transactions_.find(transaction) == transactions_.end());
+ transactions_.insert(transaction);
+}
+
+void DevToolsNetworkInterceptor::RemoveTransaction(
+ DevToolsNetworkTransaction* transaction) {
+ DCHECK(transactions_.find(transaction) != transactions_.end());
+ transactions_.erase(transaction);
+
+ if (!conditions_->IsThrottling())
+ return;
+
+ UpdateThrottles();
+ throttled_transactions_.erase(std::remove(throttled_transactions_.begin(),
+ throttled_transactions_.end(), transaction),
+ throttled_transactions_.end());
+ ArmTimer();
+}
+
+void DevToolsNetworkInterceptor::UpdateConditions(
+ const scoped_refptr<DevToolsNetworkConditions> conditions) {
+ DCHECK(conditions);
+ if (conditions_->IsThrottling())
+ UpdateThrottles();
+
+ conditions_ = conditions;
+
+ if (conditions->offline()) {
+ timer_.Stop();
+ throttled_transactions_.clear();
+ Transactions old_transactions(transactions_);
+ Transactions::iterator it = old_transactions.begin();
+ for (;it != old_transactions.end(); ++it) {
+ if (transactions_.find(*it) == transactions_.end())
+ continue;
+ if (!(*it)->request() || (*it)->failed())
+ continue;
+ if (ShouldFail(*it))
+ (*it)->Fail();
+ }
+ return;
+ }
+
+ if (conditions->IsThrottling()) {
+ DCHECK(conditions->download_throughput() != 0);
+ offset_ = base::TimeTicks::Now();
+ last_tick_ = 0;
+ int64_t us_tick_length =
+ (1000000L * kPacketSize) / conditions->download_throughput();
+ DCHECK(us_tick_length != 0);
+ if (us_tick_length == 0)
+ us_tick_length = 1;
+ tick_length_ = base::TimeDelta::FromMicroseconds(us_tick_length);
+ ArmTimer();
+ } else {
+ timer_.Stop();
+ int64_t length = throttled_transactions_.size();
+ for (int64_t i = 0; i < length; ++i)
+ throttled_transactions_[i]->FireThrottledCallback();
+ throttled_transactions_.clear();
+ }
+}
+
+void DevToolsNetworkInterceptor::UpdateThrottles() {
+ int64_t last_tick = (base::TimeTicks::Now() - offset_) / tick_length_;
+ int64_t ticks = last_tick - last_tick_;
+ last_tick_ = last_tick;
+
+ int64_t length = throttled_transactions_.size();
+ if (!length)
+ return;
+
+ int64_t shift = ticks % length;
+ for (int64_t i = 0; i < length; ++i) {
+ throttled_transactions_[i]->DecreaseThrottledByteCount(
+ (ticks / length) * kPacketSize + (i < shift ? kPacketSize : 0));
+ }
+ std::rotate(throttled_transactions_.begin(),
+ throttled_transactions_.begin() + shift, throttled_transactions_.end());
+}
+
+void DevToolsNetworkInterceptor::OnTimer() {
+ UpdateThrottles();
+
+ std::vector<DevToolsNetworkTransaction*> active_transactions;
+ std::vector<DevToolsNetworkTransaction*> finished_transactions;
+ size_t length = throttled_transactions_.size();
+ for (size_t i = 0; i < length; ++i) {
+ if (throttled_transactions_[i]->throttled_byte_count() < 0)
+ finished_transactions.push_back(throttled_transactions_[i]);
+ else
+ active_transactions.push_back(throttled_transactions_[i]);
+ }
+ throttled_transactions_.swap(active_transactions);
+
+ length = finished_transactions.size();
+ for (size_t i = 0; i < length; ++i)
+ finished_transactions[i]->FireThrottledCallback();
+
+ ArmTimer();
+}
+
+void DevToolsNetworkInterceptor::ArmTimer() {
+ size_t length = throttled_transactions_.size();
+ if (!length)
+ return;
+ int64_t min_ticks_left = 0x10000L;
+ for (size_t i = 0; i < length; ++i) {
+ int64_t packets_left = (throttled_transactions_[i]->throttled_byte_count() +
+ kPacketSize - 1) / kPacketSize;
+ int64_t ticks_left = (i + 1) + length * (packets_left - 1);
+ if (i == 0 || ticks_left < min_ticks_left)
+ min_ticks_left = ticks_left;
+ }
+ base::TimeTicks desired_time =
+ offset_ + tick_length_ * (last_tick_ + min_ticks_left);
+ timer_.Start(
+ FROM_HERE,
+ desired_time - base::TimeTicks::Now(),
+ base::Bind(
+ &DevToolsNetworkInterceptor::OnTimer,
+ base::Unretained(this)));
+}
+
+void DevToolsNetworkInterceptor::ThrottleTransaction(
+ DevToolsNetworkTransaction* transaction) {
+ UpdateThrottles();
+ throttled_transactions_.push_back(transaction);
+ ArmTimer();
+}
+
+bool DevToolsNetworkInterceptor::ShouldFail(
+ const DevToolsNetworkTransaction* transaction) {
+ if (!conditions_->offline())
+ return false;
+
+ if (!transaction->request_initiator().empty())
+ return false;
+
+ return true;
+}
+
+bool DevToolsNetworkInterceptor::ShouldThrottle(
+ const DevToolsNetworkTransaction* transaction) {
+ if (!conditions_->IsThrottling())
+ return false;
+
+ if (!transaction->request_initiator().empty())
+ return false;
+
+ return true;
+}