Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: chrome/browser/debugger/devtools_window.cc

Issue 149199: DevTools: Preserve devtools window contents on dock/undock. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/debugger/devtools_window.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "app/l10n_util.h" 5 #include "app/l10n_util.h"
6 #include "base/command_line.h" 6 #include "base/command_line.h"
7 #include "chrome/browser/browser.h" 7 #include "chrome/browser/browser.h"
8 #include "chrome/browser/browser_list.h" 8 #include "chrome/browser/browser_list.h"
9 #include "chrome/browser/browser_process.h" 9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/browser_window.h" 10 #include "chrome/browser/browser_window.h"
11 #include "chrome/browser/debugger/devtools_manager.h" 11 #include "chrome/browser/debugger/devtools_manager.h"
12 #include "chrome/browser/debugger/devtools_window.h" 12 #include "chrome/browser/debugger/devtools_window.h"
13 #include "chrome/browser/profile.h" 13 #include "chrome/browser/profile.h"
14 #include "chrome/browser/tab_contents/navigation_controller.h" 14 #include "chrome/browser/tab_contents/navigation_controller.h"
15 #include "chrome/browser/tab_contents/navigation_entry.h" 15 #include "chrome/browser/tab_contents/navigation_entry.h"
16 #include "chrome/browser/tab_contents/tab_contents.h" 16 #include "chrome/browser/tab_contents/tab_contents.h"
17 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
18 #include "chrome/browser/tab_contents/tab_contents_view.h" 17 #include "chrome/browser/tab_contents/tab_contents_view.h"
19 #include "chrome/browser/tabs/tab_strip_model.h" 18 #include "chrome/browser/tabs/tab_strip_model.h"
20 #include "chrome/common/bindings_policy.h" 19 #include "chrome/common/bindings_policy.h"
21 #include "chrome/common/chrome_switches.h" 20 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h" 21 #include "chrome/common/pref_names.h"
23 #include "chrome/common/pref_service.h" 22 #include "chrome/common/pref_service.h"
24 #include "chrome/common/render_messages.h" 23 #include "chrome/common/render_messages.h"
25 #include "chrome/common/url_constants.h" 24 #include "chrome/common/url_constants.h"
26 #include "grit/generated_resources.h" 25 #include "grit/generated_resources.h"
27 26
28 namespace {
29
30 class FloatingWindow : public DevToolsWindow,
31 TabStripModelObserver {
32 public:
33 FloatingWindow(Profile* profile);
34 virtual ~FloatingWindow();
35 virtual void Show();
36 virtual void Activate();
37 virtual void InspectedTabClosing();
38
39 // TabStripModelObserver implementation
40 virtual void TabClosingAt(TabContents* contents, int index);
41 virtual void TabStripEmpty();
42
43 private:
44 bool inspected_tab_closing_;
45 DISALLOW_COPY_AND_ASSIGN(FloatingWindow);
46 };
47
48 class DockedWindow : public DevToolsWindow,
49 TabContentsDelegate {
50 public:
51 DockedWindow(Profile* profile, BrowserWindow* window);
52 virtual ~DockedWindow();
53 virtual void Activate() {}
54 virtual void Show();
55 virtual void InspectedTabClosing();
56
57 private:
58 // Overridden from TabContentsDelegate:
59 virtual void OpenURLFromTab(TabContents* source,
60 const GURL& url,
61 const GURL& referrer,
62 WindowOpenDisposition disposition,
63 PageTransition::Type transition) {}
64 virtual void NavigationStateChanged(const TabContents* source,
65 unsigned changed_flags) {}
66 virtual void AddNewContents(TabContents* source,
67 TabContents* new_contents,
68 WindowOpenDisposition disposition,
69 const gfx::Rect& initial_pos,
70 bool user_gesture) {}
71 virtual void ActivateContents(TabContents* contents) {}
72 virtual void LoadingStateChanged(TabContents* source) {}
73 virtual void CloseContents(TabContents* source) {}
74 virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
75 virtual bool IsPopup(TabContents* source) { return false; }
76 virtual void URLStarredChanged(TabContents* source, bool starred) {}
77 virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
78 virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
79
80 BrowserWindow* window_;
81 DISALLOW_COPY_AND_ASSIGN(DockedWindow);
82 };
83
84 } // namespace
85
86 // static
87 DevToolsWindow* DevToolsWindow::CreateDevToolsWindow(
88 Profile* profile,
89 RenderViewHost* inspected_rvh,
90 bool docked) {
91 if (docked) {
92 BrowserWindow* window = DevToolsWindow::GetBrowserWindow(inspected_rvh);
93 if (window) {
94 return new DockedWindow(profile, window);
95 }
96 }
97 return new FloatingWindow(profile);
98 }
99 27
100 // static 28 // static
101 TabContents* DevToolsWindow::GetDevToolsContents(TabContents* inspected_tab) { 29 TabContents* DevToolsWindow::GetDevToolsContents(TabContents* inspected_tab) {
102 if (!inspected_tab) { 30 if (!inspected_tab) {
103 return NULL; 31 return NULL;
104 } 32 }
105 DevToolsClientHost* client_host = 33 DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
106 DevToolsManager::GetInstance()->
107 GetDevToolsClientHostFor(inspected_tab->render_view_host()); 34 GetDevToolsClientHostFor(inspected_tab->render_view_host());
108 if (!client_host) { 35 if (!client_host) {
109 return NULL; 36 return NULL;
110 } 37 }
111 38
112 DevToolsWindow* window = client_host->AsDevToolsWindow(); 39 DevToolsWindow* window = client_host->AsDevToolsWindow();
113 if (!window || !window->is_docked()) { 40 if (!window || !window->is_docked()) {
114 return NULL; 41 return NULL;
115 } 42 }
116 return window->tab_contents(); 43 return window->tab_contents();
117 } 44 }
118 45
119 DevToolsWindow::DevToolsWindow(bool docked) 46 DevToolsWindow::DevToolsWindow(Profile* profile,
120 : docked_(docked) { 47 RenderViewHost* inspected_rvh,
48 bool docked)
49 : profile_(profile),
50 browser_(NULL),
51 inspected_window_(NULL),
52 docked_(docked) {
53 // Create TabContents with devtools.
54 tab_contents_ = new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL);
55 GURL url(std::string(chrome::kChromeUIDevToolsURL) + "devtools.html");
56 tab_contents_->render_view_host()->AllowBindings(BindingsPolicy::DOM_UI);
57 tab_contents_->controller().LoadURL(url, GURL(), PageTransition::START_PAGE);
58
59 // Wipe out page icon so that the default application icon is used.
60 NavigationEntry* entry = tab_contents_->controller().GetActiveEntry();
61 entry->favicon().set_bitmap(SkBitmap());
62 entry->favicon().set_is_valid(true);
63
64 // Register on-load actions.
65 registrar_.Add(this,
66 NotificationType::LOAD_STOP,
67 Source<NavigationController>(&tab_contents_->controller()));
68 registrar_.Add(this,
69 NotificationType::TAB_CLOSING,
70 Source<NavigationController>(&tab_contents_->controller()));
71
72 inspected_tab_ = inspected_rvh->delegate()->GetAsTabContents();
121 } 73 }
122 74
123 DevToolsWindow::~DevToolsWindow() { 75 DevToolsWindow::~DevToolsWindow() {
124 } 76 }
125 77
126 DevToolsWindow* DevToolsWindow::AsDevToolsWindow() { 78 DevToolsWindow* DevToolsWindow::AsDevToolsWindow() {
127 return this; 79 return this;
128 } 80 }
129 81
130 RenderViewHost* DevToolsWindow::GetRenderViewHost() {
131 return tab_contents_->render_view_host();
132 }
133
134 void DevToolsWindow::SendMessageToClient(const IPC::Message& message) { 82 void DevToolsWindow::SendMessageToClient(const IPC::Message& message) {
135 RenderViewHost* target_host = tab_contents_->render_view_host(); 83 RenderViewHost* target_host = tab_contents_->render_view_host();
136 IPC::Message* m = new IPC::Message(message); 84 IPC::Message* m = new IPC::Message(message);
137 m->set_routing_id(target_host->routing_id()); 85 m->set_routing_id(target_host->routing_id());
138 target_host->Send(m); 86 target_host->Send(m);
139 } 87 }
140 88
141 void DevToolsWindow::Observe(NotificationType type, 89 void DevToolsWindow::InspectedTabClosing() {
142 const NotificationSource& source, 90 if (docked_) {
143 const NotificationDetails& details) { 91 // Update dev tools to reflect removed dev tools window.
144 tab_contents_->render_view_host()-> 92 inspected_window_->UpdateDevTools();
145 ExecuteJavascriptInWebFrame( 93 // In case of docked tab_contents we own it, so delete here.
146 L"", docked_ ? L"WebInspector.setAttachedWindow(true);" : 94
147 L"WebInspector.setAttachedWindow(false);"); 95 // Instead of deleting tab contents, we add it into the
96 // stub browser and initiate regular closure;
97 Browser* b = Browser::Create(profile_);
98 b->tabstrip_model()->AddTabContents(tab_contents_, -1, false,
99 PageTransition::START_PAGE, true);
100 b->CloseAllTabs();
101 delete this;
102 } else {
103 // First, initiate self-destruct to free all the registrars.
104 // Then close all tabs. Browser will take care of deleting tab_contents
105 // for us.
106 Browser* browser = browser_;
107 delete this;
108 browser->CloseAllTabs();
109 }
148 } 110 }
149 111
150 GURL DevToolsWindow::GetContentsUrl() { 112 void DevToolsWindow::Show() {
151 return GURL(std::string(chrome::kChromeUIDevToolsURL) + "devtools.html"); 113 if (docked_) {
114 // Just tell inspected browser to update splitter.
115 inspected_window_ = GetInspectedBrowserWindow();
116 if (inspected_window_) {
117 tab_contents_->set_delegate(this);
118 inspected_window_->UpdateDevTools();
119 tab_contents_->view()->SetInitialFocus();
120 return;
121 } else {
122 // Sometimes we don't know where to dock. Stay undocked.
123 docked_ = false;
124 }
125 }
126
127 if (!browser_) {
128 CreateDevToolsBrowser();
129 }
130 browser_->window()->Show();
131 tab_contents_->view()->SetInitialFocus();
152 } 132 }
153 133
154 void DevToolsWindow::InitTabContents(TabContents* tab_contents) { 134 void DevToolsWindow::Activate() {
155 tab_contents_ = tab_contents; 135 if (!docked_ && !browser_->window()->IsActive()) {
156 registrar_.Add(this, NotificationType::LOAD_STOP, 136 browser_->window()->Activate();
157 Source<NavigationController>(&tab_contents_->controller())); 137 }
158 } 138 }
159 139
160 // static 140 void DevToolsWindow::SetDocked(bool docked) {
161 BrowserWindow* DevToolsWindow::GetBrowserWindow(RenderViewHost* rvh) { 141 if (docked_ == docked) {
162 for (BrowserList::const_iterator it = BrowserList::begin(); 142 return;
163 it != BrowserList::end(); ++it) {
164 Browser* browser = *it;
165 for (int i = 0; i < browser->tab_count(); ++i) {
166 TabContents* tab_contents = browser->GetTabContentsAt(i);
167 if (tab_contents->render_view_host() == rvh) {
168 return browser->window();
169 }
170 }
171 } 143 }
172 return NULL; 144 docked_ = docked;
145
146 if (docked) {
147 // Detach window from the external devtools browser. It will lead to
148 // the browser object's close and delete. Remove observer first.
149 TabStripModel* tabstrip_model = browser_->tabstrip_model();
150 tabstrip_model->DetachTabContentsAt(
151 tabstrip_model->GetIndexOfTabContents(tab_contents_));
152 browser_ = NULL;
153 } else {
154 // Update inspected window to hide split and reset it.
155 inspected_window_->UpdateDevTools();
156 inspected_window_ = NULL;
157 }
158 Show();
173 } 159 }
174 160
175 // 161 RenderViewHost* DevToolsWindow::GetRenderViewHost() {
176 // Floating window implementation 162 return tab_contents_->render_view_host();
177 // 163 }
178 FloatingWindow::FloatingWindow(Profile* profile) 164
179 : DevToolsWindow(false), 165 void DevToolsWindow::CreateDevToolsBrowser() {
180 TabStripModelObserver(),
181 inspected_tab_closing_(false) {
182 // TODO(pfeldman): Make browser's getter for this key static. 166 // TODO(pfeldman): Make browser's getter for this key static.
183 std::wstring wp_key = L""; 167 std::wstring wp_key = L"";
184 wp_key.append(prefs::kBrowserWindowPlacement); 168 wp_key.append(prefs::kBrowserWindowPlacement);
185 wp_key.append(L"_"); 169 wp_key.append(L"_");
186 wp_key.append(L"DevToolsApp"); 170 wp_key.append(L"DevToolsApp");
187 171
188 PrefService* prefs = g_browser_process->local_state(); 172 PrefService* prefs = g_browser_process->local_state();
189 if (!prefs->FindPreference(wp_key.c_str())) { 173 if (!prefs->FindPreference(wp_key.c_str())) {
190 prefs->RegisterDictionaryPref(wp_key.c_str()); 174 prefs->RegisterDictionaryPref(wp_key.c_str());
191 } 175 }
192 176
193 const DictionaryValue* wp_pref = prefs->GetDictionary(wp_key.c_str()); 177 const DictionaryValue* wp_pref = prefs->GetDictionary(wp_key.c_str());
194 if (!wp_pref) { 178 if (!wp_pref) {
195 DictionaryValue* defaults = prefs->GetMutableDictionary(wp_key.c_str()); 179 DictionaryValue* defaults = prefs->GetMutableDictionary(wp_key.c_str());
196 defaults->SetInteger(L"left", 100); 180 defaults->SetInteger(L"left", 100);
197 defaults->SetInteger(L"top", 100); 181 defaults->SetInteger(L"top", 100);
198 defaults->SetInteger(L"right", 740); 182 defaults->SetInteger(L"right", 740);
199 defaults->SetInteger(L"bottom", 740); 183 defaults->SetInteger(L"bottom", 740);
200 defaults->SetBoolean(L"maximized", false); 184 defaults->SetBoolean(L"maximized", false);
201 defaults->SetBoolean(L"always_on_top", false); 185 defaults->SetBoolean(L"always_on_top", false);
202 } 186 }
203 187
204 browser_ = Browser::CreateForApp(L"DevToolsApp", profile, false); 188 browser_ = Browser::CreateForApp(L"DevToolsApp", profile_, false);
205 browser_->AddTabWithURL(GetContentsUrl(), GURL(), PageTransition::START_PAGE, 189 browser_->tabstrip_model()->AddTabContents(
206 true, -1, false, NULL); 190 tab_contents_, -1, false, PageTransition::START_PAGE, true);
207 TabContents* tab_contents = browser_->GetSelectedTabContents();
208 browser_->tabstrip_model()->AddObserver(this);
209
210 // Wipe out page icon so that the default application icon is used.
211 NavigationEntry* entry = tab_contents->controller().GetActiveEntry();
212 entry->favicon().set_bitmap(SkBitmap());
213 entry->favicon().set_is_valid(true);
214
215 InitTabContents(tab_contents);
216 } 191 }
217 192
218 FloatingWindow::~FloatingWindow() { 193 BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() {
194 for (BrowserList::const_iterator it = BrowserList::begin();
195 it != BrowserList::end(); ++it) {
196 Browser* browser = *it;
197 for (int i = 0; i < browser->tab_count(); ++i) {
198 TabContents* tab_contents = browser->GetTabContentsAt(i);
199 if (tab_contents == inspected_tab_) {
200 return browser->window();
201 }
202 }
203 }
204 return NULL;
219 } 205 }
220 206
221 void FloatingWindow::Activate() { 207 void DevToolsWindow::Observe(NotificationType type,
222 if (!browser_->window()->IsActive()) { 208 const NotificationSource& source,
223 browser_->window()->Activate(); 209 const NotificationDetails& details) {
210 if (type == NotificationType::LOAD_STOP) {
211 tab_contents_->render_view_host()->
212 ExecuteJavascriptInWebFrame(
213 L"", docked_ ? L"WebInspector.setAttachedWindow(true);" :
214 L"WebInspector.setAttachedWindow(false);");
215 } else if (type == NotificationType::TAB_CLOSING) {
216 if (Source<NavigationController>(source).ptr() ==
217 &tab_contents_->controller()) {
218 // This happens when browser closes all of its tabs as a result
219 // of window.Close event.
220 // Notify manager that this DevToolsClientHost no longer exists and
221 // initiate self-destuct here.
222 NotifyCloseListener();
223 delete this;
224 }
224 } 225 }
225 } 226 }
226
227 void FloatingWindow::Show() {
228 browser_->window()->Show();
229 tab_contents_->view()->SetInitialFocus();
230 }
231
232 void FloatingWindow::InspectedTabClosing() {
233 inspected_tab_closing_ = true;
234 browser_->CloseAllTabs();
235 }
236
237 void FloatingWindow::TabClosingAt(TabContents* contents, int index) {
238 if (!inspected_tab_closing_ && contents == tab_contents_) {
239 // Notify manager that this DevToolsClientHost no longer exists.
240 NotifyCloseListener();
241 }
242 }
243
244 void FloatingWindow::TabStripEmpty() {
245 delete this;
246 }
247
248 //
249 // Docked window implementation
250 //
251 DockedWindow::DockedWindow(Profile* profile, BrowserWindow* window)
252 : DevToolsWindow(true),
253 window_(window) {
254 TabContents* tab_contents = new TabContents(profile,
255 NULL, MSG_ROUTING_NONE, NULL);
256 tab_contents->render_view_host()->AllowBindings(BindingsPolicy::DOM_UI);
257 tab_contents->controller().LoadURL(GetContentsUrl(), GURL(),
258 PageTransition::START_PAGE);
259 tab_contents->set_delegate(this);
260 browser_ = NULL;
261 InitTabContents(tab_contents);
262 }
263
264 DockedWindow::~DockedWindow() {
265 }
266
267 void DockedWindow::Show() {
268 window_->UpdateDevTools();
269 tab_contents_->view()->SetInitialFocus();
270 }
271
272 void DockedWindow::InspectedTabClosing() {
273 window_->UpdateDevTools();
274 delete this;
275 }
OLDNEW
« no previous file with comments | « chrome/browser/debugger/devtools_window.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698