Close detached DevTools window (rather than open a new instance) when it receives an F12 keypress


BUG=139581
TEST=manual


Review URL: https://chromiumcodereview.appspot.com/10823233

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@154694 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index 081479f..f9d6832a 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -182,6 +182,7 @@
 #define IDC_EXTENSION_ERRORS            40031
 #define IDC_SHOW_SYNC_ERROR             40032
 #define IDC_SHOW_SETTINGS_CHANGE_FIRST  40033
+#define IDC_DEV_TOOLS_TOGGLE            40034
 #define IDC_SHOW_SETTINGS_CHANGE_LAST   40133
 #define IDC_SHOW_AVATAR_MENU            40134
 #define IDC_EXTENSION_DISABLED_FIRST    40135
diff --git a/chrome/browser/debugger/devtools_sanity_browsertest.cc b/chrome/browser/debugger/devtools_sanity_browsertest.cc
index c063d32..a549360 100644
--- a/chrome/browser/debugger/devtools_sanity_browsertest.cc
+++ b/chrome/browser/debugger/devtools_sanity_browsertest.cc
@@ -383,7 +383,7 @@
   void OpenDevToolsWindowForSharedWorker(WorkerData* worker_data) {
     Profile* profile = browser()->profile();
     window_ = DevToolsWindow::CreateDevToolsWindowForWorker(profile);
-    window_->Show(DEVTOOLS_TOGGLE_ACTION_NONE);
+    window_->Show(DEVTOOLS_TOGGLE_ACTION_SHOW);
     DevToolsAgentHost* agent_host =
         DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker(
             worker_data->worker_process_id,
diff --git a/chrome/browser/debugger/devtools_toggle_action.h b/chrome/browser/debugger/devtools_toggle_action.h
index a083cf1..83fbb5f 100644
--- a/chrome/browser/debugger/devtools_toggle_action.h
+++ b/chrome/browser/debugger/devtools_toggle_action.h
@@ -6,9 +6,10 @@
 #define CHROME_BROWSER_DEBUGGER_DEVTOOLS_TOGGLE_ACTION_H_
 
 enum DevToolsToggleAction {
-  DEVTOOLS_TOGGLE_ACTION_NONE,
+  DEVTOOLS_TOGGLE_ACTION_SHOW,
   DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE,
-  DEVTOOLS_TOGGLE_ACTION_INSPECT
+  DEVTOOLS_TOGGLE_ACTION_INSPECT,
+  DEVTOOLS_TOGGLE_ACTION_TOGGLE
 };
 
 #endif  // CHROME_BROWSER_DEBUGGER_DEVTOOLS_TOGGLE_ACTION_H_
diff --git a/chrome/browser/debugger/devtools_window.cc b/chrome/browser/debugger/devtools_window.cc
index ce7194f..f8a5d15 100644
--- a/chrome/browser/debugger/devtools_window.cc
+++ b/chrome/browser/debugger/devtools_window.cc
@@ -103,15 +103,7 @@
 
 // static
 bool DevToolsWindow::IsDevToolsWindow(RenderViewHost* window_rvh) {
-  if (g_instances == NULL)
-    return false;
-  DevToolsWindowList& instances = g_instances.Get();
-  for (DevToolsWindowList::iterator it = instances.begin();
-       it != instances.end(); ++it) {
-    if ((*it)->tab_contents_->web_contents()->GetRenderViewHost() == window_rvh)
-      return true;
-  }
-  return false;
+  return AsDevToolsWindow(window_rvh) != NULL;
 }
 
 // static
@@ -131,7 +123,7 @@
         worker_agent,
         window->frontend_host_);
   }
-  window->Show(DEVTOOLS_TOGGLE_ACTION_NONE);
+  window->Show(DEVTOOLS_TOGGLE_ACTION_SHOW);
   return window;
 }
 
@@ -145,16 +137,23 @@
 DevToolsWindow* DevToolsWindow::OpenDevToolsWindow(
     RenderViewHost* inspected_rvh) {
   return ToggleDevToolsWindow(inspected_rvh, true,
-                              DEVTOOLS_TOGGLE_ACTION_NONE);
+                              DEVTOOLS_TOGGLE_ACTION_SHOW);
 }
 
 // static
 DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow(
-    RenderViewHost* inspected_rvh,
+    Browser* browser,
     DevToolsToggleAction action) {
+  if (action == DEVTOOLS_TOGGLE_ACTION_TOGGLE && browser->is_devtools()) {
+    chrome::CloseAllTabs(browser);
+    return NULL;
+  }
+  RenderViewHost* inspected_rvh =
+      chrome::GetActiveWebContents(browser)->GetRenderViewHost();
+
   return ToggleDevToolsWindow(inspected_rvh,
-                              action == DEVTOOLS_TOGGLE_ACTION_INSPECT,
-                              action);
+                       action == DEVTOOLS_TOGGLE_ACTION_INSPECT,
+                       action);
 }
 
 void DevToolsWindow::InspectElement(RenderViewHost* inspected_rvh,
@@ -197,7 +196,7 @@
       browser_(NULL),
       docked_(docked),
       is_loaded_(false),
-      action_on_load_(DEVTOOLS_TOGGLE_ACTION_NONE) {
+      action_on_load_(DEVTOOLS_TOGGLE_ACTION_SHOW) {
   frontend_host_ = DevToolsClientHost::CreateDevToolsFrontendHost(
       tab_contents->web_contents(),
       this);
@@ -349,7 +348,7 @@
       inspected_window = NULL;
     }
   }
-  Show(DEVTOOLS_TOGGLE_ACTION_NONE);
+  Show(DEVTOOLS_TOGGLE_ACTION_SHOW);
 }
 
 RenderViewHost* DevToolsWindow::GetRenderViewHost() {
@@ -514,13 +513,14 @@
       break;
     case DEVTOOLS_TOGGLE_ACTION_INSPECT:
       CallClientFunction("InspectorFrontendAPI.enterInspectElementMode", NULL);
-    case DEVTOOLS_TOGGLE_ACTION_NONE:
+    case DEVTOOLS_TOGGLE_ACTION_SHOW:
+    case DEVTOOLS_TOGGLE_ACTION_TOGGLE:
       // Do nothing.
       break;
     default:
       NOTREACHED();
   }
