Commit 7c17b699 authored by jam@chromium.org's avatar jam@chromium.org

Add a menu item to content_shell to open devtools to make it more discoverable.

Since the devtools server is running for each content shell browser process, the user doesn't specify a server port anymore. Instead I let the system pick. This made it necessary to plumb the data back from net::HttpServer.

For now I only added Windows and Linux UI. Mac UI will be done later.

BUG=90445
Review URL: https://chromiumcodereview.appspot.com/10837177

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150808 0039d316-1c4b-4281-b951-d872f2087c98
parent 9e52129b
......@@ -1134,6 +1134,9 @@ const char kReloadKilledTabs[] = "reload-killed-tabs";
// Uses custom front-end URL for the remote debugging.
const char kRemoteDebuggingFrontend[] = "remote-debugging-frontend";
// Enables remote debug over HTTP on the specified port.
const char kRemoteDebuggingPort[] = "remote-debugging-port";
// Enables print preview in the renderer. This flag is generated internally by
// Chrome and does nothing when directly passed to the browser.
const char kRendererPrintPreview[] = "renderer-print-preview";
......
......@@ -302,6 +302,7 @@ extern const char kRecordStats[];
extern const char kRecordMode[];
extern const char kReloadKilledTabs[];
extern const char kRemoteDebuggingFrontend[];
extern const char kRemoteDebuggingPort[];
extern const char kRendererPrintPreview[];
extern const char kResetVariationState[];
extern const char kRestoreLastSession[];
......
......@@ -167,6 +167,17 @@ void DevToolsHttpHandlerImpl::SetRenderViewHostBinding(
binding_ = default_binding_.get();
}
GURL DevToolsHttpHandlerImpl::GetFrontendURL(RenderViewHost* render_view_host) {
net::IPEndPoint ip_address;
if (server_->GetLocalAddress(&ip_address))
return GURL();
std::string host = ip_address.ToString();
std::string id = binding_->GetIdentifier(render_view_host);
return GURL(std::string("http://") +
ip_address.ToString() +
GetFrontendURLInternal(id, host));
}
static std::string PathWithoutParams(const std::string& path) {
size_t query_position = path.find("?");
if (query_position != std::string::npos)
......@@ -377,6 +388,17 @@ DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() {
return page_list;
}
std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal(
const std::string rvh_id,
const std::string& host) {
return base::StringPrintf(
"%s%sws=%s/devtools/page/%s",
overridden_frontend_url_.c_str(),
overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&",
host.c_str(),
rvh_id.c_str());
}
void DevToolsHttpHandlerImpl::OnJsonRequestUI(
int connection_id,
const net::HttpServerRequestInfo& info) {
......@@ -396,12 +418,8 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI(
base::StringPrintf("ws://%s/devtools/page/%s",
host.c_str(),
i->id.c_str()));
std::string devtools_frontend_url = base::StringPrintf(
"%s%sws=%s/devtools/page/%s",
overridden_frontend_url_.c_str(),
overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&",
host.c_str(),
i->id.c_str());
std::string devtools_frontend_url = GetFrontendURLInternal(i->id.c_str(),
host);
page_info->SetString("devtoolsFrontendUrl", devtools_frontend_url);
}
}
......
......@@ -53,6 +53,7 @@ class DevToolsHttpHandlerImpl
virtual void Stop() OVERRIDE;
virtual void SetRenderViewHostBinding(
RenderViewHostBinding* binding) OVERRIDE;
virtual GURL GetFrontendURL(RenderViewHost* render_view_host) OVERRIDE;
// net::HttpServer::Delegate implementation.
virtual void OnHttpRequest(int connection_id,
......@@ -64,15 +65,12 @@ class DevToolsHttpHandlerImpl
const std::string& data) OVERRIDE;
virtual void OnClose(int connection_id) OVERRIDE;
PageList GeneratePageList();
virtual void OnJsonRequestUI(int connection_id,
const net::HttpServerRequestInfo& info);
virtual void OnWebSocketRequestUI(int connection_id,
const net::HttpServerRequestInfo& info);
virtual void OnWebSocketMessageUI(int connection_id,
const std::string& data);
virtual void OnCloseUI(int connection_id);
void OnJsonRequestUI(int connection_id,
const net::HttpServerRequestInfo& info);
void OnWebSocketRequestUI(int connection_id,
const net::HttpServerRequestInfo& info);
void OnWebSocketMessageUI(int connection_id, const std::string& data);
void OnCloseUI(int connection_id);
// net::URLRequest::Delegate implementation.
virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
......@@ -93,6 +91,12 @@ class DevToolsHttpHandlerImpl
void AcceptWebSocket(int connection_id,
const net::HttpServerRequestInfo& request);
PageList GeneratePageList();
// Returns the front end url without the host at the beginning.
std::string GetFrontendURLInternal(const std::string rvh_id,
const std::string& host);
std::string overridden_frontend_url_;
scoped_ptr<const net::StreamListenSocketFactory> socket_factory_;
scoped_refptr<net::HttpServer> server_;
......
......@@ -9,6 +9,8 @@
#include "content/common/content_export.h"
class GURL;
namespace net {
class StreamListenSocketFactory;
class URLRequestContextGetter;
......@@ -56,6 +58,9 @@ class DevToolsHttpHandler {
// default implementation will be used.
virtual void SetRenderViewHostBinding(RenderViewHostBinding* binding) = 0;
// Returns the URL for the address to debug |render_view_host|.
virtual GURL GetFrontendURL(RenderViewHost* render_view_host) = 0;
protected:
virtual ~DevToolsHttpHandler() {}
};
......
......@@ -527,9 +527,6 @@ const char kProcessType[] = "type";
// Register Pepper plugins (see pepper_plugin_registry.cc for its format).
const char kRegisterPepperPlugins[] = "register-pepper-plugins";
// Enables remote debug over HTTP on the specified port.
const char kRemoteDebuggingPort[] = "remote-debugging-port";
// Causes the renderer process to throw an assertion on launch.
const char kRendererAssertTest[] = "renderer-assert-test";
......
......@@ -166,7 +166,6 @@ CONTENT_EXPORT extern const char kProcessPerSite[];
CONTENT_EXPORT extern const char kProcessPerTab[];
CONTENT_EXPORT extern const char kProcessType[];
CONTENT_EXPORT extern const char kRegisterPepperPlugins[];
CONTENT_EXPORT extern const char kRemoteDebuggingPort[];
CONTENT_EXPORT extern const char kRendererAssertTest[];
extern const char kRendererCmdPrefix[];
CONTENT_EXPORT extern const char kRendererProcess[];
......
......@@ -12,6 +12,7 @@
#define IDM_EXIT 105
#define IDM_CLOSE_WINDOW 106
#define IDM_NEW_WINDOW 107
#define IDM_SHOW_DEVELOPER_TOOLS 108
#define IDC_CONTENTSHELL 109
#define IDD_ALERT 130
#define IDD_CONFIRM 131
......
......@@ -8,8 +8,10 @@
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_details.h"
......@@ -17,6 +19,9 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/shell/shell_browser_main_parts.h"
#include "content/shell/shell_content_browser_client.h"
#include "content/shell/shell_devtools_delegate.h"
#include "content/shell/shell_javascript_dialog_creator.h"
#include "content/shell/shell_messages.h"
#include "content/shell/shell_switches.h"
......@@ -151,6 +156,19 @@ void Shell::UpdateNavigationControls() {
PlatformEnableUIControl(STOP_BUTTON, web_contents_->IsLoading());
}
void Shell::ShowDevTools() {
ShellContentBrowserClient* browser_client =
static_cast<ShellContentBrowserClient*>(
GetContentClient()->browser());
ShellDevToolsDelegate* delegate =
browser_client->shell_browser_main_parts()->devtools_delegate();
GURL url = delegate->devtools_http_handler()->GetFrontendURL(
web_contents()->GetRenderViewHost());
CreateNewWindow(
web_contents()->GetBrowserContext(),
url, NULL, MSG_ROUTING_NONE, NULL);
}
gfx::NativeView Shell::GetContentView() {
if (!web_contents_.get())
return NULL;
......
......@@ -58,6 +58,7 @@ class Shell : public WebContentsDelegate,
void Stop();
void UpdateNavigationControls();
void Close();
void ShowDevTools();
// Do one time initialization at application startup.
static void PlatformInitialize();
......
......@@ -30,6 +30,10 @@ BEGIN
MENUITEM "&Close Window", IDM_CLOSE_WINDOW
MENUITEM "E&xit", IDM_EXIT
END
POPUP "&Debug"
BEGIN
MENUITEM "&Show Developer Tools...", IDM_SHOW_DEVELOPER_TOOLS
END
END
......
......@@ -16,7 +16,6 @@ namespace content {
class DownloadManagerDelegate;
class ResourceContext;
class ShellBrowserMainParts;
class ShellDownloadManagerDelegate;
class ShellBrowserContext : public BrowserContext {
......
......@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/string_number_conversions.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/common/content_switches.h"
......@@ -82,22 +81,10 @@ void ShellBrowserMainParts::PreMainMessageLoopRun() {
#if defined(OS_ANDROID)
devtools_delegate_ = new ShellDevToolsDelegate(
0, // On android the port number isn't used.
browser_context_->GetRequestContext());
#else
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
std::string port_str =
command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
int port;
if (base::StringToInt(port_str, &port) && port > 0 && port < 65535) {
devtools_delegate_ = new ShellDevToolsDelegate(
port,
browser_context_->GetRequestContext());
} else {
DLOG(WARNING) << "Invalid http debugger port number " << port;
}
}
devtools_delegate_ = new ShellDevToolsDelegate(
browser_context_->GetRequestContext());
#endif
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
......
......@@ -44,6 +44,9 @@ class ShellContentBrowserClient : public ContentBrowserClient {
ShellResourceDispatcherHostDelegate* resource_dispatcher_host_delegate() {
return resource_dispatcher_host_delegate_.get();
}
ShellBrowserMainParts* shell_browser_main_parts() {
return shell_browser_main_parts_;
}
private:
scoped_ptr<ShellResourceDispatcherHostDelegate>
......
......@@ -4,8 +4,6 @@
#include "content/shell/shell_devtools_delegate.h"
#include <algorithm>
#include "content/public/browser/devtools_http_handler.h"
#include "grit/shell_resources.h"
#include "net/base/tcp_listen_socket.h"
......@@ -16,11 +14,10 @@
namespace content {
ShellDevToolsDelegate::ShellDevToolsDelegate(
int port,
net::URLRequestContextGetter* context_getter)
: context_getter_(context_getter) {
devtools_http_handler_ = DevToolsHttpHandler::Start(
new net::TCPListenSocketFactory("127.0.0.1", port),
new net::TCPListenSocketFactory("127.0.0.1", 0),
"",
context_getter_,
this);
......
......@@ -21,7 +21,7 @@ class DevToolsHttpHandler;
class ShellDevToolsDelegate : public DevToolsHttpHandlerDelegate {
public:
ShellDevToolsDelegate(int port, net::URLRequestContextGetter* context_getter);
explicit ShellDevToolsDelegate(net::URLRequestContextGetter* context_getter);
virtual ~ShellDevToolsDelegate();
// Stops http server.
......@@ -32,6 +32,10 @@ class ShellDevToolsDelegate : public DevToolsHttpHandlerDelegate {
virtual bool BundlesFrontendResources() OVERRIDE;
virtual std::string GetFrontendResourcesBaseURL() OVERRIDE;
DevToolsHttpHandler* devtools_http_handler() {
return devtools_http_handler_;
}
private:
net::URLRequestContextGetter* context_getter_;
DevToolsHttpHandler* devtools_http_handler_;
......
......@@ -28,7 +28,6 @@ const char kFrontEndURL[] =
namespace content {
ShellDevToolsDelegate::ShellDevToolsDelegate(
int port,
net::URLRequestContextGetter* context_getter)
: context_getter_(context_getter) {
devtools_http_handler_ = DevToolsHttpHandler::Start(
......
......@@ -23,6 +23,40 @@
namespace content {
namespace {
// Callback for Debug > Show web inspector... menu item.
gboolean ShowWebInspectorActivated(GtkWidget* widget, Shell* shell) {
shell->ShowDevTools();
return FALSE; // Don't stop this message.
}
GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text,
GCallback callback, Shell* shell) {
GtkWidget* entry = gtk_menu_item_new_with_label(text);
g_signal_connect(entry, "activate", callback, shell);
gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry);
return entry;
}
GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text) {
GtkWidget* menu_widget = gtk_menu_new();
GtkWidget* menu_header = gtk_menu_item_new_with_label(text);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_header), menu_widget);
gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_header);
return menu_widget;
}
GtkWidget* CreateMenuBar(Shell* shell) {
GtkWidget* menu_bar = gtk_menu_bar_new();
GtkWidget* debug_menu = CreateMenu(menu_bar, "Debug");
AddMenuEntry(debug_menu, "Show web inspector...",
G_CALLBACK(ShowWebInspectorActivated), shell);
return menu_bar;
}
} // namespace
void Shell::PlatformInitialize() {
}
......@@ -73,6 +107,10 @@ void Shell::PlatformCreateWindow(int width, int height) {
vbox_ = gtk_vbox_new(FALSE, 0);
// Create the menu bar.
GtkWidget* menu_bar = CreateMenuBar(this);
gtk_box_pack_start(GTK_BOX(vbox_), menu_bar, FALSE, FALSE, 0);
// Create the object that mediates accelerators.
GtkAccelGroup* accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group);
......
......@@ -236,6 +236,9 @@ LRESULT CALLBACK Shell::WndProc(HWND hwnd, UINT message, WPARAM wParam,
case IDM_EXIT:
PlatformExit();
break;
case IDM_SHOW_DEVELOPER_TOOLS:
shell->ShowDevTools();
break;
case IDC_NAV_BACK:
shell->GoBackOrForward(-1);
break;
......
......@@ -24,6 +24,8 @@
#include "base/sys_byteorder.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
using std::string;
......@@ -115,6 +117,21 @@ void StreamListenSocket::Send(const string& str, bool append_linefeed) {
Send(str.data(), static_cast<int>(str.length()), append_linefeed);
}
int StreamListenSocket::GetLocalAddress(IPEndPoint* address) {
SockaddrStorage storage;
if (getsockname(socket_, storage.addr, &storage.addr_len)) {
#if defined(OS_WIN)
int err = WSAGetLastError();
#else
int err = errno;
#endif
return MapSystemError(err);
}
if (!address->FromSockAddr(storage.addr, storage.addr_len))
return ERR_FAILED;
return OK;
}
SocketDescriptor StreamListenSocket::AcceptSocket() {
SocketDescriptor conn = HANDLE_EINTR(accept(socket_, NULL, NULL));
if (conn == kInvalidSocket)
......
......@@ -47,6 +47,8 @@ typedef SOCKET SocketDescriptor;
namespace net {
class IPEndPoint;
class NET_EXPORT StreamListenSocket
: public base::RefCountedThreadSafe<StreamListenSocket>,
#if defined(OS_WIN)
......@@ -79,6 +81,9 @@ class NET_EXPORT StreamListenSocket
void Send(const char* bytes, int len, bool append_linefeed = false);
void Send(const std::string& str, bool append_linefeed = false);
// Copies the local address to |address|. Returns a network error code.
int GetLocalAddress(IPEndPoint* address);
static const SocketDescriptor kInvalidSocket;
static const int kSocketError;
......
......@@ -83,8 +83,7 @@ void HttpServer::Send500(int connection_id, const std::string& message) {
connection->Send500(message);
}
void HttpServer::Close(int connection_id)
{
void HttpServer::Close(int connection_id) {
HttpConnection* connection = FindConnection(connection_id);
if (connection == NULL)
return;
......@@ -94,6 +93,10 @@ void HttpServer::Close(int connection_id)
DidClose(connection->socket_);
}
int HttpServer::GetLocalAddress(IPEndPoint* address) {
return server_->GetLocalAddress(address);
}
void HttpServer::DidAccept(StreamListenSocket* server,
StreamListenSocket* socket) {
HttpConnection* connection = new HttpConnection(this, socket);
......
......@@ -16,6 +16,7 @@ namespace net {
class HttpConnection;
class HttpServerRequestInfo;
class IPEndPoint;
class WebSocket;
class HttpServer : public StreamListenSocket::Delegate,
......@@ -53,6 +54,9 @@ class HttpServer : public StreamListenSocket::Delegate,
void Send500(int connection_id, const std::string& message);
void Close(int connection_id);
// Copies the local address to |address|. Returns a network error code.
int GetLocalAddress(IPEndPoint* address);
// ListenSocketDelegate
virtual void DidAccept(StreamListenSocket* server,
StreamListenSocket* socket) OVERRIDE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment