From 9a9bc5530e13f1ba7ab1fafd857c94125fc1c26b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 5 Jun 2015 11:20:20 +0800 Subject: [PATCH] Handle network requests from devtools --- .../browser/inspectable_web_contents_impl.cc | 100 ++++++++++++++++++ .../browser/inspectable_web_contents_impl.h | 11 +- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/brightray/browser/inspectable_web_contents_impl.cc b/brightray/browser/inspectable_web_contents_impl.cc index 43fc7132db..bc3a9aba54 100644 --- a/brightray/browser/inspectable_web_contents_impl.cc +++ b/brightray/browser/inspectable_web_contents_impl.cc @@ -19,10 +19,14 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_http_handler.h" #include "content/public/browser/host_zoom_map.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_view_host.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_fetcher_response_writer.h" namespace brightray { @@ -86,6 +90,59 @@ double GetNextZoomLevel(double level, bool out) { return level; } +// ResponseWriter ------------------------------------------------------------- + +class ResponseWriter : public net::URLFetcherResponseWriter { + public: + ResponseWriter(base::WeakPtr bindings, int stream_id); + ~ResponseWriter() override; + + // URLFetcherResponseWriter overrides: + int Initialize(const net::CompletionCallback& callback) override; + int Write(net::IOBuffer* buffer, + int num_bytes, + const net::CompletionCallback& callback) override; + int Finish(const net::CompletionCallback& callback) override; + + private: + base::WeakPtr bindings_; + int stream_id_; + + DISALLOW_COPY_AND_ASSIGN(ResponseWriter); +}; + +ResponseWriter::ResponseWriter(base::WeakPtr bindings, + int stream_id) + : bindings_(bindings), + stream_id_(stream_id) { +} + +ResponseWriter::~ResponseWriter() { +} + +int ResponseWriter::Initialize(const net::CompletionCallback& callback) { + return net::OK; +} + +int ResponseWriter::Write(net::IOBuffer* buffer, + int num_bytes, + const net::CompletionCallback& callback) { + base::FundamentalValue* id = new base::FundamentalValue(stream_id_); + base::StringValue* chunk = + new base::StringValue(std::string(buffer->data(), num_bytes)); + + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&InspectableWebContentsImpl::CallClientFunction, + bindings_, "DevToolsAPI.streamWrite", + base::Owned(id), base::Owned(chunk), nullptr)); + return num_bytes; +} + +int ResponseWriter::Finish(const net::CompletionCallback& callback) { + return net::OK; +} + } // namespace // Implemented separately on each platform. @@ -245,6 +302,24 @@ void InspectableWebContentsImpl::LoadNetworkResource( const std::string& url, const std::string& headers, int stream_id) { + GURL gurl(url); + if (!gurl.is_valid()) { + base::DictionaryValue response; + response.SetInteger("statusCode", 404); + callback.Run(&response); + return; + } + + auto browser_context = static_cast(devtools_web_contents_->GetBrowserContext()); + + net::URLFetcher* fetcher = + net::URLFetcher::Create(gurl, net::URLFetcher::GET, this); + pending_requests_[fetcher] = callback; + fetcher->SetRequestContext(browser_context->url_request_context_getter()); + fetcher->SetExtraRequestHeaders(headers); + fetcher->SaveResponseWithWriter(scoped_ptr( + new ResponseWriter(weak_factory_.GetWeakPtr(), stream_id))); + fetcher->Start(); } void InspectableWebContentsImpl::SetIsDocked(const DispatchCallback& callback, @@ -406,6 +481,9 @@ void InspectableWebContentsImpl::WebContentsDestroyed() { agent_host_->DetachClient(); Observe(nullptr); agent_host_ = nullptr; + + for (const auto& pair : pending_requests_) + delete pair.first; } bool InspectableWebContentsImpl::AddMessageToConsole( @@ -449,6 +527,28 @@ void InspectableWebContentsImpl::WebContentsFocused( delegate_->DevToolsFocused(); } +void InspectableWebContentsImpl::OnURLFetchComplete(const net::URLFetcher* source) { + DCHECK(source); + PendingRequestsMap::iterator it = pending_requests_.find(source); + DCHECK(it != pending_requests_.end()); + + base::DictionaryValue response; + base::DictionaryValue* headers = new base::DictionaryValue(); + net::HttpResponseHeaders* rh = source->GetResponseHeaders(); + response.SetInteger("statusCode", rh ? rh->response_code() : 200); + response.Set("headers", headers); + + void* iterator = NULL; + std::string name; + std::string value; + while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) + headers->SetString(name, value); + + it->second.Run(&response); + pending_requests_.erase(it); + delete source; +} + void InspectableWebContentsImpl::SendMessageAck(int request_id, const base::Value* arg) { base::FundamentalValue id_value(request_id); diff --git a/brightray/browser/inspectable_web_contents_impl.h b/brightray/browser/inspectable_web_contents_impl.h index bde6e1b4aa..932b0fd6a9 100644 --- a/brightray/browser/inspectable_web_contents_impl.h +++ b/brightray/browser/inspectable_web_contents_impl.h @@ -16,6 +16,7 @@ #include "content/public/browser/devtools_frontend_host.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" +#include "net/url_request/url_fetcher_delegate.h" #include "ui/gfx/geometry/rect.h" class PrefRegistrySimple; @@ -35,7 +36,8 @@ class InspectableWebContentsImpl : public content::DevToolsAgentHostClient, public content::WebContentsObserver, public content::WebContentsDelegate, - public DevToolsEmbedderMessageDispatcher::Delegate { + public DevToolsEmbedderMessageDispatcher::Delegate, + public net::URLFetcherDelegate { public: static void RegisterPrefs(PrefRegistrySimple* pref_registry); @@ -130,7 +132,7 @@ class InspectableWebContentsImpl : const GURL& validated_url) override; void WebContentsDestroyed() override; - // content::WebContentsDelegate + // content::WebContentsDelegate: bool AddMessageToConsole(content::WebContents* source, int32 level, const base::string16& message, @@ -150,6 +152,9 @@ class InspectableWebContentsImpl : void CloseContents(content::WebContents* source) override; void WebContentsFocused(content::WebContents* contents) override; + // net::URLFetcherDelegate: + void OnURLFetchComplete(const net::URLFetcher* source) override; + void SendMessageAck(int request_id, const base::Value* arg1); @@ -167,6 +172,8 @@ class InspectableWebContentsImpl : InspectableWebContentsDelegate* delegate_; + using PendingRequestsMap = std::map; + PendingRequestsMap pending_requests_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(InspectableWebContentsImpl);