Add InspectableWebContents

This class can be used to create a content::WebContents that can be inspected
by the Chrome Dev Tools. This requires embedding applications to copy
content_shell.pak into their resource bundle.

Right now the dev tools are always docked to the bottom of the view; we don't
yet support undocking or changing the docked side.

Fixes #1.
This commit is contained in:
Adam Roben
2013-03-14 09:03:50 -04:00
parent e1b5e5e1bf
commit b2a79856ef
22 changed files with 601 additions and 5 deletions

View File

@@ -2,9 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.
#include "browser_main_parts.h"
#include "browser/browser_main_parts.h"
#include "browser_context.h"
#include "browser/browser_context.h"
#include "browser/devtools_delegate.h"
#include "content/public/browser/devtools_http_handler.h"
#include "net/base/tcp_listen_socket.h"
namespace brightray {
@@ -12,10 +16,18 @@ BrowserMainParts::BrowserMainParts() {
}
BrowserMainParts::~BrowserMainParts() {
devtools_http_handler_->Stop();
devtools_http_handler_ = nullptr;
}
void BrowserMainParts::PreMainMessageLoopRun() {
browser_context_.reset(new BrowserContext);
// These two objects are owned by devtools_http_handler_.
auto delegate = new DevToolsDelegate;
auto factory = new net::TCPListenSocketFactory("127.0.0.1", 0);
devtools_http_handler_ = content::DevToolsHttpHandler::Start(factory, std::string(), delegate);
}
}

View File

@@ -9,6 +9,10 @@
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/browser_main_parts.h"
namespace content {
class DevToolsHttpHandler;
}
namespace brightray {
class BrowserContext;
@@ -19,6 +23,7 @@ public:
~BrowserMainParts();
BrowserContext* browser_context() { return browser_context_.get(); }
content::DevToolsHttpHandler* devtools_http_handler() { return devtools_http_handler_; }
protected:
#if defined(OS_MACOSX)
@@ -29,6 +34,7 @@ protected:
private:
scoped_ptr<BrowserContext> browser_context_;
content::DevToolsHttpHandler* devtools_http_handler_;
DISALLOW_COPY_AND_ASSIGN(BrowserMainParts);
};

View File

@@ -0,0 +1,39 @@
// Copyright (c) 2012 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 "devtools_delegate.h"
namespace brightray {
DevToolsDelegate::DevToolsDelegate() {
}
DevToolsDelegate::~DevToolsDelegate() {
}
std::string DevToolsDelegate::GetDiscoveryPageHTML() {
return std::string();
}
bool DevToolsDelegate::BundlesFrontendResources() {
return true;
}
base::FilePath DevToolsDelegate::GetDebugFrontendDir() {
return base::FilePath();
}
std::string DevToolsDelegate::GetPageThumbnailData(const GURL&) {
return std::string();
}
content::RenderViewHost* DevToolsDelegate::CreateNewTarget() {
return nullptr;
}
content::DevToolsHttpHandlerDelegate::TargetType DevToolsDelegate::GetTargetType(content::RenderViewHost*) {
return kTargetTypeTab;
}
}

View File

@@ -0,0 +1,28 @@
// Copyright (c) 2012 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 BRIGHTRAY_BROWSER_DEVTOOLS_DELEGATE_H_
#define BRIGHTRAY_BROWSER_DEVTOOLS_DELEGATE_H_
#include "content/public/browser/devtools_http_handler_delegate.h"
namespace brightray {
class DevToolsDelegate : public content::DevToolsHttpHandlerDelegate {
public:
DevToolsDelegate();
~DevToolsDelegate();
private:
virtual std::string GetDiscoveryPageHTML() OVERRIDE;
virtual bool BundlesFrontendResources() OVERRIDE;
virtual base::FilePath GetDebugFrontendDir() OVERRIDE;
virtual std::string GetPageThumbnailData(const GURL&) OVERRIDE;
virtual content::RenderViewHost* CreateNewTarget() OVERRIDE;
virtual TargetType GetTargetType(content::RenderViewHost*) OVERRIDE;
};
}
#endif

View File