-  action_on_load_ = DEVTOOLS_TOGGLE_ACTION_NONE;
+  action_on_load_ = DEVTOOLS_TOGGLE_ACTION_SHOW;
 }
 
 std::string SkColorToRGBAString(SkColor color) {
@@ -623,7 +623,7 @@
   DevToolsManager* manager = DevToolsManager::GetInstance();
   DevToolsClientHost* host = manager->GetDevToolsClientHostFor(agent);
   DevToolsWindow* window = AsDevToolsWindow(host);
-  if (host != NULL && window == NULL) {
+  if (host && !window) {
     // Break remote debugging / extension debugging session.
     manager->UnregisterDevToolsClientHostFor(agent);
   }
@@ -665,6 +665,19 @@
   return NULL;
 }
 
+// static
+DevToolsWindow* DevToolsWindow::AsDevToolsWindow(RenderViewHost* window_rvh) {
+  if (g_instances == NULL)
+    return NULL;
+  DevToolsWindowList& instances = g_instances.Get();
+  for (DevToolsWindowList::iterator it = instances.begin();
+       it != instances.end(); ++it) {
+    if ((*it)->tab_contents_->web_contents()->GetRenderViewHost() == window_rvh)
+      return *it;
+  }
+  return NULL;
+}
+
 void DevToolsWindow::ActivateWindow() {
   if (!docked_) {
     if (!browser_->window()->IsActive()) {
diff --git a/chrome/browser/debugger/devtools_window.h b/chrome/browser/debugger/devtools_window.h
index dfe73ab..ef5cc38d 100644
--- a/chrome/browser/debugger/devtools_window.h
+++ b/chrome/browser/debugger/devtools_window.h
@@ -57,7 +57,13 @@
   static DevToolsWindow* OpenDevToolsWindow(
       content::RenderViewHost* inspected_rvh);
   static DevToolsWindow* ToggleDevToolsWindow(
+      Browser* browser,
+      DevToolsToggleAction action);
+
+  // Exposed for testing, normal clients should not use this method.
+  static DevToolsWindow* ToggleDevToolsWindow(
       content::RenderViewHost* inspected_rvh,
+      bool force_open,
       DevToolsToggleAction action);
   static void InspectElement(
       content::RenderViewHost* inspected_rvh, int x, int y);
@@ -129,11 +135,8 @@
 
   virtual void FrameNavigating(const std::string& url) OVERRIDE {}
 
-  static DevToolsWindow* ToggleDevToolsWindow(
-      content::RenderViewHost* inspected_rvh,
-      bool force_open,
-      DevToolsToggleAction action);
   static DevToolsWindow* AsDevToolsWindow(content::DevToolsClientHost*);
+  static DevToolsWindow* AsDevToolsWindow(content::RenderViewHost*);
 
   // content::DevToolsClientHandlerDelegate overrides.
   virtual void ActivateWindow() OVERRIDE;
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
index 9a527c9..a98bb1a 100644
--- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
+++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -305,7 +305,7 @@
 
   // DevTools start in a separate process.
   DevToolsWindow::ToggleDevToolsWindow(
-      devtools, DEVTOOLS_TOGGLE_ACTION_INSPECT);
+      devtools, true, DEVTOOLS_TOGGLE_ACTION_INSPECT);
   host_count++;
   EXPECT_EQ(tab_count, browser()->tab_count());
   EXPECT_EQ(host_count, RenderProcessHostCount());
@@ -338,7 +338,7 @@
 
   // DevTools start in a separate process.
   DevToolsWindow::ToggleDevToolsWindow(
-      devtools, DEVTOOLS_TOGGLE_ACTION_INSPECT);
+      devtools, true, DEVTOOLS_TOGGLE_ACTION_INSPECT);
   host_count++;
   EXPECT_EQ(tab_count, browser()->tab_count());
   EXPECT_EQ(host_count, RenderProcessHostCount());
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index c6c553b1..fec9e70e 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -488,7 +488,7 @@
       CreateApplicationShortcuts(browser_);
       break;
     case IDC_DEV_TOOLS:
-      ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_NONE);
+      ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_SHOW);
       break;
     case IDC_DEV_TOOLS_CONSOLE:
       ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE);
