summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--chrome/browser/devtools/chrome_devtools_manager_delegate.cc73
-rw-r--r--chrome/browser/devtools/chrome_devtools_manager_delegate.h1
-rw-r--r--chrome/browser/devtools/devtools_network_conditions.cc40
-rw-r--r--chrome/browser/devtools/devtools_network_conditions.h23
-rw-r--r--chrome/browser/devtools/devtools_network_controller.cc215
-rw-r--r--chrome/browser/devtools/devtools_network_controller.h56
-rw-r--r--chrome/browser/devtools/devtools_network_controller_unittest.cc93
-rw-r--r--chrome/browser/devtools/devtools_network_interceptor.cc183
-rw-r--r--chrome/browser/devtools/devtools_network_interceptor.h70
-rw-r--r--chrome/browser/devtools/devtools_network_transaction.cc53
-rw-r--r--chrome/browser/devtools/devtools_network_transaction.h29
-rw-r--r--chrome/chrome_debugger.gypi2
12 files changed, 528 insertions, 310 deletions
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
index 473309d..3dd74ac 100644
--- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
+++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -61,9 +61,15 @@ base::DictionaryValue* ChromeDevToolsManagerDelegate::HandleCommand(
DevToolsProtocol::ParseCommand(command_dict));
if (!command)
return NULL;
+
const std::string method = command->method();
+ scoped_ptr<DevToolsProtocol::Response> response;
+
if (method == chrome::devtools::Network::emulateNetworkConditions::kName)
- return EmulateNetworkConditions(agent_host, command.get())->Serialize();
+ response = EmulateNetworkConditions(agent_host, command.get());
+
+ if (response)
+ return response->Serialize();
return NULL;
}
@@ -81,41 +87,35 @@ ChromeDevToolsManagerDelegate::EmulateNetworkConditions(
content::DevToolsAgentHost* agent_host,
DevToolsProtocol::Command* command) {
base::DictionaryValue* params = command->params();
-
- std::vector<std::string> domains;
- base::ListValue* domain_list = NULL;
- const char* domains_param =
- chrome::devtools::Network::emulateNetworkConditions::kParamDomains;
- if (!params || !params->GetList(domains_param, &domain_list))
- return command->InvalidParamResponse(domains_param);
- size_t size = domain_list->GetSize();
- for (size_t i = 0; i < size; ++i) {
- std::string domain;
- if (!domain_list->GetString(i, &domain))
- return command->InvalidParamResponse(domains_param);
- domains.push_back(domain);
- }
+ namespace names = ::chrome::devtools::Network::emulateNetworkConditions;
bool offline = false;
- const char* offline_param =
- chrome::devtools::Network::emulateNetworkConditions::kParamOffline;
- if (!params->GetBoolean(offline_param, &offline))
- return command->InvalidParamResponse(offline_param);
-
- double maximal_throughput = 0.0;
- const char* maximal_throughput_param =
-chrome::devtools::Network::emulateNetworkConditions::kParamMaximalThroughput;
- if (!params->GetDouble(maximal_throughput_param, &maximal_throughput))
- return command->InvalidParamResponse(maximal_throughput_param);
- if (maximal_throughput < 0.0)
- maximal_throughput = 0.0;
+ if (!params || !params->GetBoolean(names::kParamOffline, &offline))
+ return command->InvalidParamResponse(names::kParamOffline);
+
+ double latency = 0.0;
+ if (!params->GetDouble(names::kParamLatency, &latency))
+ return command->InvalidParamResponse(names::kParamLatency);
+ if (latency < 0.0)
+ latency = 0.0;
+
+ double download_throughput = 0.0;
+ if (!params->GetDouble(names::kParamDownloadThroughput, &download_throughput))
+ return command->InvalidParamResponse(names::kParamDownloadThroughput);
+ if (download_throughput < 0.0)
+ download_throughput = 0.0;
+
+ double upload_throughput = 0.0;
+ if (!params->GetDouble(names::kParamUploadThroughput, &upload_throughput))
+ return command->InvalidParamResponse(names::kParamUploadThroughput);
+ if (upload_throughput < 0.0)
+ upload_throughput = 0.0;
EnsureDevtoolsCallbackRegistered();
- scoped_refptr<DevToolsNetworkConditions> conditions;
- if (offline || maximal_throughput)
- conditions = new DevToolsNetworkConditions(domains, maximal_throughput);
+ scoped_refptr<DevToolsNetworkConditions> conditions(
+ new DevToolsNetworkConditions(
+ offline, latency, download_throughput, upload_throughput));
- emulate_network_conditions_client_id_ = agent_host->GetId();
UpdateNetworkState(agent_host, conditions);
return command->SuccessResponse(NULL);
}
@@ -126,14 +126,15 @@ void ChromeDevToolsManagerDelegate::UpdateNetworkState(
Profile* profile = GetProfile(agent_host);
if (!profile)
return;
- profile->GetDevToolsNetworkController()->SetNetworkState(conditions);
+ profile->GetDevToolsNetworkController()->SetNetworkState(
+ agent_host->GetId(), conditions);
}
void ChromeDevToolsManagerDelegate::OnDevToolsStateChanged(
content::DevToolsAgentHost* agent_host,
bool attached) {
- if (agent_host->GetId() == emulate_network_conditions_client_id_) {
- emulate_network_conditions_client_id_ = std::string();
- UpdateNetworkState(agent_host, scoped_refptr<DevToolsNetworkConditions>());
- }
+ scoped_refptr<DevToolsNetworkConditions> conditions;
+ if (attached)
+ conditions = new DevToolsNetworkConditions();
+ UpdateNetworkState(agent_host, conditions);
}
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.h b/chrome/browser/devtools/chrome_devtools_manager_delegate.h
index bdbbbbf..6385c0c 100644
--- a/chrome/browser/devtools/chrome_devtools_manager_delegate.h
+++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.h
@@ -37,7 +37,6 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
scoped_ptr<DevToolsProtocol::Response> EmulateNetworkConditions(
content::DevToolsAgentHost* agent_host,
DevToolsProtocol::Command* command);
- std::string emulate_network_conditions_client_id_;
void UpdateNetworkState(
content::DevToolsAgentHost* agent_host,
diff --git a/chrome/browser/devtools/devtools_network_conditions.cc b/chrome/browser/devtools/devtools_network_conditions.cc
index 59e06b8..534e787 100644
--- a/chrome/browser/devtools/devtools_network_conditions.cc
+++ b/chrome/browser/devtools/devtools_network_conditions.cc
@@ -6,31 +6,35 @@
#include "url/gurl.h"
-DevToolsNetworkConditions::DevToolsNetworkConditions(
- const std::vector<std::string>& domains,
- double maximal_throughput)
- : domains_(domains),
- maximal_throughput_(maximal_throughput) {
+DevToolsNetworkConditions::DevToolsNetworkConditions()
+ : offline_(false),
+ latency_(0),
+ download_throughput_(0),
+ upload_throughput_(0) {
}
-DevToolsNetworkConditions::~DevToolsNetworkConditions() {
+DevToolsNetworkConditions::DevToolsNetworkConditions(bool offline)
+ : offline_(offline),
+ latency_(0),
+ download_throughput_(0),
+ upload_throughput_(0) {
}
-bool DevToolsNetworkConditions::HasMatchingDomain(const GURL& url) const {
- Domains::const_iterator domain = domains_.begin();
- if (domain == domains_.end())
- return true;
- for (; domain != domains_.end(); ++domain) {
- if (url.DomainIs(domain->data()))
- return true;
- }
- return false;
+DevToolsNetworkConditions::DevToolsNetworkConditions(
+ bool offline,
+ double latency,
+ double download_throughput,
+ double upload_throughput)
+ : offline_(offline),
+ latency_(latency),
+ download_throughput_(download_throughput),
+ upload_throughput_(upload_throughput) {
}
-bool DevToolsNetworkConditions::IsOffline() const {
- return maximal_throughput_ == 0.0;
+DevToolsNetworkConditions::~DevToolsNetworkConditions() {
}
bool DevToolsNetworkConditions::IsThrottling() const {
- return maximal_throughput_ != 0.0;
+ return (latency_ != 0) || (download_throughput_ != 0.0) ||
+ (upload_throughput_ != 0);
}
diff --git a/chrome/browser/devtools/devtools_network_conditions.h b/chrome/browser/devtools/devtools_network_conditions.h
index 7c9d477..e19f77e 100644
--- a/chrome/browser/devtools/devtools_network_conditions.h
+++ b/chrome/browser/devtools/devtools_network_conditions.h
@@ -16,24 +16,29 @@ class GURL;
class DevToolsNetworkConditions
: public base::RefCounted<DevToolsNetworkConditions> {
public:
- DevToolsNetworkConditions(const std::vector<std::string>& domains,
- double maximal_throughput);
+ DevToolsNetworkConditions();
+ explicit DevToolsNetworkConditions(bool offline);
+ DevToolsNetworkConditions(bool offline,
+ double latency,
+ double download_throughput,
+ double upload_throughput);
- bool HasMatchingDomain(const GURL& url) const;
- bool IsOffline() const;
bool IsThrottling() const;
- double maximal_throughput() const { return maximal_throughput_; }
+ bool offline() const { return offline_; }
+ double latency() const { return latency_; }
+ double download_throughput() const { return download_throughput_; }
+ double upload_throughput() const { return upload_throughput_; }
private:
friend class base::RefCounted<DevToolsNetworkConditions>;
virtual ~DevToolsNetworkConditions();
- // List of domains that will be affected by network conditions.
- typedef std::vector<std::string> Domains;
- const Domains domains_;
- const double maximal_throughput_;
+ const bool offline_;
+ const double latency_;
+ const double download_throughput_;
+ const double upload_throughput_;
DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkConditions);
};
diff --git a/chrome/browser/devtools/devtools_network_controller.cc b/chrome/browser/devtools/devtools_network_controller.cc
index 176ac66..566a2108 100644
--- a/chrome/browser/devtools/devtools_network_controller.cc
+++ b/chrome/browser/devtools/devtools_network_controller.cc
@@ -4,52 +4,52 @@
#include "chrome/browser/devtools/devtools_network_controller.h"
-#include "base/time/time.h"
#include "chrome/browser/devtools/devtools_network_conditions.h"
+#include "chrome/browser/devtools/devtools_network_interceptor.h"
#include "chrome/browser/devtools/devtools_network_transaction.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_io_data.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/resource_context.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_request_info.h"
using content::BrowserThread;
-namespace {
-
-const char kDevToolsRequestInitiator[] = "X-DevTools-Request-Initiator";
-int64_t kPacketSize = 1500;
-
-} // namespace
-
DevToolsNetworkController::DevToolsNetworkController()
- : weak_ptr_factory_(this) {
+ : default_interceptor_(new DevToolsNetworkInterceptor()),
+ appcache_interceptor_(new DevToolsNetworkInterceptor()),
+ weak_ptr_factory_(this) {
}
DevToolsNetworkController::~DevToolsNetworkController() {
}
-void DevToolsNetworkController::AddTransaction(
+base::WeakPtr<DevToolsNetworkInterceptor>
+DevToolsNetworkController::GetInterceptor(
DevToolsNetworkTransaction* transaction) {
DCHECK(thread_checker_.CalledOnValidThread());
- transactions_.insert(transaction);
-}
+ DCHECK(transaction->request());
-void DevToolsNetworkController::RemoveTransaction(
- DevToolsNetworkTransaction* transaction) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(transactions_.find(transaction) != transactions_.end());
- transactions_.erase(transaction);
-
- if (conditions_ && conditions_->IsThrottling()) {
- UpdateThrottles();
- throttled_transactions_.erase(std::remove(throttled_transactions_.begin(),
- throttled_transactions_.end(), transaction),
- throttled_transactions_.end());
- ArmTimer();
- }
+ if (!interceptors_.size())
+ return default_interceptor_->GetWeakPtr();
+
+ if (transaction->request()->load_flags & net::LOAD_DISABLE_INTERCEPT)
+ return appcache_interceptor_->GetWeakPtr();
+
+ transaction->ProcessRequest();
+
+ const std::string& client_id = transaction->client_id();
+ if (client_id.empty())
+ return default_interceptor_->GetWeakPtr();
+
+ DevToolsNetworkInterceptor* interceptor = interceptors_.get(client_id);
+ DCHECK(interceptor);
+ if (!interceptor)
+ return default_interceptor_->GetWeakPtr();
+
+ return interceptor->GetWeakPtr();
}
void DevToolsNetworkController::SetNetworkState(
+ const std::string& client_id,
const scoped_refptr<DevToolsNetworkConditions> conditions) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
@@ -58,146 +58,47 @@ void DevToolsNetworkController::SetNetworkState(
base::Bind(
&DevToolsNetworkController::SetNetworkStateOnIO,
weak_ptr_factory_.GetWeakPtr(),
+ client_id,
conditions));
}
void DevToolsNetworkController::SetNetworkStateOnIO(
+ const std::string& client_id,
const scoped_refptr<DevToolsNetworkConditions> conditions) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (conditions_ && conditions_->IsThrottling())
- UpdateThrottles();
-
- conditions_ = conditions;
- if (!conditions || !(conditions->IsThrottling() || conditions->IsOffline())) {
- timer_.Stop();
- int64_t length = throttled_transactions_.size();
- for (int64_t i = 0; i < length; ++i)
- throttled_transactions_[i]->FireThrottledCallback();
- throttled_transactions_.clear();
- }
- if (!conditions)
- return;
-
- if (conditions_->IsOffline()) {
- // Iterate over a copy of set, because failing of transaction could
- // result in creating a new one, or (theoretically) destroying one.
- Transactions old_transactions(transactions_);
- for (Transactions::iterator it = old_transactions.begin();
- it != old_transactions.end(); ++it) {
- if (transactions_.find(*it) == transactions_.end())
- continue;
- if (!(*it)->request() || (*it)->failed())
- continue;
- if (ShouldFail((*it)->request()))
- (*it)->Fail();
+ DevToolsNetworkInterceptor* interceptor = interceptors_.get(client_id);
+ if (!interceptor) {
+ DCHECK(conditions);
+ if (!conditions)
+ return;
+ Interceptor new_interceptor = Interceptor(new DevToolsNetworkInterceptor());
+ new_interceptor->UpdateConditions(conditions);
+ interceptors_.set(client_id, new_interceptor.Pass());
+ } else {
+ if (!conditions) {
+ scoped_refptr<DevToolsNetworkConditions> online_conditions(
+ new DevToolsNetworkConditions());
+ interceptor->UpdateConditions(online_conditions);
+ interceptors_.erase(client_id);
+ } else {
+ interceptor->UpdateConditions(conditions);
}
}
- if (conditions_->IsThrottling()) {
- DCHECK(conditions_->maximal_throughput() != 0);
- offset_ = base::TimeTicks::Now();
- last_tick_ = 0;
- int64_t us_tick_length =
- (1000000L * kPacketSize) / conditions_->maximal_throughput();
- DCHECK(us_tick_length != 0);
- if (us_tick_length == 0)
- us_tick_length = 1;
- tick_length_ = base::TimeDelta::FromMicroseconds(us_tick_length);
- ArmTimer();
- }
-}
-
-bool DevToolsNetworkController::ShouldFail(
- const net::HttpRequestInfo* request) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(request);
- if (!conditions_ || !conditions_->IsOffline())
- return false;
-
- if (!conditions_->HasMatchingDomain(request->url))
- return false;
-
- return !request->extra_headers.HasHeader(kDevToolsRequestInitiator);
-}
-
-bool DevToolsNetworkController::ShouldThrottle(
- const net::HttpRequestInfo* request) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(request);
- if (!conditions_ || !conditions_->IsThrottling())
- return false;
-
- if (!conditions_->HasMatchingDomain(request->url))
- return false;
-
- return !request->extra_headers.HasHeader(kDevToolsRequestInitiator);
-}
-
-void DevToolsNetworkController::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 DevToolsNetworkController::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]);
+ bool has_offline_interceptors = false;
+ Interceptors::iterator it = interceptors_.begin();
+ for (; it != interceptors_.end(); ++it) {
+ if (it->second->conditions()->offline()) {
+ has_offline_interceptors = true;
+ break;
+ }
}
- throttled_transactions_.swap(active_transactions);
-
- length = finished_transactions.size();
- for (size_t i = 0; i < length; ++i)
- finished_transactions[i]->FireThrottledCallback();
-
- ArmTimer();
-}
-void DevToolsNetworkController::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;
+ bool is_appcache_offline = appcache_interceptor_->conditions()->offline();
+ if (is_appcache_offline != has_offline_interceptors) {
+ scoped_refptr<DevToolsNetworkConditions> appcache_conditions(
+ new DevToolsNetworkConditions(has_offline_interceptors));
+ appcache_interceptor_->UpdateConditions(appcache_conditions);
}
- base::TimeTicks desired_time =
- offset_ + tick_length_ * (last_tick_ + min_ticks_left);
- timer_.Start(
- FROM_HERE,
- desired_time - base::TimeTicks::Now(),
- base::Bind(
- &DevToolsNetworkController::OnTimer,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void DevToolsNetworkController::ThrottleTransaction(
- DevToolsNetworkTransaction* transaction) {
- UpdateThrottles();
- throttled_transactions_.push_back(transaction);
- ArmTimer();
}
diff --git a/chrome/browser/devtools/devtools_network_controller.h b/chrome/browser/devtools/devtools_network_controller.h
index a9edd0f..6550da4 100644
--- a/chrome/browser/devtools/devtools_network_controller.h
+++ b/chrome/browser/devtools/devtools_network_controller.h
@@ -5,34 +5,18 @@
#ifndef CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_CONTROLLER_H_
#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_CONTROLLER_H_
-#include <set>
#include <string>
-#include <vector>
+#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
-#include "base/timer/timer.h"
class DevToolsNetworkConditions;
+class DevToolsNetworkInterceptor;
class DevToolsNetworkTransaction;
-class GURL;
-class Profile;
-
-namespace base {
-class TimeDelta;
-class TimeTicks;
-}
-
-namespace content {
-class ResourceContext;
-}
-
-namespace net {
-struct HttpRequestInfo;
-}
namespace test {
class DevToolsNetworkControllerHelper;
@@ -45,17 +29,13 @@ class DevToolsNetworkController {
DevToolsNetworkController();
virtual ~DevToolsNetworkController();
- void AddTransaction(DevToolsNetworkTransaction* transaction);
-
- void RemoveTransaction(DevToolsNetworkTransaction* transaction);
-
// Applies network emulation configuration.
void SetNetworkState(
+ const std::string& client_id,
const scoped_refptr<DevToolsNetworkConditions> conditions);
- bool ShouldFail(const net::HttpRequestInfo* request);
- bool ShouldThrottle(const net::HttpRequestInfo* request);
- void ThrottleTransaction(DevToolsNetworkTransaction* transaction);
+ base::WeakPtr<DevToolsNetworkInterceptor> GetInterceptor(
+ DevToolsNetworkTransaction* transaction);
protected:
friend class test::DevToolsNetworkControllerHelper;
@@ -64,24 +44,16 @@ class DevToolsNetworkController {
// Controller must be constructed on IO thread.
base::ThreadChecker thread_checker_;
- typedef scoped_refptr<DevToolsNetworkConditions> Conditions;
-
- void SetNetworkStateOnIO(const Conditions conditions);
-
- typedef std::set<DevToolsNetworkTransaction*> Transactions;
- Transactions transactions_;
-
- Conditions conditions_;
-
- void UpdateThrottles();
- void ArmTimer();
- void OnTimer();
+ void SetNetworkStateOnIO(
+ const std::string& client_id,
+ const scoped_refptr<DevToolsNetworkConditions> conditions);
- std::vector<DevToolsNetworkTransaction*> throttled_transactions_;
- base::OneShotTimer<DevToolsNetworkController> timer_;
- base::TimeTicks offset_;
- base::TimeDelta tick_length_;
- uint64_t last_tick_;
+ typedef scoped_ptr<DevToolsNetworkInterceptor> Interceptor;
+ Interceptor default_interceptor_;
+ Interceptor appcache_interceptor_;
+ typedef base::ScopedPtrHashMap<std::string, DevToolsNetworkInterceptor>
+ Interceptors;
+ Interceptors interceptors_;
base::WeakPtrFactory<DevToolsNetworkController> weak_ptr_factory_;
diff --git a/chrome/browser/devtools/devtools_network_controller_unittest.cc b/chrome/browser/devtools/devtools_network_controller_unittest.cc
index 708b9e1..07bba5e 100644
--- a/chrome/browser/devtools/devtools_network_controller_unittest.cc
+++ b/chrome/browser/devtools/devtools_network_controller_unittest.cc
@@ -10,6 +10,7 @@
#include "base/run_loop.h"
#include "chrome/browser/devtools/devtools_network_conditions.h"
#include "chrome/browser/devtools/devtools_network_controller.h"
+#include "chrome/browser/devtools/devtools_network_interceptor.h"
#include "chrome/browser/devtools/devtools_network_transaction.h"
#include "net/http/http_transaction_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -17,9 +18,8 @@
namespace test {
-const char kHttpDotCom[] = "http://dot.com";
-const char kHttpDotOrg[] = "http://dot.org";
-const char kCom[] = "com";
+const char kClientId[] = "42";
+const char kAnotherClientId[] = "24";
class TestCallback {
public:
@@ -44,7 +44,9 @@ class DevToolsNetworkControllerHelper {
mock_transaction_(kSimpleGET_Transaction),
buffer_(new net::IOBuffer(64)) {
mock_transaction_.test_mode = TEST_MODE_SYNC_NET_START;
- mock_transaction_.url = kHttpDotCom;
+ mock_transaction_.url = "http://dot.com";
+ mock_transaction_.request_headers =
+ "X-DevTools-Emulate-Network-Conditions-Client-Id: 42\r\n";
AddMockTransaction(&mock_transaction_);
scoped_ptr<net::HttpTransaction> network_transaction;
@@ -60,13 +62,10 @@ class DevToolsNetworkControllerHelper {
return request_.get();
}
- void SetNetworkState(bool offline) {
- std::vector<std::string> domains;
- domains.push_back(kCom);
- scoped_refptr<DevToolsNetworkConditions> conditions;
- if (offline)
- conditions = new DevToolsNetworkConditions(domains, 0.0);
- controller_.SetNetworkStateOnIO(conditions);
+ void SetNetworkState(const std::string id, bool offline) {
+ scoped_refptr<DevToolsNetworkConditions> conditions(
+ new DevToolsNetworkConditions(offline));
+ controller_.SetNetworkStateOnIO(id, conditions);
}
int Start() {
@@ -78,6 +77,10 @@ class DevToolsNetworkControllerHelper {
return transaction_->Read(buffer_.get(), 64, completion_callback_);
}
+ bool ShouldFail() {
+ return transaction_->interceptor_->ShouldFail(transaction_.get());
+ }
+
~DevToolsNetworkControllerHelper() {
RemoveMockTransaction(&mock_transaction_);
}
@@ -101,19 +104,37 @@ class DevToolsNetworkControllerHelper {
TEST(DevToolsNetworkControllerTest, SingleDisableEnable) {
DevToolsNetworkControllerHelper helper;
- DevToolsNetworkController* controller = helper.controller();
- net::HttpRequestInfo* request = helper.GetRequest();
-
- EXPECT_FALSE(controller->ShouldFail(request));
- helper.SetNetworkState(true);
- EXPECT_TRUE(controller->ShouldFail(request));
- helper.SetNetworkState(false);
- EXPECT_FALSE(controller->ShouldFail(request));
+ helper.SetNetworkState(kClientId, false);
+ helper.Start();
+
+ EXPECT_FALSE(helper.ShouldFail());
+ helper.SetNetworkState(kClientId, true);
+ EXPECT_TRUE(helper.ShouldFail());
+ helper.SetNetworkState(kClientId, false);
+ EXPECT_FALSE(helper.ShouldFail());
+
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST(DevToolsNetworkControllerTest, InterceptorIsolation) {
+ DevToolsNetworkControllerHelper helper;
+ helper.SetNetworkState(kClientId, false);
+ helper.Start();
+
+ EXPECT_FALSE(helper.ShouldFail());
+ helper.SetNetworkState(kAnotherClientId, true);
+ EXPECT_FALSE(helper.ShouldFail());
+ helper.SetNetworkState(kClientId, true);
+ EXPECT_TRUE(helper.ShouldFail());
+
+ helper.SetNetworkState(kAnotherClientId, false);
+ helper.SetNetworkState(kClientId, false);
+ base::RunLoop().RunUntilIdle();
}
TEST(DevToolsNetworkControllerTest, FailOnStart) {
DevToolsNetworkControllerHelper helper;
- helper.SetNetworkState(true);
+ helper.SetNetworkState(kClientId, true);
int rv = helper.Start();
EXPECT_EQ(rv, net::ERR_INTERNET_DISCONNECTED);
@@ -124,6 +145,7 @@ TEST(DevToolsNetworkControllerTest, FailOnStart) {
TEST(DevToolsNetworkControllerTest, FailRunningTransaction) {
DevToolsNetworkControllerHelper helper;
+ helper.SetNetworkState(kClientId, false);
TestCallback* callback = helper.callback();
int rv = helper.Start();
@@ -134,7 +156,7 @@ TEST(DevToolsNetworkControllerTest, FailRunningTransaction) {
EXPECT_EQ(rv, net::ERR_IO_PENDING);
EXPECT_EQ(callback->run_count(), 0);
- helper.SetNetworkState(true);
+ helper.SetNetworkState(kClientId, true);
EXPECT_EQ(callback->run_count(), 1);
EXPECT_EQ(callback->value(), net::ERR_INTERNET_DISCONNECTED);
@@ -145,19 +167,20 @@ TEST(DevToolsNetworkControllerTest, FailRunningTransaction) {
EXPECT_EQ(callback->run_count(), 1);
// Check that transaction in not failed second time.
- helper.SetNetworkState(false);
- helper.SetNetworkState(true);
+ helper.SetNetworkState(kClientId, false);
+ helper.SetNetworkState(kClientId, true);
EXPECT_EQ(callback->run_count(), 1);
}
TEST(DevToolsNetworkControllerTest, ReadAfterFail) {
DevToolsNetworkControllerHelper helper;
+ helper.SetNetworkState(kClientId, false);
int rv = helper.Start();
EXPECT_EQ(rv, net::OK);
EXPECT_TRUE(helper.transaction()->request());
- helper.SetNetworkState(true);
+ helper.SetNetworkState(kClientId, true);
EXPECT_TRUE(helper.transaction()->failed());
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(64));
@@ -171,25 +194,15 @@ TEST(DevToolsNetworkControllerTest, ReadAfterFail) {
TEST(DevToolsNetworkControllerTest, AllowsDevToolsRequests) {
DevToolsNetworkControllerHelper helper;
+ helper.SetNetworkState(kClientId, false);
helper.mock_transaction()->request_headers =
+ "X-DevTools-Emulate-Network-Conditions-Client-Id: 42\r\n"
"X-DevTools-Request-Initiator: frontend\r\n";
- DevToolsNetworkController* controller = helper.controller();
- net::HttpRequestInfo* request = helper.GetRequest();
-
- EXPECT_FALSE(controller->ShouldFail(request));
- helper.SetNetworkState(true);
- EXPECT_FALSE(controller->ShouldFail(request));
-}
-
-TEST(DevToolsNetworkControllerTest, AllowsNotMatchingRequests) {
- DevToolsNetworkControllerHelper helper;
- helper.mock_transaction()->url = kHttpDotOrg;
- DevToolsNetworkController* controller = helper.controller();
- net::HttpRequestInfo* request = helper.GetRequest();
+ helper.Start();
- EXPECT_FALSE(controller->ShouldFail(request));
- helper.SetNetworkState(true);
- EXPECT_FALSE(controller->ShouldFail(request));
+ EXPECT_FALSE(helper.ShouldFail());
+ helper.SetNetworkState(kClientId, true);
+ EXPECT_FALSE(helper.ShouldFail());
}
} // namespace test
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;
+}
diff --git a/chrome/browser/devtools/devtools_network_interceptor.h b/chrome/browser/devtools/devtools_network_interceptor.h
new file mode 100644
index 0000000..564bdf6
--- /dev/null
+++ b/chrome/browser/devtools/devtools_network_interceptor.h
@@ -0,0 +1,70 @@
+// 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.
+
+#ifndef CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_INTERCEPTOR_H_
+#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_INTERCEPTOR_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/timer/timer.h"
+
+class DevToolsNetworkConditions;
+class DevToolsNetworkTransaction;
+
+namespace base {
+class TimeDelta;
+class TimeTicks;
+}
+
+// DevToolsNetworkInterceptor emulates network conditions for transactions with
+// specific client id.
+class DevToolsNetworkInterceptor {
+
+ public:
+ DevToolsNetworkInterceptor();
+ virtual ~DevToolsNetworkInterceptor();
+
+ base::WeakPtr<DevToolsNetworkInterceptor> GetWeakPtr();
+
+ // Applies network emulation configuration.
+ void UpdateConditions(
+ const scoped_refptr<DevToolsNetworkConditions> conditions);
+
+ void AddTransaction(DevToolsNetworkTransaction* transaction);
+ void RemoveTransaction(DevToolsNetworkTransaction* transaction);
+
+ bool ShouldFail(const DevToolsNetworkTransaction* transaction);
+ bool ShouldThrottle(const DevToolsNetworkTransaction* transaction);
+ void ThrottleTransaction(DevToolsNetworkTransaction* transaction);
+
+ const DevToolsNetworkConditions* conditions() const {
+ return conditions_.get();
+ }
+
+ private:
+ scoped_refptr<DevToolsNetworkConditions> conditions_;
+
+ void UpdateThrottles();
+ void ArmTimer();
+ void OnTimer();
+
+ typedef std::set<DevToolsNetworkTransaction*> Transactions;
+ Transactions transactions_;
+
+ std::vector<DevToolsNetworkTransaction*> throttled_transactions_;
+ base::OneShotTimer<DevToolsNetworkInterceptor> timer_;
+ base::TimeTicks offset_;
+ base::TimeDelta tick_length_;
+ uint64_t last_tick_;
+
+ base::WeakPtrFactory<DevToolsNetworkInterceptor> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkInterceptor);
+};
+
+#endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_INTERCEPTOR_H_
diff --git a/chrome/browser/devtools/devtools_network_transaction.cc b/chrome/browser/devtools/devtools_network_transaction.cc
index 8a72e01..b2afc98 100644
--- a/chrome/browser/devtools/devtools_network_transaction.cc
+++ b/chrome/browser/devtools/devtools_network_transaction.cc
@@ -5,11 +5,20 @@
#include "chrome/browser/devtools/devtools_network_transaction.h"
#include "chrome/browser/devtools/devtools_network_controller.h"
+#include "chrome/browser/devtools/devtools_network_interceptor.h"
#include "net/base/net_errors.h"
#include "net/base/upload_progress.h"
#include "net/http/http_network_transaction.h"
#include "net/http/http_request_info.h"
+namespace {
+
+const char kDevToolsRequestInitiator[] = "X-DevTools-Request-Initiator";
+const char kDevToolsEmulateNetworkConditionsClientId[] =
+ "X-DevTools-Emulate-Network-Conditions-Client-Id";
+
+} // namespace
+
DevToolsNetworkTransaction::DevToolsNetworkTransaction(
DevToolsNetworkController* controller,
scoped_ptr<net::HttpTransaction> network_transaction)
@@ -22,11 +31,11 @@ DevToolsNetworkTransaction::DevToolsNetworkTransaction(
proxy_callback_(base::Bind(&DevToolsNetworkTransaction::OnCallback,
base::Unretained(this))) {
DCHECK(controller);
- controller->AddTransaction(this);
}
DevToolsNetworkTransaction::~DevToolsNetworkTransaction() {
- controller_->RemoveTransaction(this);
+ if (interceptor_)
+ interceptor_->RemoveTransaction(this);
}
void DevToolsNetworkTransaction::Throttle(int result) {
@@ -37,7 +46,8 @@ void DevToolsNetworkTransaction::Throttle(int result) {
if (result > 0)
throttled_byte_count_ += result;
- controller_->ThrottleTransaction(this);
+ if (interceptor_)
+ interceptor_->ThrottleTransaction(this);
}
void DevToolsNetworkTransaction::OnCallback(int rv) {
@@ -45,7 +55,7 @@ void DevToolsNetworkTransaction::OnCallback(int rv) {
return;
DCHECK(!callback_.is_null());
if (callback_type_ == START || callback_type_ == READ) {
- if (controller_->ShouldThrottle(request_)) {
+ if (interceptor_ && interceptor_->ShouldThrottle(this)) {
Throttle(rv);
return;
}
@@ -68,7 +78,7 @@ int DevToolsNetworkTransaction::SetupCallback(
return result;
}
- if (!controller_->ShouldThrottle(request_))
+ if (!interceptor_ || !interceptor_->ShouldThrottle(this))
return result;
// Only START and READ operation throttling is supported.
@@ -109,17 +119,46 @@ int DevToolsNetworkTransaction::Start(
const net::BoundNetLog& net_log) {
DCHECK(request);
request_ = request;
+ interceptor_ = controller_->GetInterceptor(this);
+ interceptor_->AddTransaction(this);
- if (controller_->ShouldFail(request_)) {
+ if (interceptor_->ShouldFail(this)) {
failed_ = true;
network_transaction_->SetBeforeNetworkStartCallback(
BeforeNetworkStartCallback());
return net::ERR_INTERNET_DISCONNECTED;
}
- int rv = network_transaction_->Start(request, proxy_callback_, net_log);
+ int rv = network_transaction_->Start(request_, proxy_callback_, net_log);
return SetupCallback(callback, rv, START);
}
+void DevToolsNetworkTransaction::ProcessRequest() {
+ DCHECK(request_);
+ bool has_devtools_client_id = request_->extra_headers.HasHeader(
+ kDevToolsEmulateNetworkConditionsClientId);
+ bool has_devtools_request_initiator = request_->extra_headers.HasHeader(
+ kDevToolsRequestInitiator);
+ if (!has_devtools_client_id && !has_devtools_request_initiator)
+ return;
+
+ custom_request_.reset(new net::HttpRequestInfo(*request_));
+
+ if (has_devtools_client_id) {
+ custom_request_->extra_headers.GetHeader(
+ kDevToolsEmulateNetworkConditionsClientId, &client_id_);
+ custom_request_->extra_headers.RemoveHeader(
+ kDevToolsEmulateNetworkConditionsClientId);
+ }
+
+ if (has_devtools_request_initiator) {
+ custom_request_->extra_headers.GetHeader(
+ kDevToolsRequestInitiator, &request_initiator_);
+ custom_request_->extra_headers.RemoveHeader(kDevToolsRequestInitiator);
+ }
+
+ request_ = custom_request_.get();
+}
+
int DevToolsNetworkTransaction::RestartIgnoringLastError(
const net::CompletionCallback& callback) {
if (failed_)
diff --git a/chrome/browser/devtools/devtools_network_transaction.h b/chrome/browser/devtools/devtools_network_transaction.h
index 37e84ed..77ae9217 100644
--- a/chrome/browser/devtools/devtools_network_transaction.h
+++ b/chrome/browser/devtools/devtools_network_transaction.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_TRANSACTION_H_
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/load_states.h"
#include "net/base/request_priority.h"
@@ -13,6 +14,7 @@
#include "net/websockets/websocket_handshake_stream_base.h"
class DevToolsNetworkController;
+class DevToolsNetworkInterceptor;
class GURL;
namespace net {
@@ -26,6 +28,10 @@ class IOBuffer;
struct LoadTimingInfo;
class UploadProgress;
class X509Certificate;
+} // namespace net
+
+namespace test {
+class DevToolsNetworkControllerHelper;
}
// DevToolsNetworkTransaction is a wrapper for network transaction. All
@@ -42,6 +48,11 @@ class DevToolsNetworkTransaction : public net::HttpTransaction {
virtual ~DevToolsNetworkTransaction();
const net::HttpRequestInfo* request() const { return request_; }
+
+ // Checks if request contains DevTools specific headers. Found values are
+ // remembered and corresponding keys are removed from headers.
+ void ProcessRequest();
+
bool failed() const { return failed_; }
// Runs callback (if any) with net::ERR_INTERNET_DISCONNECTED result value.
@@ -52,6 +63,12 @@ class DevToolsNetworkTransaction : public net::HttpTransaction {
throttled_byte_count_ -= delta;
}
+ const std::string& request_initiator() const { return request_initiator_; }
+
+ const std::string& client_id() const {
+ return client_id_;
+ }
+
void FireThrottledCallback();
// HttpTransaction methods:
@@ -92,11 +109,15 @@ class DevToolsNetworkTransaction : public net::HttpTransaction {
const BeforeNetworkStartCallback& callback) OVERRIDE;
virtual int ResumeNetworkStart() OVERRIDE;
+ protected:
+ friend class test::DevToolsNetworkControllerHelper;
+
private:
// Proxy callback handler. Runs saved callback.
void OnCallback(int result);
DevToolsNetworkController* controller_;
+ base::WeakPtr<DevToolsNetworkInterceptor> interceptor_;
// Real network transaction.
scoped_ptr<net::HttpTransaction> network_transaction_;
@@ -109,6 +130,14 @@ class DevToolsNetworkTransaction : public net::HttpTransaction {
// True if Fail was already invoked.
bool failed_;
+ // Value of "X-DevTools-Request-Initiator" request header.
+ std::string request_initiator_;
+
+ // Value of "X-DevTools-Emulate-Network-Conditions-Client-Id" request header.
+ std::string client_id_;
+
+ scoped_ptr<net::HttpRequestInfo> custom_request_;
+
enum CallbackType {
NONE,
READ,
diff --git a/chrome/chrome_debugger.gypi b/chrome/chrome_debugger.gypi
index fd5627f..fcd4cb1 100644
--- a/chrome/chrome_debugger.gypi
+++ b/chrome/chrome_debugger.gypi
@@ -68,6 +68,8 @@
'browser/devtools/devtools_network_conditions.h',
'browser/devtools/devtools_network_controller.cc',
'browser/devtools/devtools_network_controller.h',
+ 'browser/devtools/devtools_network_interceptor.cc',
+ 'browser/devtools/devtools_network_interceptor.h',
'browser/devtools/devtools_network_transaction.cc',
'browser/devtools/devtools_network_transaction.h',
'browser/devtools/devtools_network_transaction_factory.cc',