Commit 167c81a3 authored by pfeldman@chromium.org's avatar pfeldman@chromium.org

DevTools: Preserve devtools window contents on dock/undock.

Review URL: http://codereview.chromium.org/149199

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20016 0039d316-1c4b-4281-b951-d872f2087c98
parent 34f464fb
......@@ -128,7 +128,7 @@ void DevToolsManager::OpenDevToolsWindow(RenderViewHost* inspected_rvh) {
if (!host) {
bool docked = inspected_rvh->process()->profile()->GetPrefs()->
GetBoolean(prefs::kDevToolsOpenDocked);
host = DevToolsWindow::CreateDevToolsWindow(
host = new DevToolsWindow(
inspected_rvh->site_instance()->browsing_instance()->profile(),
inspected_rvh,
docked);
......@@ -277,11 +277,5 @@ void DevToolsManager::ReopenWindow(RenderViewHost* client_rvh, bool docked) {
DevToolsWindow* window = client_host->AsDevToolsWindow();
DCHECK(window);
if (window->is_docked() == docked) {
return;
}
SendDetachToAgent(inspected_rvh);
UnregisterDevToolsClientHostFor(inspected_rvh);
OpenDevToolsWindow(inspected_rvh);
window->SetDocked(docked);
}
......@@ -14,7 +14,6 @@
#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/common/bindings_policy.h"
......@@ -25,85 +24,13 @@
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
namespace {
class FloatingWindow : public DevToolsWindow,
TabStripModelObserver {
public:
FloatingWindow(Profile* profile);
virtual ~FloatingWindow();
virtual void Show();
virtual void Activate();
virtual void InspectedTabClosing();
// TabStripModelObserver implementation
virtual void TabClosingAt(TabContents* contents, int index);
virtual void TabStripEmpty();
private:
bool inspected_tab_closing_;
DISALLOW_COPY_AND_ASSIGN(FloatingWindow);
};
class DockedWindow : public DevToolsWindow,
TabContentsDelegate {
public:
DockedWindow(Profile* profile, BrowserWindow* window);
virtual ~DockedWindow();
virtual void Activate() {}
virtual void Show();
virtual void InspectedTabClosing();
private:
// Overridden from TabContentsDelegate:
virtual void OpenURLFromTab(TabContents* source,
const GURL& url,
const GURL& referrer,
WindowOpenDisposition disposition,
PageTransition::Type transition) {}
virtual void NavigationStateChanged(const TabContents* source,
unsigned changed_flags) {}
virtual void AddNewContents(TabContents* source,
TabContents* new_contents,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
bool user_gesture) {}
virtual void ActivateContents(TabContents* contents) {}
virtual void LoadingStateChanged(TabContents* source) {}
virtual void CloseContents(TabContents* source) {}
virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
virtual bool IsPopup(TabContents* source) { return false; }
virtual void URLStarredChanged(TabContents* source, bool starred) {}
virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
BrowserWindow* window_;
DISALLOW_COPY_AND_ASSIGN(DockedWindow);
};
} // namespace
// static
DevToolsWindow* DevToolsWindow::CreateDevToolsWindow(
Profile* profile,
RenderViewHost* inspected_rvh,
bool docked) {
if (docked) {
BrowserWindow* window = DevToolsWindow::GetBrowserWindow(inspected_rvh);
if (window) {
return new DockedWindow(profile, window);
}
}
return new FloatingWindow(profile);
}
// static
TabContents* DevToolsWindow::GetDevToolsContents(TabContents* inspected_tab) {
if (!inspected_tab) {
return NULL;
}
DevToolsClientHost* client_host =
DevToolsManager::GetInstance()->
DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
GetDevToolsClientHostFor(inspected_tab->render_view_host());
if (!client_host) {
return NULL;
......@@ -116,8 +43,33 @@ TabContents* DevToolsWindow::GetDevToolsContents(TabContents* inspected_tab) {
return window->tab_contents();
}
DevToolsWindow::DevToolsWindow(bool docked)
: docked_(docked) {
DevToolsWindow::DevToolsWindow(Profile* profile,
RenderViewHost* inspected_rvh,
bool docked)
: profile_(profile),
browser_(NULL),
inspected_window_(NULL),
docked_(docked) {
// Create TabContents with devtools.
tab_contents_ = new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL);
GURL url(std::string(chrome::kChromeUIDevToolsURL) + "devtools.html");
tab_contents_->render_view_host()->AllowBindings(BindingsPolicy::DOM_UI);
tab_contents_->controller().LoadURL(url, GURL(), PageTransition::START_PAGE);
// Wipe out page icon so that the default application icon is used.
NavigationEntry* entry = tab_contents_->controller().GetActiveEntry();
entry->favicon().set_bitmap(SkBitmap());
entry->favicon().set_is_valid(true);
// Register on-load actions.
registrar_.Add(this,
NotificationType::LOAD_STOP,
Source<NavigationController>(&tab_contents_->controller()));
registrar_.Add(this,
NotificationType::TAB_CLOSING,
Source<NavigationController>(&tab_contents_->controller()));
inspected_tab_ = inspected_rvh->delegate()->GetAsTabContents();
}
DevToolsWindow::~DevToolsWindow() {
......@@ -127,10 +79,6 @@ DevToolsWindow* DevToolsWindow::AsDevToolsWindow() {
return this;
}
RenderViewHost* DevToolsWindow::GetRenderViewHost() {
return tab_contents_->render_view_host();
}
void DevToolsWindow::SendMessageToClient(const IPC::Message& message) {
RenderViewHost* target_host = tab_contents_->render_view_host();
IPC::Message* m = new IPC::Message(message);
......@@ -138,47 +86,83 @@ void DevToolsWindow::SendMessageToClient(const IPC::Message& message) {
target_host->Send(m);
}
void DevToolsWindow::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
tab_contents_->render_view_host()->
ExecuteJavascriptInWebFrame(
L"", docked_ ? L"WebInspector.setAttachedWindow(true);" :
L"WebInspector.setAttachedWindow(false);");
}
void DevToolsWindow::InspectedTabClosing() {
if (docked_) {
// Update dev tools to reflect removed dev tools window.
inspected_window_->UpdateDevTools();
// In case of docked tab_contents we own it, so delete here.
GURL DevToolsWindow::GetContentsUrl() {
return GURL(std::string(chrome::kChromeUIDevToolsURL) + "devtools.html");
// Instead of deleting tab contents, we add it into the
// stub browser and initiate regular closure;
Browser* b = Browser::Create(profile_);
b->tabstrip_model()->AddTabContents(tab_contents_, -1, false,
PageTransition::START_PAGE, true);
b->CloseAllTabs();
delete this;
} else {
// First, initiate self-destruct to free all the registrars.
// Then close all tabs. Browser will take care of deleting tab_contents
// for us.
Browser* browser = browser_;
delete this;
browser->CloseAllTabs();
}
}
void DevToolsWindow::InitTabContents(TabContents* tab_contents) {
tab_contents_ = tab_contents;
registrar_.Add(this, NotificationType::LOAD_STOP,
Source<NavigationController>(&tab_contents_->controller()));
void DevToolsWindow::Show() {
if (docked_) {
// Just tell inspected browser to update splitter.
inspected_window_ = GetInspectedBrowserWindow();
if (inspected_window_) {
tab_contents_->set_delegate(this);
inspected_window_->UpdateDevTools();
tab_contents_->view()->SetInitialFocus();
return;
} else {
// Sometimes we don't know where to dock. Stay undocked.
docked_ = false;
}
}
if (!browser_) {
CreateDevToolsBrowser();
}
browser_->window()->Show();
tab_contents_->view()->SetInitialFocus();
}
// static
BrowserWindow* DevToolsWindow::GetBrowserWindow(RenderViewHost* rvh) {
for (BrowserList::const_iterator it = BrowserList::begin();
it != BrowserList::end(); ++it) {
Browser* browser = *it;
for (int i = 0; i < browser->tab_count(); ++i) {
TabContents* tab_contents = browser->GetTabContentsAt(i);
if (tab_contents->render_view_host() == rvh) {
return browser->window();
void DevToolsWindow::Activate() {
if (!docked_ && !browser_->window()->IsActive()) {
browser_->window()->Activate();
}
}
void DevToolsWindow::SetDocked(bool docked) {
if (docked_ == docked) {
return;
}
docked_ = docked;
if (docked) {
// Detach window from the external devtools browser. It will lead to
// the browser object's close and delete. Remove observer first.
TabStripModel* tabstrip_model = browser_->tabstrip_model();
tabstrip_model->DetachTabContentsAt(
tabstrip_model->GetIndexOfTabContents(tab_contents_));
browser_ = NULL;
} else {
// Update inspected window to hide split and reset it.
inspected_window_->UpdateDevTools();
inspected_window_ = NULL;
}
return NULL;
Show();
}
RenderViewHost* DevToolsWindow::GetRenderViewHost() {
return tab_contents_->render_view_host();
}
//
// Floating window implementation
//
FloatingWindow::FloatingWindow(Profile* profile)
: DevToolsWindow(false),
TabStripModelObserver(),
inspected_tab_closing_(false) {
void DevToolsWindow::CreateDevToolsBrowser() {
// TODO(pfeldman): Make browser's getter for this key static.
std::wstring wp_key = L"";
wp_key.append(prefs::kBrowserWindowPlacement);
......@@ -201,75 +185,42 @@ FloatingWindow::FloatingWindow(Profile* profile)
defaults->SetBoolean(L"always_on_top", false);
}
browser_ = Browser::CreateForApp(L"DevToolsApp", profile, false);
browser_->AddTabWithURL(GetContentsUrl(), GURL(), PageTransition::START_PAGE,
true, -1, false, NULL);
TabContents* tab_contents = browser_->GetSelectedTabContents();
browser_->tabstrip_model()->AddObserver(this);
// Wipe out page icon so that the default application icon is used.
NavigationEntry* entry = tab_contents->controller().GetActiveEntry();
entry->favicon().set_bitmap(SkBitmap());
entry->favicon().set_is_valid(true);
InitTabContents(tab_contents);
browser_ = Browser::CreateForApp(L"DevToolsApp", profile_, false);
browser_->tabstrip_model()->AddTabContents(
tab_contents_, -1, false, PageTransition::START_PAGE, true);
}
FloatingWindow::~FloatingWindow() {
}
void FloatingWindow::Activate() {
if (!browser_->window()->IsActive()) {
browser_->window()->Activate();
BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() {
for (BrowserList::const_iterator it = BrowserList::begin();
it != BrowserList::end(); ++it) {
Browser* browser = *it;
for (int i = 0; i < browser->tab_count(); ++i) {
TabContents* tab_contents = browser->GetTabContentsAt(i);
if (tab_contents == inspected_tab_) {
return browser->window();
}
}
void FloatingWindow::Show() {
browser_->window()->Show();
tab_contents_->view()->SetInitialFocus();
}
void FloatingWindow::InspectedTabClosing() {
inspected_tab_closing_ = true;
browser_->CloseAllTabs();
}
void FloatingWindow::TabClosingAt(TabContents* contents, int index) {
if (!inspected_tab_closing_ && contents == tab_contents_) {
// Notify manager that this DevToolsClientHost no longer exists.
NotifyCloseListener();
}
}
return NULL;
}
void FloatingWindow::TabStripEmpty() {
delete this;
}
//
// Docked window implementation
//
DockedWindow::DockedWindow(Profile* profile, BrowserWindow* window)
: DevToolsWindow(true),
window_(window) {
TabContents* tab_contents = new TabContents(profile,
NULL, MSG_ROUTING_NONE, NULL);
tab_contents->render_view_host()->AllowBindings(BindingsPolicy::DOM_UI);
tab_contents->controller().LoadURL(GetContentsUrl(), GURL(),
PageTransition::START_PAGE);
tab_contents->set_delegate(this);
browser_ = NULL;
InitTabContents(tab_contents);
}
DockedWindow::~DockedWindow() {
}
void DockedWindow::Show() {
window_->UpdateDevTools();
tab_contents_->view()->SetInitialFocus();
}
void DockedWindow::InspectedTabClosing() {
window_->UpdateDevTools();
void DevToolsWindow::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
if (type == NotificationType::LOAD_STOP) {
tab_contents_->render_view_host()->
ExecuteJavascriptInWebFrame(
L"", docked_ ? L"WebInspector.setAttachedWindow(true);" :
L"WebInspector.setAttachedWindow(false);");
} else if (type == NotificationType::TAB_CLOSING) {
if (Source<NavigationController>(source).ptr() ==
&tab_contents_->controller()) {
// This happens when browser closes all of its tabs as a result
// of window.Close event.
// Notify manager that this DevToolsClientHost no longer exists and
// initiate self-destuct here.
NotifyCloseListener();
delete this;
}
}
}
......@@ -8,7 +8,9 @@
#include <string>
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/debugger/devtools_client_host.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
......@@ -22,45 +24,68 @@ class Profile;
class RenderViewHost;
class TabContents;
class DevToolsWindow : public DevToolsClientHost, public NotificationObserver {
class DevToolsWindow :
public DevToolsClientHost,
public NotificationObserver,
TabContentsDelegate {
public:
static DevToolsWindow* CreateDevToolsWindow(Profile* profile,
RenderViewHost* inspected_rvh,
bool docked);
static TabContents* GetDevToolsContents(TabContents* inspected_tab);
DevToolsWindow(Profile* profile, RenderViewHost* inspected_rvh, bool docked);
virtual ~DevToolsWindow();
virtual void Show() = 0;
virtual void Activate() = 0;
bool is_docked() { return docked_; };
RenderViewHost* GetRenderViewHost();
// DevToolsClientHost override.
// Overridden from DevToolsClientHost.
virtual DevToolsWindow* AsDevToolsWindow();
virtual void SendMessageToClient(const IPC::Message& message);
virtual void InspectedTabClosing();
// NotificationObserver override.
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
void Show();
void Activate();
void SetDocked(bool docked);
RenderViewHost* GetRenderViewHost();
TabContents* tab_contents() { return tab_contents_; }
Browser* browser() { return browser_; }
Browser* browser() { return browser_; } // For tests.
bool is_docked() { return docked_; };
private:
void CreateDevToolsBrowser();
BrowserWindow* GetInspectedBrowserWindow();
protected:
DevToolsWindow(bool docked);
GURL GetContentsUrl();
void InitTabContents(TabContents* tab_contents);
// Overridden from NotificationObserver.
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
// Overridden from TabContentsDelegate.
virtual void OpenURLFromTab(TabContents* source,
const GURL& url,
const GURL& referrer,
WindowOpenDisposition disposition,
PageTransition::Type transition) {}
virtual void NavigationStateChanged(const TabContents* source,
unsigned changed_flags) {}
virtual void AddNewContents(TabContents* source,
TabContents* new_contents,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
bool user_gesture) {}
virtual void ActivateContents(TabContents* contents) {}
virtual void LoadingStateChanged(TabContents* source) {}
virtual void CloseContents(TabContents* source) {}
virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
virtual bool IsPopup(TabContents* source) { return false; }
virtual void URLStarredChanged(TabContents* source, bool starred) {}
virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
Profile* profile_;
TabContents* inspected_tab_;
TabContents* tab_contents_;
Browser* browser_;
private:
static BrowserWindow* GetBrowserWindow(RenderViewHost* rvh);
NotificationRegistrar registrar_;
BrowserWindow* inspected_window_;
bool docked_;
NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(DevToolsWindow);
};
......
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