Merge pull request #145 from deepak1556/devtools_network_emulation_patch
enabling network emulation in devtools
This commit is contained in:
commit
3f3fbc03fc
19 changed files with 1292 additions and 3 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
35
brightray/browser/net/devtools_network_conditions.cc
Normal file
35
brightray/browser/net/devtools_network_conditions.cc
Normal file
|
@ -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
|
43
brightray/browser/net/devtools_network_conditions.h
Normal file
43
brightray/browser/net/devtools_network_conditions.h
Normal file
|
@ -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_
|
74
brightray/browser/net/devtools_network_controller.cc
Normal file
74
brightray/browser/net/devtools_network_controller.cc
Normal file
|
@ -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
|
40
brightray/browser/net/devtools_network_controller.h
Normal file
40
brightray/browser/net/devtools_network_controller.h
Normal file
|
@ -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_
|
255
brightray/browser/net/devtools_network_interceptor.cc
Normal file
255
brightray/browser/net/devtools_network_interceptor.cc
Normal file
|
@ -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
|
84
brightray/browser/net/devtools_network_interceptor.h
Normal file
84
brightray/browser/net/devtools_network_interceptor.h
Normal file
|
@ -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_
|
173
brightray/browser/net/devtools_network_protocol_handler.cc
Normal file
173
brightray/browser/net/devtools_network_protocol_handler.cc
Normal file
|
@ -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, ¶ms))
|
||||
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
|
47
brightray/browser/net/devtools_network_protocol_handler.h
Normal file
47
brightray/browser/net/devtools_network_protocol_handler.h
Normal file
|
@ -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_
|
283
brightray/browser/net/devtools_network_transaction.cc
Normal file
283
brightray/browser/net/devtools_network_transaction.cc
Normal file
|
@ -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
|
131
brightray/browser/net/devtools_network_transaction.h
Normal file
131
brightray/browser/net/devtools_network_transaction.h
Normal file
|
@ -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_
|
|
@ -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
|
39
brightray/browser/net/devtools_network_transaction_factory.h
Normal file
39
brightray/browser/net/devtools_network_transaction_factory.h
Normal file
|
@ -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_
|
|
@ -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_));
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in a new issue