diff --git a/brightray/browser/browser_context.cc b/brightray/browser/browser_context.cc
index f5d6effdeba0..96e21ae854de 100644
--- a/brightray/browser/browser_context.cc
+++ b/brightray/browser/browser_context.cc
@@ -136,6 +136,7 @@ net::URLRequestContextGetter* BrowserContext::CreateRequestContext(
   DCHECK(!url_request_getter_.get());
   url_request_getter_ = new URLRequestContextGetter(
       this,
+      GetDevToolsNetworkController(),
       net_log,
       GetPath(),
       in_memory_,
@@ -147,6 +148,12 @@ net::URLRequestContextGetter* BrowserContext::CreateRequestContext(
   return url_request_getter_.get();
 }
 
+DevToolsNetworkController* BrowserContext::GetDevToolsNetworkController() {
+  if (!controller_)
+    controller_.reset(new DevToolsNetworkController);
+  return controller_.get();
+}
+
 net::NetworkDelegate* BrowserContext::CreateNetworkDelegate() {
   return new NetworkDelegate;
 }
diff --git a/brightray/browser/browser_context.h b/brightray/browser/browser_context.h
index 836d17c84bf1..e6c339d8eefe 100644
--- a/brightray/browser/browser_context.h
+++ b/brightray/browser/browser_context.h
@@ -7,6 +7,7 @@
 
 #include <map>
 
+#include "browser/net/devtools_network_controller.h"
 #include "browser/permission_manager.h"
 #include "browser/url_request_context_getter.h"
 
@@ -57,6 +58,7 @@ class BrowserContext : public base::RefCounted<BrowserContext>,
       NetLog* net_log,
       content::ProtocolHandlerMap* protocol_handlers,
       content::URLRequestInterceptorScopedVector protocol_interceptors);
+  DevToolsNetworkController* GetDevToolsNetworkController();
 
   net::URLRequestContextGetter* url_request_context_getter() const {
     return url_request_getter_.get();
@@ -107,6 +109,7 @@ class BrowserContext : public base::RefCounted<BrowserContext>,
   base::FilePath path_;
   bool in_memory_;
   scoped_ptr<ResourceContext> resource_context_;
+  scoped_ptr<DevToolsNetworkController> controller_;
   scoped_refptr<URLRequestContextGetter> url_request_getter_;
   scoped_ptr<PrefService> prefs_;
   scoped_ptr<PermissionManager> permission_manager_;
diff --git a/brightray/browser/devtools_manager_delegate.cc b/brightray/browser/devtools_manager_delegate.cc
index 89c3469fc0d7..95b6fb3b5b28 100644
--- a/brightray/browser/devtools_manager_delegate.cc
+++ b/brightray/browser/devtools_manager_delegate.cc
@@ -6,6 +6,8 @@
 
 #include <vector>
 
+#include "browser/net/devtools_network_protocol_handler.h"
+
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
@@ -140,7 +142,8 @@ DevToolsManagerDelegate::CreateHttpHandler() {
       GetBrightrayUserAgent());
 }
 
-DevToolsManagerDelegate::DevToolsManagerDelegate() {
+DevToolsManagerDelegate::DevToolsManagerDelegate()
+    : handler_(new DevToolsNetworkProtocolHandler) {
   // NB(zcbenz): This call does nothing, the only purpose is to make sure the
   // devtools_discovery module is linked into the final executable on Linux.
   // Though it is possible to achieve this by modifying the gyp settings, it
@@ -155,7 +158,7 @@ DevToolsManagerDelegate::~DevToolsManagerDelegate() {
 base::DictionaryValue* DevToolsManagerDelegate::HandleCommand(
     content::DevToolsAgentHost* agent_host,
     base::DictionaryValue* command) {
-  return NULL;
+  return handler_->HandleCommand(agent_host, command);
 }
 
 }  // namespace brightray
diff --git a/brightray/browser/devtools_manager_delegate.h b/brightray/browser/devtools_manager_delegate.h
index 154ea9ccbf75..ed8e357482b2 100644
--- a/brightray/browser/devtools_manager_delegate.h
+++ b/brightray/browser/devtools_manager_delegate.h
@@ -16,6 +16,8 @@ class DevToolsHttpHandler;
 
 namespace brightray {
 
+class DevToolsNetworkProtocolHandler;
+
 class DevToolsManagerDelegate : public content::DevToolsManagerDelegate {
  public:
   static devtools_http_handler::DevToolsHttpHandler* CreateHttpHandler();
@@ -32,6 +34,8 @@ class DevToolsManagerDelegate : public content::DevToolsManagerDelegate {
                                        base::DictionaryValue* command) override;
 
  private:
+  scoped_ptr<DevToolsNetworkProtocolHandler> handler_;
+
   DISALLOW_COPY_AND_ASSIGN(DevToolsManagerDelegate);
 };
 
diff --git a/brightray/browser/net/devtools_network_conditions.cc b/brightray/browser/net/devtools_network_conditions.cc
new file mode 100644
index 000000000000..0005c7f56c74
--- /dev/null
+++ b/brightray/browser/net/devtools_network_conditions.cc
@@ -0,0 +1,35 @@
+// 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 "browser/net/devtools_network_conditions.h"
+
+namespace brightray {
+
+DevToolsNetworkConditions::DevToolsNetworkConditions(bool offline)
+    : offline_(offline),
+      latency_(0),
+      download_throughput_(0),
+      upload_throughput_(0) {
+}
+
+DevToolsNetworkConditions::DevToolsNetworkConditions(
+    bool offline,
+    double latency,
+    double download_throughput,
+    double upload_throughput)
+    : offline_(offline),
+      latency_(latency),
+      download_throughput_(download_throughput),
+      upload_throughput_(upload_throughput) {
+}
+
+DevToolsNetworkConditions::~DevToolsNetworkConditions() {
+}
+
+bool DevToolsNetworkConditions::IsThrottling() const {
+  return !offline_ && ((latency_ != 0.0) || (download_throughput_ != 0.0) ||
+      (upload_throughput_ != 0.0));
+}
+
+}  // namespace brightray
diff --git a/brightray/browser/net/devtools_network_conditions.h b/brightray/browser/net/devtools_network_conditions.h
new file mode 100644
index 000000000000..81aae86f8d49
--- /dev/null
+++ b/brightray/browser/net/devtools_network_conditions.h
@@ -0,0 +1,43 @@
+// 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 BROWSER_DEVTOOLS_NETWORK_CONDITIONS_H_
+#define BROWSER_DEVTOOLS_NETWORK_CONDITIONS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "url/gurl.h"
+
+namespace brightray {
+
+class DevToolsNetworkConditions {
+ public:
+  explicit DevToolsNetworkConditions(bool offline);
+  DevToolsNetworkConditions(bool offline,
+                            double latency,
+                            double download_throughput,
+                            double upload_throughput);
+  ~DevToolsNetworkConditions();
+
+  bool IsThrottling() const;
+
+  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:
+  const bool offline_;
+  const double latency_;
+  const double download_throughput_;
+  const double upload_throughput_;
+
+  DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkConditions);
+};
+
+}  // namespace brightray
+
+#endif  // BROWSER_DEVTOOLS_NETWORK_CONDITIONS_H_
diff --git a/brightray/browser/net/devtools_network_controller.cc b/brightray/browser/net/devtools_network_controller.cc
new file mode 100644
index 000000000000..42ebf06471fe
--- /dev/null
+++ b/brightray/browser/net/devtools_network_controller.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2015 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-CHROMIUM file.
+
+#include "browser/net/devtools_network_controller.h"
+
+#include "browser/net/devtools_network_conditions.h"
+#include "browser/net/devtools_network_interceptor.h"
+#include "browser/net/devtools_network_transaction.h"
+
+#include "base/bind.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+namespace brightray {
+
+DevToolsNetworkController::DevToolsNetworkController()
+    : default_interceptor_(new DevToolsNetworkInterceptor) {
+}
+
+DevToolsNetworkController::~DevToolsNetworkController() {
+}
+
+void DevToolsNetworkController::SetNetworkState(
+    const std::string& client_id,
+    scoped_ptr<DevToolsNetworkConditions> conditions) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (client_id.empty()) {
+    if (!conditions)
+      return;
+    default_interceptor_->UpdateConditions(conditions.Pass());
+    return;
+  }
+
+  auto interceptor = interceptors_.get(client_id);
+  if (!interceptor) {
+    if (!conditions)
+      return;
+    scoped_ptr<DevToolsNetworkInterceptor> new_interceptor(
+        new DevToolsNetworkInterceptor);
+    new_interceptor->UpdateConditions(conditions.Pass());
+    interceptors_.set(client_id, new_interceptor.Pass());
+  } else {
+    if (!conditions) {
+      scoped_ptr<DevToolsNetworkConditions> online_conditions(
+          new DevToolsNetworkConditions(false));
+      interceptor->UpdateConditions(online_conditions.Pass());
+      interceptors_.erase(client_id);
+    } else {
+      interceptor->UpdateConditions(conditions.Pass());
+    }
+  }
+}
+
+base::WeakPtr<DevToolsNetworkInterceptor>
+DevToolsNetworkController::GetInterceptor(DevToolsNetworkTransaction* transaction) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(transaction->request());
+
+  if (!interceptors_.size())
+    return default_interceptor_->GetWeakPtr();
+
+  transaction->ProcessRequest();
+  auto& client_id = transaction->client_id();
+  auto interceptor = interceptors_.get(client_id);
+  if (!interceptor)
+    return default_interceptor_->GetWeakPtr();
+
+  return interceptor->GetWeakPtr();
+}
+
+}  // namespace brightray
diff --git a/brightray/browser/net/devtools_network_controller.h b/brightray/browser/net/devtools_network_controller.h
new file mode 100644
index 000000000000..a73268f798f3
--- /dev/null
+++ b/brightray/browser/net/devtools_network_controller.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2015 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-CHROMIUM file.
+
+#ifndef BROWSER_DEVTOOLS_NETWORK_CONTROLLER_H_
+#define BROWSER_DEVTOOLS_NETWORK_CONTROLLER_H_
+
+#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+
+namespace brightray {
+
+class DevToolsNetworkConditions;
+class DevToolsNetworkInterceptor;
+class DevToolsNetworkTransaction;
+
+class DevToolsNetworkController {
+ public:
+  DevToolsNetworkController();
+  virtual ~DevToolsNetworkController();
+
+  void SetNetworkState(const std::string& client_id,
+                       scoped_ptr<DevToolsNetworkConditions> conditions);
+  base::WeakPtr<DevToolsNetworkInterceptor> GetInterceptor(
+      DevToolsNetworkTransaction* transaction);
+
+ private:
+  using InterceptorMap = base::ScopedPtrHashMap<std::string,
+                                                scoped_ptr<DevToolsNetworkInterceptor>>;
+  scoped_ptr<DevToolsNetworkInterceptor> default_interceptor_;
+  InterceptorMap interceptors_;
+
+  DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkController);
+};
+
+}  // namespace brightray
+
+#endif  // BROWSER_DEVTOOLS_NETWORK_CONTROLLER_H_
diff --git a/brightray/browser/net/devtools_network_interceptor.cc b/brightray/browser/net/devtools_network_interceptor.cc
new file mode 100644
index 000000000000..78afb00a09a5
--- /dev/null
+++ b/brightray/browser/net/devtools_network_interceptor.cc
@@ -0,0 +1,255 @@
+// 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 "browser/net/devtools_network_interceptor.h"
+
+#include <limits>
+
+#include "browser/net/devtools_network_conditions.h"
+#include "browser/net/devtools_network_transaction.h"
+
+#include "base/time/time.h"
+#include "net/base/load_timing_info.h"
+
+namespace brightray {
+
+namespace {
+
+int64_t kPacketSize = 1500;
+
+}  // namespace
+
+DevToolsNetworkInterceptor::DevToolsNetworkInterceptor()
+    : conditions_(new DevToolsNetworkConditions(false)),
+      weak_ptr_factory_(this) {
+}
+
+DevToolsNetworkInterceptor::~DevToolsNetworkInterceptor() {
+}
+
+base::WeakPtr<DevToolsNetworkInterceptor>
+DevToolsNetworkInterceptor::GetWeakPtr() {
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
+void DevToolsNetworkInterceptor::UpdateConditions(
+    scoped_ptr<DevToolsNetworkConditions> conditions) {
+  DCHECK(conditions);
+  base::TimeTicks now = base::TimeTicks::Now();
+  if (conditions_->IsThrottling())
+    UpdateThrottledTransactions(now);
+
+  conditions_ = conditions.Pass();
+
+  if (conditions_->offline()) {
+    timer_.Stop();
+    throttled_transactions_.clear();
+    suspended_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_NE(conditions_->download_throughput(), 0);
+    offset_ = now;
+    last_tick_ = 0;
+    int64_t us_tick_length =
+        (1000000L * kPacketSize) / conditions_->download_throughput();
+    DCHECK_NE(us_tick_length, 0);
+    if (us_tick_length == 0)
+      us_tick_length = 1;
+    tick_length_ = base::TimeDelta::FromMicroseconds(us_tick_length);
+    latency_length_ = base::TimeDelta();
+    double latency = conditions_->latency();
+    if (latency > 0)
+      latency_length_ = base::TimeDelta::FromMillisecondsD(latency);
+    ArmTimer(now);
+  } else {
+    timer_.Stop();
+
+    std::vector<DevToolsNetworkTransaction*> throttled_transactions;
+    throttled_transactions.swap(throttled_transactions_);
+    for (auto& throttled_transaction : throttled_transactions)
+      FireThrottledCallback(throttled_transaction);
+
+    SuspendedTransactions suspended_transactions;
+    suspended_transactions.swap(suspended_transactions_);
+    for (auto& suspended_transaction : suspended_transactions)
+      FireThrottledCallback(suspended_transaction.first);
+  }
+}
+
+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;
+
+  base::TimeTicks now = base::TimeTicks::Now();
+  UpdateThrottledTransactions(now);
+  throttled_transactions_.erase(std::remove(throttled_transactions_.begin(),
+      throttled_transactions_.end(), transaction),
+      throttled_transactions_.end());
+
+  SuspendedTransactions::iterator it = suspended_transactions_.begin();
+  for (; it != suspended_transactions_.end(); ++it) {
+    if (it->first == transaction) {
+      suspended_transactions_.erase(it);
+      break;
+    }
+  }
+
+  ArmTimer(now);
+}
+
+bool DevToolsNetworkInterceptor::ShouldFail(
+    const DevToolsNetworkTransaction* transaction) {
+  return conditions_->offline();
+}
+
+bool DevToolsNetworkInterceptor::ShouldThrottle(
+    const DevToolsNetworkTransaction* transaction) {
+  return conditions_->IsThrottling();
+}
+
+void DevToolsNetworkInterceptor::ThrottleTransaction(
+    DevToolsNetworkTransaction* transaction, bool start) {
+  base::TimeTicks now = base::TimeTicks::Now();
+  UpdateThrottledTransactions(now);
+  if (start && latency_length_ != base::TimeDelta()) {
+    net::LoadTimingInfo load_timing_info;
+    base::TimeTicks send_end;
+    if (transaction->GetLoadTimingInfo(&load_timing_info))
+      send_end = load_timing_info.send_end;
+    if (send_end.is_null())
+      send_end = now;
+    int64_t us_send_end = (send_end - base::TimeTicks()).InMicroseconds();
+    suspended_transactions_.push_back(
+        SuspendedTransaction(transaction, us_send_end));
+    UpdateSuspendedTransactions(now);
+  } else {
+    throttled_transactions_.push_back(transaction);
+  }
+  ArmTimer(now);
+}
+
+void DevToolsNetworkInterceptor::UpdateThrottledTransactions(
+    base::TimeTicks now) {
+  int64_t last_tick = (now - offset_) / tick_length_;
+  int64_t ticks = last_tick - last_tick_;
+  last_tick_ = last_tick;
+
+  int64_t length = throttled_transactions_.size();
+  if (!length) {
+    UpdateSuspendedTransactions(now);
+    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());
+
+  UpdateSuspendedTransactions(now);
+}
+
+void DevToolsNetworkInterceptor::UpdateSuspendedTransactions(
+    base::TimeTicks now) {
+  int64_t activation_baseline =
+      (now - latency_length_ - base::TimeTicks()).InMicroseconds();
+  SuspendedTransactions suspended_transactions;
+  SuspendedTransactions::iterator it = suspended_transactions_.begin();
+  for (; it != suspended_transactions_.end(); ++it) {
+    if (it->second <= activation_baseline)
+      throttled_transactions_.push_back(it->first);
+    else
+      suspended_transactions.push_back(*it);
+  }
+  suspended_transactions_.swap(suspended_transactions);
+}
+
+void DevToolsNetworkInterceptor::ArmTimer(base::TimeTicks now) {
+  size_t throttle_count = throttled_transactions_.size();
+  size_t suspend_count = suspended_transactions_.size();
+  if (!throttle_count && !suspend_count)
+    return;
+
+  int64_t min_ticks_left = 0x10000L;
+  for (size_t i = 0; i < throttle_count; ++i) {
+    int64_t packets_left = (throttled_transactions_[i]->throttled_byte_count() +
+        kPacketSize - 1) / kPacketSize;
+    int64_t ticks_left = (i + 1) + throttle_count * (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);
+
+  int64_t min_baseline = std::numeric_limits<int64>::max();
+  for (size_t i = 0; i < suspend_count; ++i) {
+    if (suspended_transactions_[i].second < min_baseline)
+      min_baseline = suspended_transactions_[i].second;
+  }
+
+  if (suspend_count) {
+    base::TimeTicks activation_time = base::TimeTicks() +
+        base::TimeDelta::FromMicroseconds(min_baseline) + latency_length_;
+    if (activation_time < desired_time)
+      desired_time = activation_time;
+  }
+
+  timer_.Start(FROM_HERE, desired_time - now,
+      base::Bind(&DevToolsNetworkInterceptor::OnTimer,
+                 base::Unretained(this)));
+}
+
+void DevToolsNetworkInterceptor::OnTimer() {
+  base::TimeTicks now = base::TimeTicks::Now();
+  UpdateThrottledTransactions(now);
+
+  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);
+
+  for (auto& transaction : finished_transactions)
+    FireThrottledCallback(transaction);
+
+  ArmTimer(now);
+}
+
+void DevToolsNetworkInterceptor::FireThrottledCallback(
+    DevToolsNetworkTransaction* transaction) {
+  if (transactions_.find(transaction) != transactions_.end())
+    transaction->FireThrottledCallback();
+}
+
+}  // namespace brightray
diff --git a/brightray/browser/net/devtools_network_interceptor.h b/brightray/browser/net/devtools_network_interceptor.h
new file mode 100644
index 000000000000..330a7340bd57
--- /dev/null
+++ b/brightray/browser/net/devtools_network_interceptor.h
@@ -0,0 +1,84 @@
+// 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 BROWSER_DEVTOOLS_NETWORK_INTERCEPTOR_H_
+#define BROWSER_DEVTOOLS_NETWORK_INTERCEPTOR_H_
+
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/timer/timer.h"
+
+namespace base {
+class TimeDelta;
+class TimeTicks;
+}
+
+namespace brightray {
+
+class DevToolsNetworkConditions;
+class DevToolsNetworkTransaction;
+
+class DevToolsNetworkInterceptor {
+ public:
+  DevToolsNetworkInterceptor();
+  virtual ~DevToolsNetworkInterceptor();
+
+  base::WeakPtr<DevToolsNetworkInterceptor> GetWeakPtr();
+
+  // Applies network emulation configuration.
+  void UpdateConditions(scoped_ptr<DevToolsNetworkConditions> conditions);
+
+  void AddTransaction(DevToolsNetworkTransaction* transaction);
+  void RemoveTransaction(DevToolsNetworkTransaction* transaction);
+
+  // Returns whether transaction should fail with |net::ERR_INTERNET_DISCONNECTED|
+  bool ShouldFail(const DevToolsNetworkTransaction* transaction);
+  // Returns whether transaction should be throttled.
+  bool ShouldThrottle(const DevToolsNetworkTransaction* transaction);
+
+  void ThrottleTransaction(DevToolsNetworkTransaction* transaction, bool start);
+
+  const DevToolsNetworkConditions* conditions() const {
+    return conditions_.get();
+  }
+
+ private:
+  void UpdateThrottledTransactions(base::TimeTicks now);
+  void UpdateSuspendedTransactions(base::TimeTicks now);
+  void ArmTimer(base::TimeTicks now);
+  void OnTimer();
+  void FireThrottledCallback(DevToolsNetworkTransaction* transaction);
+
+  scoped_ptr<DevToolsNetworkConditions> conditions_;
+
+  using Transactions = std::set<DevToolsNetworkTransaction*>;
+  Transactions transactions_;
+
+  // Transactions suspended for a latency period.
+  using SuspendedTransaction = std::pair<DevToolsNetworkTransaction*, int64_t>;
+  using SuspendedTransactions = std::vector<SuspendedTransaction>;
+  SuspendedTransactions suspended_transactions_;
+
+  // Transactions waiting certain amount of transfer to be accounted.
+  std::vector<DevToolsNetworkTransaction*> throttled_transactions_;
+
+  base::OneShotTimer<DevToolsNetworkInterceptor> timer_;
+  base::TimeTicks offset_;
+  base::TimeDelta tick_length_;
+  base::TimeDelta latency_length_;
+  uint64_t last_tick_;
+
+  base::WeakPtrFactory<DevToolsNetworkInterceptor> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkInterceptor);
+};
+
+}  // namespace brightray
+
+#endif  // BROWSER_DEVTOOLS_NETWORK_INTERCEPTOR_H_
diff --git a/brightray/browser/net/devtools_network_protocol_handler.cc b/brightray/browser/net/devtools_network_protocol_handler.cc
new file mode 100644
index 000000000000..b94a04132897
--- /dev/null
+++ b/brightray/browser/net/devtools_network_protocol_handler.cc
@@ -0,0 +1,173 @@
+// Copyright (c) 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-CHROMIUM file.
+
+#include "browser/net/devtools_network_protocol_handler.h"
+
+#include "browser/browser_context.h"
+#include "browser/net/devtools_network_conditions.h"
+#include "browser/net/devtools_network_controller.h"
+
+#include "base/strings/stringprintf.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/devtools_agent_host.h"
+
+using content::BrowserThread;
+
+namespace brightray {
+
+namespace {
+
+namespace params {
+
+const char kDownloadThroughput[] = "downloadThroughput";
+const char kLatency[] = "latency";
+const char kOffline[] = "offline";
+const char kUploadThroughput[] = "uploadThroughput";
+const char kResult[] = "result";
+const char kErrorCode[] = "code";
+const char kErrorMessage[] = "message";
+
+}  //  namespace params
+
+const char kEmulateNetworkConditions[] = "Network.emulateNetworkConditions";
+const char kCanEmulateNetworkConditions[] = "Network.canEmulateNetworkConditions";
+const char kId[] = "id";
+const char kMethod[] = "method";
+const char kParams[] = "params";
+const char kError[] = "error";
+// JSON RPC 2.0 spec: http://www.jsonrpc.org/specification#error_object
+const int kErrorInvalidParams = -32602;
+
+
+bool ParseCommand(const base::DictionaryValue* command,
+                  int* id,
+                  std::string* method,
+                  const base::DictionaryValue** params) {
+  if (!command)
+    return false;
+
+  if (!command->GetInteger(kId, id) || *id < 0)
+    return false;
+
+  if (!command->GetString(kMethod, method))
+    return false;
+
+  if (!command->GetDictionary(kParams, params))
+    *params = nullptr;
+
+  return true;
+}
+
+scoped_ptr<base::DictionaryValue>
+CreateSuccessResponse(int id, scoped_ptr<base::DictionaryValue> result) {
+  scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue);
+  response->SetInteger(kId, id);
+  response->Set(params::kResult, result.release());
+  return response.Pass();
+}
+
+scoped_ptr<base::DictionaryValue>
+CreateFailureResponse(int id, const std::string& param) {
+  scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue);
+  auto error_object = new base::DictionaryValue;
+  response->Set(kError, error_object);
+  error_object->SetInteger(params::kErrorCode, kErrorInvalidParams);
+  error_object->SetString(params::kErrorMessage,
+      base::StringPrintf("Missing or Invalid '%s' parameter", param.c_str()));
+  return response.Pass();
+}
+
+void UpdateNetworkStateInIO(brightray::DevToolsNetworkController* controller,
+                            const std::string& client_id,
+                            scoped_ptr<brightray::DevToolsNetworkConditions> conditions) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  controller->SetNetworkState(client_id, conditions.Pass());
+}
+
+}  // namespace
+
+DevToolsNetworkProtocolHandler::DevToolsNetworkProtocolHandler() {
+}
+
+DevToolsNetworkProtocolHandler::~DevToolsNetworkProtocolHandler() {
+}
+
+base::DictionaryValue* DevToolsNetworkProtocolHandler::HandleCommand(
+    content::DevToolsAgentHost* agent_host,
+    base::DictionaryValue* command) {
+  int id = 0;
+  std::string method;
+  const base::DictionaryValue* params = nullptr;
+
+  if (!ParseCommand(command, &id, &method, &params))
+    return nullptr;
+
+  if (method == kEmulateNetworkConditions)
+    return EmulateNetworkConditions(agent_host, id, params).release();
+
+  if (method == kCanEmulateNetworkConditions)
+    return CanEmulateNetworkConditions(agent_host, id, params).release();
+
+  return nullptr;
+}
+
+scoped_ptr<base::DictionaryValue>
+DevToolsNetworkProtocolHandler::CanEmulateNetworkConditions(
+    content::DevToolsAgentHost* agent_host,
+    int id,
+    const base::DictionaryValue* params) {
+  scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
+  result->SetBoolean(params::kResult, true);
+  return CreateSuccessResponse(id, result.Pass());
+}
+
+scoped_ptr<base::DictionaryValue>
+DevToolsNetworkProtocolHandler::EmulateNetworkConditions(
+    content::DevToolsAgentHost* agent_host,
+    int id,
+    const base::DictionaryValue* params) {
+  bool offline = false;
+  if (!params || !params->GetBoolean(params::kOffline, &offline))
+    return CreateFailureResponse(id, params::kOffline);
+
+  double latency = 0.0;
+  if (!params->GetDouble(params::kLatency, &latency))
+    return CreateFailureResponse(id, params::kLatency);
+  if (latency < 0.0)
+    latency = 0.0;
+
+  double download_throughput = 0.0;
+  if (!params->GetDouble(params::kDownloadThroughput, &download_throughput))
+    return CreateFailureResponse(id, params::kDownloadThroughput);
+  if (download_throughput < 0.0)
+    download_throughput = 0.0;
+
+  double upload_throughput = 0.0;
+  if (!params->GetDouble(params::kUploadThroughput, &upload_throughput))
+    return CreateFailureResponse(id, params::kUploadThroughput);
+  if (upload_throughput < 0.0)
+    upload_throughput = 0.0;
+
+  scoped_ptr<DevToolsNetworkConditions> conditions(
+      new DevToolsNetworkConditions(offline,
+                                    latency,
+                                    download_throughput,
+                                    upload_throughput));
+  UpdateNetworkState(agent_host, conditions.Pass());
+  return scoped_ptr<base::DictionaryValue>();
+}
+
+void DevToolsNetworkProtocolHandler::UpdateNetworkState(
+    content::DevToolsAgentHost* agent_host,
+    scoped_ptr<DevToolsNetworkConditions> conditions) {
+  auto browser_context =
+      static_cast<brightray::BrowserContext*>(agent_host->GetBrowserContext());
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::Bind(&UpdateNetworkStateInIO,
+                                     browser_context->GetDevToolsNetworkController(),
+                                     agent_host->GetId(),
+                                     base::Passed(&conditions)));
+}
+
+}  // namespace brightray
diff --git a/brightray/browser/net/devtools_network_protocol_handler.h b/brightray/browser/net/devtools_network_protocol_handler.h
new file mode 100644
index 000000000000..4fba01b74d3c
--- /dev/null
+++ b/brightray/browser/net/devtools_network_protocol_handler.h
@@ -0,0 +1,47 @@
+// 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 BROWSER_DEVTOOLS_NETWORK_PROTOCOL_HANDLER_H_
+#define BROWSER_DEVTOOLS_NETWORK_PROTOCOL_HANDLER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+
+namespace content {
+class DevToolsAgentHost;
+}
+
+namespace brightray {
+
+class DevToolsNetworkConditions;
+
+class DevToolsNetworkProtocolHandler {
+ public:
+  DevToolsNetworkProtocolHandler();
+  ~DevToolsNetworkProtocolHandler();
+
+  base::DictionaryValue* HandleCommand(
+      content::DevToolsAgentHost* agent_host,
+      base::DictionaryValue* command);
+
+ private:
+  scoped_ptr<base::DictionaryValue> CanEmulateNetworkConditions(
+      content::DevToolsAgentHost* agent_host,
+      int command_id,
+      const base::DictionaryValue* params);
+  scoped_ptr<base::DictionaryValue> EmulateNetworkConditions(
+      content::DevToolsAgentHost* agent_host,
+      int command_id,
+      const base::DictionaryValue* params);
+  void UpdateNetworkState(
+      content::DevToolsAgentHost* agent_host,
+      scoped_ptr<DevToolsNetworkConditions> conditions);
+
+  DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkProtocolHandler);
+};
+
+}  // namespace brightray
+
+#endif  // BROWSER_DEVTOOLS_NETWORK_PROTOCOL_HANDLER_H_
diff --git a/brightray/browser/net/devtools_network_transaction.cc b/brightray/browser/net/devtools_network_transaction.cc
new file mode 100644
index 000000000000..c8c74a67999f
--- /dev/null
+++ b/brightray/browser/net/devtools_network_transaction.cc
@@ -0,0 +1,283 @@
+// Copyright (c) 2015 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-CHROMIUM file.
+
+#include "browser/net/devtools_network_transaction.h"
+
+#include "browser/net/devtools_network_controller.h"
+#include "browser/net/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"
+#include "net/socket/connection_attempts.h"
+
+namespace brightray {
+
+namespace {
+
+const char kDevToolsEmulateNetworkConditionsClientId[] =
+    "X-DevTools-Emulate-Network-Conditions-Client-Id";
+
+}  // namespace
+
+DevToolsNetworkTransaction::DevToolsNetworkTransaction(
+    DevToolsNetworkController* controller,
+    scoped_ptr<net::HttpTransaction> transaction)
+    : controller_(controller),
+      transaction_(transaction.Pass()),
+      request_(nullptr),
+      failed_(false),
+      throttled_byte_count_(0),
+      callback_type_(NONE) {
+  proxy_callback_ = base::Bind(&DevToolsNetworkTransaction::OnCallback,
+                                base::Unretained(this));
+}
+
+DevToolsNetworkTransaction::~DevToolsNetworkTransaction() {
+  if (interceptor_)
+    interceptor_->RemoveTransaction(this);
+}
+
+void DevToolsNetworkTransaction::ProcessRequest() {
+  DCHECK(request_);
+
+  bool has_devtools_client_id = request_->extra_headers.HasHeader(
+      kDevToolsEmulateNetworkConditionsClientId);
+  if (!has_devtools_client_id)
+    return;
+
+  custom_request_.reset(new net::HttpRequestInfo(*request_));
+  custom_request_->extra_headers.GetHeader(
+      kDevToolsEmulateNetworkConditionsClientId, &client_id_);
+  custom_request_->extra_headers.RemoveHeader(
+      kDevToolsEmulateNetworkConditionsClientId);
+
+  request_ = custom_request_.get();
+}
+
+void DevToolsNetworkTransaction::Fail() {
+  DCHECK(request_);
+  DCHECK(!failed_);
+
+  failed_ = true;
+  transaction_->SetBeforeNetworkStartCallback(
+      BeforeNetworkStartCallback());
+
+  if (callback_.is_null())
+    return;
+
+  net::CompletionCallback original_callback = callback_;
+  callback_.Reset();
+  callback_type_ = NONE;
+  original_callback.Run(net::ERR_INTERNET_DISCONNECTED);
+}
+
+void DevToolsNetworkTransaction::DecreaseThrottledByteCount(
+    int64_t delta) {
+  throttled_byte_count_ -= delta;
+}
+
+int DevToolsNetworkTransaction::Start(
+    const net::HttpRequestInfo* request,
+    const net::CompletionCallback& callback,
+    const net::BoundNetLog& net_log) {
+  DCHECK(request);
+
+  request_ = request;
+  interceptor_ = controller_->GetInterceptor(this);
+  interceptor_->AddTransaction(this);
+
+  if (interceptor_->ShouldFail(this)) {
+    failed_ = true;
+    transaction_->SetBeforeNetworkStartCallback(BeforeNetworkStartCallback());
+    return net::ERR_INTERNET_DISCONNECTED;
+  }
+  int rv = transaction_->Start(request_, proxy_callback_, net_log);
+  return SetupCallback(callback, rv, START);
+}
+
+int DevToolsNetworkTransaction::RestartIgnoringLastError(
+    const net::CompletionCallback& callback) {
+  if (failed_)
+    return net::ERR_INTERNET_DISCONNECTED;
+  int rv = transaction_->RestartIgnoringLastError(proxy_callback_);
+  return SetupCallback(callback, rv, RESTART_IGNORING_LAST_ERROR);
+}
+
+int DevToolsNetworkTransaction::RestartWithCertificate(
+    net::X509Certificate* client_certificate,
+    const net::CompletionCallback& callback) {
+  if (failed_)
+    return net::ERR_INTERNET_DISCONNECTED;
+  int rv = transaction_->RestartWithCertificate(client_certificate, proxy_callback_);
+  return SetupCallback(callback, rv, RESTART_WITH_CERTIFICATE);
+}
+
+int DevToolsNetworkTransaction::RestartWithAuth(
+    const net::AuthCredentials& credentials,
+    const net::CompletionCallback& callback) {
+  if (failed_)
+    return net::ERR_INTERNET_DISCONNECTED;
+  int rv = transaction_->RestartWithAuth(credentials, proxy_callback_);
+  return SetupCallback(callback, rv, RESTART_WITH_AUTH);
+}
+
+bool DevToolsNetworkTransaction::IsReadyToRestartForAuth() {
+  return transaction_->IsReadyToRestartForAuth();
+}
+
+int DevToolsNetworkTransaction::Read(
+    net::IOBuffer* buffer,
+    int length,
+    const net::CompletionCallback& callback) {
+  if (failed_)
+    return net::ERR_INTERNET_DISCONNECTED;
+  int rv = transaction_->Read(buffer, length, proxy_callback_);
+  return SetupCallback(callback, rv, READ);
+}
+
+void DevToolsNetworkTransaction::StopCaching() {
+  transaction_->StopCaching();
+}
+
+bool DevToolsNetworkTransaction::GetFullRequestHeaders(
+    net::HttpRequestHeaders* headers) const {
+  return transaction_->GetFullRequestHeaders(headers);
+}
+
+int64_t DevToolsNetworkTransaction::GetTotalReceivedBytes() const {
+  return transaction_->GetTotalReceivedBytes();
+}
+
+void DevToolsNetworkTransaction::DoneReading() {
+  transaction_->DoneReading();
+}
+
+const net::HttpResponseInfo*
+DevToolsNetworkTransaction::GetResponseInfo() const {
+  return transaction_->GetResponseInfo();
+}
+
+net::LoadState DevToolsNetworkTransaction::GetLoadState() const {
+  return transaction_->GetLoadState();
+}
+
+net::UploadProgress DevToolsNetworkTransaction::GetUploadProgress() const {
+  return transaction_->GetUploadProgress();
+}
+
+void DevToolsNetworkTransaction::SetQuicServerInfo(
+    net::QuicServerInfo* info) {
+  transaction_->SetQuicServerInfo(info);
+}
+
+bool DevToolsNetworkTransaction::GetLoadTimingInfo(
+    net::LoadTimingInfo* info) const {
+  return transaction_->GetLoadTimingInfo(info);
+}
+
+void DevToolsNetworkTransaction::SetPriority(net::RequestPriority priority) {
+  transaction_->SetPriority(priority);
+}
+
+void DevToolsNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
+    net::WebSocketHandshakeStreamBase::CreateHelper* helper) {
+  transaction_->SetWebSocketHandshakeStreamCreateHelper(helper);
+}
+
+void DevToolsNetworkTransaction::SetBeforeNetworkStartCallback(
+    const BeforeNetworkStartCallback& callback) {
+  transaction_->SetBeforeNetworkStartCallback(callback);
+}
+
+void DevToolsNetworkTransaction::SetBeforeProxyHeadersSentCallback(
+    const BeforeProxyHeadersSentCallback& callback) {
+  transaction_->SetBeforeProxyHeadersSentCallback(callback);
+}
+
+int DevToolsNetworkTransaction::ResumeNetworkStart() {
+  if (failed_)
+    return net::ERR_INTERNET_DISCONNECTED;
+  return transaction_->ResumeNetworkStart();
+}
+
+void DevToolsNetworkTransaction::GetConnectionAttempts(
+    net::ConnectionAttempts* out) const {
+  transaction_->GetConnectionAttempts(out);
+}
+
+void DevToolsNetworkTransaction::OnCallback(int rv) {
+  if (failed_ || callback_.is_null())
+    return;
+
+  if (callback_type_ == START || callback_type_ == READ) {
+    if (interceptor_ && interceptor_->ShouldThrottle(this)) {
+      Throttle(rv);
+      return;
+    }
+  }
+
+  net::CompletionCallback original_callback = callback_;
+  callback_.Reset();
+  callback_type_ = NONE;
+  original_callback.Run(rv);
+}
+
+int DevToolsNetworkTransaction::SetupCallback(
+    net::CompletionCallback callback,
+    int result,
+    CallbackType callback_type) {
+  DCHECK(callback_type_ == NONE);
+
+  if (result == net::ERR_IO_PENDING) {
+    callback_type_ = callback_type;
+    callback_ = callback;
+    return result;
+  }
+
+  if (!interceptor_ || !interceptor_->ShouldThrottle(this))
+    return result;
+
+  // Only START and READ operation throttling is supported.
+  if (callback_type != START && callback_type != READ)
+    return result;
+
+  // In case of error |throttled_byte_count_| is unknown.
+  if (result < 0)
+    return result;
+
+  // URLRequestJob relies on synchronous end-of-stream notification.
+  if (callback_type == READ && result == 0)
+    return result;
+
+  callback_type_ = callback_type;
+  callback_ = callback;
+  Throttle(result);
+  return net::ERR_IO_PENDING;
+}
+
+void DevToolsNetworkTransaction::Throttle(int result) {
+  throttled_result_ = result;
+
+  if (callback_type_ == START)
+    throttled_byte_count_ += transaction_->GetTotalReceivedBytes();
+  if (result > 0)
+    throttled_byte_count_ += result;
+
+  if (interceptor_)
+    interceptor_->ThrottleTransaction(this, callback_type_ == START);
+}
+
+void DevToolsNetworkTransaction::FireThrottledCallback() {
+  DCHECK(!callback_.is_null());
+  DCHECK(callback_type_ == READ || callback_type_ == START);
+
+  net::CompletionCallback original_callback = callback_;
+  callback_.Reset();
+  callback_type_ = NONE;
+  original_callback.Run(throttled_result_);
+}
+
+}  // namespace brightray
diff --git a/brightray/browser/net/devtools_network_transaction.h b/brightray/browser/net/devtools_network_transaction.h
new file mode 100644
index 000000000000..19295bf0dc76
--- /dev/null
+++ b/brightray/browser/net/devtools_network_transaction.h
@@ -0,0 +1,131 @@
+// 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 BROWSER_DEVTOOLS_NETWORK_TRANSACTION_H_
+#define BROWSER_DEVTOOLS_NETWORK_TRANSACTION_H_
+
+#include <stdint.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"
+#include "net/http/http_transaction.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
+
+namespace brightray {
+
+class DevToolsNetworkController;
+class DevToolsNetworkInterceptor;
+
+class DevToolsNetworkTransaction : public net::HttpTransaction {
+ public:
+  DevToolsNetworkTransaction(
+      DevToolsNetworkController* controller,
+      scoped_ptr<net::HttpTransaction> network_transaction);
+  ~DevToolsNetworkTransaction() override;
+
+  // Checks if request contains DevTools specific headers. Found values are
+  // remembered and corresponding keys are removed from headers.
+  void ProcessRequest();
+
+  // Runs callback with net::ERR_INTERNET_DISCONNECTED result.
+  void Fail();
+
+  void DecreaseThrottledByteCount(int64_t delta);
+  void FireThrottledCallback();
+
+  // HttpTransaction methods:
+  int Start(const net::HttpRequestInfo* request,
+            const net::CompletionCallback& callback,
+            const net::BoundNetLog& net_log) override;
+  int RestartIgnoringLastError(
+      const net::CompletionCallback& callback) override;
+  int RestartWithCertificate(net::X509Certificate* client_cert,
+                             const net::CompletionCallback& callback) override;
+  int RestartWithAuth(const net::AuthCredentials& credentials,
+                      const net::CompletionCallback& callback) override;
+  bool IsReadyToRestartForAuth() override;
+
+  int Read(net::IOBuffer* buf,
+           int buf_len,
+           const net::CompletionCallback& callback) override;
+  void StopCaching() override;
+  bool GetFullRequestHeaders(net::HttpRequestHeaders* headers) const override;
+  int64_t GetTotalReceivedBytes() const override;
+  void DoneReading() override;
+  const net::HttpResponseInfo* GetResponseInfo() const override;
+  net::LoadState GetLoadState() const override;
+  net::UploadProgress GetUploadProgress() const override;
+  void SetQuicServerInfo(net::QuicServerInfo* quic_server_info) override;
+  bool GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override;
+  void SetPriority(net::RequestPriority priority) override;
+  void SetWebSocketHandshakeStreamCreateHelper(
+      net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) override;
+  void SetBeforeNetworkStartCallback(
+      const BeforeNetworkStartCallback& callback) override;
+  void SetBeforeProxyHeadersSentCallback(
+      const BeforeProxyHeadersSentCallback& callback) override;
+  int ResumeNetworkStart() override;
+  void GetConnectionAttempts(net::ConnectionAttempts* out) const override;
+
+  bool failed() const { return failed_; }
+
+  const net::HttpRequestInfo* request() const { return request_; }
+
+  int64_t throttled_byte_count() const { return throttled_byte_count_; }
+
+  const std::string& client_id() const {
+    return client_id_;
+  }
+
+ private:
+  enum CallbackType {
+      NONE,
+      READ,
+      RESTART_IGNORING_LAST_ERROR,
+      RESTART_WITH_AUTH,
+      RESTART_WITH_CERTIFICATE,
+      START
+  };
+
+  // Proxy callback handler. Runs saved callback.
+  void OnCallback(int result);
+
+  int SetupCallback(
+      net::CompletionCallback callback,
+      int result,
+      CallbackType callback_type);
+  void Throttle(int result);
+
+  DevToolsNetworkController* controller_;
+  base::WeakPtr<DevToolsNetworkInterceptor> interceptor_;
+
+  // Modified request. Should be destructed after |transaction_|
+  scoped_ptr<net::HttpRequestInfo> custom_request_;
+
+  // Original network transaction.
+  scoped_ptr<net::HttpTransaction> transaction_;
+
+  const net::HttpRequestInfo* request_;
+
+  // True if Fail was already invoked.
+  bool failed_;
+
+  // Value of "X-DevTools-Emulate-Network-Conditions-Client-Id" request header.
+  std::string client_id_;
+
+  int throttled_result_;
+  int64_t throttled_byte_count_;
+  CallbackType callback_type_;
+  net::CompletionCallback proxy_callback_;
+  net::CompletionCallback callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkTransaction);
+};
+
+}  // namespace brightray
+
+#endif  // BROWSER_DEVTOOLS_NETWORK_TRANSACTION_H_
diff --git a/brightray/browser/net/devtools_network_transaction_factory.cc b/brightray/browser/net/devtools_network_transaction_factory.cc
new file mode 100644
index 000000000000..72367112f8fb
--- /dev/null
+++ b/brightray/browser/net/devtools_network_transaction_factory.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2015 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-CHROMIUM file.
+
+#include "browser/net/devtools_network_transaction_factory.h"
+
+#include "browser/net/devtools_network_controller.h"
+#include "browser/net/devtools_network_transaction.h"
+
+#include "net/base/net_errors.h"
+#include "net/http/http_network_layer.h"
+#include "net/http/http_network_transaction.h"
+
+namespace brightray {
+
+DevToolsNetworkTransactionFactory::DevToolsNetworkTransactionFactory(
+    DevToolsNetworkController* controller,
+    net::HttpNetworkSession* session)
+    : controller_(controller),
+      network_layer_(new net::HttpNetworkLayer(session)) {
+}
+
+DevToolsNetworkTransactionFactory::~DevToolsNetworkTransactionFactory() {
+}
+
+int DevToolsNetworkTransactionFactory::CreateTransaction(
+    net::RequestPriority priority,
+    scoped_ptr<net::HttpTransaction>* transaction) {
+  scoped_ptr<net::HttpTransaction> new_transaction;
+  int rv = network_layer_->CreateTransaction(priority, &new_transaction);
+  if (rv != net::OK)
+    return rv;
+  transaction->reset(new DevToolsNetworkTransaction(controller_, new_transaction.Pass()));
+  return net::OK;
+}
+
+net::HttpCache* DevToolsNetworkTransactionFactory::GetCache() {
+  return network_layer_->GetCache();
+}
+
+net::HttpNetworkSession* DevToolsNetworkTransactionFactory::GetSession() {
+  return network_layer_->GetSession();
+}
+
+}  // namespace brightray
diff --git a/brightray/browser/net/devtools_network_transaction_factory.h b/brightray/browser/net/devtools_network_transaction_factory.h
new file mode 100644
index 000000000000..a14d97c1d131
--- /dev/null
+++ b/brightray/browser/net/devtools_network_transaction_factory.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2015 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-CHROMIUM file.
+
+#ifndef BROWSER_DEVTOOLS_NETWORK_TRANSACTION_FACTORY_H_
+#define BROWSER_DEVTOOLS_NETWORK_TRANSACTION_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_transaction_factory.h"
+
+namespace brightray {
+
+class DevToolsNetworkController;
+
+class DevToolsNetworkTransactionFactory : public net::HttpTransactionFactory {
+ public:
+  explicit DevToolsNetworkTransactionFactory(
+      DevToolsNetworkController* controller,
+      net::HttpNetworkSession* session);
+  ~DevToolsNetworkTransactionFactory() override;
+
+  // net::HttpTransactionFactory:
+  int CreateTransaction(net::RequestPriority priority,
+                        scoped_ptr<net::HttpTransaction>* transaction) override;
+  net::HttpCache* GetCache() override;
+  net::HttpNetworkSession* GetSession() override;
+
+ private:
+  DevToolsNetworkController*  controller_;
+  scoped_ptr<net::HttpTransactionFactory> network_layer_;
+
+  DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkTransactionFactory);
+};
+
+}  // namespace brightray
+
+#endif  // BROWSER_DEVTOOLS_NETWORK_TRANSACTION_FACTORY_H_
diff --git a/brightray/browser/url_request_context_getter.cc b/brightray/browser/url_request_context_getter.cc
index 4150b777f7ab..840e86ce9c0e 100644
--- a/brightray/browser/url_request_context_getter.cc
+++ b/brightray/browser/url_request_context_getter.cc
@@ -6,6 +6,8 @@
 
 #include <algorithm>
 