@@ -0,0 +1,84 @@
// Copyright (c) 2012 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 "devtools_frontend.h"
#include "browser/browser_client.h"
#include "browser/browser_main_parts.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_client_host.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/web_contents.h"
namespace brightray {
content::WebContents* DevToolsFrontend::Show(content::WebContents* inspected_contents) {
// frontend will delete itself when the WebContents closes.
auto frontend = new DevToolsFrontend(inspected_contents);
return frontend->web_contents();
}
DevToolsFrontend::DevToolsFrontend(content::WebContents* inspected_contents)
: WebContentsObserver(content::WebContents::Create(content::WebContents::CreateParams(inspected_contents->GetBrowserContext()))),
agent_host_(content::DevToolsAgentHost::GetFor(inspected_contents->GetRenderViewHost())),
frontend_host_(content::DevToolsClientHost::CreateDevToolsFrontendHost(web_contents(), this)) {
auto client = static_cast<BrowserClient*>(content::GetContentClient()->browser());
auto handler = client->browser_main_parts()->devtools_http_handler();
auto url = handler->GetFrontendURL(nullptr);
web_contents()->GetController().LoadURL(url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
}
DevToolsFrontend::~DevToolsFrontend() {
}
void DevToolsFrontend::ActivateWindow() {
}
void DevToolsFrontend::ChangeAttachedWindowHeight(unsigned height) {
}
void DevToolsFrontend::CloseWindow() {
}
void DevToolsFrontend::MoveWindow(int x, int y) {
}
void DevToolsFrontend::SetDockSide(const std::string& side) {
}
void DevToolsFrontend::OpenInNewTab(const std::string& url) {
}
void DevToolsFrontend::SaveToFile(const std::string& url, const std::string& content, bool save_as) {
}
void DevToolsFrontend::AppendToFile(const std::string& url, const std::string& content) {
}
void DevToolsFrontend::RequestFileSystems() {
}
void DevToolsFrontend::AddFileSystem() {
}
void DevToolsFrontend::RemoveFileSystem(const std::string& file_system_path) {
}
void DevToolsFrontend::InspectedContentsClosing() {
}
void DevToolsFrontend::RenderViewCreated(content::RenderViewHost* render_view_host) {
content::DevToolsClientHost::SetupDevToolsFrontendClient(web_contents()->GetRenderViewHost());
content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(agent_host_, frontend_host_.get());
}
void DevToolsFrontend::WebContentsDestroyed(content::WebContents*) {
content::DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_.get());
delete this;
}
}

View File

@@ -0,0 +1,52 @@
// Copyright (c) 2012 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 BRIGHTRAY_BROWSER_DEVTOOLS_FRONTEND_H_
#define BRIGHTRAY_BROWSER_DEVTOOLS_FRONTEND_H_
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/devtools_frontend_host_delegate.h"
#include "content/public/browser/web_contents_observer.h"
namespace content {
class DevToolsAgentHost;
class DevToolsClientHost;
}
namespace brightray {
class DevToolsFrontend : content::DevToolsFrontendHostDelegate, content::WebContentsObserver {
public:
static content::WebContents* Show(content::WebContents* inspected_contents);
private:
DevToolsFrontend(content::WebContents* inspected_contents);
~DevToolsFrontend();
virtual void ActivateWindow() OVERRIDE;
virtual void ChangeAttachedWindowHeight(unsigned height) OVERRIDE;
virtual void CloseWindow() OVERRIDE;
virtual void MoveWindow(int x, int y) OVERRIDE;
virtual void SetDockSide(const std::string& side) OVERRIDE;
virtual void OpenInNewTab(const std::string& url) OVERRIDE;
virtual void SaveToFile(const std::string& url,
const std::string& content,
bool save_as) OVERRIDE;
virtual void AppendToFile(const std::string& url,
const std::string& content) OVERRIDE;
virtual void RequestFileSystems() OVERRIDE;
virtual void AddFileSystem() OVERRIDE;
virtual void RemoveFileSystem(const std::string& file_system_path) OVERRIDE;
virtual void InspectedContentsClosing() OVERRIDE;
virtual void RenderViewCreated(content::RenderViewHost*) OVERRIDE;
virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE;
scoped_refptr<content::DevToolsAgentHost> agent_host_;
scoped_ptr<content::DevToolsClientHost> frontend_host_;
};
}
#endif

View File

@@ -0,0 +1,11 @@
#include "browser/inspectable_web_contents.h"
#include "browser/inspectable_web_contents_impl.h"
namespace brightray {
InspectableWebContents* InspectableWebContents::Create(const content::WebContents::CreateParams& create_params) {
return new InspectableWebContentsImpl(create_params);
}
}

View File

