| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,340 @@ | ||
| // Copyright (c) 2015 University of Szeged. | ||
| // 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 file. | ||
|
|
||
| #include "sprocket/browser/devtools/devtools_frontend.h" | ||
|
|
||
| #include "base/command_line.h" | ||
| #include "base/json/json_reader.h" | ||
| #include "base/json/json_writer.h" | ||
| #include "base/strings/string_number_conversions.h" | ||
| #include "base/strings/stringprintf.h" | ||
| #include "base/strings/utf_string_conversions.h" | ||
| #include "base/values.h" | ||
| #include "components/devtools_http_handler/devtools_http_handler.h" | ||
| #include "content/public/browser/browser_thread.h" | ||
| #include "content/public/browser/render_frame_host.h" | ||
| #include "content/public/browser/render_view_host.h" | ||
| #include "content/public/browser/web_contents.h" | ||
| #include "content/public/common/content_client.h" | ||
| #include "sprocket/browser/ui/window.h" | ||
| #include "sprocket/browser/web_contents.h" | ||
| #include "sprocket/browser/browser_context.h" | ||
| #include "sprocket/browser/browser_main_parts.h" | ||
| #include "sprocket/browser/content_browser_client.h" | ||
| #include "sprocket/browser/devtools/devtools_manager_delegate.h" | ||
| #include "sprocket/common/switches.h" | ||
| #include "net/base/io_buffer.h" | ||
| #include "net/base/net_errors.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 { | ||
|
|
||
|
|
||
| // ResponseWriter ------------------------------------------------------------- | ||
|
|
||
| class ResponseWriter : public net::URLFetcherResponseWriter { | ||
| public: | ||
| ResponseWriter(base::WeakPtr<SprocketDevToolsFrontend> sprocket_devtools_, | ||
| 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<SprocketDevToolsFrontend> sprocket_devtools_; | ||
| int stream_id_; | ||
|
|
||
| DISALLOW_COPY_AND_ASSIGN(ResponseWriter); | ||
| }; | ||
|
|
||
| ResponseWriter::ResponseWriter( | ||
| base::WeakPtr<SprocketDevToolsFrontend> sprocket_devtools, | ||
| int stream_id) | ||
| : sprocket_devtools_(sprocket_devtools), | ||
| 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(&SprocketDevToolsFrontend::CallClientFunction, | ||
| sprocket_devtools_, "DevToolsAPI.streamWrite", | ||
| base::Owned(id), base::Owned(chunk), nullptr)); | ||
| return num_bytes; | ||
| } | ||
|
|
||
| int ResponseWriter::Finish(const net::CompletionCallback& callback) { | ||
| return net::OK; | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| // This constant should be in sync with | ||
| // the constant at devtools_ui_bindings.cc. | ||
| const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; | ||
|
|
||
| // static | ||
| SprocketDevToolsFrontend* SprocketDevToolsFrontend::Show( | ||
| content::WebContents* inspected_contents) { | ||
| SprocketWindow* window = SprocketWindow::CreateNewWindow(gfx::Size()); | ||
| SprocketWebContents* web_contents = | ||
| SprocketWebContents::CreateSprocketWebContents(window, | ||
| inspected_contents->GetBrowserContext(), | ||
| GURL(), | ||
| gfx::Size()); | ||
| SprocketDevToolsFrontend* devtools_frontend = new SprocketDevToolsFrontend( | ||
| web_contents, | ||
| inspected_contents); | ||
|
|
||
| devtools_http_handler::DevToolsHttpHandler* http_handler = | ||
| SprocketContentBrowserClient::Get() | ||
| ->browser_main_parts() | ||
| ->devtools_http_handler(); | ||
| web_contents->LoadURL(http_handler->GetFrontendURL("/devtools/inspector.html")); | ||
|
|
||
| return devtools_frontend; | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::Activate() { | ||
| frontend_contents_->ActivateContents(web_contents()); | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::Focus() { | ||
| web_contents()->Focus(); | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::InspectElementAt(int x, int y) { | ||
| if (agent_host_) | ||
| agent_host_->InspectElement(x, y); | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::Close() { | ||
| frontend_contents_->Close(); | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::DisconnectFromTarget() { | ||
| if (!agent_host_) | ||
| return; | ||
| agent_host_->DetachClient(); | ||
| agent_host_ = NULL; | ||
| } | ||
|
|
||
| SprocketDevToolsFrontend::SprocketDevToolsFrontend(SprocketWebContents* frontend_contents, | ||
| content::WebContents* inspected_contents) | ||
| : content::WebContentsObserver(frontend_contents->web_contents()), | ||
| frontend_contents_(frontend_contents), | ||
| inspected_contents_(inspected_contents), | ||
| weak_factory_(this) { | ||
| } | ||
|
|
||
| SprocketDevToolsFrontend::~SprocketDevToolsFrontend() { | ||
| for (const auto& pair : pending_requests_) | ||
| delete pair.first; | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::RenderViewCreated( | ||
| content::RenderViewHost* render_view_host) { | ||
| if (!frontend_host_) { | ||
| frontend_host_.reset( | ||
| content::DevToolsFrontendHost::Create(web_contents()->GetMainFrame(), this)); | ||
| } | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::DocumentAvailableInMainFrame() { | ||
| agent_host_ = content::DevToolsAgentHost::GetOrCreateFor(inspected_contents_); | ||
| agent_host_->AttachClient(this); | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::WebContentsDestroyed() { | ||
| if (agent_host_) | ||
| agent_host_->DetachClient(); | ||
| delete this; | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::HandleMessageFromDevToolsFrontend( | ||
| const std::string& message) { | ||
| if (!agent_host_) | ||
| return; | ||
| std::string method; | ||
| base::ListValue* params = NULL; | ||
| base::DictionaryValue* dict = NULL; | ||
| scoped_ptr<base::Value> parsed_message = base::JSONReader::Read(message); | ||
| if (!parsed_message || | ||
| !parsed_message->GetAsDictionary(&dict) || | ||
| !dict->GetString("method", &method)) { | ||
| return; | ||
| } | ||
| int request_id = 0; | ||
| dict->GetInteger("id", &request_id); | ||
| dict->GetList("params", ¶ms); | ||
|
|
||
| std::string browser_message; | ||
| if (method == "sendMessageToBrowser" && params && | ||
| params->GetSize() == 1 && params->GetString(0, &browser_message)) { | ||
| agent_host_->DispatchProtocolMessage(browser_message); | ||
| } else if (method == "loadCompleted") { | ||
| web_contents()->GetMainFrame()->ExecuteJavaScript( | ||
| base::ASCIIToUTF16("DevToolsAPI.setUseSoftMenu(true);")); | ||
| } else if (method == "loadNetworkResource" && params->GetSize() == 3) { | ||
| // TODO(pfeldman): handle some of the embedder messages in content. | ||
| std::string url; | ||
| std::string headers; | ||
| int stream_id; | ||
| if (!params->GetString(0, &url) || | ||
| !params->GetString(1, &headers) || | ||
| !params->GetInteger(2, &stream_id)) { | ||
| return; | ||
| } | ||
|
|
||
| GURL gurl(url); | ||
| if (!gurl.is_valid()) { | ||
| base::DictionaryValue response; | ||
| response.SetInteger("statusCode", 404); | ||
| SendMessageAck(request_id, &response); | ||
| return; | ||
| } | ||
|
|
||
| net::URLFetcher* fetcher = | ||
| net::URLFetcher::Create(gurl, net::URLFetcher::GET, this).release(); | ||
| pending_requests_[fetcher] = request_id; | ||
| fetcher->SetRequestContext(web_contents()->GetBrowserContext()-> | ||
| GetRequestContext()); | ||
| fetcher->SetExtraRequestHeaders(headers); | ||
| fetcher->SaveResponseWithWriter(scoped_ptr<net::URLFetcherResponseWriter>( | ||
| new ResponseWriter(weak_factory_.GetWeakPtr(), stream_id))); | ||
| fetcher->Start(); | ||
| return; | ||
| } else if (method == "getPreferences") { | ||
| SendMessageAck(request_id, &preferences_); | ||
| return; | ||
| } else if (method == "setPreference") { | ||
| std::string name; | ||
| std::string value; | ||
| if (!params->GetString(0, &name) || | ||
| !params->GetString(1, &value)) { | ||
| return; | ||
| } | ||
| preferences_.SetStringWithoutPathExpansion(name, value); | ||
| } else if (method == "removePreference") { | ||
| std::string name; | ||
| if (!params->GetString(0, &name)) | ||
| return; | ||
| preferences_.RemoveWithoutPathExpansion(name, nullptr); | ||
| } else { | ||
| return; | ||
| } | ||
|
|
||
| if (request_id) | ||
| SendMessageAck(request_id, nullptr); | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::HandleMessageFromDevToolsFrontendToBackend( | ||
| const std::string& message) { | ||
| if (agent_host_) | ||
| agent_host_->DispatchProtocolMessage(message); | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::DispatchProtocolMessage( | ||
| content::DevToolsAgentHost* agent_host, | ||
| const std::string& message) { | ||
| if (message.length() < kMaxMessageChunkSize) { | ||
| base::string16 javascript = base::UTF8ToUTF16( | ||
| "DevToolsAPI.dispatchMessage(" + message + ");"); | ||
| web_contents()->GetMainFrame()->ExecuteJavaScript(javascript); | ||
| return; | ||
| } | ||
|
|
||
| base::FundamentalValue total_size(static_cast<int>(message.length())); | ||
| for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) { | ||
| std::string param; | ||
| base::JSONWriter::Write( | ||
| base::StringValue(message.substr(pos, kMaxMessageChunkSize)), ¶m); | ||
| std::string code = "DevToolsAPI.dispatchMessageChunk(" + param + ");"; | ||
| base::string16 javascript = base::UTF8ToUTF16(code); | ||
| web_contents()->GetMainFrame()->ExecuteJavaScript(javascript); | ||
| } | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::OnURLFetchComplete(const net::URLFetcher* source) { | ||
| // TODO(pfeldman): this is a copy of chrome's devtools_ui_bindings.cc. | ||
| // We should handle some of the commands including this one in content. | ||
| 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); | ||
|
|
||
| SendMessageAck(it->second, &response); | ||
| pending_requests_.erase(it); | ||
| delete source; | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::CallClientFunction( | ||
| const std::string& function_name, | ||
| const base::Value* arg1, | ||
| const base::Value* arg2, | ||
| const base::Value* arg3) { | ||
| std::string javascript = function_name + "("; | ||
| if (arg1) { | ||
| std::string json; | ||
| base::JSONWriter::Write(*arg1, &json); | ||
| javascript.append(json); | ||
| if (arg2) { | ||
| base::JSONWriter::Write(*arg2, &json); | ||
| javascript.append(", ").append(json); | ||
| if (arg3) { | ||
| base::JSONWriter::Write(*arg3, &json); | ||
| javascript.append(", ").append(json); | ||
| } | ||
| } | ||
| } | ||
| javascript.append(");"); | ||
| web_contents()->GetMainFrame()->ExecuteJavaScript( | ||
| base::UTF8ToUTF16(javascript)); | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::SendMessageAck(int request_id, | ||
| const base::Value* arg) { | ||
| base::FundamentalValue id_value(request_id); | ||
| CallClientFunction("DevToolsAPI.embedderMessageAck", | ||
| &id_value, arg, nullptr); | ||
| } | ||
|
|
||
| void SprocketDevToolsFrontend::AgentHostClosed( | ||
| content::DevToolsAgentHost* agent_host, | ||
| bool replaced) { | ||
| frontend_contents_->Close(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| // Copyright (c) 2015 University of Szeged. | ||
| // 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 file. | ||
|
|
||
| #ifndef SPROCKET_BROWSER_DEVTOOLS_FRONTEND_H_ | ||
| #define SPROCKET_BROWSER_DEVTOOLS_FRONTEND_H_ | ||
|
|
||
| #include "base/basictypes.h" | ||
| #include "base/compiler_specific.h" | ||
| #include "base/memory/ref_counted.h" | ||
| #include "base/memory/scoped_ptr.h" | ||
| #include "base/memory/weak_ptr.h" | ||
| #include "base/values.h" | ||
| #include "content/public/browser/devtools_agent_host.h" | ||
| #include "content/public/browser/devtools_frontend_host.h" | ||
| #include "content/public/browser/web_contents_observer.h" | ||
| #include "net/url_request/url_fetcher_delegate.h" | ||
|
|
||
| namespace base { | ||
| class Value; | ||
| } | ||
|
|
||
| namespace content { | ||
| class RenderViewHost; | ||
| class WebContents; | ||
| } | ||
|
|
||
| class SprocketWebContents; | ||
|
|
||
| class SprocketDevToolsFrontend : public content::WebContentsObserver, | ||
| public content::DevToolsFrontendHost::Delegate, | ||
| public content::DevToolsAgentHostClient, | ||
| public net::URLFetcherDelegate { | ||
| public: | ||
| static SprocketDevToolsFrontend* Show(content::WebContents* inspected_contents); | ||
|
|
||
| void Activate(); | ||
| void Focus(); | ||
| void InspectElementAt(int x, int y); | ||
| void Close(); | ||
|
|
||
| void DisconnectFromTarget(); | ||
|
|
||
| SprocketWebContents* frontend_contents() const { return frontend_contents_; } | ||
|
|
||
| void CallClientFunction(const std::string& function_name, | ||
| const base::Value* arg1, | ||
| const base::Value* arg2, | ||
| const base::Value* arg3); | ||
|
|
||
| protected: | ||
| SprocketDevToolsFrontend(SprocketWebContents* frontend_contents, | ||
| content::WebContents* inspected_contents); | ||
| ~SprocketDevToolsFrontend() override; | ||
|
|
||
| // content::DevToolsAgentHostClient implementation. | ||
| void AgentHostClosed(content::DevToolsAgentHost* agent_host, bool replaced) override; | ||
| void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host, | ||
| const std::string& message) override; | ||
| base::DictionaryValue* preferences() { return &preferences_; } | ||
|
|
||
| private: | ||
| // WebContentsObserver overrides | ||
| void RenderViewCreated(content::RenderViewHost* render_view_host) override; | ||
| void DocumentAvailableInMainFrame() override; | ||
| void WebContentsDestroyed() override; | ||
|
|
||
| // content::DevToolsFrontendHost::Delegate implementation. | ||
| void HandleMessageFromDevToolsFrontend(const std::string& message) override; | ||
| void HandleMessageFromDevToolsFrontendToBackend( | ||
| const std::string& message) override; | ||
|
|
||
| // net::URLFetcherDelegate overrides. | ||
| void OnURLFetchComplete(const net::URLFetcher* source) override; | ||
|
|
||
| void SendMessageAck(int request_id, | ||
| const base::Value* arg1); | ||
|
|
||
| SprocketWebContents* frontend_contents_; | ||
| content::WebContents* inspected_contents_; | ||
| scoped_refptr<content::DevToolsAgentHost> agent_host_; | ||
| scoped_ptr<content::DevToolsFrontendHost> frontend_host_; | ||
| using PendingRequestsMap = std::map<const net::URLFetcher*, int>; | ||
| PendingRequestsMap pending_requests_; | ||
| base::DictionaryValue preferences_; | ||
| base::WeakPtrFactory<SprocketDevToolsFrontend> weak_factory_; | ||
|
|
||
| DISALLOW_COPY_AND_ASSIGN(SprocketDevToolsFrontend); | ||
| }; | ||
|
|
||
| #endif // SPROCKET_BROWSER_DEVTOOLS_FRONTEND_H_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,231 @@ | ||
| // Copyright (c) 2015 University of Szeged. | ||
| // 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 file. | ||
|
|
||
| #include "sprocket/browser/devtools/devtools_manager_delegate.h" | ||
|
|
||
| #include <vector> | ||
|
|
||
| #include "base/bind.h" | ||
| #include "base/command_line.h" | ||
| #include "base/files/file_path.h" | ||
| #include "base/strings/string_number_conversions.h" | ||
| #include "base/strings/stringprintf.h" | ||
| #include "base/strings/utf_string_conversions.h" | ||
| #include "components/devtools_discovery/basic_target_descriptor.h" | ||
| #include "components/devtools_discovery/devtools_discovery_manager.h" | ||
| #include "components/devtools_http_handler/devtools_http_handler.h" | ||
| #include "content/public/browser/devtools_agent_host.h" | ||
| #include "content/public/browser/devtools_frontend_host.h" | ||
| #include "content/public/browser/favicon_status.h" | ||
| #include "content/public/browser/navigation_entry.h" | ||
| #include "content/public/browser/render_view_host.h" | ||
| #include "content/public/browser/web_contents.h" | ||
| #include "content/public/common/content_switches.h" | ||
| #include "content/public/common/url_constants.h" | ||
| #include "content/public/common/user_agent.h" | ||
| #include "sprocket/browser/web_contents.h" | ||
| #include "sprocket/browser/ui/window.h" | ||
| #include "sprocket/common/content_client.h" | ||
| #include "grit/sprocket_resources.h" | ||
| #include "net/base/net_errors.h" | ||
| #include "net/socket/tcp_server_socket.h" | ||
| #include "ui/base/resource/resource_bundle.h" | ||
|
|
||
| #if defined(OS_ANDROID) | ||
| #include "content/public/browser/android/devtools_auth.h" | ||
| #include "net/socket/unix_domain_server_socket_posix.h" | ||
| #endif | ||
|
|
||
| using devtools_http_handler::DevToolsHttpHandler; | ||
|
|
||
| namespace { | ||
|
|
||
| #if defined(OS_ANDROID) | ||
| const char kFrontEndURL[] = | ||
| "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/inspector.html"; | ||
| #endif | ||
|
|
||
| const int kBackLog = 10; | ||
|
|
||
| #if defined(OS_ANDROID) | ||
| class UnixDomainServerSocketFactory | ||
| : public DevToolsHttpHandler::ServerSocketFactory { | ||
| public: | ||
| explicit UnixDomainServerSocketFactory(const std::string& socket_name) | ||
| : socket_name_(socket_name) {} | ||
|
|
||
| private: | ||
| // DevToolsHttpHandler::ServerSocketFactory. | ||
| scoped_ptr<net::ServerSocket> CreateForHttpServer() override { | ||
| scoped_ptr<net::ServerSocket> socket( | ||
| new net::UnixDomainServerSocket( | ||
| base::Bind(&content::CanUserConnectToDevTools), | ||
| true /* use_abstract_namespace */)); | ||
| if (socket->ListenWithAddressAndPort(socket_name_, 0, kBackLog) != net::OK) | ||
| return scoped_ptr<net::ServerSocket>(); | ||
|
|
||
| return socket; | ||
| } | ||
|
|
||
| std::string socket_name_; | ||
|
|
||
| DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory); | ||
| }; | ||
| #else | ||
| class TCPServerSocketFactory | ||
| : public DevToolsHttpHandler::ServerSocketFactory { | ||
| public: | ||
| TCPServerSocketFactory(const std::string& address, uint16 port) | ||
| : address_(address), port_(port) { | ||
| } | ||
|
|
||
| private: | ||
| // DevToolsHttpHandler::ServerSocketFactory. | ||
| scoped_ptr<net::ServerSocket> CreateForHttpServer() override { | ||
| scoped_ptr<net::ServerSocket> socket( | ||
| new net::TCPServerSocket(nullptr, net::NetLog::Source())); | ||
| if (socket->ListenWithAddressAndPort(address_, port_, kBackLog) != net::OK) | ||
| return scoped_ptr<net::ServerSocket>(); | ||
|
|
||
| return socket; | ||
| } | ||
|
|
||
| std::string address_; | ||
| uint16 port_; | ||
|
|
||
| DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory); | ||
| }; | ||
| #endif | ||
|
|
||
| scoped_ptr<DevToolsHttpHandler::ServerSocketFactory> | ||
| CreateSocketFactory() { | ||
| const base::CommandLine& command_line = | ||
| *base::CommandLine::ForCurrentProcess(); | ||
| #if defined(OS_ANDROID) | ||
| std::string socket_name = "sprocket_devtools_remote"; | ||
| if (command_line.HasSwitch(switches::kRemoteDebuggingSocketName)) { | ||
| socket_name = command_line.GetSwitchValueASCII( | ||
| switches::kRemoteDebuggingSocketName); | ||
| } | ||
| return scoped_ptr<DevToolsHttpHandler::ServerSocketFactory>( | ||
| new UnixDomainServerSocketFactory(socket_name)); | ||
| #else | ||
| // See if the user specified a port on the command line (useful for | ||
| // automation). If not, use an ephemeral port by specifying 0. | ||
| uint16 port = 0; | ||
| if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) { | ||
| int temp_port; | ||
| std::string port_str = | ||
| command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort); | ||
| if (base::StringToInt(port_str, &temp_port) && | ||
| temp_port > 0 && temp_port < 65535) { | ||
| port = static_cast<uint16>(temp_port); | ||
| } else { | ||
| DLOG(WARNING) << "Invalid http debugger port number " << temp_port; | ||
| } | ||
| } | ||
| return scoped_ptr<DevToolsHttpHandler::ServerSocketFactory>( | ||
| new TCPServerSocketFactory("127.0.0.1", port)); | ||
| #endif | ||
| } | ||
|
|
||
| scoped_ptr<devtools_discovery::DevToolsTargetDescriptor> | ||
| CreateNewSprocketTarget(content::BrowserContext* browser_context, const GURL& url) { | ||
| SprocketWindow* window = SprocketWindow::CreateNewWindow(gfx::Size()); | ||
| SprocketWebContents* web_contents = | ||
| SprocketWebContents::CreateSprocketWebContents(window, | ||
| browser_context, | ||
| url, | ||
| gfx::Size()); | ||
| return make_scoped_ptr(new devtools_discovery::BasicTargetDescriptor( | ||
| content::DevToolsAgentHost::GetOrCreateFor(web_contents->web_contents()))); | ||
| } | ||
|
|
||
| // SprocketDevToolsDelegate ---------------------------------------------------- | ||
|
|
||
| class SprocketDevToolsDelegate : | ||
| public devtools_http_handler::DevToolsHttpHandlerDelegate { | ||
| public: | ||
| explicit SprocketDevToolsDelegate(content::BrowserContext* browser_context); | ||
| ~SprocketDevToolsDelegate() override; | ||
|
|
||
| // devtools_http_handler::DevToolsHttpHandlerDelegate implementation. | ||
| std::string GetDiscoveryPageHTML() override; | ||
| std::string GetFrontendResource(const std::string& path) override; | ||
| std::string GetPageThumbnailData(const GURL& url) override; | ||
|
|
||
| private: | ||
| content::BrowserContext* browser_context_; | ||
|
|
||
| DISALLOW_COPY_AND_ASSIGN(SprocketDevToolsDelegate); | ||
| }; | ||
|
|
||
| SprocketDevToolsDelegate::SprocketDevToolsDelegate(content::BrowserContext* browser_context) | ||
| : browser_context_(browser_context) { | ||
| devtools_discovery::DevToolsDiscoveryManager::GetInstance()-> | ||
| SetCreateCallback(base::Bind(&CreateNewSprocketTarget, | ||
| base::Unretained(browser_context))); | ||
| } | ||
|
|
||
| SprocketDevToolsDelegate::~SprocketDevToolsDelegate() { | ||
| devtools_discovery::DevToolsDiscoveryManager::GetInstance()-> | ||
| SetCreateCallback( | ||
| devtools_discovery::DevToolsDiscoveryManager::CreateCallback()); | ||
| } | ||
|
|
||
| std::string SprocketDevToolsDelegate::GetDiscoveryPageHTML() { | ||
| #if defined(OS_ANDROID) | ||
| return std::string(); | ||
| #else | ||
| return ResourceBundle::GetSharedInstance().GetRawDataResource( | ||
| IDR_SPROCKET_DEVTOOLS_DISCOVERY_PAGE).as_string(); | ||
| #endif | ||
| } | ||
|
|
||
| std::string SprocketDevToolsDelegate::GetFrontendResource( | ||
| const std::string& path) { | ||
| return content::DevToolsFrontendHost::GetFrontendResource(path).as_string(); | ||
| } | ||
|
|
||
| std::string SprocketDevToolsDelegate::GetPageThumbnailData(const GURL& url) { | ||
| return std::string(); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| // SprocketDevToolsManagerDelegate ---------------------------------------------- | ||
|
|
||
| // static | ||
| DevToolsHttpHandler* | ||
| SprocketDevToolsManagerDelegate::CreateHttpHandler( | ||
| content::BrowserContext* browser_context) { | ||
| std::string frontend_url; | ||
| #if defined(OS_ANDROID) | ||
| frontend_url = base::StringPrintf(kFrontEndURL, content::GetWebKitRevision().c_str()); | ||
| #endif | ||
| return new DevToolsHttpHandler( | ||
| CreateSocketFactory(), | ||
| frontend_url, | ||
| new SprocketDevToolsDelegate(browser_context), | ||
| base::FilePath(), | ||
| base::FilePath(), | ||
| std::string(), | ||
| GetSprocketUserAgent()); | ||
| } | ||
|
|
||
| SprocketDevToolsManagerDelegate::SprocketDevToolsManagerDelegate( | ||
| content::BrowserContext* browser_context) | ||
| : browser_context_(browser_context) { | ||
| } | ||
|
|
||
| SprocketDevToolsManagerDelegate::~SprocketDevToolsManagerDelegate() { | ||
| } | ||
|
|
||
| base::DictionaryValue* SprocketDevToolsManagerDelegate::HandleCommand( | ||
| content::DevToolsAgentHost* agent_host, | ||
| base::DictionaryValue* command) { | ||
| return NULL; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| // Copyright (c) 2015 University of Szeged. | ||
| // 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 file. | ||
|
|
||
| #ifndef SPROCKET_BROWSER_DEVTOOLS_MANAGER_DELEGATE_H_ | ||
| #define SPROCKET_BROWSER_DEVTOOLS_MANAGER_DELEGATE_H_ | ||
|
|
||
| #include "base/basictypes.h" | ||
| #include "base/compiler_specific.h" | ||
| #include "components/devtools_http_handler/devtools_http_handler_delegate.h" | ||
| #include "content/public/browser/devtools_manager_delegate.h" | ||
|
|
||
| namespace devtools_http_handler { | ||
| class DevToolsHttpHandler; | ||
| } | ||
|
|
||
| namespace content { | ||
| class BrowserContext; | ||
| } | ||
|
|
||
| class SprocketDevToolsManagerDelegate : public content::DevToolsManagerDelegate { | ||
| public: | ||
| static devtools_http_handler::DevToolsHttpHandler* CreateHttpHandler( | ||
| content::BrowserContext* browser_context); | ||
|
|
||
| explicit SprocketDevToolsManagerDelegate(content::BrowserContext* browser_context); | ||
| ~SprocketDevToolsManagerDelegate() override; | ||
|
|
||
| // DevToolsManagerDelegate implementation. | ||
| void Inspect(content::BrowserContext* browser_context, | ||
| content::DevToolsAgentHost* agent_host) override {} | ||
| void DevToolsAgentStateChanged(content::DevToolsAgentHost* agent_host, | ||
| bool attached) override {} | ||
| base::DictionaryValue* HandleCommand(content::DevToolsAgentHost* agent_host, | ||
| base::DictionaryValue* command) override; | ||
|
|
||
| private: | ||
| content::BrowserContext* browser_context_; | ||
|
|
||
| DISALLOW_COPY_AND_ASSIGN(SprocketDevToolsManagerDelegate); | ||
| }; | ||
|
|
||
| #endif // SPROCKET_BROWSER_DEVTOOLS_MANAGER_DELEGATE_H_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| diff --git a/chrome/test/chromedriver/chrome/device_manager.cc b/chrome/test/chromedriver/chrome/device_manager.cc | ||
| index 8e77f0c..48ec7e1 100644 | ||
| --- a/chrome/test/chromedriver/chrome/device_manager.cc | ||
| +++ b/chrome/test/chromedriver/chrome/device_manager.cc | ||
| @@ -55,6 +55,12 @@ Status Device::SetUp(const std::string& package, | ||
| device_socket = "content_shell_devtools_remote"; | ||
| command_line_file = "/data/local/tmp/content-shell-command-line"; | ||
| exec_name = "content_shell"; | ||
| + } else if (package.compare("hu.uszeged.sprocket_apk") == 0) { | ||
| + // Sprocket. | ||
| + known_activity = ".SprocketActivity"; | ||
| + device_socket = "sprocket_devtools_remote"; | ||
| + command_line_file = "/data/local/tmp/sprocket-command-line"; | ||
| + exec_name = "sprocket"; | ||
| } else if (package.compare("org.chromium.chrome.shell") == 0) { | ||
| // ChromeShell | ||
| known_activity = ".ChromeShellActivity"; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids | ||
| index a64ae83..653becf 100644 | ||
| --- a/tools/gritsettings/resource_ids | ||
| +++ b/tools/gritsettings/resource_ids | ||
| @@ -160,6 +160,9 @@ | ||
| "content/shell/shell_resources.grd": { | ||
| "includes": [25500], | ||
| }, | ||
| + "sprocket/sprocket_resources.grd": { | ||
| + "includes": [25600], | ||
| + }, | ||
| # This file is generated during the build. | ||
| "<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing/tracing_resources.grd": { | ||
| "includes": [25750], |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| <html> | ||
| <head> | ||
| <title>Sprocket remote debugging</title> | ||
| <style> | ||
| </style> | ||
|
|
||
| <script> | ||
| function onLoad() { | ||
| var tabs_list_request = new XMLHttpRequest(); | ||
| tabs_list_request.open("GET", "/json/list?t=" + new Date().getTime(), true); | ||
| tabs_list_request.onreadystatechange = onReady; | ||
| tabs_list_request.send(); | ||
| } | ||
|
|
||
| function onReady() { | ||
| if(this.readyState == 4 && this.status == 200) { | ||
| if(this.response != null) | ||
| var responseJSON = JSON.parse(this.response); | ||
| for (var i = 0; i < responseJSON.length; ++i) | ||
| appendItem(responseJSON[i]); | ||
| } | ||
| } | ||
|
|
||
| function appendItem(item_object) { | ||
| var frontend_ref; | ||
| if (item_object.devtoolsFrontendUrl) { | ||
| frontend_ref = document.createElement("a"); | ||
| frontend_ref.href = item_object.devtoolsFrontendUrl; | ||
| frontend_ref.title = item_object.title; | ||
| } else { | ||
| frontend_ref = document.createElement("div"); | ||
| frontend_ref.title = "The tab already has active debugging session"; | ||
| } | ||
|
|
||
| var text = document.createElement("div"); | ||
| if (item_object.title) | ||
| text.innerText = item_object.title; | ||
| else | ||
| text.innerText = "(untitled tab)"; | ||
| text.style.cssText = "background-image:url(" + item_object.faviconUrl + ")"; | ||
| frontend_ref.appendChild(text); | ||
|
|
||
| var item = document.createElement("p"); | ||
| item.appendChild(frontend_ref); | ||
|
|
||
| document.getElementById("items").appendChild(item); | ||
| } | ||
| </script> | ||
| </head> | ||
| <body onload='onLoad()'> | ||
| <div id='caption'>Inspectable WebContents</div> | ||
| <div id='items'></div> | ||
| </body> | ||
| </html> |