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

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

Issue 19820004: Per the Chromium style guide/dos-and-donts doc, don't inline non-"cheap (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/devtools/devtools_window.h" 5 #include "chrome/browser/devtools/devtools_window.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 const char kDockSideUndocked[] = "undocked"; 96 const char kDockSideUndocked[] = "undocked";
97 const char kDockSideMinimized[] = "minimized"; 97 const char kDockSideMinimized[] = "minimized";
98 98
99 // Minimal height of devtools pane or content pane when devtools are docked 99 // Minimal height of devtools pane or content pane when devtools are docked
100 // to the browser window. 100 // to the browser window.
101 const int kMinDevToolsHeight = 50; 101 const int kMinDevToolsHeight = 50;
102 const int kMinDevToolsWidth = 150; 102 const int kMinDevToolsWidth = 150;
103 const int kMinContentsSize = 50; 103 const int kMinContentsSize = 50;
104 const int kMinimizedDevToolsHeight = 24; 104 const int kMinimizedDevToolsHeight = 24;
105 105
106 class DevToolsWindow::InspectedWebContentsObserver
107 : public content::WebContentsObserver {
108 public:
109 explicit InspectedWebContentsObserver(content::WebContents* web_contents)
110 : WebContentsObserver(web_contents) {
111 }
112 106
113 content::WebContents* Get() { return web_contents(); } 107 // DevToolsConfirmInfoBarDelegate ---------------------------------------------
114 };
115
116 class DevToolsWindow::FrontendWebContentsObserver
117 : public content::WebContentsObserver {
118 public:
119 explicit FrontendWebContentsObserver(content::WebContents* web_contents)
120 : WebContentsObserver(web_contents) {
121 }
122 private:
123 // Overriden from contents::WebContentsObserver.
124 virtual void AboutToNavigateRenderView(
125 RenderViewHost* render_view_host) OVERRIDE {
126 content::DevToolsClientHost::SetupDevToolsFrontendClient(render_view_host);
127 }
128 };
129 108
130 typedef Callback<void(bool)> ConfirmInfoBarCallback; 109 typedef Callback<void(bool)> ConfirmInfoBarCallback;
131 110
132 class DevToolsConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { 111 class DevToolsConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
133 public: 112 public:
134 DevToolsConfirmInfoBarDelegate( 113 DevToolsConfirmInfoBarDelegate(InfoBarService* infobar_service,
135 InfoBarService* infobar_service, 114 const ConfirmInfoBarCallback& callback,
136 const ConfirmInfoBarCallback& callback, 115 string16 message);
137 string16 message)
138 : ConfirmInfoBarDelegate(infobar_service),
139 callback_(callback),
140 message_(message) {
141 }
142 116
143 virtual string16 GetMessageText() const OVERRIDE { return message_; } 117 virtual string16 GetMessageText() const OVERRIDE;
144 118 virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
145 virtual bool Accept() OVERRIDE { 119 virtual bool Accept() OVERRIDE;
146 callback_.Run(true); 120 virtual bool Cancel() OVERRIDE;
147 callback_.Reset();
148 return true;
149 }
150
151 virtual bool Cancel() OVERRIDE {
152 callback_.Run(false);
153 callback_.Reset();
154 return true;
155 }
156
157 virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE {
158 return l10n_util::GetStringUTF16((button == BUTTON_OK)
159 ? IDS_DEV_TOOLS_CONFIRM_ALLOW_BUTTON
160 : IDS_DEV_TOOLS_CONFIRM_DENY_BUTTON);
161 }
162 121
163 private: 122 private:
164 virtual ~DevToolsConfirmInfoBarDelegate() { 123 virtual ~DevToolsConfirmInfoBarDelegate();
165 if (!callback_.is_null()) {
166 callback_.Run(false);
167 }
168 }
169 124
170 ConfirmInfoBarCallback callback_; 125 ConfirmInfoBarCallback callback_;
171 string16 message_; 126 string16 message_;
172 }; 127 };
173 128
129 DevToolsConfirmInfoBarDelegate::DevToolsConfirmInfoBarDelegate(
130 InfoBarService* infobar_service,
131 const ConfirmInfoBarCallback& callback,
132 string16 message)
133 : ConfirmInfoBarDelegate(infobar_service),
134 callback_(callback),
135 message_(message) {
136 }
137
138 string16 DevToolsConfirmInfoBarDelegate::GetMessageText() const {
139 return message_;
140 }
141
142 string16 DevToolsConfirmInfoBarDelegate::GetButtonLabel(
143 InfoBarButton button) const {
144 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
145 IDS_DEV_TOOLS_CONFIRM_ALLOW_BUTTON : IDS_DEV_TOOLS_CONFIRM_DENY_BUTTON);
146 }
147
148 bool DevToolsConfirmInfoBarDelegate::Accept() {
149 callback_.Run(true);
150 callback_.Reset();
151 return true;
152 }
153
154 bool DevToolsConfirmInfoBarDelegate::Cancel() {
155 callback_.Run(false);
156 callback_.Reset();
157 return true;
158 }
159
160 DevToolsConfirmInfoBarDelegate::~DevToolsConfirmInfoBarDelegate() {
161 if (!callback_.is_null()) {
162 callback_.Run(false);
163 }
164 }
165
166
167 // DevToolsWindow::InspectedWebContentsObserver -------------------------------
168
169 class DevToolsWindow::InspectedWebContentsObserver
170 : public content::WebContentsObserver {
171 public:
172 explicit InspectedWebContentsObserver(content::WebContents* web_contents);
173
174 content::WebContents* web_contents() {
175 return WebContentsObserver::web_contents();
176 }
177 };
178
179 DevToolsWindow::InspectedWebContentsObserver::InspectedWebContentsObserver(
180 content::WebContents* web_contents)
181 : WebContentsObserver(web_contents) {
182 }
183
184
185 // DevToolsWindow::FrontendWebContentsObserver --------------------------------
186
187 class DevToolsWindow::FrontendWebContentsObserver
188 : public content::WebContentsObserver {
189 public:
190 explicit FrontendWebContentsObserver(content::WebContents* web_contents);
191
192 private:
193 // Overriden from contents::WebContentsObserver.
194 virtual void AboutToNavigateRenderView(
195 RenderViewHost* render_view_host) OVERRIDE;
196 };
197
198 DevToolsWindow::FrontendWebContentsObserver::FrontendWebContentsObserver(
199 content::WebContents* web_contents)
200 : WebContentsObserver(web_contents) {
201 }
202
203 void DevToolsWindow::FrontendWebContentsObserver::AboutToNavigateRenderView(
204 content::RenderViewHost* render_view_host) {
205 content::DevToolsClientHost::SetupDevToolsFrontendClient(render_view_host);
206 }
207
208
209 // DevToolsWindow -------------------------------------------------------------
210
211 namespace {
212
213 std::string SkColorToRGBAString(SkColor color) {
214 // We convert the alpha using DoubleToString because StringPrintf will use
215 // locale specific formatters (e.g., use , instead of . in German).
216 return base::StringPrintf("rgba(%d,%d,%d,%s)", SkColorGetR(color),
217 SkColorGetG(color), SkColorGetB(color),
218 base::DoubleToString(SkColorGetA(color) / 255.0).c_str());
219 }
220
221 DictionaryValue* CreateFileSystemValue(
222 DevToolsFileHelper::FileSystem file_system) {
223 DictionaryValue* file_system_value = new DictionaryValue();
224 file_system_value->SetString("fileSystemName", file_system.file_system_name);
225 file_system_value->SetString("rootURL", file_system.root_url);
226 file_system_value->SetString("fileSystemPath", file_system.file_system_path);
227 return file_system_value;
228 }
229
230 } // namespace
231
232 DevToolsWindow::~DevToolsWindow() {
233 DevToolsWindowList& instances = g_instances.Get();
234 DevToolsWindowList::iterator it = std::find(instances.begin(),
235 instances.end(),
236 this);
237 DCHECK(it != instances.end());
238 instances.erase(it);
239 }
240
174 // static 241 // static
175 std::string DevToolsWindow::GetDevToolsWindowPlacementPrefKey() { 242 std::string DevToolsWindow::GetDevToolsWindowPlacementPrefKey() {
176 std::string wp_key; 243 std::string wp_key;
177 wp_key.append(prefs::kBrowserWindowPlacement); 244 wp_key.append(prefs::kBrowserWindowPlacement);
178 wp_key.append("_"); 245 wp_key.append("_");
179 wp_key.append(kDevToolsApp); 246 wp_key.append(kDevToolsApp);
180 return wp_key; 247 return wp_key;
181 } 248 }
182 249
183 // static 250 // static
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 } 332 }
266 RenderViewHost* inspected_rvh = 333 RenderViewHost* inspected_rvh =
267 browser->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(); 334 browser->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost();
268 335
269 return ToggleDevToolsWindow(inspected_rvh, 336 return ToggleDevToolsWindow(inspected_rvh,
270 action == DEVTOOLS_TOGGLE_ACTION_INSPECT, 337 action == DEVTOOLS_TOGGLE_ACTION_INSPECT,
271 action); 338 action);
272 } 339 }
273 340
274 // static 341 // static
275 void DevToolsWindow::InspectElement(RenderViewHost* inspected_rvh,
276 int x,
277 int y) {
278 scoped_refptr<DevToolsAgentHost> agent(
279 DevToolsAgentHost::GetOrCreateFor(inspected_rvh));
280 agent->InspectElement(x, y);
281 // TODO(loislo): we should initiate DevTools window opening from within
282 // renderer. Otherwise, we still can hit a race condition here.
283 OpenDevToolsWindow(inspected_rvh);
284 }
285
286 // static
287 void DevToolsWindow::OpenExternalFrontend( 342 void DevToolsWindow::OpenExternalFrontend(
288 Profile* profile, 343 Profile* profile,
289 const std::string& frontend_url, 344 const std::string& frontend_url,
290 content::DevToolsAgentHost* agent_host) { 345 content::DevToolsAgentHost* agent_host) {
291 DevToolsWindow* window = FindDevToolsWindow(agent_host); 346 DevToolsWindow* window = FindDevToolsWindow(agent_host);
292 if (!window) { 347 if (!window) {
293 window = Create(profile, DevToolsUI::GetProxyURL(frontend_url), NULL, 348 window = Create(profile, DevToolsUI::GetProxyURL(frontend_url), NULL,
294 DEVTOOLS_DOCK_SIDE_UNDOCKED, false); 349 DEVTOOLS_DOCK_SIDE_UNDOCKED, false);
295 DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( 350 DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
296 agent_host, window->frontend_host_.get()); 351 agent_host, window->frontend_host_.get());
297 } 352 }
298 window->Show(DEVTOOLS_TOGGLE_ACTION_SHOW); 353 window->Show(DEVTOOLS_TOGGLE_ACTION_SHOW);
299 } 354 }
300 355
301 // static 356 // static
302 DevToolsWindow* DevToolsWindow::Create( 357 DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow(
303 Profile* profile,
304 const GURL& frontend_url,
305 RenderViewHost* inspected_rvh, 358 RenderViewHost* inspected_rvh,
306 DevToolsDockSide dock_side, 359 bool force_open,
307 bool shared_worker_frontend) { 360 DevToolsToggleAction action) {
308 // Create WebContents with devtools. 361 scoped_refptr<DevToolsAgentHost> agent(
309 GURL url = GetDevToolsURL(profile, frontend_url, dock_side, 362 DevToolsAgentHost::GetOrCreateFor(inspected_rvh));
310 shared_worker_frontend); 363 DevToolsManager* manager = DevToolsManager::GetInstance();
311 return new DevToolsWindow(profile, url, inspected_rvh, dock_side); 364 DevToolsWindow* window = FindDevToolsWindow(agent.get());
365 bool do_open = force_open;
366 if (!window) {
367 Profile* profile = Profile::FromBrowserContext(
368 inspected_rvh->GetProcess()->GetBrowserContext());
369 DevToolsDockSide dock_side = GetDockSideFromPrefs(profile);
370 window = Create(profile, GURL(), inspected_rvh, dock_side, false);
371 manager->RegisterDevToolsClientHostFor(agent.get(),
372 window->frontend_host_.get());
373 do_open = true;
374 }
375
376 // Update toolbar to reflect DevTools changes.
377 window->UpdateBrowserToolbar();
378
379 // If window is docked and visible, we hide it on toggle. If window is
380 // undocked, we show (activate) it. If window is minimized, we maximize it.
381 if (window->dock_side_ == DEVTOOLS_DOCK_SIDE_MINIMIZED)
382 window->Restore();
383 else if (!window->IsDocked() || do_open)
384 window->Show(action);
385 else
386 window->CloseWindow();
387
388 return window;
312 } 389 }
313 390
314 DevToolsWindow::DevToolsWindow(Profile* profile, 391 // static
315 const GURL& url, 392 void DevToolsWindow::InspectElement(RenderViewHost* inspected_rvh,
316 RenderViewHost* inspected_rvh, 393 int x,
317 DevToolsDockSide dock_side) 394 int y) {
318 : profile_(profile), 395 scoped_refptr<DevToolsAgentHost> agent(
319 browser_(NULL), 396 DevToolsAgentHost::GetOrCreateFor(inspected_rvh));
320 dock_side_(dock_side), 397 agent->InspectElement(x, y);
321 is_loaded_(false), 398 // TODO(loislo): we should initiate DevTools window opening from within
322 action_on_load_(DEVTOOLS_TOGGLE_ACTION_SHOW), 399 // renderer. Otherwise, we still can hit a race condition here.
323 weak_factory_(this), 400 OpenDevToolsWindow(inspected_rvh);
324 width_(-1),
325 height_(-1),
326 dock_side_before_minimized_(dock_side) {
327 web_contents_ = WebContents::Create(WebContents::CreateParams(profile));
328 frontend_contents_observer_.reset(
329 new FrontendWebContentsObserver(web_contents_));
330
331 web_contents_->GetController().LoadURL(url, content::Referrer(),
332 content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
333
334 frontend_host_.reset(
335 DevToolsClientHost::CreateDevToolsFrontendHost(web_contents_, this));
336 file_helper_.reset(new DevToolsFileHelper(web_contents_, profile));
337
338 g_instances.Get().push_back(this);
339 // Wipe out page icon so that the default application icon is used.
340 NavigationEntry* entry = web_contents_->GetController().GetActiveEntry();
341 entry->GetFavicon().image = gfx::Image();
342 entry->GetFavicon().valid = true;
343
344 // Register on-load actions.
345 registrar_.Add(
346 this,
347 content::NOTIFICATION_LOAD_STOP,
348 content::Source<NavigationController>(&web_contents_->GetController()));
349 registrar_.Add(
350 this,
351 chrome::NOTIFICATION_TAB_CLOSING,
352 content::Source<NavigationController>(&web_contents_->GetController()));
353 registrar_.Add(
354 this,
355 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
356 content::Source<ThemeService>(
357 ThemeServiceFactory::GetForProfile(profile_)));
358 // There is no inspected_rvh in case of shared workers.
359 if (inspected_rvh)
360 inspected_contents_observer_.reset(new InspectedWebContentsObserver(
361 WebContents::FromRenderViewHost(inspected_rvh)));
362 } 401 }
363 402
364 DevToolsWindow::~DevToolsWindow() { 403 // static
365 DevToolsWindowList& instances = g_instances.Get(); 404 int DevToolsWindow::GetMinimumWidth() {
366 DevToolsWindowList::iterator it = std::find(instances.begin(), 405 return kMinDevToolsWidth;
367 instances.end(),
368 this);
369 DCHECK(it != instances.end());
370 instances.erase(it);
371 } 406 }
372 407
373 content::WebContents* DevToolsWindow::GetInspectedWebContents() { 408 // static
374 if (!inspected_contents_observer_) 409 int DevToolsWindow::GetMinimumHeight() {
375 return NULL; 410 return kMinDevToolsHeight;
376 return inspected_contents_observer_->Get(); 411 }
412
413 // static
414 int DevToolsWindow::GetMinimizedHeight() {
415 return kMinimizedDevToolsHeight;
377 } 416 }
378 417
379 void DevToolsWindow::InspectedContentsClosing() { 418 void DevToolsWindow::InspectedContentsClosing() {
380 Hide(); 419 Hide();
381 } 420 }
382 421
383 void DevToolsWindow::Hide() { 422 RenderViewHost* DevToolsWindow::GetRenderViewHost() {
384 if (IsDocked()) { 423 return web_contents_->GetRenderViewHost();
385 // Update dev tools to reflect removed dev tools window.
386 BrowserWindow* inspected_window = GetInspectedBrowserWindow();
387 if (inspected_window)
388 inspected_window->UpdateDevTools();
389 // In case of docked web_contents_, we own it so delete here.
390 delete web_contents_;
391
392 delete this;
393 } else {
394 // First, initiate self-destruct to free all the registrars.
395 // Then close all tabs. Browser will take care of deleting web_contents_
396 // for us.
397 Browser* browser = browser_;
398 delete this;
399 browser->tab_strip_model()->CloseAllTabs();
400 }
401 }
402
403 void DevToolsWindow::Show(DevToolsToggleAction action) {
404 if (IsDocked()) {
405 Browser* inspected_browser;
406 int inspected_tab_index;
407 // Tell inspected browser to update splitter and switch to inspected panel.
408 if (!IsInspectedBrowserPopup() &&
409 FindInspectedBrowserAndTabIndex(&inspected_browser,
410 &inspected_tab_index)) {
411 BrowserWindow* inspected_window = inspected_browser->window();
412 web_contents_->SetDelegate(this);
413 inspected_window->UpdateDevTools();
414 web_contents_->GetView()->SetInitialFocus();
415 inspected_window->Show();
416 TabStripModel* tab_strip_model = inspected_browser->tab_strip_model();
417 tab_strip_model->ActivateTabAt(inspected_tab_index, true);
418 PrefsTabHelper::CreateForWebContents(web_contents_);
419 GetRenderViewHost()->SyncRendererPrefs();
420 ScheduleAction(action);
421 return;
422 } else {
423 // Sometimes we don't know where to dock. Stay undocked.
424 dock_side_ = DEVTOOLS_DOCK_SIDE_UNDOCKED;
425 }
426 }
427
428 // Avoid consecutive window switching if the devtools window has been opened
429 // and the Inspect Element shortcut is pressed in the inspected tab.
430 bool should_show_window =
431 !browser_ || action != DEVTOOLS_TOGGLE_ACTION_INSPECT;
432
433 if (!browser_)
434 CreateDevToolsBrowser();
435
436 if (should_show_window) {
437 browser_->window()->Show();
438 web_contents_->GetView()->SetInitialFocus();
439 }
440
441 ScheduleAction(action);
442 } 424 }
443 425
444 DevToolsClientHost* DevToolsWindow::GetDevToolsClientHostForTest() { 426 DevToolsClientHost* DevToolsWindow::GetDevToolsClientHostForTest() {
445 return frontend_host_.get(); 427 return frontend_host_.get();
446 } 428 }
447 429
448 int DevToolsWindow::GetWidth(int container_width) { 430 int DevToolsWindow::GetWidth(int container_width) {
449 if (width_ == -1) { 431 if (width_ == -1) {
450 width_ = profile_->GetPrefs()-> 432 width_ = profile_->GetPrefs()->
451 GetInteger(prefs::kDevToolsVSplitLocation); 433 GetInteger(prefs::kDevToolsVSplitLocation);
(...skipping 23 matching lines...) Expand all
475 height_ = container_height / 3; 457 height_ = container_height / 3;
476 458
477 // Respect the minimum devtools width preset. 459 // Respect the minimum devtools width preset.
478 height_ = std::max(kMinDevToolsHeight, height_); 460 height_ = std::max(kMinDevToolsHeight, height_);
479 461
480 // But it should never compromise the content window size. 462 // But it should never compromise the content window size.
481 height_ = std::min(container_height - kMinContentsSize, height_); 463 height_ = std::min(container_height - kMinContentsSize, height_);
482 return height_; 464 return height_;
483 } 465 }
484 466
485 int DevToolsWindow::GetMinimumWidth() {
486 return kMinDevToolsWidth;
487 }
488
489 int DevToolsWindow::GetMinimumHeight() {
490 return kMinDevToolsHeight;
491 }
492
493 void DevToolsWindow::SetWidth(int width) { 467 void DevToolsWindow::SetWidth(int width) {
494 width_ = width; 468 width_ = width;
495 profile_->GetPrefs()->SetInteger(prefs::kDevToolsVSplitLocation, width); 469 profile_->GetPrefs()->SetInteger(prefs::kDevToolsVSplitLocation, width);
496 } 470 }
497 471
498 void DevToolsWindow::SetHeight(int height) { 472 void DevToolsWindow::SetHeight(int height) {
499 height_ = height; 473 height_ = height;
500 profile_->GetPrefs()->SetInteger(prefs::kDevToolsHSplitLocation, height); 474 profile_->GetPrefs()->SetInteger(prefs::kDevToolsHSplitLocation, height);
501 } 475 }
502 476
503 int DevToolsWindow::GetMinimizedHeight() { 477 void DevToolsWindow::Show(DevToolsToggleAction action) {
504 return kMinimizedDevToolsHeight; 478 if (IsDocked()) {
505 } 479 Browser* inspected_browser;
506 480 int inspected_tab_index;
507 RenderViewHost* DevToolsWindow::GetRenderViewHost() { 481 // Tell inspected browser to update splitter and switch to inspected panel.
508 return web_contents_->GetRenderViewHost(); 482 if (!IsInspectedBrowserPopup() &&
509 } 483 FindInspectedBrowserAndTabIndex(&inspected_browser,
510 484 &inspected_tab_index)) {
511 void DevToolsWindow::CreateDevToolsBrowser() { 485 BrowserWindow* inspected_window = inspected_browser->window();
512 std::string wp_key = GetDevToolsWindowPlacementPrefKey(); 486 web_contents_->SetDelegate(this);
513 PrefService* prefs = profile_->GetPrefs(); 487 inspected_window->UpdateDevTools();
514 const DictionaryValue* wp_pref = prefs->GetDictionary(wp_key.c_str()); 488 web_contents_->GetView()->SetInitialFocus();
515 if (!wp_pref || wp_pref->empty()) { 489 inspected_window->Show();
516 DictionaryPrefUpdate update(prefs, wp_key.c_str()); 490 TabStripModel* tab_strip_model = inspected_browser->tab_strip_model();
517 DictionaryValue* defaults = update.Get(); 491 tab_strip_model->ActivateTabAt(inspected_tab_index, true);
518 defaults->SetInteger("left", 100); 492 PrefsTabHelper::CreateForWebContents(web_contents_);
519 defaults->SetInteger("top", 100); 493 GetRenderViewHost()->SyncRendererPrefs();
520 defaults->SetInteger("right", 740); 494 ScheduleAction(action);
521 defaults->SetInteger("bottom", 740); 495 return;
522 defaults->SetBoolean("maximized", false); 496 } else {
523 defaults->SetBoolean("always_on_top", false); 497 // Sometimes we don't know where to dock. Stay undocked.
524 } 498 dock_side_ = DEVTOOLS_DOCK_SIDE_UNDOCKED;
525
526 chrome::HostDesktopType host_desktop_type =
527 chrome::GetHostDesktopTypeForNativeView(
528 web_contents_->GetView()->GetNativeView());
529
530 browser_ = new Browser(Browser::CreateParams::CreateForDevTools(
531 profile_, host_desktop_type));
532 browser_->tab_strip_model()->AddWebContents(
533 web_contents_, -1, content::PAGE_TRANSITION_AUTO_TOPLEVEL,
534 TabStripModel::ADD_ACTIVE);
535 GetRenderViewHost()->SyncRendererPrefs();
536 }
537
538 bool DevToolsWindow::FindInspectedBrowserAndTabIndex(Browser** browser,
539 int* tab) {
540 content::WebContents* inspected_web_contents = GetInspectedWebContents();
541 if (!inspected_web_contents)
542 return false;
543
544 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
545 int tab_index = it->tab_strip_model()->GetIndexOfWebContents(
546 inspected_web_contents);
547 if (tab_index != TabStripModel::kNoTab) {
548 *browser = *it;
549 *tab = tab_index;
550 return true;
551 } 499 }
552 } 500 }
553 return false; 501
554 } 502 // Avoid consecutive window switching if the devtools window has been opened
555 503 // and the Inspect Element shortcut is pressed in the inspected tab.
556 BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() { 504 bool should_show_window =
557 Browser* browser = NULL; 505 !browser_ || action != DEVTOOLS_TOGGLE_ACTION_INSPECT;
558 int tab; 506
559 return FindInspectedBrowserAndTabIndex(&browser, &tab) ? 507 if (!browser_)
560 browser->window() : NULL; 508 CreateDevToolsBrowser();
561 } 509
562 510 if (should_show_window) {
563 bool DevToolsWindow::IsInspectedBrowserPopup() { 511 browser_->window()->Show();
564 Browser* browser = NULL; 512 web_contents_->GetView()->SetInitialFocus();
565 int tab; 513 }
566 if (!FindInspectedBrowserAndTabIndex(&browser, &tab)) 514
567 return false; 515 ScheduleAction(action);
568 516 }
569 return browser->is_type_popup(); 517
570 } 518 DevToolsWindow::DevToolsWindow(Profile* profile,
571 519 const GURL& url,
572 void DevToolsWindow::UpdateFrontendDockSide() { 520 RenderViewHost* inspected_rvh,
573 base::StringValue dock_side(SideToString(dock_side_)); 521 DevToolsDockSide dock_side)
574 CallClientFunction("InspectorFrontendAPI.setDockSide", &dock_side); 522 : profile_(profile),
575 base::FundamentalValue docked(IsDocked()); 523 browser_(NULL),
576 CallClientFunction("InspectorFrontendAPI.setAttachedWindow", &docked); 524 dock_side_(dock_side),
577 } 525 is_loaded_(false),
578 526 action_on_load_(DEVTOOLS_TOGGLE_ACTION_SHOW),
579 527 weak_factory_(this),
580 void DevToolsWindow::AddDevToolsExtensionsToClient() { 528 width_(-1),
581 content::WebContents* inspected_web_contents = GetInspectedWebContents(); 529 height_(-1),
582 if (inspected_web_contents) { 530 dock_side_before_minimized_(dock_side) {
583 SessionTabHelper* session_tab_helper = 531 web_contents_ = WebContents::Create(WebContents::CreateParams(profile));
584 SessionTabHelper::FromWebContents(inspected_web_contents); 532 frontend_contents_observer_.reset(
585 if (session_tab_helper) { 533 new FrontendWebContentsObserver(web_contents_));
586 base::FundamentalValue tabId(session_tab_helper->session_id().id()); 534
587 CallClientFunction("WebInspector.setInspectedTabId", &tabId); 535 web_contents_->GetController().LoadURL(url, content::Referrer(),
588 } 536 content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
589 } 537
590 ListValue results; 538 frontend_host_.reset(
591 Profile* profile = 539 DevToolsClientHost::CreateDevToolsFrontendHost(web_contents_, this));
592 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); 540 file_helper_.reset(new DevToolsFileHelper(web_contents_, profile));
593 const ExtensionService* extension_service = extensions::ExtensionSystem::Get( 541
594 profile->GetOriginalProfile())->extension_service(); 542 g_instances.Get().push_back(this);
595 if (!extension_service) 543 // Wipe out page icon so that the default application icon is used.
596 return; 544 NavigationEntry* entry = web_contents_->GetController().GetActiveEntry();
597 545 entry->GetFavicon().image = gfx::Image();
598 const ExtensionSet* extensions = extension_service->extensions(); 546 entry->GetFavicon().valid = true;
599 547
600 for (ExtensionSet::const_iterator extension = extensions->begin(); 548 // Register on-load actions.
601 extension != extensions->end(); ++extension) { 549 registrar_.Add(
602 if (extensions::ManifestURL::GetDevToolsPage(extension->get()).is_empty()) 550 this,
603 continue; 551 content::NOTIFICATION_LOAD_STOP,
604 DictionaryValue* extension_info = new DictionaryValue(); 552 content::Source<NavigationController>(&web_contents_->GetController()));
605 extension_info->Set( 553 registrar_.Add(
606 "startPage", 554 this,
607 new StringValue( 555 chrome::NOTIFICATION_TAB_CLOSING,
608 extensions::ManifestURL::GetDevToolsPage(extension->get()).spec())); 556 content::Source<NavigationController>(&web_contents_->GetController()));
609 extension_info->Set("name", new StringValue((*extension)->name())); 557 registrar_.Add(
610 bool allow_experimental = (*extension)->HasAPIPermission( 558 this,
611 extensions::APIPermission::kExperimental); 559 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
612 extension_info->Set("exposeExperimentalAPIs", 560 content::Source<ThemeService>(
613 new base::FundamentalValue(allow_experimental)); 561 ThemeServiceFactory::GetForProfile(profile_)));
614 results.Append(extension_info); 562 // There is no inspected_rvh in case of shared workers.
615 } 563 if (inspected_rvh)
616 CallClientFunction("WebInspector.addExtensions", &results); 564 inspected_contents_observer_.reset(new InspectedWebContentsObserver(
617 } 565 WebContents::FromRenderViewHost(inspected_rvh)));
618 566 }
619 WebContents* DevToolsWindow::OpenURLFromTab(WebContents* source, 567
620 const OpenURLParams& params) { 568 // static
621 if (!params.url.SchemeIs(chrome::kChromeDevToolsScheme)) { 569 DevToolsWindow* DevToolsWindow::Create(
622 content::WebContents* inspected_web_contents = GetInspectedWebContents(); 570 Profile* profile,
623 if (inspected_web_contents) 571 const GURL& frontend_url,
624 return inspected_web_contents->OpenURL(params); 572 RenderViewHost* inspected_rvh,
573 DevToolsDockSide dock_side,
574 bool shared_worker_frontend) {
575 // Create WebContents with devtools.
576 GURL url = GetDevToolsURL(profile, frontend_url, dock_side,
577 shared_worker_frontend);
578 return new DevToolsWindow(profile, url, inspected_rvh, dock_side);
579 }
580
581 // static
582 GURL DevToolsWindow::GetDevToolsURL(Profile* profile,
583 const GURL& base_url,
584 DevToolsDockSide dock_side,
585 bool shared_worker_frontend) {
586 ThemeService* tp = ThemeServiceFactory::GetForProfile(profile);
587 CHECK(tp);
588
589 SkColor color_toolbar =
590 tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
591 SkColor color_tab_text =
592 tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
593
594 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
595 bool experiments_enabled =
596 command_line.HasSwitch(switches::kEnableDevToolsExperiments);
597
598 std::string frontend_url = base_url.is_empty() ?
599 chrome::kChromeUIDevToolsURL : base_url.spec();
600 std::string params_separator =
601 frontend_url.find("?") == std::string::npos ? "?" : "&";
602 std::string url_string = base::StringPrintf("%s%s"
603 "dockSide=%s&toolbarColor=%s&textColor=%s%s%s",
604 frontend_url.c_str(),
605 params_separator.c_str(),
606 SideToString(dock_side).c_str(),
607 SkColorToRGBAString(color_toolbar).c_str(),
608 SkColorToRGBAString(color_tab_text).c_str(),
609 shared_worker_frontend ? "&isSharedWorker=true" : "",
610 experiments_enabled ? "&experiments=true" : "");
611 return GURL(url_string);
612 }
613
614 // static
615 DevToolsWindow* DevToolsWindow::FindDevToolsWindow(
616 DevToolsAgentHost* agent_host) {
617 DevToolsManager* manager = DevToolsManager::GetInstance();
618 DevToolsWindowList& instances = g_instances.Get();
619 for (DevToolsWindowList::iterator it = instances.begin();
620 it != instances.end(); ++it) {
621 if (manager->GetDevToolsAgentHostFor((*it)->frontend_host_.get()) ==
622 agent_host)
623 return *it;
624 }
625 return NULL;
626 }
627
628 // static
629 DevToolsWindow* DevToolsWindow::AsDevToolsWindow(RenderViewHost* window_rvh) {
630 if (g_instances == NULL)
625 return NULL; 631 return NULL;
626 } 632 DevToolsWindowList& instances = g_instances.Get();
627 633 for (DevToolsWindowList::iterator it = instances.begin();
628 DevToolsManager* manager = DevToolsManager::GetInstance(); 634 it != instances.end(); ++it) {
629 scoped_refptr<DevToolsAgentHost> agent_host( 635 if ((*it)->web_contents_->GetRenderViewHost() == window_rvh)
630 manager->GetDevToolsAgentHostFor(frontend_host_.get())); 636 return *it;
631 if (!agent_host.get()) 637 }
632 return NULL; 638 return NULL;
633 manager->ClientHostClosing(frontend_host_.get()); 639 }
634 manager->RegisterDevToolsClientHostFor(agent_host.get(), 640
635 frontend_host_.get()); 641 // static
636 642 DevToolsDockSide DevToolsWindow::GetDockSideFromPrefs(Profile* profile) {
637 chrome::NavigateParams nav_params(profile_, params.url, params.transition); 643 std::string dock_side =
638 FillNavigateParamsFromOpenURLParams(&nav_params, params); 644 profile->GetPrefs()->GetString(prefs::kDevToolsDockSide);
639 nav_params.source_contents = source; 645
640 nav_params.tabstrip_add_types = TabStripModel::ADD_NONE; 646 // Migrate prefs
641 nav_params.window_action = chrome::NavigateParams::SHOW_WINDOW; 647 if (dock_side == kOldPrefBottom || dock_side == kOldPrefRight) {
642 nav_params.user_gesture = params.user_gesture; 648 bool docked = profile->GetPrefs()->GetBoolean(prefs::kDevToolsOpenDocked);
643 chrome::Navigate(&nav_params); 649 if (dock_side == kOldPrefBottom)
644 return nav_params.target_contents; 650 return docked ? DEVTOOLS_DOCK_SIDE_BOTTOM : DEVTOOLS_DOCK_SIDE_UNDOCKED;
645 } 651 else
646 652 return docked ? DEVTOOLS_DOCK_SIDE_RIGHT : DEVTOOLS_DOCK_SIDE_UNDOCKED;
647 void DevToolsWindow::CallClientFunction(const std::string& function_name, 653 }
648 const Value* arg1, 654
649 const Value* arg2) { 655 if (dock_side == kPrefUndocked)
650 std::string params; 656 return DEVTOOLS_DOCK_SIDE_UNDOCKED;
651 if (arg1) { 657 else if (dock_side == kPrefRight)
652 std::string json; 658 return DEVTOOLS_DOCK_SIDE_RIGHT;
653 base::JSONWriter::Write(arg1, &json); 659 // Default to docked to bottom
654 params.append(json); 660 return DEVTOOLS_DOCK_SIDE_BOTTOM;
655 if (arg2) { 661 }
656 base::JSONWriter::Write(arg2, &json); 662
657 params.append(", " + json); 663 // static
658 } 664 std::string DevToolsWindow::SideToString(DevToolsDockSide dock_side) {
659 } 665 std::string dock_side_string;
660 string16 javascript = ASCIIToUTF16(function_name + "(" + params + ");"); 666 switch (dock_side) {
661 web_contents_->GetRenderViewHost()-> 667 case DEVTOOLS_DOCK_SIDE_UNDOCKED: return kDockSideUndocked;
662 ExecuteJavascriptInWebFrame(string16(), javascript); 668 case DEVTOOLS_DOCK_SIDE_RIGHT: return kDockSideRight;
669 case DEVTOOLS_DOCK_SIDE_BOTTOM: return kDockSideBottom;
670 case DEVTOOLS_DOCK_SIDE_MINIMIZED: return kDockSideMinimized;
671 }
672 return kDockSideUndocked;
673 }
674
675 // static
676 DevToolsDockSide DevToolsWindow::SideFromString(
677 const std::string& dock_side) {
678 if (dock_side == kDockSideRight)
679 return DEVTOOLS_DOCK_SIDE_RIGHT;
680 if (dock_side == kDockSideBottom)
681 return DEVTOOLS_DOCK_SIDE_BOTTOM;
682 if (dock_side == kDockSideMinimized)
683 return DEVTOOLS_DOCK_SIDE_MINIMIZED;
684 return DEVTOOLS_DOCK_SIDE_UNDOCKED;
663 } 685 }
664 686
665 void DevToolsWindow::Observe(int type, 687 void DevToolsWindow::Observe(int type,
666 const content::NotificationSource& source, 688 const content::NotificationSource& source,
667 const content::NotificationDetails& details) { 689 const content::NotificationDetails& details) {
668 if (type == content::NOTIFICATION_LOAD_STOP && !is_loaded_) { 690 if (type == content::NOTIFICATION_LOAD_STOP && !is_loaded_) {
669 is_loaded_ = true; 691 is_loaded_ = true;
670 UpdateTheme(); 692 UpdateTheme();
671 DoAction(); 693 DoAction();
672 AddDevToolsExtensionsToClient(); 694 AddDevToolsExtensionsToClient();
673 } else if (type == chrome::NOTIFICATION_TAB_CLOSING) { 695 } else if (type == chrome::NOTIFICATION_TAB_CLOSING) {
674 if (content::Source<NavigationController>(source).ptr() == 696 if (content::Source<NavigationController>(source).ptr() ==
675 &web_contents_->GetController()) { 697 &web_contents_->GetController()) {
676 // This happens when browser closes all of its tabs as a result 698 // This happens when browser closes all of its tabs as a result
677 // of window.Close event. 699 // of window.Close event.
678 // Notify manager that this DevToolsClientHost no longer exists and 700 // Notify manager that this DevToolsClientHost no longer exists and
679 // initiate self-destuct here. 701 // initiate self-destuct here.
680 DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_.get()); 702 DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_.get());
681 UpdateBrowserToolbar(); 703 UpdateBrowserToolbar();
682 delete this; 704 delete this;
683 } 705 }
684 } else if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) { 706 } else if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) {
685 UpdateTheme(); 707 UpdateTheme();
686 } 708 }
687 } 709 }
688 710
689 void DevToolsWindow::ScheduleAction(DevToolsToggleAction action) { 711 WebContents* DevToolsWindow::OpenURLFromTab(WebContents* source,
690 action_on_load_ = action; 712 const OpenURLParams& params) {
691 if (is_loaded_) 713 if (!params.url.SchemeIs(chrome::kChromeDevToolsScheme)) {
692 DoAction(); 714 content::WebContents* inspected_web_contents = GetInspectedWebContents();
693 } 715 if (inspected_web_contents)
716 return inspected_web_contents->OpenURL(params);
717 return NULL;
718 }
694 719
695 void DevToolsWindow::DoAction() { 720 DevToolsManager* manager = DevToolsManager::GetInstance();
696 UpdateFrontendDockSide(); 721 scoped_refptr<DevToolsAgentHost> agent_host(
697 switch (action_on_load_) { 722 manager->GetDevToolsAgentHostFor(frontend_host_.get()));
698 case DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE: 723 if (!agent_host.get())
699 CallClientFunction("InspectorFrontendAPI.showConsole", NULL); 724 return NULL;
700 break; 725 manager->ClientHostClosing(frontend_host_.get());
701 case DEVTOOLS_TOGGLE_ACTION_INSPECT: 726 manager->RegisterDevToolsClientHostFor(agent_host.get(),
702 CallClientFunction("InspectorFrontendAPI.enterInspectElementMode", NULL); 727 frontend_host_.get());
703 case DEVTOOLS_TOGGLE_ACTION_SHOW:
704 case DEVTOOLS_TOGGLE_ACTION_TOGGLE:
705 // Do nothing.
706 break;
707 default:
708 NOTREACHED();
709 }
710 action_on_load_ = DEVTOOLS_TOGGLE_ACTION_SHOW;
711 }
712 728
713 std::string SkColorToRGBAString(SkColor color) { 729 chrome::NavigateParams nav_params(profile_, params.url, params.transition);
714 // We convert the alpha using DoubleToString because StringPrintf will use 730 FillNavigateParamsFromOpenURLParams(&nav_params, params);
715 // locale specific formatters (e.g., use , instead of . in German). 731 nav_params.source_contents = source;
716 return base::StringPrintf("rgba(%d,%d,%d,%s)", SkColorGetR(color), 732 nav_params.tabstrip_add_types = TabStripModel::ADD_NONE;
717 SkColorGetG(color), SkColorGetB(color), 733 nav_params.window_action = chrome::NavigateParams::SHOW_WINDOW;
718 base::DoubleToString(SkColorGetA(color) / 255.0).c_str()); 734 nav_params.user_gesture = params.user_gesture;
719 } 735 chrome::Navigate(&nav_params);
720 736 return nav_params.target_contents;
721 // static
722 GURL DevToolsWindow::GetDevToolsURL(Profile* profile,
723 const GURL& base_url,
724 DevToolsDockSide dock_side,
725 bool shared_worker_frontend) {
726 ThemeService* tp = ThemeServiceFactory::GetForProfile(profile);
727 CHECK(tp);
728
729 SkColor color_toolbar =
730 tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
731 SkColor color_tab_text =
732 tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
733
734 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
735 bool experiments_enabled =
736 command_line.HasSwitch(switches::kEnableDevToolsExperiments);
737
738 std::string frontend_url = base_url.is_empty() ?
739 chrome::kChromeUIDevToolsURL : base_url.spec();
740 std::string params_separator =
741 frontend_url.find("?") == std::string::npos ? "?" : "&";
742 std::string url_string = base::StringPrintf("%s%s"
743 "dockSide=%s&toolbarColor=%s&textColor=%s%s%s",
744 frontend_url.c_str(),
745 params_separator.c_str(),
746 SideToString(dock_side).c_str(),
747 SkColorToRGBAString(color_toolbar).c_str(),
748 SkColorToRGBAString(color_tab_text).c_str(),
749 shared_worker_frontend ? "&isSharedWorker=true" : "",
750 experiments_enabled ? "&experiments=true" : "");
751 return GURL(url_string);
752 }
753
754 void DevToolsWindow::UpdateTheme() {
755 ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_);
756 CHECK(tp);
757
758 SkColor color_toolbar =
759 tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
760 SkColor color_tab_text =
761 tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
762 std::string command = base::StringPrintf(
763 "InspectorFrontendAPI.setToolbarColors(\"%s\", \"%s\")",
764 SkColorToRGBAString(color_toolbar).c_str(),
765 SkColorToRGBAString(color_tab_text).c_str());
766 web_contents_->GetRenderViewHost()->
767 ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(command));
768 } 737 }
769 738
770 void DevToolsWindow::AddNewContents(WebContents* source, 739 void DevToolsWindow::AddNewContents(WebContents* source,
771 WebContents* new_contents, 740 WebContents* new_contents,
772 WindowOpenDisposition disposition, 741 WindowOpenDisposition disposition,
773 const gfx::Rect& initial_pos, 742 const gfx::Rect& initial_pos,
774 bool user_gesture, 743 bool user_gesture,
775 bool* was_blocked) { 744 bool* was_blocked) {
776 content::WebContents* inspected_web_contents = GetInspectedWebContents(); 745 content::WebContents* inspected_web_contents = GetInspectedWebContents();
777 if (inspected_web_contents) { 746 if (inspected_web_contents) {
778 inspected_web_contents->GetDelegate()->AddNewContents( 747 inspected_web_contents->GetDelegate()->AddNewContents(
779 source, new_contents, disposition, initial_pos, user_gesture, 748 source, new_contents, disposition, initial_pos, user_gesture,
780 was_blocked); 749 was_blocked);
781 } 750 }
782 } 751 }
783 752
753 void DevToolsWindow::CloseContents(content::WebContents* source) {
754 }
755
784 bool DevToolsWindow::PreHandleKeyboardEvent( 756 bool DevToolsWindow::PreHandleKeyboardEvent(
785 WebContents* source, 757 WebContents* source,
786 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { 758 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
787 if (IsDocked()) { 759 if (IsDocked()) {
788 BrowserWindow* inspected_window = GetInspectedBrowserWindow(); 760 BrowserWindow* inspected_window = GetInspectedBrowserWindow();
789 if (inspected_window) 761 if (inspected_window)
790 return inspected_window->PreHandleKeyboardEvent( 762 return inspected_window->PreHandleKeyboardEvent(
791 event, is_keyboard_shortcut); 763 event, is_keyboard_shortcut);
792 } 764 }
793 return false; 765 return false;
794 } 766 }
795 767
796 void DevToolsWindow::HandleKeyboardEvent(WebContents* source, 768 void DevToolsWindow::HandleKeyboardEvent(WebContents* source,
797 const NativeWebKeyboardEvent& event) { 769 const NativeWebKeyboardEvent& event) {
798 if (IsDocked()) { 770 if (IsDocked()) {
799 if (event.windowsKeyCode == 0x08) { 771 if (event.windowsKeyCode == 0x08) {
800 // Do not navigate back in history on Windows (http://crbug.com/74156). 772 // Do not navigate back in history on Windows (http://crbug.com/74156).
801 return; 773 return;
802 } 774 }
803 BrowserWindow* inspected_window = GetInspectedBrowserWindow(); 775 BrowserWindow* inspected_window = GetInspectedBrowserWindow();
804 if (inspected_window) 776 if (inspected_window)
805 inspected_window->HandleKeyboardEvent(event); 777 inspected_window->HandleKeyboardEvent(event);
806 } 778 }
807 } 779 }
808 780
809 // static 781 content::JavaScriptDialogManager* DevToolsWindow::GetJavaScriptDialogManager() {
810 DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow( 782 content::WebContents* inspected_web_contents = GetInspectedWebContents();
811 RenderViewHost* inspected_rvh, 783 if (inspected_web_contents && inspected_web_contents->GetDelegate()) {
812 bool force_open, 784 return inspected_web_contents->GetDelegate()->
813 DevToolsToggleAction action) { 785 GetJavaScriptDialogManager();
814 scoped_refptr<DevToolsAgentHost> agent(
815 DevToolsAgentHost::GetOrCreateFor(inspected_rvh));
816 DevToolsManager* manager = DevToolsManager::GetInstance();
817 DevToolsWindow* window = FindDevToolsWindow(agent.get());
818 bool do_open = force_open;
819 if (!window) {
820 Profile* profile = Profile::FromBrowserContext(
821 inspected_rvh->GetProcess()->GetBrowserContext());
822 DevToolsDockSide dock_side = GetDockSideFromPrefs(profile);
823 window = Create(profile, GURL(), inspected_rvh, dock_side, false);
824 manager->RegisterDevToolsClientHostFor(agent.get(),
825 window->frontend_host_.get());
826 do_open = true;
827 } 786 }
828 787 return content::WebContentsDelegate::GetJavaScriptDialogManager();
829 // Update toolbar to reflect DevTools changes.
830 window->UpdateBrowserToolbar();
831
832 // If window is docked and visible, we hide it on toggle. If window is
833 // undocked, we show (activate) it. If window is minimized, we maximize it.
834 if (window->dock_side_ == DEVTOOLS_DOCK_SIDE_MINIMIZED)
835 window->Restore();
836 else if (!window->IsDocked() || do_open)
837 window->Show(action);
838 else
839 window->CloseWindow();
840
841 return window;
842 } 788 }
843 789
844 // static 790 content::ColorChooser* DevToolsWindow::OpenColorChooser(
845 DevToolsWindow* DevToolsWindow::FindDevToolsWindow( 791 WebContents* web_contents, SkColor initial_color) {
846 DevToolsAgentHost* agent_host) { 792 return chrome::ShowColorChooser(web_contents, initial_color);
847 DevToolsManager* manager = DevToolsManager::GetInstance();
848 DevToolsWindowList& instances = g_instances.Get();
849 for (DevToolsWindowList::iterator it = instances.begin();
850 it != instances.end(); ++it) {
851 if (manager->GetDevToolsAgentHostFor((*it)->frontend_host_.get()) ==
852 agent_host)
853 return *it;
854 }
855 return NULL;
856 } 793 }
857 794
858 // static 795 void DevToolsWindow::RunFileChooser(WebContents* web_contents,
859 DevToolsWindow* DevToolsWindow::AsDevToolsWindow(RenderViewHost* window_rvh) { 796 const FileChooserParams& params) {
860 if (g_instances == NULL) 797 FileSelectHelper::RunFileChooser(web_contents, params);
861 return NULL; 798 }
862 DevToolsWindowList& instances = g_instances.Get(); 799
863 for (DevToolsWindowList::iterator it = instances.begin(); 800 void DevToolsWindow::WebContentsFocused(WebContents* contents) {
864 it != instances.end(); ++it) { 801 Browser* inspected_browser = NULL;
865 if ((*it)->web_contents_->GetRenderViewHost() == window_rvh) 802 int inspected_tab_index = -1;
866 return *it; 803
804 if (IsDocked() && FindInspectedBrowserAndTabIndex(&inspected_browser,
805 &inspected_tab_index)) {
806 inspected_browser->window()->WebContentsFocused(contents);
867 } 807 }
868 return NULL;
869 } 808 }
870 809
871 void DevToolsWindow::ActivateWindow() { 810 void DevToolsWindow::ActivateWindow() {
872 if (!IsDocked()) { 811 if (!IsDocked()) {
873 if (!browser_->window()->IsActive()) { 812 if (!browser_->window()->IsActive()) {
874 browser_->window()->Activate(); 813 browser_->window()->Activate();
875 } 814 }
876 } else { 815 } else {
877 BrowserWindow* inspected_window = GetInspectedBrowserWindow(); 816 BrowserWindow* inspected_window = GetInspectedBrowserWindow();
878 if (inspected_window) 817 if (inspected_window)
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 case DEVTOOLS_DOCK_SIDE_MINIMIZED: 886 case DEVTOOLS_DOCK_SIDE_MINIMIZED:
948 // We don't persist minimized state. 887 // We don't persist minimized state.
949 break; 888 break;
950 } 889 }
951 profile_->GetPrefs()->SetString(prefs::kDevToolsDockSide, pref_value); 890 profile_->GetPrefs()->SetString(prefs::kDevToolsDockSide, pref_value);
952 } 891 }
953 892
954 Show(DEVTOOLS_TOGGLE_ACTION_SHOW); 893 Show(DEVTOOLS_TOGGLE_ACTION_SHOW);
955 } 894 }
956 895
957 void DevToolsWindow::Restore() {
958 if (dock_side_ == DEVTOOLS_DOCK_SIDE_MINIMIZED)
959 SetDockSide(SideToString(dock_side_before_minimized_));
960 }
961
962 void DevToolsWindow::OpenInNewTab(const std::string& url) { 896 void DevToolsWindow::OpenInNewTab(const std::string& url) {
963 OpenURLParams params(GURL(url), 897 OpenURLParams params(GURL(url),
964 content::Referrer(), 898 content::Referrer(),
965 NEW_FOREGROUND_TAB, 899 NEW_FOREGROUND_TAB,
966 content::PAGE_TRANSITION_LINK, 900 content::PAGE_TRANSITION_LINK,
967 false /* is_renderer_initiated */); 901 false /* is_renderer_initiated */);
968 content::WebContents* inspected_web_contents = GetInspectedWebContents(); 902 content::WebContents* inspected_web_contents = GetInspectedWebContents();
969 if (inspected_web_contents) { 903 if (inspected_web_contents) {
970 inspected_web_contents->OpenURL(params); 904 inspected_web_contents->OpenURL(params);
971 } else { 905 } else {
(...skipping 27 matching lines...) Expand all
999 url)); 933 url));
1000 } 934 }
1001 935
1002 void DevToolsWindow::AppendToFile(const std::string& url, 936 void DevToolsWindow::AppendToFile(const std::string& url,
1003 const std::string& content) { 937 const std::string& content) {
1004 file_helper_->Append(url, content, Bind(&DevToolsWindow::AppendedTo, 938 file_helper_->Append(url, content, Bind(&DevToolsWindow::AppendedTo,
1005 weak_factory_.GetWeakPtr(), 939 weak_factory_.GetWeakPtr(),
1006 url)); 940 url));
1007 } 941 }
1008 942
1009 namespace {
1010
1011 DictionaryValue* CreateFileSystemValue(
1012 DevToolsFileHelper::FileSystem file_system) {
1013 DictionaryValue* file_system_value = new DictionaryValue();
1014 file_system_value->SetString("fileSystemName", file_system.file_system_name);
1015 file_system_value->SetString("rootURL", file_system.root_url);
1016 file_system_value->SetString("fileSystemPath", file_system.file_system_path);
1017 return file_system_value;
1018 }
1019
1020 } // namespace
1021
1022 void DevToolsWindow::RequestFileSystems() { 943 void DevToolsWindow::RequestFileSystems() {
1023 CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme)); 944 CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme));
1024 file_helper_->RequestFileSystems( 945 file_helper_->RequestFileSystems(
1025 Bind(&DevToolsWindow::FileSystemsLoaded, weak_factory_.GetWeakPtr())); 946 Bind(&DevToolsWindow::FileSystemsLoaded, weak_factory_.GetWeakPtr()));
1026 } 947 }
1027 948
1028 void DevToolsWindow::AddFileSystem() { 949 void DevToolsWindow::AddFileSystem() {
1029 CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme)); 950 CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme));
1030 file_helper_->AddFileSystem( 951 file_helper_->AddFileSystem(
1031 Bind(&DevToolsWindow::FileSystemAdded, weak_factory_.GetWeakPtr()), 952 Bind(&DevToolsWindow::FileSystemAdded, weak_factory_.GetWeakPtr()),
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( 1006 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
1086 new DevToolsConfirmInfoBarDelegate( 1007 new DevToolsConfirmInfoBarDelegate(
1087 infobar_service, 1008 infobar_service,
1088 callback, 1009 callback,
1089 message))); 1010 message)));
1090 } else { 1011 } else {
1091 callback.Run(false); 1012 callback.Run(false);
1092 } 1013 }
1093 } 1014 }
1094 1015
1095 content::JavaScriptDialogManager* DevToolsWindow::GetJavaScriptDialogManager() { 1016 void DevToolsWindow::CreateDevToolsBrowser() {
1096 content::WebContents* inspected_web_contents = GetInspectedWebContents(); 1017 std::string wp_key = GetDevToolsWindowPlacementPrefKey();
1097 if (inspected_web_contents && inspected_web_contents->GetDelegate()) { 1018 PrefService* prefs = profile_->GetPrefs();
1098 return inspected_web_contents->GetDelegate()-> 1019 const DictionaryValue* wp_pref = prefs->GetDictionary(wp_key.c_str());
1099 GetJavaScriptDialogManager(); 1020 if (!wp_pref || wp_pref->empty()) {
1021 DictionaryPrefUpdate update(prefs, wp_key.c_str());
1022 DictionaryValue* defaults = update.Get();
1023 defaults->SetInteger("left", 100);
1024 defaults->SetInteger("top", 100);
1025 defaults->SetInteger("right", 740);
1026 defaults->SetInteger("bottom", 740);
1027 defaults->SetBoolean("maximized", false);
1028 defaults->SetBoolean("always_on_top", false);
1100 } 1029 }
1101 return content::WebContentsDelegate::GetJavaScriptDialogManager(); 1030
1031 chrome::HostDesktopType host_desktop_type =
1032 chrome::GetHostDesktopTypeForNativeView(
1033 web_contents_->GetView()->GetNativeView());
1034
1035 browser_ = new Browser(Browser::CreateParams::CreateForDevTools(
1036 profile_, host_desktop_type));
1037 browser_->tab_strip_model()->AddWebContents(
1038 web_contents_, -1, content::PAGE_TRANSITION_AUTO_TOPLEVEL,
1039 TabStripModel::ADD_ACTIVE);
1040 GetRenderViewHost()->SyncRendererPrefs();
1102 } 1041 }
1103 1042
1104 content::ColorChooser* DevToolsWindow::OpenColorChooser( 1043 bool DevToolsWindow::FindInspectedBrowserAndTabIndex(Browser** browser,
1105 WebContents* web_contents, SkColor initial_color) { 1044 int* tab) {
1106 return chrome::ShowColorChooser(web_contents, initial_color); 1045 content::WebContents* inspected_web_contents = GetInspectedWebContents();
1046 if (!inspected_web_contents)
1047 return false;
1048
1049 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1050 int tab_index = it->tab_strip_model()->GetIndexOfWebContents(
1051 inspected_web_contents);
1052 if (tab_index != TabStripModel::kNoTab) {
1053 *browser = *it;
1054 *tab = tab_index;
1055 return true;
1056 }
1057 }
1058 return false;
1107 } 1059 }
1108 1060
1109 void DevToolsWindow::RunFileChooser(WebContents* web_contents, 1061 BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() {
1110 const FileChooserParams& params) { 1062 Browser* browser = NULL;
1111 FileSelectHelper::RunFileChooser(web_contents, params); 1063 int tab;
1064 return FindInspectedBrowserAndTabIndex(&browser, &tab) ?
1065 browser->window() : NULL;
1112 } 1066 }
1113 1067
1114 void DevToolsWindow::WebContentsFocused(WebContents* contents) { 1068 bool DevToolsWindow::IsInspectedBrowserPopup() {
1115 Browser* inspected_browser = NULL; 1069 Browser* browser = NULL;
1116 int inspected_tab_index = -1; 1070 int tab;
1071 if (!FindInspectedBrowserAndTabIndex(&browser, &tab))
1072 return false;
1117 1073
1118 if (IsDocked() && FindInspectedBrowserAndTabIndex(&inspected_browser, 1074 return browser->is_type_popup();
1119 &inspected_tab_index)) { 1075 }
1120 inspected_browser->window()->WebContentsFocused(contents); 1076
1077 void DevToolsWindow::UpdateFrontendDockSide() {
1078 base::StringValue dock_side(SideToString(dock_side_));
1079 CallClientFunction("InspectorFrontendAPI.setDockSide", &dock_side);
1080 base::FundamentalValue docked(IsDocked());
1081 CallClientFunction("InspectorFrontendAPI.setAttachedWindow", &docked);
1082 }
1083
1084 void DevToolsWindow::Hide() {
1085 if (IsDocked()) {
1086 // Update dev tools to reflect removed dev tools window.
1087 BrowserWindow* inspected_window = GetInspectedBrowserWindow();
1088 if (inspected_window)
1089 inspected_window->UpdateDevTools();
1090 // In case of docked web_contents_, we own it so delete here.
1091 delete web_contents_;
1092
1093 delete this;
1094 } else {
1095 // First, initiate self-destruct to free all the registrars.
1096 // Then close all tabs. Browser will take care of deleting web_contents_
1097 // for us.
1098 Browser* browser = browser_;
1099 delete this;
1100 browser->tab_strip_model()->CloseAllTabs();
1121 } 1101 }
1122 } 1102 }
1123 1103
1104 void DevToolsWindow::ScheduleAction(DevToolsToggleAction action) {
1105 action_on_load_ = action;
1106 if (is_loaded_)
1107 DoAction();
1108 }
1109
1110 void DevToolsWindow::DoAction() {
1111 UpdateFrontendDockSide();
1112 switch (action_on_load_) {
1113 case DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE:
1114 CallClientFunction("InspectorFrontendAPI.showConsole", NULL);
1115 break;
1116 case DEVTOOLS_TOGGLE_ACTION_INSPECT:
1117 CallClientFunction("InspectorFrontendAPI.enterInspectElementMode", NULL);
1118 case DEVTOOLS_TOGGLE_ACTION_SHOW:
1119 case DEVTOOLS_TOGGLE_ACTION_TOGGLE:
1120 // Do nothing.
1121 break;
1122 default:
1123 NOTREACHED();
1124 }
1125 action_on_load_ = DEVTOOLS_TOGGLE_ACTION_SHOW;
1126 }
1127
1128 void DevToolsWindow::UpdateTheme() {
1129 ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_);
1130 CHECK(tp);
1131
1132 SkColor color_toolbar =
1133 tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
1134 SkColor color_tab_text =
1135 tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
1136 std::string command = base::StringPrintf(
1137 "InspectorFrontendAPI.setToolbarColors(\"%s\", \"%s\")",
1138 SkColorToRGBAString(color_toolbar).c_str(),
1139 SkColorToRGBAString(color_tab_text).c_str());
1140 web_contents_->GetRenderViewHost()->
1141 ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(command));
1142 }
1143
1144 void DevToolsWindow::AddDevToolsExtensionsToClient() {
1145 content::WebContents* inspected_web_contents = GetInspectedWebContents();
1146 if (inspected_web_contents) {
1147 SessionTabHelper* session_tab_helper =
1148 SessionTabHelper::FromWebContents(inspected_web_contents);
1149 if (session_tab_helper) {
1150 base::FundamentalValue tabId(session_tab_helper->session_id().id());
1151 CallClientFunction("WebInspector.setInspectedTabId", &tabId);
1152 }
1153 }
1154 ListValue results;
1155 Profile* profile =
1156 Profile::FromBrowserContext(web_contents_->GetBrowserContext());
1157 const ExtensionService* extension_service = extensions::ExtensionSystem::Get(
1158 profile->GetOriginalProfile())->extension_service();
1159 if (!extension_service)
1160 return;
1161
1162 const ExtensionSet* extensions = extension_service->extensions();
1163
1164 for (ExtensionSet::const_iterator extension = extensions->begin();
1165 extension != extensions->end(); ++extension) {
1166 if (extensions::ManifestURL::GetDevToolsPage(extension->get()).is_empty())
1167 continue;
1168 DictionaryValue* extension_info = new DictionaryValue();
1169 extension_info->Set(
1170 "startPage",
1171 new StringValue(
1172 extensions::ManifestURL::GetDevToolsPage(extension->get()).spec()));
1173 extension_info->Set("name", new StringValue((*extension)->name()));
1174 bool allow_experimental = (*extension)->HasAPIPermission(
1175 extensions::APIPermission::kExperimental);
1176 extension_info->Set("exposeExperimentalAPIs",
1177 new base::FundamentalValue(allow_experimental));
1178 results.Append(extension_info);
1179 }
1180 CallClientFunction("WebInspector.addExtensions", &results);
1181 }
1182
1183 void DevToolsWindow::CallClientFunction(const std::string& function_name,
1184 const Value* arg1,
1185 const Value* arg2) {
1186 std::string params;
1187 if (arg1) {
1188 std::string json;
1189 base::JSONWriter::Write(arg1, &json);
1190 params.append(json);
1191 if (arg2) {
1192 base::JSONWriter::Write(arg2, &json);
1193 params.append(", " + json);
1194 }
1195 }
1196 string16 javascript = ASCIIToUTF16(function_name + "(" + params + ");");
1197 web_contents_->GetRenderViewHost()->
1198 ExecuteJavascriptInWebFrame(string16(), javascript);
1199 }
1200
1124 void DevToolsWindow::UpdateBrowserToolbar() { 1201 void DevToolsWindow::UpdateBrowserToolbar() {
1125 content::WebContents* inspected_web_contents = GetInspectedWebContents(); 1202 content::WebContents* inspected_web_contents = GetInspectedWebContents();
1126 if (!inspected_web_contents) 1203 if (!inspected_web_contents)
1127 return; 1204 return;
1128 BrowserWindow* inspected_window = GetInspectedBrowserWindow(); 1205 BrowserWindow* inspected_window = GetInspectedBrowserWindow();
1129 if (inspected_window) 1206 if (inspected_window)
1130 inspected_window->UpdateToolbar(inspected_web_contents, false); 1207 inspected_window->UpdateToolbar(inspected_web_contents, false);
1131 } 1208 }
1132 1209
1133 bool DevToolsWindow::IsDocked() { 1210 bool DevToolsWindow::IsDocked() {
1134 return dock_side_ != DEVTOOLS_DOCK_SIDE_UNDOCKED; 1211 return dock_side_ != DEVTOOLS_DOCK_SIDE_UNDOCKED;
1135 } 1212 }
1136 1213
1137 // static 1214 void DevToolsWindow::Restore() {
1138 DevToolsDockSide DevToolsWindow::GetDockSideFromPrefs(Profile* profile) { 1215 if (dock_side_ == DEVTOOLS_DOCK_SIDE_MINIMIZED)
1139 std::string dock_side = 1216 SetDockSide(SideToString(dock_side_before_minimized_));
1140 profile->GetPrefs()->GetString(prefs::kDevToolsDockSide);
1141
1142 // Migrate prefs
1143 if (dock_side == kOldPrefBottom || dock_side == kOldPrefRight) {
1144 bool docked = profile->GetPrefs()->GetBoolean(prefs::kDevToolsOpenDocked);
1145 if (dock_side == kOldPrefBottom)
1146 return docked ? DEVTOOLS_DOCK_SIDE_BOTTOM : DEVTOOLS_DOCK_SIDE_UNDOCKED;
1147 else
1148 return docked ? DEVTOOLS_DOCK_SIDE_RIGHT : DEVTOOLS_DOCK_SIDE_UNDOCKED;
1149 }
1150
1151 if (dock_side == kPrefUndocked)
1152 return DEVTOOLS_DOCK_SIDE_UNDOCKED;
1153 else if (dock_side == kPrefRight)
1154 return DEVTOOLS_DOCK_SIDE_RIGHT;
1155 // Default to docked to bottom
1156 return DEVTOOLS_DOCK_SIDE_BOTTOM;
1157 } 1217 }
1158 1218
1159 // static 1219 content::WebContents* DevToolsWindow::GetInspectedWebContents() {
1160 std::string DevToolsWindow::SideToString(DevToolsDockSide dock_side) { 1220 if (!inspected_contents_observer_)
1161 std::string dock_side_string; 1221 return NULL;
1162 switch (dock_side) { 1222 return inspected_contents_observer_->web_contents();
1163 case DEVTOOLS_DOCK_SIDE_UNDOCKED: return kDockSideUndocked;
1164 case DEVTOOLS_DOCK_SIDE_RIGHT: return kDockSideRight;
1165 case DEVTOOLS_DOCK_SIDE_BOTTOM: return kDockSideBottom;
1166 case DEVTOOLS_DOCK_SIDE_MINIMIZED: return kDockSideMinimized;
1167 }
1168 return kDockSideUndocked;
1169 } 1223 }
1170
1171 // static
1172 DevToolsDockSide DevToolsWindow::SideFromString(
1173 const std::string& dock_side) {
1174 if (dock_side == kDockSideRight)
1175 return DEVTOOLS_DOCK_SIDE_RIGHT;
1176 if (dock_side == kDockSideBottom)
1177 return DEVTOOLS_DOCK_SIDE_BOTTOM;
1178 if (dock_side == kDockSideMinimized)
1179 return DEVTOOLS_DOCK_SIDE_MINIMIZED;
1180 return DEVTOOLS_DOCK_SIDE_UNDOCKED;
1181 }
OLDNEW
« no previous file with comments | « chrome/browser/devtools/devtools_window.h ('k') | chrome/browser/media/chrome_media_stream_infobar_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698