@@ -0,0 +1,23 @@
#ifndef BRIGHTRAY_INSPECTABLE_WEB_CONTENTS_H_
#define BRIGHTRAY_INSPECTABLE_WEB_CONTENTS_H_
#include "content/public/browser/web_contents.h"
namespace brightray {
class InspectableWebContentsView;
class InspectableWebContents {
public:
static InspectableWebContents* Create(const content::WebContents::CreateParams&);
virtual ~InspectableWebContents() {}
virtual InspectableWebContentsView* GetView() const = 0;
virtual content::WebContents* GetWebContents() const = 0;
virtual void ShowDevTools() = 0;
};
}
#endif

View File

@@ -0,0 +1,33 @@
#include "browser/inspectable_web_contents_impl.h"
#include "browser/devtools_frontend.h"
#include "browser/inspectable_web_contents_view.h"
namespace brightray {
// Implemented separately on each platform.
InspectableWebContentsView* CreateInspectableContentsView(InspectableWebContentsImpl*);
InspectableWebContentsImpl::InspectableWebContentsImpl(const content::WebContents::CreateParams& create_params)
: web_contents_(content::WebContents::Create(create_params)) {
view_.reset(CreateInspectableContentsView(this));
}
InspectableWebContentsImpl::~InspectableWebContentsImpl() {
}
InspectableWebContentsView* InspectableWebContentsImpl::GetView() const {
return view_.get();
}
content::WebContents* InspectableWebContentsImpl::GetWebContents() const {
return web_contents_.get();
}
void InspectableWebContentsImpl::ShowDevTools() {
if (!devtools_web_contents_)
devtools_web_contents_.reset(DevToolsFrontend::Show(web_contents_.get()));
view_->ShowDevTools();
}
}

View File

@@ -0,0 +1,32 @@
#ifndef BRIGHTRAY_BROWSER_INSPECTABLE_WEB_CONTENTS_IMPL_H_
#define BRIGHTRAY_BROWSER_INSPECTABLE_WEB_CONTENTS_IMPL_H_
#include "browser/inspectable_web_contents.h"
namespace brightray {
class InspectableWebContentsView;
class InspectableWebContentsImpl : public InspectableWebContents {
public:
InspectableWebContentsImpl(const content::WebContents::CreateParams&);
virtual ~InspectableWebContentsImpl() OVERRIDE;
virtual InspectableWebContentsView* GetView() const OVERRIDE;
virtual content::WebContents* GetWebContents() const OVERRIDE;
virtual void ShowDevTools() OVERRIDE;
content::WebContents* devtools_web_contents() { return devtools_web_contents_.get(); }
private:
scoped_ptr<content::WebContents> web_contents_;
scoped_ptr<content::WebContents> devtools_web_contents_;
scoped_ptr<InspectableWebContentsView> view_;
DISALLOW_COPY_AND_ASSIGN(InspectableWebContentsImpl);
};
}
#endif

View File

@@ -0,0 +1,19 @@
#ifndef BRIGHTRAY_BROWSER_INSPECTABLE_WEB_CONTENTS_VIEW_H_
#define BRIGHTRAY_BROWSER_INSPECTABLE_WEB_CONTENTS_VIEW_H_
#include "ui/gfx/native_widget_types.h"
namespace brightray {
class InspectableWebContentsView {
public:
virtual ~InspectableWebContentsView() {}
virtual gfx::NativeView GetNativeView() const = 0;
virtual void ShowDevTools() = 0;
};
}
#endif

View File

@@ -0,0 +1,34 @@
#ifndef BRIGHTRAY_BROWSER_INSPECTABLE_WEB_CONTENTS_VIEW_MAC_H_
#define BRIGHTRAY_BROWSER_INSPECTABLE_WEB_CONTENTS_VIEW_MAC_H_
#import "browser/inspectable_web_contents_view.h"
#import "base/memory/scoped_nsobject.h"
@class BRYInspectableWebContentsView;
namespace brightray {
class InspectableWebContentsImpl;
class InspectableWebContentsViewMac : public InspectableWebContentsView {
public:
InspectableWebContentsViewMac(InspectableWebContentsImpl*);
virtual gfx::NativeView GetNativeView() const OVERRIDE;
virtual void ShowDevTools() OVERRIDE;
InspectableWebContentsImpl* inspectable_web_contents() { return inspectable_web_contents_; }
private:
// Owns us.
InspectableWebContentsImpl* inspectable_web_contents_;
scoped_nsobject<BRYInspectableWebContentsView> view_;
DISALLOW_COPY_AND_ASSIGN(InspectableWebContentsViewMac);
};
}
#endif

View File

