diff options
author | eustas@chromium.org <eustas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-02 16:03:08 +0000 |
---|---|---|
committer | eustas@chromium.org <eustas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-02 16:03:08 +0000 |
commit | a4205207e8e6bba4ebe0946b9d0b34abe946065f (patch) | |
tree | d3eb03bd5a2b18d30be9a887bc0291e4a93ce455 /chrome/browser/devtools | |
parent | dbe9bfab6e9b264b1b339e8c1c422f0b5dfa2a6c (diff) | |
download | chromium_src-a4205207e8e6bba4ebe0946b9d0b34abe946065f.zip chromium_src-a4205207e8e6bba4ebe0946b9d0b34abe946065f.tar.gz chromium_src-a4205207e8e6bba4ebe0946b9d0b34abe946065f.tar.bz2 |
Add the ability for DevTools to wrap network transactions.
The eventual goal is to allow it to simulate flaky network connections.
Docs:
https://docs.google.com/a/google.com/document/d/1SkuWqLYIUpMDI05n7vgx8zdkunyUsxGs9tvUPDOqEJY/edit
https://docs.google.com/a/google.com/document/d/19O_UeUfCFZg5cEnH5jkkZ6_tqsfaLQLYUEIGyXw3oTo/edit
BUG=245436
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=273584
Review URL: https://codereview.chromium.org/182993003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274253 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/devtools')
9 files changed, 826 insertions, 1 deletions
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc index 9b1f08b..9eb641c 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc @@ -4,14 +4,40 @@ #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h" +#include "base/values.h" +#include "chrome/browser/devtools/devtools_network_controller.h" +#include "chrome/browser/devtools/devtools_protocol.h" +#include "chrome/browser/devtools/devtools_protocol_constants.h" #include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/profiles/profile.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_agent_host.h" +#include "content/public/browser/devtools_manager.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/site_instance.h" -ChromeDevToolsManagerDelegate::ChromeDevToolsManagerDelegate() { +ChromeDevToolsManagerDelegate::ChromeDevToolsManagerDelegate() + : devtools_callback_(base::Bind( + &ChromeDevToolsManagerDelegate::OnDevToolsStateChanged, + base::Unretained(this))), + devtools_callback_registered_(false) { + // This constructor is invoked from DevToolsManagerImpl constructor, so it + // shouldn't call DevToolsManager::GetInstance() } ChromeDevToolsManagerDelegate::~ChromeDevToolsManagerDelegate() { + // This destructor is invoked from DevToolsManagerImpl destructor, so it + // shouldn't call DevToolsManager::GetInstance() +} + +void ChromeDevToolsManagerDelegate::EnsureDevtoolsCallbackRegistered() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!devtools_callback_registered_) { + content::DevToolsManager::GetInstance()->AddAgentStateCallback( + devtools_callback_); + devtools_callback_registered_ = true; + } } void ChromeDevToolsManagerDelegate::Inspect( @@ -30,5 +56,53 @@ void ChromeDevToolsManagerDelegate::Inspect( base::DictionaryValue* ChromeDevToolsManagerDelegate::HandleCommand( content::DevToolsAgentHost* agent_host, base::DictionaryValue* command_dict) { + scoped_ptr<DevToolsProtocol::Command> command( + DevToolsProtocol::ParseCommand(command_dict)); + if (!command) + return NULL; + const std::string method = command->method(); + if (method == chrome::devtools::Network::emulateNetworkConditions::kName) + return EmulateNetworkConditions(agent_host, command.get())->Serialize(); return NULL; } + +Profile* ChromeDevToolsManagerDelegate::GetProfile( + content::DevToolsAgentHost* agent_host) { + content::RenderViewHost* host = agent_host->GetRenderViewHost(); + if (!host) + return NULL; + return Profile::FromBrowserContext(host->GetSiteInstance()->GetProcess()-> + GetBrowserContext()); +} + +scoped_ptr<DevToolsProtocol::Response> +ChromeDevToolsManagerDelegate::EmulateNetworkConditions( + content::DevToolsAgentHost* agent_host, + DevToolsProtocol::Command* command) { + base::DictionaryValue* params = command->params(); + bool offline = false; + const char* offline_param = + chrome::devtools::Network::emulateNetworkConditions::kParamOffline; + if (!params || !params->GetBoolean(offline_param, &offline)) + return command->InvalidParamResponse(offline_param); + + EnsureDevtoolsCallbackRegistered(); + UpdateNetworkState(agent_host, offline); + return command->SuccessResponse(NULL); +} + +void ChromeDevToolsManagerDelegate::UpdateNetworkState( + content::DevToolsAgentHost* agent_host, + bool offline) { + Profile* profile = GetProfile(agent_host); + if (!profile) + return; + profile->GetDevToolsNetworkController()->SetNetworkState( + agent_host->GetId(), offline); +} + +void ChromeDevToolsManagerDelegate::OnDevToolsStateChanged( + content::DevToolsAgentHost* agent_host, + bool attached) { + UpdateNetworkState(agent_host, false); +} diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.h b/chrome/browser/devtools/chrome_devtools_manager_delegate.h index 4de8369..9b38332 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.h +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.h @@ -5,10 +5,14 @@ #ifndef CHROME_BROWSER_DEVTOOLS_CHROME_DEVTOOLS_MANAGER_DELEGATE_H_ #define CHROME_BROWSER_DEVTOOLS_CHROME_DEVTOOLS_MANAGER_DELEGATE_H_ +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/macros.h" +#include "chrome/browser/devtools/devtools_protocol.h" #include "content/public/browser/devtools_manager_delegate.h" +class Profile; + class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate { public: ChromeDevToolsManagerDelegate(); @@ -22,6 +26,21 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate { base::DictionaryValue* command_dict) OVERRIDE; private: + base::Callback<void(content::DevToolsAgentHost*, bool)> devtools_callback_; + bool devtools_callback_registered_; + void EnsureDevtoolsCallbackRegistered(); + + Profile* GetProfile(content::DevToolsAgentHost* agent_host); + + scoped_ptr<DevToolsProtocol::Response> EmulateNetworkConditions( + content::DevToolsAgentHost* agent_host, + DevToolsProtocol::Command* command); + + void UpdateNetworkState(content::DevToolsAgentHost* agent_host, bool offline); + + void OnDevToolsStateChanged(content::DevToolsAgentHost* agent_host, + bool attached); + DISALLOW_COPY_AND_ASSIGN(ChromeDevToolsManagerDelegate); }; diff --git a/chrome/browser/devtools/devtools_network_controller.cc b/chrome/browser/devtools/devtools_network_controller.cc new file mode 100644 index 0000000..4ed7dfa --- /dev/null +++ b/chrome/browser/devtools/devtools_network_controller.cc @@ -0,0 +1,92 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/devtools/devtools_network_controller.h" + +#include "chrome/browser/devtools/devtools_network_transaction.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_io_data.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/resource_context.h" + +using content::BrowserThread; + +namespace { + +const char kDevToolsRequestInitiator[] = "X-DevTools-Request-Initiator"; + +} // namespace + +DevToolsNetworkController::DevToolsNetworkController() + : weak_ptr_factory_(this) { +} + +DevToolsNetworkController::~DevToolsNetworkController() { +} + +void DevToolsNetworkController::AddTransaction( + DevToolsNetworkTransaction* transaction) { + DCHECK(thread_checker_.CalledOnValidThread()); + transactions_.insert(transaction); +} + +void DevToolsNetworkController::RemoveTransaction( + DevToolsNetworkTransaction* transaction) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(transactions_.find(transaction) != transactions_.end()); + transactions_.erase(transaction); +} + +void DevToolsNetworkController::SetNetworkState( + const std::string& client_id, + bool offline) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind( + &DevToolsNetworkController::SetNetworkStateOnIO, + weak_ptr_factory_.GetWeakPtr(), + client_id, + offline)); +} + +void DevToolsNetworkController::SetNetworkStateOnIO( + const std::string& client_id, + bool offline) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (!offline) { + clients_.erase(client_id); + return; + } + clients_.insert(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(); + } +} + +bool DevToolsNetworkController::ShouldFail( + const net::HttpRequestInfo* request) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(request); + if (clients_.empty()) + return false; + + if (request->extra_headers.HasHeader(kDevToolsRequestInitiator)) + return false; + + // TODO: Add domain blacklist. + + return true; +} diff --git a/chrome/browser/devtools/devtools_network_controller.h b/chrome/browser/devtools/devtools_network_controller.h new file mode 100644 index 0000000..b917049 --- /dev/null +++ b/chrome/browser/devtools/devtools_network_controller.h @@ -0,0 +1,73 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_CONTROLLER_H_ +#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_CONTROLLER_H_ + +#include <set> +#include <string> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" + +class DevToolsNetworkTransaction; +class GURL; +class Profile; + +namespace content { +class ResourceContext; +} + +namespace net { +struct HttpRequestInfo; +} + +namespace test { +class DevToolsNetworkControllerHelper; +} + +// DevToolsNetworkController tracks DevToolsNetworkTransactions. +class DevToolsNetworkController { + + public: + DevToolsNetworkController(); + virtual ~DevToolsNetworkController(); + + void AddTransaction(DevToolsNetworkTransaction* transaction); + + void RemoveTransaction(DevToolsNetworkTransaction* transaction); + + // Applies network emulation configuration. + // |client_id| should be DevToolsAgentHost GUID. + void SetNetworkState( + const std::string& client_id, + bool disable_network); + + bool ShouldFail(const net::HttpRequestInfo* request); + + protected: + friend class test::DevToolsNetworkControllerHelper; + + private: + // Controller must be constructed on IO thread. + base::ThreadChecker thread_checker_; + + void SetNetworkStateOnIO( + const std::string& client_id, + bool disable_network); + + typedef std::set<DevToolsNetworkTransaction*> Transactions; + Transactions transactions_; + + typedef std::set<std::string> Clients; + Clients clients_; + + base::WeakPtrFactory<DevToolsNetworkController> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkController); +}; + +#endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_CONTROLLER_H_ diff --git a/chrome/browser/devtools/devtools_network_controller_unittest.cc b/chrome/browser/devtools/devtools_network_controller_unittest.cc new file mode 100644 index 0000000..6fe6256 --- /dev/null +++ b/chrome/browser/devtools/devtools_network_controller_unittest.cc @@ -0,0 +1,193 @@ +// 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 <string> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "chrome/browser/devtools/devtools_network_controller.h" +#include "chrome/browser/devtools/devtools_network_transaction.h" +#include "net/http/http_transaction_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace test { + +const char kClientId[] = "42"; +const char kAnotherClientId[] = "24"; + +class TestCallback { + public: + TestCallback() : run_count_(0), value_(0) {} + void Run(int value) { + run_count_++; + value_ = value; + } + int run_count() { return run_count_; } + int value() { return value_; } + + private: + int run_count_; + int value_; +}; + +class DevToolsNetworkControllerHelper { + public: + DevToolsNetworkControllerHelper() : + completion_callback_( + base::Bind(&TestCallback::Run, base::Unretained(&callback_))), + mock_transaction_(kSimpleGET_Transaction), + buffer_(new net::IOBuffer(64)) { + mock_transaction_.test_mode = TEST_MODE_SYNC_NET_START; + mock_transaction_.url = "http://dot.com"; + AddMockTransaction(&mock_transaction_); + + scoped_ptr<net::HttpTransaction> network_transaction; + network_layer_.CreateTransaction( + net::DEFAULT_PRIORITY, &network_transaction); + transaction_.reset(new DevToolsNetworkTransaction( + &controller_, network_transaction.Pass())); + } + + net::HttpRequestInfo* GetRequest() { + if (!request_) + request_.reset(new MockHttpRequest(mock_transaction_)); + return request_.get(); + } + + void SetNetworkState(const std::string& client_id, bool offline) { + controller_.SetNetworkStateOnIO(client_id, offline); + } + + int Start() { + return transaction_->Start( + GetRequest(), completion_callback_, net::BoundNetLog()); + } + + int Read() { + return transaction_->Read(buffer_.get(), 64, completion_callback_); + } + + ~DevToolsNetworkControllerHelper() { + RemoveMockTransaction(&mock_transaction_); + } + + TestCallback* callback() { return &callback_; } + MockTransaction* mock_transaction() { return &mock_transaction_; } + DevToolsNetworkController* controller() { return &controller_; } + DevToolsNetworkTransaction* transaction() { return transaction_.get(); } + + private: + base::MessageLoop message_loop_; + MockNetworkLayer network_layer_; + TestCallback callback_; + net::CompletionCallback completion_callback_; + MockTransaction mock_transaction_; + DevToolsNetworkController controller_; + scoped_ptr<DevToolsNetworkTransaction> transaction_; + scoped_refptr<net::IOBuffer> buffer_; + scoped_ptr<MockHttpRequest> request_; +}; + +TEST(DevToolsNetworkControllerTest, SingleDisableEnable) { + 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(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); + EXPECT_TRUE(controller->ShouldFail(request)); + helper.SetNetworkState(kAnotherClientId, false); + EXPECT_FALSE(controller->ShouldFail(request)); +} + +TEST(DevToolsNetworkControllerTest, FailOnStart) { + DevToolsNetworkControllerHelper helper; + helper.SetNetworkState(kClientId, true); + + int rv = helper.Start(); + EXPECT_EQ(rv, net::ERR_INTERNET_DISCONNECTED); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(helper.callback()->run_count(), 0); +} + +TEST(DevToolsNetworkControllerTest, FailRunningTransaction) { + DevToolsNetworkControllerHelper helper; + TestCallback* callback = helper.callback(); + + int rv = helper.Start(); + EXPECT_EQ(rv, net::OK); + + scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(64)); + rv = helper.Read(); + EXPECT_EQ(rv, net::ERR_IO_PENDING); + EXPECT_EQ(callback->run_count(), 0); + + helper.SetNetworkState(kClientId, true); + EXPECT_EQ(callback->run_count(), 1); + EXPECT_EQ(callback->value(), net::ERR_INTERNET_DISCONNECTED); + + // Wait until HttpTrancation completes reading and invokes callback. + // DevToolsNetworkTransaction should ignore callback, because it has + // reported network error already. + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(callback->run_count(), 1); + + // Check that transaction in not failed second time. + helper.SetNetworkState(kClientId, false); + helper.SetNetworkState(kClientId, true); + EXPECT_EQ(callback->run_count(), 1); +} + +TEST(DevToolsNetworkControllerTest, ReadAfterFail) { + DevToolsNetworkControllerHelper helper; + + int rv = helper.Start(); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(helper.transaction()->request()); + + helper.SetNetworkState(kClientId, true); + EXPECT_TRUE(helper.transaction()->failed()); + + scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(64)); + rv = helper.Read(); + EXPECT_EQ(rv, net::ERR_INTERNET_DISCONNECTED); + + // Check that callback is never invoked. + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(helper.callback()->run_count(), 0); +} + +TEST(DevToolsNetworkControllerTest, AllowsDevToolsRequests) { + DevToolsNetworkControllerHelper helper; + helper.mock_transaction()->request_headers = + "X-DevTools-Request-Initiator: frontend\r\n"; + DevToolsNetworkController* controller = helper.controller(); + net::HttpRequestInfo* request = helper.GetRequest(); + + EXPECT_FALSE(controller->ShouldFail(request)); + helper.SetNetworkState(kClientId, true); + EXPECT_FALSE(controller->ShouldFail(request)); +} + +} // namespace test diff --git a/chrome/browser/devtools/devtools_network_transaction.cc b/chrome/browser/devtools/devtools_network_transaction.cc new file mode 100644 index 0000000..bba196c --- /dev/null +++ b/chrome/browser/devtools/devtools_network_transaction.cc @@ -0,0 +1,178 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/devtools/devtools_network_transaction.h" + +#include "chrome/browser/devtools/devtools_network_controller.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" + +DevToolsNetworkTransaction::DevToolsNetworkTransaction( + DevToolsNetworkController* controller, + scoped_ptr<net::HttpTransaction> network_transaction) + : controller_(controller), + network_transaction_(network_transaction.Pass()), + request_(NULL), + failed_(false), + proxy_callback_(base::Bind(&DevToolsNetworkTransaction::OnCallback, + base::Unretained(this))) { + DCHECK(controller); + controller->AddTransaction(this); +} + +DevToolsNetworkTransaction::~DevToolsNetworkTransaction() { + controller_->RemoveTransaction(this); +} + +void DevToolsNetworkTransaction::OnCallback(int rv) { + if (failed_) + return; + DCHECK(!callback_.is_null()); + net::CompletionCallback callback = callback_; + callback_.Reset(); + callback.Run(rv); +} + +void DevToolsNetworkTransaction::Fail() { + DCHECK(request_); + DCHECK(!failed_); + failed_ = true; + network_transaction_->SetBeforeNetworkStartCallback( + BeforeNetworkStartCallback()); + if (callback_.is_null()) + return; + net::CompletionCallback callback = callback_; + callback_.Reset(); + callback.Run(net::ERR_INTERNET_DISCONNECTED); +} + +int DevToolsNetworkTransaction::Start( + const net::HttpRequestInfo* request, + const net::CompletionCallback& callback, + const net::BoundNetLog& net_log) { + DCHECK(request); + request_ = request; + + if (controller_->ShouldFail(request_)) { + failed_ = true; + network_transaction_->SetBeforeNetworkStartCallback( + BeforeNetworkStartCallback()); + 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; +} + +int DevToolsNetworkTransaction::RestartIgnoringLastError( + const net::CompletionCallback& callback) { + if (failed_) + return net::ERR_INTERNET_DISCONNECTED; + int rv = network_transaction_->RestartIgnoringLastError(proxy_callback_); + if (rv == net::ERR_IO_PENDING) + callback_ = callback; + return rv; +} + +int DevToolsNetworkTransaction::RestartWithCertificate( + net::X509Certificate* client_cert, + const net::CompletionCallback& callback) { + if (failed_) + return net::ERR_INTERNET_DISCONNECTED; + int rv = network_transaction_->RestartWithCertificate( + client_cert, proxy_callback_); + if (rv == net::ERR_IO_PENDING) + callback_ = callback; + return rv; +} + +int DevToolsNetworkTransaction::RestartWithAuth( + const net::AuthCredentials& credentials, + const net::CompletionCallback& callback) { + 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; +} + +bool DevToolsNetworkTransaction::IsReadyToRestartForAuth() { + return network_transaction_->IsReadyToRestartForAuth(); +} + +int DevToolsNetworkTransaction::Read( + net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback) { + 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; +} + +void DevToolsNetworkTransaction::StopCaching() { + network_transaction_->StopCaching(); +} + +bool DevToolsNetworkTransaction::GetFullRequestHeaders( + net::HttpRequestHeaders* headers) const { + return network_transaction_->GetFullRequestHeaders(headers); +} + +int64 DevToolsNetworkTransaction::GetTotalReceivedBytes() const { + return network_transaction_->GetTotalReceivedBytes(); +} + +void DevToolsNetworkTransaction::DoneReading() { + network_transaction_->DoneReading(); +} + +const net::HttpResponseInfo* +DevToolsNetworkTransaction::GetResponseInfo() const { + return network_transaction_->GetResponseInfo(); +} + +net::LoadState DevToolsNetworkTransaction::GetLoadState() const { + return network_transaction_->GetLoadState(); +} + +net::UploadProgress DevToolsNetworkTransaction::GetUploadProgress() const { + return network_transaction_->GetUploadProgress(); +} + +void DevToolsNetworkTransaction::SetQuicServerInfo( + net::QuicServerInfo* quic_server_info) { + network_transaction_->SetQuicServerInfo(quic_server_info); +} + +bool DevToolsNetworkTransaction::GetLoadTimingInfo( + net::LoadTimingInfo* load_timing_info) const { + return network_transaction_->GetLoadTimingInfo(load_timing_info); +} + +void DevToolsNetworkTransaction::SetPriority(net::RequestPriority priority) { + network_transaction_->SetPriority(priority); +} + +void DevToolsNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper( + net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) { + network_transaction_->SetWebSocketHandshakeStreamCreateHelper(create_helper); +} + +void DevToolsNetworkTransaction::SetBeforeNetworkStartCallback( + const BeforeNetworkStartCallback& callback) { + network_transaction_->SetBeforeNetworkStartCallback(callback); +} + +int DevToolsNetworkTransaction::ResumeNetworkStart() { + if (failed_) + return net::ERR_INTERNET_DISCONNECTED; + return network_transaction_->ResumeNetworkStart(); +} diff --git a/chrome/browser/devtools/devtools_network_transaction.h b/chrome/browser/devtools/devtools_network_transaction.h new file mode 100644 index 0000000..5a51ab2 --- /dev/null +++ b/chrome/browser/devtools/devtools_network_transaction.h @@ -0,0 +1,111 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_TRANSACTION_H_ +#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_TRANSACTION_H_ + +#include "base/memory/scoped_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" + +class DevToolsNetworkController; +class GURL; + +namespace net { +class AuthCredentials; +class BoundNetLog; +class HttpRequestHeaders; +struct HttpRequestInfo; +class HttpResponseInfo; +class HttpNetworkSession; +class IOBuffer; +struct LoadTimingInfo; +class UploadProgress; +class X509Certificate; +} + +// DevToolsNetworkTransaction is a wrapper for network transaction. All +// HttpTransaction methods are proxied to real transaction, but |callback| +// parameter is saved and replaced with proxy callback. Fail method should be +// used to simulate network outage. It runs saved callback (if any) with +// net::ERR_INTERNET_DISCONNECTED result value. +class DevToolsNetworkTransaction : public net::HttpTransaction { + public: + DevToolsNetworkTransaction( + DevToolsNetworkController* controller, + scoped_ptr<net::HttpTransaction> network_transaction); + + virtual ~DevToolsNetworkTransaction(); + + const net::HttpRequestInfo* request() const { return request_; } + bool failed() const { return failed_; } + + // Runs callback (if any) with net::ERR_INTERNET_DISCONNECTED result value. + void Fail(); + + // HttpTransaction methods: + virtual int Start( + const net::HttpRequestInfo* request, + const net::CompletionCallback& callback, + const net::BoundNetLog& net_log) OVERRIDE; + virtual int RestartIgnoringLastError( + const net::CompletionCallback& callback) OVERRIDE; + virtual int RestartWithCertificate( + net::X509Certificate* client_cert, + const net::CompletionCallback& callback) OVERRIDE; + virtual int RestartWithAuth( + const net::AuthCredentials& credentials, + const net::CompletionCallback& callback) OVERRIDE; + virtual bool IsReadyToRestartForAuth() OVERRIDE; + + virtual int Read( + net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback) OVERRIDE; + virtual void StopCaching() OVERRIDE; + virtual bool GetFullRequestHeaders( + net::HttpRequestHeaders* headers) const OVERRIDE; + virtual int64 GetTotalReceivedBytes() const OVERRIDE; + virtual void DoneReading() OVERRIDE; + virtual const net::HttpResponseInfo* GetResponseInfo() const OVERRIDE; + virtual net::LoadState GetLoadState() const OVERRIDE; + virtual net::UploadProgress GetUploadProgress() const OVERRIDE; + virtual void SetQuicServerInfo( + net::QuicServerInfo* quic_server_info) OVERRIDE; + virtual bool GetLoadTimingInfo( + net::LoadTimingInfo* load_timing_info) const OVERRIDE; + virtual void SetPriority(net::RequestPriority priority) OVERRIDE; + virtual void SetWebSocketHandshakeStreamCreateHelper( + net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) OVERRIDE; + virtual void SetBeforeNetworkStartCallback( + const BeforeNetworkStartCallback& callback) OVERRIDE; + virtual int ResumeNetworkStart() OVERRIDE; + + private: + // Proxy callback handler. Runs saved callback. + void OnCallback(int result); + + DevToolsNetworkController* controller_; + + // Real network transaction. + scoped_ptr<net::HttpTransaction> network_transaction_; + + const net::HttpRequestInfo* request_; + + // True if Start was already invoked. + bool started_; + + // True if Fail was already invoked. + bool failed_; + + net::CompletionCallback proxy_callback_; + net::CompletionCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkTransaction); +}; + +#endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_TRANSACTION_H_ diff --git a/chrome/browser/devtools/devtools_network_transaction_factory.cc b/chrome/browser/devtools/devtools_network_transaction_factory.cc new file mode 100644 index 0000000..3fd8b84 --- /dev/null +++ b/chrome/browser/devtools/devtools_network_transaction_factory.cc @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/devtools/devtools_network_transaction_factory.h" + +#include "chrome/browser/devtools/devtools_network_controller.h" +#include "chrome/browser/devtools/devtools_network_transaction.h" +#include "net/base/net_errors.h" +#include "net/http/http_network_layer.h" +#include "net/http/http_network_transaction.h" + +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>* trans) { + scoped_ptr<net::HttpTransaction> network_transaction; + int rv = network_layer_->CreateTransaction(priority, &network_transaction); + if (rv != net::OK) { + return rv; + } + trans->reset( + new DevToolsNetworkTransaction(controller_, network_transaction.Pass())); + return net::OK; +} + +net::HttpCache* DevToolsNetworkTransactionFactory::GetCache() { + return network_layer_->GetCache(); +} + +net::HttpNetworkSession* DevToolsNetworkTransactionFactory::GetSession() { + return network_layer_->GetSession(); +} diff --git a/chrome/browser/devtools/devtools_network_transaction_factory.h b/chrome/browser/devtools/devtools_network_transaction_factory.h new file mode 100644 index 0000000..9faec2c --- /dev/null +++ b/chrome/browser/devtools/devtools_network_transaction_factory.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 CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_TRANSACTION_FACTORY_H_ +#define CHROME_BROWSER_DEVTOOLS_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" + +class DevToolsNetworkController; + +namespace net { +class HttpCache; +class HttpNetworkSession; +class HttpTransaction; +} + +// NetworkTransactionFactory wraps HttpNetworkTransactions. +class DevToolsNetworkTransactionFactory : public net::HttpTransactionFactory { + public: + DevToolsNetworkTransactionFactory( + DevToolsNetworkController* controller, + net::HttpNetworkSession* session); + virtual ~DevToolsNetworkTransactionFactory(); + + // net::HttpTransactionFactory methods: + virtual int CreateTransaction( + net::RequestPriority priority, + scoped_ptr<net::HttpTransaction>* trans) OVERRIDE; + virtual net::HttpCache* GetCache() OVERRIDE; + virtual net::HttpNetworkSession* GetSession() OVERRIDE; + + private: + DevToolsNetworkController* controller_; + scoped_ptr<net::HttpTransactionFactory> network_layer_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsNetworkTransactionFactory); +}; + +#endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_NETWORK_TRANSACTION_FACTORY_H_ |