@@ -496,6 +496,9 @@
     case IDC_DEV_TOOLS_INSPECT:
       ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_INSPECT);
       break;
+    case IDC_DEV_TOOLS_TOGGLE:
+      ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_TOGGLE);
+      break;
     case IDC_TASK_MANAGER:
       OpenTaskManager(browser_, false);
       break;
@@ -930,6 +933,8 @@
                                         dev_tools_enabled);
   command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_INSPECT,
                                         dev_tools_enabled);
+  command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_TOGGLE,
+                                        dev_tools_enabled);
 }
 
 void BrowserCommandController::UpdateCommandsForBookmarkEditing() {
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index 29e40b4..6e77ea7 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -820,10 +820,7 @@
     content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
   else
     content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
-
-  DevToolsWindow::ToggleDevToolsWindow(
-      GetActiveWebContents(browser)->GetRenderViewHost(),
-      action);
+  DevToolsWindow::ToggleDevToolsWindow(browser, action);
 }
 
 bool CanOpenTaskManager() {
diff --git a/chrome/browser/ui/gtk/accelerators_gtk.cc b/chrome/browser/ui/gtk/accelerators_gtk.cc
index b33abf7..d1116b3 100644
--- a/chrome/browser/ui/gtk/accelerators_gtk.cc
+++ b/chrome/browser/ui/gtk/accelerators_gtk.cc
@@ -135,7 +135,7 @@
   { GDK_u, IDC_VIEW_SOURCE, GDK_CONTROL_MASK },
   { GDK_i, IDC_DEV_TOOLS,
     GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
-  { GDK_F12, IDC_DEV_TOOLS, GdkModifierType(0) },
+  { GDK_F12, IDC_DEV_TOOLS_TOGGLE, GdkModifierType(0) },
   { GDK_j, IDC_DEV_TOOLS_CONSOLE,
     GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
   { GDK_c, IDC_DEV_TOOLS_INSPECT,
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc
index 1476d4bf..3c5b056 100644
--- a/chrome/browser/ui/views/accelerator_table.cc
+++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -34,7 +34,7 @@
   { ui::VKEY_RIGHT, ui::EF_ALT_DOWN, IDC_FORWARD },
   { ui::VKEY_BACK, ui::EF_SHIFT_DOWN, IDC_FORWARD },
   { ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_DEV_TOOLS },
-  { ui::VKEY_F12, ui::EF_NONE, IDC_DEV_TOOLS },
+  { ui::VKEY_F12, ui::EF_NONE, IDC_DEV_TOOLS_TOGGLE },
   { ui::VKEY_J, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
     IDC_DEV_TOOLS_CONSOLE },
   { ui::VKEY_C, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
diff --git a/chrome/browser/ui/views/extensions/extension_popup.cc b/chrome/browser/ui/views/extensions/extension_popup.cc
index f730556..9184a714 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.cc
+++ b/chrome/browser/ui/views/extensions/extension_popup.cc
@@ -213,6 +213,7 @@
 
   if (inspect_with_devtools_) {
     DevToolsWindow::ToggleDevToolsWindow(host()->render_view_host(),
+        true,
         DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE);
   }
 }
diff --git a/chrome/browser/ui/views/external_tab_container_win.cc b/chrome/browser/ui/views/external_tab_container_win.cc
index 9944a7a..5a960cb2 100644
--- a/chrome/browser/ui/views/external_tab_container_win.cc
+++ b/chrome/browser/ui/views/external_tab_container_win.cc
@@ -1069,18 +1069,27 @@
     case IDC_DEV_TOOLS:
       DevToolsWindow::ToggleDevToolsWindow(
           tab_contents_->web_contents()->GetRenderViewHost(),
-          DEVTOOLS_TOGGLE_ACTION_NONE);
+          false,
+          DEVTOOLS_TOGGLE_ACTION_SHOW);
       break;
     case IDC_DEV_TOOLS_CONSOLE:
       DevToolsWindow::ToggleDevToolsWindow(
           tab_contents_->web_contents()->GetRenderViewHost(),
+          false,
           DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE);
       break;
     case IDC_DEV_TOOLS_INSPECT:
       DevToolsWindow::ToggleDevToolsWindow(
           tab_contents_->web_contents()->GetRenderViewHost(),
+          false,
           DEVTOOLS_TOGGLE_ACTION_INSPECT);
       break;
+    case IDC_DEV_TOOLS_TOGGLE:
+      DevToolsWindow::ToggleDevToolsWindow(
+          tab_contents_->web_contents()->GetRenderViewHost(),
+          false,
+          DEVTOOLS_TOGGLE_ACTION_TOGGLE);
+      break;
     default:
       NOTREACHED() << "Unsupported accelerator: " << command_id;
       return false;