@@ -0,0 +1,28 @@
#import "browser/inspectable_web_contents_view_mac.h"
#import "browser/inspectable_web_contents.h"
#import "browser/mac/bry_inspectable_web_contents_view_private.h"
#import "content/public/browser/web_contents_view.h"
#import <AppKit/AppKit.h>
namespace brightray {
InspectableWebContentsView* CreateInspectableContentsView(InspectableWebContentsImpl* inspectable_web_contents) {
return new InspectableWebContentsViewMac(inspectable_web_contents);
}
InspectableWebContentsViewMac::InspectableWebContentsViewMac(InspectableWebContentsImpl* inspectable_web_contents)
: inspectable_web_contents_(inspectable_web_contents),
view_([[BRYInspectableWebContentsView alloc] initWithInspectableWebContentsViewMac:this]) {
}
gfx::NativeView InspectableWebContentsViewMac::GetNativeView() const {
return view_.get();
}
void InspectableWebContentsViewMac::ShowDevTools() {
[view_ setDevToolsVisible:YES];
}
}

View File

@@ -0,0 +1,12 @@
#import <AppKit/AppKit.h>
@class BRYInspectableWebContentsViewPrivate;
@interface BRYInspectableWebContentsView : NSView {
@private
BRYInspectableWebContentsViewPrivate *_private;
}
- (IBAction)showDevTools:(id)sender;
@end

View File

@@ -0,0 +1,77 @@
#import "browser/mac/bry_inspectable_web_contents_view.h"
#import "browser/inspectable_web_contents_impl.h"
#import "browser/inspectable_web_contents_view_mac.h"
#import "browser/mac/bry_inspectable_web_contents_view_private.h"
#import "content/public/browser/web_contents_view.h"
using namespace brightray;
@interface BRYInspectableWebContentsViewPrivate : NSObject {
@public
InspectableWebContentsViewMac *inspectableWebContentsView;
NSSplitView *splitView;
}
@end
@implementation BRYInspectableWebContentsView
- (instancetype)initWithInspectableWebContentsViewMac:(InspectableWebContentsViewMac *)inspectableWebContentsView {
self = [super init];
if (!self)
return nil;
_private = [[BRYInspectableWebContentsViewPrivate alloc] init];
_private->inspectableWebContentsView = inspectableWebContentsView;
_private->splitView = [[NSSplitView alloc] init];
[self addSubview:_private->splitView];
_private->splitView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
_private->splitView.dividerStyle = NSSplitViewDividerStyleThin;
[_private->splitView addSubview:inspectableWebContentsView->inspectable_web_contents()->GetWebContents()->GetView()->GetNativeView()];
return self;
}
- (void)dealloc {
[_private release];
_private = nil;
[super dealloc];
}
- (IBAction)showDevTools:(id)sender {
_private->inspectableWebContentsView->inspectable_web_contents()->ShowDevTools();
}
- (void)setDevToolsVisible:(BOOL)visible {
BOOL wasVisible = _private->splitView.subviews.count == 2;
if (wasVisible == visible)
return;
auto devToolsWebContents = _private->inspectableWebContentsView->inspectable_web_contents()->devtools_web_contents();
auto devToolsView = devToolsWebContents->GetView()->GetNativeView();
if (visible) {
auto inspectedView = _private->inspectableWebContentsView->inspectable_web_contents()->GetWebContents()->GetView()->GetNativeView();
CGRect frame = NSRectToCGRect(inspectedView.frame);
CGRect inspectedViewFrame;
CGRect devToolsFrame;
CGRectDivide(frame, &inspectedViewFrame, &devToolsFrame, CGRectGetHeight(frame) * 2 / 3, CGRectMaxYEdge);
inspectedView.frame = NSRectFromCGRect(inspectedViewFrame);
devToolsView.frame = NSRectFromCGRect(devToolsFrame);
[_private->splitView addSubview:devToolsView];
} else {
[devToolsView removeFromSuperview];
}
[_private->splitView adjustSubviews];
}
@end
@implementation BRYInspectableWebContentsViewPrivate
@end

View File

@@ -0,0 +1,12 @@
#import "browser/mac/bry_inspectable_web_contents_view.h"
namespace brightray {
class InspectableWebContentsViewMac;
}
@interface BRYInspectableWebContentsView (Private)
- (instancetype)initWithInspectableWebContentsViewMac:(brightray::InspectableWebContentsViewMac *)inspectableWebContentsView;
- (void)setDevToolsVisible:(BOOL)visible;
@end