devtools_window.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/devtools/devtools_window.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/debugger/debugger_api.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/file_select_helper.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/infobars/confirm_infobar_delegate.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/prefs/pref_service_syncable.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/scoped_user_pref_update.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_tab_helper.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/themes/theme_properties.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/themes/theme_service.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/themes/theme_service_factory.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/webui/devtools_ui.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/manifest_url_handler.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/render_messages.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h"
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/child_process_security_policy.h"
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/devtools_agent_host.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/devtools_client_host.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/devtools_manager.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/favicon_status.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/load_notification_details.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/bindings_policy.h"
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_client.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/page_transition_types.h"
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/url_constants.h"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::vector<DevToolsWindow*> DevToolsWindowList;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<DevToolsWindowList>::Leaky
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     g_instances = LAZY_INSTANCE_INITIALIZER;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::Bind;
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::Callback;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DevToolsAgentHost;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DevToolsClientHost;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DevToolsManager;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::FileChooserParams;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NativeWebKeyboardEvent;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::OpenURLParams;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char DevToolsWindow::kDevToolsApp[] = "DevToolsApp";
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kOldPrefBottom[] = "bottom";
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kOldPrefRight[] = "right";
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefBottom[] = "dock_bottom";
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefRight[] = "dock_right";
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrefUndocked[] = "undocked";
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDockSideBottom[] = "bottom";
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDockSideRight[] = "right";
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDockSideUndocked[] = "undocked";
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kDockSideMinimized[] = "minimized";
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Minimal height of devtools pane or content pane when devtools are docked
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the browser window.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinDevToolsHeight = 50;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinDevToolsWidth = 150;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinContentsSize = 50;
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kMinimizedDevToolsHeight = 24;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DevToolsWindow::InspectedWebContentsObserver
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : public content::WebContentsObserver {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit InspectedWebContentsObserver(content::WebContents* web_contents)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : WebContentsObserver(web_contents) {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* Get() { return web_contents(); }
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DevToolsWindow::FrontendWebContentsObserver
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : public content::WebContentsObserver {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit FrontendWebContentsObserver(content::WebContents* web_contents)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : WebContentsObserver(web_contents) {
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overriden from contents::WebContentsObserver.
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void AboutToNavigateRenderView(
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RenderViewHost* render_view_host) OVERRIDE {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::DevToolsClientHost::SetupDevToolsFrontendClient(render_view_host);
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef Callback<void(bool)> ConfirmInfoBarCallback;
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DevToolsConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DevToolsConfirmInfoBarDelegate(
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      InfoBarService* infobar_service,
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const ConfirmInfoBarCallback& callback,
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      string16 message)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : ConfirmInfoBarDelegate(infobar_service),
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        callback_(callback),
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        message_(message) {
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual string16 GetMessageText() const OVERRIDE { return message_; }
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool Accept() OVERRIDE {
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback_.Run(true);
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback_.Reset();
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool Cancel() OVERRIDE {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback_.Run(false);
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback_.Reset();
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE {
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return l10n_util::GetStringUTF16((button == BUTTON_OK)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         ? IDS_DEV_TOOLS_CONFIRM_ALLOW_BUTTON
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         : IDS_DEV_TOOLS_CONFIRM_DENY_BUTTON);
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~DevToolsConfirmInfoBarDelegate() {
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!callback_.is_null()) {
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback_.Run(false);
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConfirmInfoBarCallback callback_;
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  string16 message_;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string DevToolsWindow::GetDevToolsWindowPlacementPrefKey() {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string wp_key;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  wp_key.append(prefs::kBrowserWindowPlacement);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  wp_key.append("_");
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  wp_key.append(kDevToolsApp);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return wp_key;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsWindow::RegisterUserPrefs(
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterBooleanPref(
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kDevToolsOpenDocked,
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      true,
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterStringPref(
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kDevToolsDockSide,
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kDockSideBottom,
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterDictionaryPref(
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kDevToolsEditedFiles,
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterDictionaryPref(
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kDevToolsFileSystemPaths,
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterDictionaryPref(
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetDevToolsWindowPlacementPrefKey().c_str(),
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::GetDockedInstanceForInspectedTab(
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebContents* inspected_web_contents) {
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!inspected_web_contents)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!DevToolsAgentHost::HasFor(inspected_web_contents->GetRenderViewHost()))
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetOrCreateFor(
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      inspected_web_contents->GetRenderViewHost()));
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DevToolsWindow* window = FindDevToolsWindow(agent);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return window && window->IsDocked() ? window : NULL;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DevToolsWindow::IsDevToolsWindow(RenderViewHost* window_rvh) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AsDevToolsWindow(window_rvh) != NULL;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindowForWorker(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DevToolsAgentHost* worker_agent) {
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DevToolsWindow* window = FindDevToolsWindow(worker_agent);
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!window) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window = DevToolsWindow::CreateDevToolsWindowForWorker(profile);
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Will disconnect the current client host if there is one.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        worker_agent,
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window->frontend_host_.get());
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->Show(DEVTOOLS_TOGGLE_ACTION_SHOW);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return window;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::CreateDevToolsWindowForWorker(
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile) {
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Create(profile, GURL(), NULL, DEVTOOLS_DOCK_SIDE_UNDOCKED, true);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindow(
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderViewHost* inspected_rvh) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ToggleDevToolsWindow(inspected_rvh, true,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              DEVTOOLS_TOGGLE_ACTION_SHOW);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow(
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DevToolsToggleAction action) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (action == DEVTOOLS_TOGGLE_ACTION_TOGGLE && browser->is_devtools()) {
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser->tab_strip_model()->CloseAllTabs();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderViewHost* inspected_rvh =
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ToggleDevToolsWindow(inspected_rvh,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       action == DEVTOOLS_TOGGLE_ACTION_INSPECT,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       action);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::InspectElement(RenderViewHost* inspected_rvh,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int x,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int y) {
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent(
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DevToolsAgentHost::GetOrCreateFor(inspected_rvh));
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  agent->InspectElement(x, y);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(loislo): we should initiate DevTools window opening from within
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // renderer. Otherwise, we still can hit a race condition here.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenDevToolsWindow(inspected_rvh);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsWindow::OpenExternalFrontend(
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Profile* profile,
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& frontend_url,
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::DevToolsAgentHost* agent_host) {
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DevToolsWindow* window = FindDevToolsWindow(agent_host);
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!window) {
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window = Create(profile, DevToolsUI::GetProxyURL(frontend_url), NULL,
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    DEVTOOLS_DOCK_SIDE_UNDOCKED, false);
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        agent_host, window->frontend_host_.get());
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  window->Show(DEVTOOLS_TOGGLE_ACTION_SHOW);
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::Create(
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GURL& frontend_url,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderViewHost* inspected_rvh,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DevToolsDockSide dock_side,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool shared_worker_frontend) {
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create WebContents with devtools.
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL url = GetDevToolsURL(profile, frontend_url, dock_side,
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            shared_worker_frontend);
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return new DevToolsWindow(profile, url, inspected_rvh, dock_side);
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DevToolsWindow::DevToolsWindow(Profile* profile,
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               const GURL& url,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               RenderViewHost* inspected_rvh,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               DevToolsDockSide dock_side)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile),
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_(NULL),
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dock_side_(dock_side),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_loaded_(false),
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      action_on_load_(DEVTOOLS_TOGGLE_ACTION_SHOW),
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this),
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      width_(-1),
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      height_(-1),
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dock_side_before_minimized_(dock_side) {
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  web_contents_ = WebContents::Create(WebContents::CreateParams(profile));
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  frontend_contents_observer_.reset(
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new FrontendWebContentsObserver(web_contents_));
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  web_contents_->GetController().LoadURL(url, content::Referrer(),
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (url.host() == chrome::kChromeUIDevToolsBundledHost) {
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Only allow file scheme in embedded front-end by default.
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int process_id = render_view_host->GetProcess()->GetID();
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        process_id, chrome::kFileScheme);
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frontend_host_.reset(
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DevToolsClientHost::CreateDevToolsFrontendHost(web_contents_, this));
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  file_helper_.reset(new DevToolsFileHelper(web_contents_, profile));
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_instances.Get().push_back(this);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wipe out page icon so that the default application icon is used.
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NavigationEntry* entry = web_contents_->GetController().GetActiveEntry();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->GetFavicon().image = gfx::Image();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->GetFavicon().valid = true;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register on-load actions.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NOTIFICATION_LOAD_STOP,
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::Source<NavigationController>(&web_contents_->GetController()));
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_TAB_CLOSING,
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::Source<NavigationController>(&web_contents_->GetController()));
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<ThemeService>(
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ThemeServiceFactory::GetForProfile(profile_)));
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no inspected_rvh in case of shared workers.
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (inspected_rvh)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    inspected_contents_observer_.reset(new InspectedWebContentsObserver(
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        WebContents::FromRenderViewHost(inspected_rvh)));
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow::~DevToolsWindow() {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DevToolsWindowList& instances = g_instances.Get();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DevToolsWindowList::iterator it = std::find(instances.begin(),
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              instances.end(),
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              this);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != instances.end());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instances.erase(it);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)content::WebContents* DevToolsWindow::GetInspectedWebContents() {
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!inspected_contents_observer_)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return inspected_contents_observer_->Get();
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::InspectedContentsClosing() {
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Hide();
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsWindow::Hide() {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDocked()) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update dev tools to reflect removed dev tools window.
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserWindow* inspected_window = GetInspectedBrowserWindow();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inspected_window)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inspected_window->UpdateDevTools();
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // In case of docked web_contents_, we own it so delete here.
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete web_contents_;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First, initiate self-destruct to free all the registrars.
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Then close all tabs. Browser will take care of deleting web_contents_
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for us.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser = browser_;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser->tab_strip_model()->CloseAllTabs();
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::Show(DevToolsToggleAction action) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDocked()) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* inspected_browser;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int inspected_tab_index;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tell inspected browser to update splitter and switch to inspected panel.
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!IsInspectedBrowserPopup() &&
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FindInspectedBrowserAndTabIndex(&inspected_browser,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &inspected_tab_index)) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserWindow* inspected_window = inspected_browser->window();
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      web_contents_->SetDelegate(this);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inspected_window->UpdateDevTools();
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      web_contents_->GetView()->SetInitialFocus();
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inspected_window->Show();
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TabStripModel* tab_strip_model = inspected_browser->tab_strip_model();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_strip_model->ActivateTabAt(inspected_tab_index, true);
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      PrefsTabHelper::CreateForWebContents(web_contents_);
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetRenderViewHost()->SyncRendererPrefs();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScheduleAction(action);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Sometimes we don't know where to dock. Stay undocked.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dock_side_ = DEVTOOLS_DOCK_SIDE_UNDOCKED;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Avoid consecutive window switching if the devtools window has been opened
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and the Inspect Element shortcut is pressed in the inspected tab.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool should_show_window =
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !browser_ || action != DEVTOOLS_TOGGLE_ACTION_INSPECT;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!browser_)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateDevToolsBrowser();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_show_window) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser_->window()->Show();
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    web_contents_->GetView()->SetInitialFocus();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleAction(action);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsClientHost* DevToolsWindow::GetDevToolsClientHostForTest() {
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return frontend_host_.get();
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DevToolsWindow::GetWidth(int container_width) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (width_ == -1) {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width_ = profile_->GetPrefs()->
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetInteger(prefs::kDevToolsVSplitLocation);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By default, size devtools as 1/3 of the browser window.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (width_ == -1)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width_ = container_width / 3;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Respect the minimum devtools width preset.
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width_ = std::max(kMinDevToolsWidth, width_);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But it should never compromise the content window size unless the entire
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // window is tiny.
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width_ = std::min(container_width - kMinContentsSize, width_);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return width_;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DevToolsWindow::GetHeight(int container_height) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (height_ == -1) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    height_ = profile_->GetPrefs()->
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetInteger(prefs::kDevToolsHSplitLocation);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By default, size devtools as 1/3 of the browser window.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (height_ == -1)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    height_ = container_height / 3;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Respect the minimum devtools width preset.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  height_ = std::max(kMinDevToolsHeight, height_);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But it should never compromise the content window size.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  height_ = std::min(container_height - kMinContentsSize, height_);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return height_;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int DevToolsWindow::GetMinimumWidth() {
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return kMinDevToolsWidth;
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int DevToolsWindow::GetMinimumHeight() {
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return kMinDevToolsHeight;
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::SetWidth(int width) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width_ = width;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetPrefs()->SetInteger(prefs::kDevToolsVSplitLocation, width);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::SetHeight(int height) {
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  height_ = height;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetPrefs()->SetInteger(prefs::kDevToolsHSplitLocation, height);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int DevToolsWindow::GetMinimizedHeight() {
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return kMinimizedDevToolsHeight;
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RenderViewHost* DevToolsWindow::GetRenderViewHost() {
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_contents_->GetRenderViewHost();
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::CreateDevToolsBrowser() {
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string wp_key = GetDevToolsWindowPlacementPrefKey();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* prefs = profile_->GetPrefs();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DictionaryValue* wp_pref = prefs->GetDictionary(wp_key.c_str());
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!wp_pref || wp_pref->empty()) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryPrefUpdate update(prefs, wp_key.c_str());
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* defaults = update.Get();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defaults->SetInteger("left", 100);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defaults->SetInteger("top", 100);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defaults->SetInteger("right", 740);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defaults->SetInteger("bottom", 740);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defaults->SetBoolean("maximized", false);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defaults->SetBoolean("always_on_top", false);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::HostDesktopType host_desktop_type =
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome::GetHostDesktopTypeForNativeView(
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          web_contents_->GetView()->GetNativeView());
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser_ = new Browser(Browser::CreateParams::CreateForDevTools(
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             profile_, host_desktop_type));
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser_->tab_strip_model()->AddWebContents(
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      web_contents_, -1, content::PAGE_TRANSITION_AUTO_TOPLEVEL,
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TabStripModel::ADD_ACTIVE);
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GetRenderViewHost()->SyncRendererPrefs();
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DevToolsWindow::FindInspectedBrowserAndTabIndex(Browser** browser,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     int* tab) {
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!inspected_web_contents)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int tab_index = it->tab_strip_model()->GetIndexOfWebContents(
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        inspected_web_contents);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tab_index != TabStripModel::kNoTab) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *browser = *it;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *tab = tab_index;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* browser = NULL;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tab;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindInspectedBrowserAndTabIndex(&browser, &tab) ?
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser->window() : NULL;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DevToolsWindow::IsInspectedBrowserPopup() {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* browser = NULL;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tab;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FindInspectedBrowserAndTabIndex(&browser, &tab))
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return browser->is_type_popup();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::UpdateFrontendDockSide() {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringValue dock_side(SideToString(dock_side_));
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.setDockSide", &dock_side);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FundamentalValue docked(IsDocked());
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.setAttachedWindow", &docked);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::AddDevToolsExtensionsToClient() {
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (inspected_web_contents) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionTabHelper* session_tab_helper =
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SessionTabHelper::FromWebContents(inspected_web_contents);
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (session_tab_helper) {
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FundamentalValue tabId(session_tab_helper->session_id().id());
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CallClientFunction("WebInspector.setInspectedTabId", &tabId);
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue results;
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Profile* profile =
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Profile::FromBrowserContext(web_contents_->GetBrowserContext());
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ExtensionService* extension_service = extensions::ExtensionSystem::Get(
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile->GetOriginalProfile())->extension_service();
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_service)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ExtensionSet* extensions = extension_service->extensions();
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExtensionSet::const_iterator extension = extensions->begin();
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       extension != extensions->end(); ++extension) {
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (extensions::ManifestURL::GetDevToolsPage(*extension).is_empty())
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* extension_info = new DictionaryValue();
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    extension_info->Set("startPage", new StringValue(
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extensions::ManifestURL::GetDevToolsPage(*extension).spec()));
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_info->Set("name", new StringValue((*extension)->name()));
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allow_experimental = (*extension)->HasAPIPermission(
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions::APIPermission::kExperimental);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_info->Set("exposeExperimentalAPIs",
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new base::FundamentalValue(allow_experimental));
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results.Append(extension_info);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallClientFunction("WebInspector.addExtensions", &results);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebContents* DevToolsWindow::OpenURLFromTab(WebContents* source,
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const OpenURLParams& params) {
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.url.SchemeIs(chrome::kChromeDevToolsScheme)) {
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::WebContents* inspected_web_contents = GetInspectedWebContents();
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (inspected_web_contents)
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return inspected_web_contents->OpenURL(params);
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DevToolsManager* manager = DevToolsManager::GetInstance();
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent_host(
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      manager->GetDevToolsAgentHostFor(frontend_host_.get()));
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!agent_host)
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  manager->ClientHostClosing(frontend_host_.get());
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  manager->RegisterDevToolsClientHostFor(agent_host, frontend_host_.get());
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::NavigateParams nav_params(profile_, params.url, params.transition);
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FillNavigateParamsFromOpenURLParams(&nav_params, params);
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nav_params.source_contents = source;
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nav_params.tabstrip_add_types = TabStripModel::ADD_NONE;
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nav_params.window_action = chrome::NavigateParams::SHOW_WINDOW;
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  nav_params.user_gesture = true;
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::Navigate(&nav_params);
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return nav_params.target_contents;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::CallClientFunction(const std::string& function_name,
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const Value* arg1,
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const Value* arg2) {
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string params;
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (arg1) {
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string json;
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::JSONWriter::Write(arg1, &json);
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.append(json);
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (arg2) {
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::JSONWriter::Write(arg2, &json);
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.append(", " + json);
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  string16 javascript = ASCIIToUTF16(function_name + "(" + params + ");");
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  web_contents_->GetRenderViewHost()->
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExecuteJavascriptInWebFrame(string16(), javascript);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::Observe(int type,
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationSource& source,
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationDetails& details) {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == content::NOTIFICATION_LOAD_STOP && !is_loaded_) {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_loaded_ = true;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTheme();
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoAction();
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddDevToolsExtensionsToClient();
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (type == chrome::NOTIFICATION_TAB_CLOSING) {
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (content::Source<NavigationController>(source).ptr() ==
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &web_contents_->GetController()) {
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This happens when browser closes all of its tabs as a result
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // of window.Close event.
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Notify manager that this DevToolsClientHost no longer exists and
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // initiate self-destuct here.
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_.get());
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateBrowserToolbar();
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete this;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateTheme();
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::ScheduleAction(DevToolsToggleAction action) {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action_on_load_ = action;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_loaded_)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoAction();
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::DoAction() {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateFrontendDockSide();
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (action_on_load_) {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE:
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CallClientFunction("InspectorFrontendAPI.showConsole", NULL);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEVTOOLS_TOGGLE_ACTION_INSPECT:
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CallClientFunction("InspectorFrontendAPI.enterInspectElementMode", NULL);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEVTOOLS_TOGGLE_ACTION_SHOW:
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEVTOOLS_TOGGLE_ACTION_TOGGLE:
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Do nothing.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action_on_load_ = DEVTOOLS_TOGGLE_ACTION_SHOW;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string SkColorToRGBAString(SkColor color) {
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We convert the alpha using DoubleToString because StringPrintf will use
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // locale specific formatters (e.g., use , instead of . in German).
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::StringPrintf("rgba(%d,%d,%d,%s)", SkColorGetR(color),
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkColorGetG(color), SkColorGetB(color),
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::DoubleToString(SkColorGetA(color) / 255.0).c_str());
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL DevToolsWindow::GetDevToolsURL(Profile* profile,
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    const GURL& base_url,
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    DevToolsDockSide dock_side,
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool shared_worker_frontend) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThemeService* tp = ThemeServiceFactory::GetForProfile(profile);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(tp);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkColor color_toolbar =
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkColor color_tab_text =
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool experiments_enabled =
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(switches::kEnableDevToolsExperiments);
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string frontend_url = base_url.is_empty() ?
739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chrome::kChromeUIDevToolsURL : base_url.spec();
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string params_separator =
741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frontend_url.find("?") == std::string::npos ? "?" : "&";
742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string url_string = base::StringPrintf("%s%s"
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "dockSide=%s&toolbarColor=%s&textColor=%s%s%s",
744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frontend_url.c_str(),
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params_separator.c_str(),
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SideToString(dock_side).c_str(),
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkColorToRGBAString(color_toolbar).c_str(),
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkColorToRGBAString(color_tab_text).c_str(),
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shared_worker_frontend ? "&isSharedWorker=true" : "",
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      experiments_enabled ? "&experiments=true" : "");
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL(url_string);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::UpdateTheme() {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(tp);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkColor color_toolbar =
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkColor color_tab_text =
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string command = base::StringPrintf(
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "InspectorFrontendAPI.setToolbarColors(\"%s\", \"%s\")",
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkColorToRGBAString(color_toolbar).c_str(),
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkColorToRGBAString(color_tab_text).c_str());
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  web_contents_->GetRenderViewHost()->
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(command));
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::AddNewContents(WebContents* source,
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WebContents* new_contents,
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WindowOpenDisposition disposition,
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const gfx::Rect& initial_pos,
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool user_gesture,
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool* was_blocked) {
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (inspected_web_contents) {
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    inspected_web_contents->GetDelegate()->AddNewContents(
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        source, new_contents, disposition, initial_pos, user_gesture,
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        was_blocked);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DevToolsWindow::PreHandleKeyboardEvent(
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebContents* source,
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDocked()) {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserWindow* inspected_window = GetInspectedBrowserWindow();
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inspected_window)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return inspected_window->PreHandleKeyboardEvent(
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          event, is_keyboard_shortcut);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::HandleKeyboardEvent(WebContents* source,
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const NativeWebKeyboardEvent& event) {
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDocked()) {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event.windowsKeyCode == 0x08) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Do not navigate back in history on Windows (http://crbug.com/74156).
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserWindow* inspected_window = GetInspectedBrowserWindow();
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inspected_window)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inspected_window->HandleKeyboardEvent(event);
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow(
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderViewHost* inspected_rvh,
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool force_open,
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DevToolsToggleAction action) {
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent(
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DevToolsAgentHost::GetOrCreateFor(inspected_rvh));
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DevToolsManager* manager = DevToolsManager::GetInstance();
817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DevToolsWindow* window = FindDevToolsWindow(agent);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool do_open = force_open;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!window) {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile = Profile::FromBrowserContext(
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        inspected_rvh->GetProcess()->GetBrowserContext());
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DevToolsDockSide dock_side = GetDockSideFromPrefs(profile);
823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window = Create(profile, GURL(), inspected_rvh, dock_side, false);
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager->RegisterDevToolsClientHostFor(agent, window->frontend_host_.get());
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do_open = true;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update toolbar to reflect DevTools changes.
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->UpdateBrowserToolbar();
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If window is docked and visible, we hide it on toggle. If window is
832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // undocked, we show (activate) it. If window is minimized, we maximize it.
833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (window->dock_side_ == DEVTOOLS_DOCK_SIDE_MINIMIZED)
834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window->Restore();
835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else if (!window->IsDocked() || do_open)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->Show(action);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window->CloseWindow();
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return window;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
844c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DevToolsWindow* DevToolsWindow::FindDevToolsWindow(
845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DevToolsAgentHost* agent_host) {
846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DevToolsManager* manager = DevToolsManager::GetInstance();
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DevToolsWindowList& instances = g_instances.Get();
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (DevToolsWindowList::iterator it = instances.begin();
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != instances.end(); ++it) {
850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (manager->GetDevToolsAgentHostFor((*it)->frontend_host_.get()) ==
851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        agent_host)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return *it;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::AsDevToolsWindow(RenderViewHost* window_rvh) {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_instances == NULL)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DevToolsWindowList& instances = g_instances.Get();
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (DevToolsWindowList::iterator it = instances.begin();
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != instances.end(); ++it) {
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*it)->web_contents_->GetRenderViewHost() == window_rvh)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return *it;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::ActivateWindow() {
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsDocked()) {
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!browser_->window()->IsActive()) {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_->window()->Activate();
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserWindow* inspected_window = GetInspectedBrowserWindow();
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inspected_window)
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      web_contents_->GetView()->Focus();
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::ChangeAttachedWindowHeight(unsigned height) {
883b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  NOTREACHED(); // TODO(dgozman). This is not used anymore, remove.
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::CloseWindow() {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsDocked());
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_.get());
889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Hide();
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::MoveWindow(int x, int y) {
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsDocked()) {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect bounds = browser_->window()->GetBounds();
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds.Offset(x, y);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser_->window()->SetBounds(bounds);
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::SetDockSide(const std::string& side) {
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DevToolsDockSide requested_side = SideFromString(side);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool dock_requested = requested_side != DEVTOOLS_DOCK_SIDE_UNDOCKED;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_docked = IsDocked();
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dock_requested && (!inspected_web_contents ||
907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !GetInspectedBrowserWindow() || IsInspectedBrowserPopup())) {
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Cannot dock, avoid window flashing due to close-reopen cycle.
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (dock_side_ != DEVTOOLS_DOCK_SIDE_MINIMIZED &&
913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      requested_side == DEVTOOLS_DOCK_SIDE_MINIMIZED) {
914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dock_side_before_minimized_ = dock_side_;
915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
916c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dock_side_ = requested_side;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dock_requested) {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!is_docked) {
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Detach window from the external devtools browser. It will lead to
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the browser object's close and delete. Remove observer first.
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TabStripModel* tab_strip_model = browser_->tab_strip_model();
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tab_strip_model->DetachWebContentsAt(
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tab_strip_model->GetIndexOfWebContents(web_contents_));
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_ = NULL;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_docked) {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update inspected window to hide split and reset it.
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserWindow* inspected_window = GetInspectedBrowserWindow();
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inspected_window)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inspected_window->UpdateDevTools();
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
934c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (dock_side_ != DEVTOOLS_DOCK_SIDE_MINIMIZED) {
935c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string pref_value = kPrefBottom;
936c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (dock_side_) {
937c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case DEVTOOLS_DOCK_SIDE_UNDOCKED:
938c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          pref_value = kPrefUndocked;
939c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          break;
940c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case DEVTOOLS_DOCK_SIDE_RIGHT:
941c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          pref_value = kPrefRight;
942c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          break;
943c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case DEVTOOLS_DOCK_SIDE_BOTTOM:
944c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          pref_value = kPrefBottom;
945c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          break;
946c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case DEVTOOLS_DOCK_SIDE_MINIMIZED:
947c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          // We don't persist minimized state.
948c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          break;
949c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
950c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    profile_->GetPrefs()->SetString(prefs::kDevToolsDockSide, pref_value);
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Show(DEVTOOLS_TOGGLE_ACTION_SHOW);
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
956c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsWindow::Restore() {
957c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (dock_side_ == DEVTOOLS_DOCK_SIDE_MINIMIZED)
958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetDockSide(SideToString(dock_side_before_minimized_));
959c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
960c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::OpenInNewTab(const std::string& url) {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenURLParams params(GURL(url),
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       content::Referrer(),
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       NEW_FOREGROUND_TAB,
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       content::PAGE_TRANSITION_LINK,
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       false /* is_renderer_initiated */);
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (inspected_web_contents) {
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    inspected_web_contents->OpenURL(params);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::HostDesktopType host_desktop_type;
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (browser_) {
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_desktop_type = browser_->host_desktop_type();
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // There should always be a browser when there are no inspected web
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // contents.
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_desktop_type = chrome::GetActiveDesktop();
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const BrowserList* browser_list =
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserList::GetInstance(host_desktop_type);
9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (BrowserList::const_iterator it = browser_list->begin();
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         it != browser_list->end(); ++it) {
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*it)->type() == Browser::TYPE_TABBED) {
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*it)->OpenURL(params);
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::SaveToFile(const std::string& url,
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const std::string& content,
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool save_as) {
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_helper_->Save(url, content, save_as, Bind(&DevToolsWindow::FileSavedAs,
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 weak_factory_.GetWeakPtr(),
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 url));
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::AppendToFile(const std::string& url,
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::string& content) {
10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_helper_->Append(url, content, Bind(&DevToolsWindow::AppendedTo,
10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          weak_factory_.GetWeakPtr(),
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          url));
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DictionaryValue* CreateFileSystemValue(
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DevToolsFileHelper::FileSystem file_system) {
10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryValue* file_system_value = new DictionaryValue();
10132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_value->SetString("fileSystemName", file_system.file_system_name);
10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_value->SetString("rootURL", file_system.root_url);
10152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_value->SetString("fileSystemPath", file_system.file_system_path);
10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return file_system_value;
10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::RequestFileSystems() {
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme));
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_helper_->RequestFileSystems(
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Bind(&DevToolsWindow::FileSystemsLoaded, weak_factory_.GetWeakPtr()));
10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::AddFileSystem() {
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme));
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_helper_->AddFileSystem(
1030c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&DevToolsWindow::FileSystemAdded, weak_factory_.GetWeakPtr()),
1031c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&DevToolsWindow::ShowDevToolsConfirmInfoBar,
1032c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           weak_factory_.GetWeakPtr()));
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::RemoveFileSystem(const std::string& file_system_path) {
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme));
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_helper_->RemoveFileSystem(file_system_path);
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringValue file_system_path_value(file_system_path);
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.fileSystemRemoved",
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     &file_system_path_value);
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::FileSavedAs(const std::string& url) {
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringValue url_value(url);
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.savedURL", &url_value);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::AppendedTo(const std::string& url) {
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringValue url_value(url);
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.appendedToURL", &url_value);
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::FileSystemsLoaded(
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<DevToolsFileHelper::FileSystem>& file_systems) {
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ListValue file_systems_value;
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < file_systems.size(); ++i) {
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_systems_value.Append(CreateFileSystemValue(file_systems[i]));
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.fileSystemsLoaded",
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     &file_systems_value);
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::FileSystemAdded(
10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DevToolsFileHelper::FileSystem& file_system) {
1065c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StringValue error_string_value("");
10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryValue* file_system_value = NULL;
10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!file_system.file_system_path.empty())
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_value = CreateFileSystemValue(file_system);
10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.fileSystemAdded",
10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     &error_string_value,
10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     file_system_value);
10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_system_value)
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete file_system_value;
10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1076c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsWindow::ShowDevToolsConfirmInfoBar(
1077c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const string16& message,
1078c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConfirmInfoBarCallback& callback) {
1079c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InfoBarService* infobar_service = IsDocked() ?
1080c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      InfoBarService::FromWebContents(GetInspectedWebContents()) :
1081c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      InfoBarService::FromWebContents(web_contents_);
1082c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1083c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (infobar_service) {
1084c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
1085c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new DevToolsConfirmInfoBarDelegate(
1086c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            infobar_service,
1087c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            callback,
1088c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            message)));
1089c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
1090c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(false);
1091c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1092c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1093c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)content::JavaScriptDialogManager* DevToolsWindow::GetJavaScriptDialogManager() {
10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
10962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (inspected_web_contents && inspected_web_contents->GetDelegate()) {
10972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return inspected_web_contents->GetDelegate()->
10982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetJavaScriptDialogManager();
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return content::WebContentsDelegate::GetJavaScriptDialogManager();
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::RunFileChooser(WebContents* web_contents,
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const FileChooserParams& params) {
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileSelectHelper::RunFileChooser(web_contents, params);
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::WebContentsFocused(WebContents* contents) {
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* inspected_browser = NULL;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int inspected_tab_index = -1;
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDocked() && FindInspectedBrowserAndTabIndex(&inspected_browser,
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    &inspected_tab_index)) {
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inspected_browser->window()->WebContentsFocused(contents);
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::UpdateBrowserToolbar() {
11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!inspected_web_contents)
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserWindow* inspected_window = GetInspectedBrowserWindow();
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (inspected_window)
11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    inspected_window->UpdateToolbar(inspected_web_contents, false);
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DevToolsWindow::IsDocked() {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dock_side_ != DEVTOOLS_DOCK_SIDE_UNDOCKED;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsDockSide DevToolsWindow::GetDockSideFromPrefs(Profile* profile) {
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dock_side =
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile->GetPrefs()->GetString(prefs::kDevToolsDockSide);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Migrate prefs
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dock_side == kOldPrefBottom || dock_side == kOldPrefRight) {
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool docked = profile->GetPrefs()->GetBoolean(prefs::kDevToolsOpenDocked);
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dock_side == kOldPrefBottom)
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return docked ? DEVTOOLS_DOCK_SIDE_BOTTOM : DEVTOOLS_DOCK_SIDE_UNDOCKED;
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return docked ? DEVTOOLS_DOCK_SIDE_RIGHT : DEVTOOLS_DOCK_SIDE_UNDOCKED;
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dock_side == kPrefUndocked)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DEVTOOLS_DOCK_SIDE_UNDOCKED;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (dock_side == kPrefRight)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DEVTOOLS_DOCK_SIDE_RIGHT;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default to docked to bottom
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DEVTOOLS_DOCK_SIDE_BOTTOM;
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string DevToolsWindow::SideToString(DevToolsDockSide dock_side) {
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dock_side_string;
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (dock_side) {
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEVTOOLS_DOCK_SIDE_UNDOCKED: return kDockSideUndocked;
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEVTOOLS_DOCK_SIDE_RIGHT: return kDockSideRight;
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEVTOOLS_DOCK_SIDE_BOTTOM: return kDockSideBottom;
1160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case DEVTOOLS_DOCK_SIDE_MINIMIZED: return kDockSideMinimized;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kDockSideUndocked;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsDockSide DevToolsWindow::SideFromString(
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& dock_side) {
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dock_side == kDockSideRight)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DEVTOOLS_DOCK_SIDE_RIGHT;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dock_side == kDockSideBottom)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DEVTOOLS_DOCK_SIDE_BOTTOM;
1172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (dock_side == kDockSideMinimized)
1173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return DEVTOOLS_DOCK_SIDE_MINIMIZED;
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DEVTOOLS_DOCK_SIDE_UNDOCKED;
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1176