+#include "browser/net/devtools_network_controller.h"
+#include "browser/net/devtools_network_transaction_factory.h"
 #include "browser/net_log.h"
 #include "browser/network_delegate.h"
 
@@ -123,6 +125,7 @@ net::SSLConfigService* URLRequestContextGetter::Delegate::CreateSSLConfigService
 
 URLRequestContextGetter::URLRequestContextGetter(
     Delegate* delegate,
+    DevToolsNetworkController* controller,
     NetLog* net_log,
     const base::FilePath& base_path,
     bool in_memory,
@@ -131,6 +134,7 @@ URLRequestContextGetter::URLRequestContextGetter(
     content::ProtocolHandlerMap* protocol_handlers,
     content::URLRequestInterceptorScopedVector protocol_interceptors)
     : delegate_(delegate),
+      controller_(controller),
       net_log_(net_log),
       base_path_(base_path),
       in_memory_(in_memory),
@@ -279,13 +283,17 @@ net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
     storage_->set_host_resolver(host_resolver.Pass());
     network_session_params.host_resolver = url_request_context_->host_resolver();
 
+    net::HttpNetworkSession* session = new net::HttpNetworkSession(network_session_params);
     net::HttpCache::BackendFactory* backend = nullptr;
     if (in_memory_) {
       backend = net::HttpCache::DefaultBackend::InMemory(0);
     } else {
       backend = delegate_->CreateHttpCacheBackendFactory(base_path_);
     }
-    storage_->set_http_transaction_factory(new net::HttpCache(network_session_params, backend));
+    storage_->set_http_transaction_factory(new net::HttpCache(
+        new DevToolsNetworkTransactionFactory(controller_, session),
+        url_request_context_->net_log(),
+        backend));
 
     storage_->set_job_factory(delegate_->CreateURLRequestJobFactory(
         &protocol_handlers_, &protocol_interceptors_));
diff --git a/brightray/browser/url_request_context_getter.h b/brightray/browser/url_request_context_getter.h
index 830171a52c27..4794f1bf6e53 100644
--- a/brightray/browser/url_request_context_getter.h
+++ b/brightray/browser/url_request_context_getter.h
@@ -27,6 +27,7 @@ class URLRequestJobFactory;
 
 namespace brightray {
 
+class DevToolsNetworkController;
 class NetLog;
 
 class URLRequestContextGetter : public net::URLRequestContextGetter {
@@ -48,6 +49,7 @@ class URLRequestContextGetter : public net::URLRequestContextGetter {
 
   URLRequestContextGetter(
       Delegate* delegate,
+      DevToolsNetworkController* controller,
       NetLog* net_log,
       const base::FilePath& base_path,
       bool in_memory,
@@ -66,6 +68,7 @@ class URLRequestContextGetter : public net::URLRequestContextGetter {
  private:
   Delegate* delegate_;
 
+  DevToolsNetworkController* controller_;
   NetLog* net_log_;
   base::FilePath base_path_;
   bool in_memory_;
diff --git a/brightray/filenames.gypi b/brightray/filenames.gypi
index 8334e44cd5e8..b614b6538f2f 100644
--- a/brightray/filenames.gypi
+++ b/brightray/filenames.gypi
@@ -38,6 +38,18 @@
       'browser/media/media_capture_devices_dispatcher.h',
       'browser/media/media_stream_devices_controller.cc',
       'browser/media/media_stream_devices_controller.h',
+      'browser/net/devtools_network_conditions.cc',
+      'browser/net/devtools_network_conditions.h',
+      'browser/net/devtools_network_controller.cc',
+      'browser/net/devtools_network_controller.h',
+      'browser/net/devtools_network_interceptor.cc',
+      'browser/net/devtools_network_interceptor.h',
+      'browser/net/devtools_network_protocol_handler.cc',
+      'browser/net/devtools_network_protocol_handler.h',
+      'browser/net/devtools_network_transaction_factory.cc',
+      'browser/net/devtools_network_transaction_factory.h',
+      'browser/net/devtools_network_transaction.cc',
+      'browser/net/devtools_network_transaction.h',
       'browser/net_log.cc',
       'browser/net_log.h',
       'browser/network_delegate.cc',