summaryrefslogtreecommitdiffstats
path: root/chrome/browser/devtools
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/devtools')
-rw-r--r--chrome/browser/devtools/chrome_devtools_manager_delegate.cc10
-rw-r--r--chrome/browser/devtools/chrome_devtools_manager_delegate.h1
-rw-r--r--chrome/browser/devtools/devtools_network_controller.cc152
-rw-r--r--chrome/browser/devtools/devtools_network_controller.h29
-rw-r--r--chrome/browser/devtools/devtools_network_controller_unittest.cc41
-rw-r--r--chrome/browser/devtools/devtools_network_transaction.cc83
-rw-r--r--chrome/browser/devtools/devtools_network_transaction.h26
7 files changed, 263 insertions, 79 deletions
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
index 31089ea..473309d 100644
--- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
+++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -114,6 +114,8 @@ chrome::devtools::Network::emulateNetworkConditions::kParamMaximalThroughput;
scoped_refptr<DevToolsNetworkConditions> conditions;
if (offline || maximal_throughput)
conditions = new DevToolsNetworkConditions(domains, maximal_throughput);
+
+ emulate_network_conditions_client_id_ = agent_host->GetId();
UpdateNetworkState(agent_host, conditions);
return command->SuccessResponse(NULL);
}
@@ -124,12 +126,14 @@ void ChromeDevToolsManagerDelegate::UpdateNetworkState(
Profile* profile = GetProfile(agent_host);
if (!profile)
return;
- profile->GetDevToolsNetworkController()->SetNetworkState(
- agent_host->GetId(), conditions);
+ profile->GetDevToolsNetworkController()->SetNetworkState(conditions);
}
void ChromeDevToolsManagerDelegate::OnDevToolsStateChanged(
content::DevToolsAgentHost* agent_host,
bool attached) {
- UpdateNetworkState(agent_host, scoped_refptr<DevToolsNetworkConditions>());
+ if (agent_host->GetId() == emulate_network_conditions_client_id_) {
+ emulate_network_conditions_client_id_ = std::string();
+ UpdateNetworkState(agent_host, scoped_refptr<DevToolsNetworkConditions>());
+ }
}
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.h b/chrome/browser/devtools/chrome_devtools_manager_delegate.h
index 6385c0c..bdbbbbf 100644
--- a/chrome/browser/devtools/chrome_devtools_manager_delegate.h
+++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.h
@@ -37,6 +37,7 @@ 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_controller.cc b/chrome/browser/devtools/devtools_network_controller.cc
index 362dc46..176ac66 100644
--- a/chrome/browser/devtools/devtools_network_controller.cc
+++ b/chrome/browser/devtools/devtools_network_controller.cc
@@ -4,6 +4,7 @@
#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_transaction.h"
#include "chrome/browser/profiles/profile.h"
@@ -16,6 +17,7 @@ using content::BrowserThread;
namespace {
const char kDevToolsRequestInitiator[] = "X-DevTools-Request-Initiator";
+int64_t kPacketSize = 1500;
} // namespace
@@ -37,10 +39,17 @@ void DevToolsNetworkController::RemoveTransaction(
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();
+ }
}
void DevToolsNetworkController::SetNetworkState(
- const std::string& client_id,
const scoped_refptr<DevToolsNetworkConditions> conditions) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
@@ -49,35 +58,53 @@ 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) {
- if (client_id == active_client_id_) {
- conditions_ = NULL;
- active_client_id_ = std::string();
- }
+ 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();
+ }
}
- conditions_ = conditions;
- active_client_id_ = client_id;
-
- // 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();
+
+ 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();
}
}
@@ -93,3 +120,84 @@ bool DevToolsNetworkController::ShouldFail(
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]);
+ }
+ 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;
+ }
+ 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 f057412..a9edd0f 100644
--- a/chrome/browser/devtools/devtools_network_controller.h
+++ b/chrome/browser/devtools/devtools_network_controller.h
@@ -7,18 +7,25 @@
#include <set>
#include <string>
+#include <vector>
#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 DevToolsNetworkTransaction;
class GURL;
class Profile;
+namespace base {
+class TimeDelta;
+class TimeTicks;
+}
+
namespace content {
class ResourceContext;
}
@@ -43,12 +50,12 @@ class DevToolsNetworkController {
void RemoveTransaction(DevToolsNetworkTransaction* transaction);
// Applies network emulation configuration.
- // |client_id| should be DevToolsAgentHost GUID.
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);
protected:
friend class test::DevToolsNetworkControllerHelper;
@@ -59,19 +66,23 @@ class DevToolsNetworkController {
typedef scoped_refptr<DevToolsNetworkConditions> Conditions;
- void SetNetworkStateOnIO(
- const std::string& client_id,
- const Conditions conditions);
+ void SetNetworkStateOnIO(const Conditions conditions);
typedef std::set<DevToolsNetworkTransaction*> Transactions;
Transactions transactions_;
- // Active client id.
- std::string active_client_id_;
-
- // Active network conditions.
Conditions conditions_;
+ void UpdateThrottles();
+ void ArmTimer();
+ void OnTimer();
+
+ std::vector<DevToolsNetworkTransaction*> throttled_transactions_;
+ base::OneShotTimer<DevToolsNetworkController> timer_;
+ base::TimeTicks offset_;
+ base::TimeDelta tick_length_;
+ uint64_t last_tick_;
+
base::WeakPtrFactory<DevToolsNetworkController> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkController);
diff --git a/chrome/browser/devtools/devtools_network_controller_unittest.cc b/chrome/browser/devtools/devtools_network_controller_unittest.cc
index 38730db..708b9e1 100644
--- a/chrome/browser/devtools/devtools_network_controller_unittest.cc
+++ b/chrome/browser/devtools/devtools_network_controller_unittest.cc
@@ -17,9 +17,6 @@
namespace test {
-const char kClientId[] = "42";
-const char kAnotherClientId[] = "24";
-
const char kHttpDotCom[] = "http://dot.com";
const char kHttpDotOrg[] = "http://dot.org";
const char kCom[] = "com";
@@ -63,13 +60,13 @@ class DevToolsNetworkControllerHelper {
return request_.get();
}
- void SetNetworkState(const std::string& client_id, bool offline) {
+ 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(client_id, conditions);
+ controller_.SetNetworkStateOnIO(conditions);
}
int Start() {
@@ -108,31 +105,15 @@ TEST(DevToolsNetworkControllerTest, SingleDisableEnable) {
net::HttpRequestInfo* request = helper.GetRequest();
EXPECT_FALSE(controller->ShouldFail(request));
- helper.SetNetworkState(kClientId, true);
- EXPECT_TRUE(controller->ShouldFail(request));
- helper.SetNetworkState(kClientId, false);
- EXPECT_FALSE(controller->ShouldFail(request));
-}
-
-TEST(DevToolsNetworkControllerTest, DoubleDisableEnable) {
- DevToolsNetworkControllerHelper helper;
- DevToolsNetworkController* controller = helper.controller();
- net::HttpRequestInfo* request = helper.GetRequest();
-
- EXPECT_FALSE(controller->ShouldFail(request));
- helper.SetNetworkState(kClientId, true);
- EXPECT_TRUE(controller->ShouldFail(request));
- helper.SetNetworkState(kAnotherClientId, true);
- EXPECT_TRUE(controller->ShouldFail(request));
- helper.SetNetworkState(kClientId, false);
+ helper.SetNetworkState(true);
EXPECT_TRUE(controller->ShouldFail(request));
- helper.SetNetworkState(kAnotherClientId, false);
+ helper.SetNetworkState(false);
EXPECT_FALSE(controller->ShouldFail(request));
}
TEST(DevToolsNetworkControllerTest, FailOnStart) {
DevToolsNetworkControllerHelper helper;
- helper.SetNetworkState(kClientId, true);
+ helper.SetNetworkState(true);
int rv = helper.Start();
EXPECT_EQ(rv, net::ERR_INTERNET_DISCONNECTED);
@@ -153,7 +134,7 @@ TEST(DevToolsNetworkControllerTest, FailRunningTransaction) {
EXPECT_EQ(rv, net::ERR_IO_PENDING);
EXPECT_EQ(callback->run_count(), 0);
- helper.SetNetworkState(kClientId, true);
+ helper.SetNetworkState(true);
EXPECT_EQ(callback->run_count(), 1);
EXPECT_EQ(callback->value(), net::ERR_INTERNET_DISCONNECTED);
@@ -164,8 +145,8 @@ TEST(DevToolsNetworkControllerTest, FailRunningTransaction) {
EXPECT_EQ(callback->run_count(), 1);
// Check that transaction in not failed second time.
- helper.SetNetworkState(kClientId, false);
- helper.SetNetworkState(kClientId, true);
+ helper.SetNetworkState(false);
+ helper.SetNetworkState(true);
EXPECT_EQ(callback->run_count(), 1);
}
@@ -176,7 +157,7 @@ TEST(DevToolsNetworkControllerTest, ReadAfterFail) {
EXPECT_EQ(rv, net::OK);
EXPECT_TRUE(helper.transaction()->request());
- helper.SetNetworkState(kClientId, true);
+ helper.SetNetworkState(true);
EXPECT_TRUE(helper.transaction()->failed());
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(64));
@@ -196,7 +177,7 @@ TEST(DevToolsNetworkControllerTest, AllowsDevToolsRequests) {
net::HttpRequestInfo* request = helper.GetRequest();
EXPECT_FALSE(controller->ShouldFail(request));
- helper.SetNetworkState(kClientId, true);
+ helper.SetNetworkState(true);
EXPECT_FALSE(controller->ShouldFail(request));
}
@@ -207,7 +188,7 @@ TEST(DevToolsNetworkControllerTest, AllowsNotMatchingRequests) {
net::HttpRequestInfo* request = helper.GetRequest();
EXPECT_FALSE(controller->ShouldFail(request));
- helper.SetNetworkState(kClientId, true);
+ helper.SetNetworkState(true);
EXPECT_FALSE(controller->ShouldFail(request));
}
diff --git a/chrome/browser/devtools/devtools_network_transaction.cc b/chrome/browser/devtools/devtools_network_transaction.cc
index bba196c..8a72e01 100644
--- a/chrome/browser/devtools/devtools_network_transaction.cc
+++ b/chrome/browser/devtools/devtools_network_transaction.cc
@@ -17,6 +17,8 @@ DevToolsNetworkTransaction::DevToolsNetworkTransaction(
network_transaction_(network_transaction.Pass()),
request_(NULL),
failed_(false),
+ throttled_byte_count_(0),
+ callback_type_(NONE),
proxy_callback_(base::Bind(&DevToolsNetworkTransaction::OnCallback,
base::Unretained(this))) {
DCHECK(controller);
@@ -27,15 +29,66 @@ DevToolsNetworkTransaction::~DevToolsNetworkTransaction() {
controller_->RemoveTransaction(this);
}
+void DevToolsNetworkTransaction::Throttle(int result) {
+ throttled_result_ = result;
+
+ if (callback_type_ == START)
+ throttled_byte_count_ += network_transaction_->GetTotalReceivedBytes();
+ if (result > 0)
+ throttled_byte_count_ += result;
+
+ controller_->ThrottleTransaction(this);
+}
+
void DevToolsNetworkTransaction::OnCallback(int rv) {
if (failed_)
return;
DCHECK(!callback_.is_null());
+ if (callback_type_ == START || callback_type_ == READ) {
+ if (controller_->ShouldThrottle(request_)) {
+ Throttle(rv);
+ return;
+ }
+ }
net::CompletionCallback callback = callback_;
callback_.Reset();
+ callback_type_ = NONE;
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 (!controller_->ShouldThrottle(request_))
+ 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::Fail() {
DCHECK(request_);
DCHECK(!failed_);
@@ -46,6 +99,7 @@ void DevToolsNetworkTransaction::Fail() {
return;
net::CompletionCallback callback = callback_;
callback_.Reset();
+ callback_type_ = NONE;
callback.Run(net::ERR_INTERNET_DISCONNECTED);
}
@@ -63,9 +117,7 @@ int DevToolsNetworkTransaction::Start(
return net::ERR_INTERNET_DISCONNECTED;
}
int rv = network_transaction_->Start(request, proxy_callback_, net_log);
- if (rv == net::ERR_IO_PENDING)
- callback_ = callback;
- return rv;
+ return SetupCallback(callback, rv, START);
}
int DevToolsNetworkTransaction::RestartIgnoringLastError(
@@ -73,9 +125,7 @@ int DevToolsNetworkTransaction::RestartIgnoringLastError(
if (failed_)
return net::ERR_INTERNET_DISCONNECTED;
int rv = network_transaction_->RestartIgnoringLastError(proxy_callback_);
- if (rv == net::ERR_IO_PENDING)
- callback_ = callback;
- return rv;
+ return SetupCallback(callback, rv, RESTART_IGNORING_LAST_ERROR);
}
int DevToolsNetworkTransaction::RestartWithCertificate(
@@ -85,9 +135,7 @@ int DevToolsNetworkTransaction::RestartWithCertificate(
return net::ERR_INTERNET_DISCONNECTED;
int rv = network_transaction_->RestartWithCertificate(
client_cert, proxy_callback_);
- if (rv == net::ERR_IO_PENDING)
- callback_ = callback;
- return rv;
+ return SetupCallback(callback, rv, RESTART_WITH_CERTIFICATE);
}
int DevToolsNetworkTransaction::RestartWithAuth(
@@ -96,9 +144,7 @@ int DevToolsNetworkTransaction::RestartWithAuth(
if (failed_)
return net::ERR_INTERNET_DISCONNECTED;
int rv = network_transaction_->RestartWithAuth(credentials, proxy_callback_);
- if (rv == net::ERR_IO_PENDING)
- callback_ = callback;
- return rv;
+ return SetupCallback(callback, rv, RESTART_WITH_AUTH);
}
bool DevToolsNetworkTransaction::IsReadyToRestartForAuth() {
@@ -112,9 +158,7 @@ int DevToolsNetworkTransaction::Read(
if (failed_)
return net::ERR_INTERNET_DISCONNECTED;
int rv = network_transaction_->Read(buf, buf_len, proxy_callback_);
- if (rv == net::ERR_IO_PENDING)
- callback_ = callback;
- return rv;
+ return SetupCallback(callback, rv, READ);
}
void DevToolsNetworkTransaction::StopCaching() {
@@ -176,3 +220,12 @@ int DevToolsNetworkTransaction::ResumeNetworkStart() {
return net::ERR_INTERNET_DISCONNECTED;
return network_transaction_->ResumeNetworkStart();
}
+
+void DevToolsNetworkTransaction::FireThrottledCallback() {
+ DCHECK(!callback_.is_null());
+ DCHECK(callback_type_ == READ || callback_type_ == START);
+ net::CompletionCallback callback = callback_;
+ callback_.Reset();
+ callback_type_ = NONE;
+ callback.Run(throttled_result_);
+}
diff --git a/chrome/browser/devtools/devtools_network_transaction.h b/chrome/browser/devtools/devtools_network_transaction.h
index 5a51ab2..37e84ed 100644
--- a/chrome/browser/devtools/devtools_network_transaction.h
+++ b/chrome/browser/devtools/devtools_network_transaction.h
@@ -47,6 +47,13 @@ class DevToolsNetworkTransaction : public net::HttpTransaction {
// Runs callback (if any) with net::ERR_INTERNET_DISCONNECTED result value.
void Fail();
+ int64_t throttled_byte_count() const { return throttled_byte_count_; }
+ void DecreaseThrottledByteCount(int64_t delta) {
+ throttled_byte_count_ -= delta;
+ }
+
+ void FireThrottledCallback();
+
// HttpTransaction methods:
virtual int Start(
const net::HttpRequestInfo* request,
@@ -102,6 +109,25 @@ class DevToolsNetworkTransaction : public net::HttpTransaction {
// True if Fail was already invoked.
bool failed_;
+ enum CallbackType {
+ NONE,
+ READ,
+ RESTART_IGNORING_LAST_ERROR,
+ RESTART_WITH_AUTH,
+ RESTART_WITH_CERTIFICATE,
+ START
+ };
+
+ int SetupCallback(
+ net::CompletionCallback callback,
+ int result,
+ CallbackType callback_type);
+
+ void Throttle(int result);
+
+ int throttled_result_;
+ int64_t throttled_byte_count_;
+ CallbackType callback_type_;
net::CompletionCallback proxy_callback_;
net::CompletionCallback callback_;