devtools_window.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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.
4f2477e01787aa58f445919b809d89e252beef54fTorne (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"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/json/json_reader.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h"
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/strings/string_util.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/time/time.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chrome_page_zoom.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/debugger/debugger_api.h"
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/file_select_helper.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/infobars/confirm_infobar_delegate.h"
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/infobars/infobar.h"
29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/infobars/infobar_service.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/prefs/pref_service_syncable.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_tab_helper.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/themes/theme_properties.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/themes/theme_service.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/themes/theme_service_factory.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/browser_dialogs.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/webui/devtools_ui.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/manifest_url_handler.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/render_messages.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h"
512385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "content/public/browser/browser_thread.h"
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/child_process_security_policy.h"
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/devtools_agent_host.h"
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/devtools_client_host.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/devtools_manager.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/favicon_status.h"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/load_notification_details.h"
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/browser/native_web_keyboard_event.h"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/render_frame_host.h"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/browser/user_metrics.h"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/bindings_policy.h"
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_client.h"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/page_transition_types.h"
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/common/renderer_preferences.h"
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/url_constants.h"
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/test/test_utils.h"
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h"
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/web/WebInputEvent.h"
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/keycodes/keyboard_codes.h"
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)using base::DictionaryValue;
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochusing blink::WebInputEvent;
840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)using content::BrowserThread;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DevToolsAgentHost;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// DevToolsConfirmInfoBarDelegate ---------------------------------------------
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class DevToolsConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public:
922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // If |infobar_service| is NULL, runs |callback| with a single argument with
932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // value "false".  Otherwise, creates a dev tools confirm infobar and delegate
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // and adds the infobar to |infobar_service|.
952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  static void Create(InfoBarService* infobar_service,
962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     const DevToolsWindow::InfoBarCallback& callback,
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const base::string16& message);
982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
992385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch private:
1002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DevToolsConfirmInfoBarDelegate(
1012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      const DevToolsWindow::InfoBarCallback& callback,
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::string16& message);
1032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  virtual ~DevToolsConfirmInfoBarDelegate();
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual base::string16 GetMessageText() const OVERRIDE;
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual bool Accept() OVERRIDE;
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual bool Cancel() OVERRIDE;
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DevToolsWindow::InfoBarCallback callback_;
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const base::string16 message_;
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DISALLOW_COPY_AND_ASSIGN(DevToolsConfirmInfoBarDelegate);
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsConfirmInfoBarDelegate::Create(
1172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    InfoBarService* infobar_service,
1182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const DevToolsWindow::InfoBarCallback& callback,
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& message) {
1202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (!infobar_service) {
1212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    callback.Run(false);
1222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return;
1232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
1242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      scoped_ptr<ConfirmInfoBarDelegate>(
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          new DevToolsConfirmInfoBarDelegate(callback, message))));
1282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
1292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsConfirmInfoBarDelegate::DevToolsConfirmInfoBarDelegate(
1312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const DevToolsWindow::InfoBarCallback& callback,
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& message)
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : ConfirmInfoBarDelegate(),
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      callback_(callback),
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      message_(message) {
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochDevToolsConfirmInfoBarDelegate::~DevToolsConfirmInfoBarDelegate() {
1392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (!callback_.is_null())
1402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    callback_.Run(false);
1412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
1422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 DevToolsConfirmInfoBarDelegate::GetMessageText() const {
144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return message_;
145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 DevToolsConfirmInfoBarDelegate::GetButtonLabel(
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    InfoBarButton button) const {
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      IDS_DEV_TOOLS_CONFIRM_ALLOW_BUTTON : IDS_DEV_TOOLS_CONFIRM_DENY_BUTTON);
151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool DevToolsConfirmInfoBarDelegate::Accept() {
154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  callback_.Run(true);
155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  callback_.Reset();
156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool DevToolsConfirmInfoBarDelegate::Cancel() {
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  callback_.Run(false);
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  callback_.Reset();
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// DevToolsEventForwarder -----------------------------------------------------
166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace {
168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic const char kKeyUpEventName[] = "keyup";
170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic const char kKeyDownEventName[] = "keydown";
171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass DevToolsEventForwarder {
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  explicit DevToolsEventForwarder(DevToolsWindow* window)
177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     : devtools_window_(window) {}
178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Registers whitelisted shortcuts with the forwarder.
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Only registered keys will be forwarded to the DevTools frontend.
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void SetWhitelistedShortcuts(const std::string& message);
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Forwards a keyboard event to the DevTools frontend if it is whitelisted.
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Returns |true| if the event has been forwarded, |false| otherwise.
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool ForwardEvent(const content::NativeWebKeyboardEvent& event);
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  static int VirtualKeyCodeWithoutLocation(int key_code);
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  static bool KeyWhitelistingAllowed(int key_code, int modifiers);
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  static int CombineKeyCodeAndModifiers(int key_code, int modifiers);
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DevToolsWindow* devtools_window_;
193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::set<int> whitelisted_keys_;
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DISALLOW_COPY_AND_ASSIGN(DevToolsEventForwarder);
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid DevToolsEventForwarder::SetWhitelistedShortcuts(
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const std::string& message) {
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message));
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::ListValue* shortcut_list;
202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!parsed_message->GetAsList(&shortcut_list))
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return;
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::ListValue::iterator it = shortcut_list->begin();
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (; it != shortcut_list->end(); ++it) {
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::DictionaryValue* dictionary;
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!(*it)->GetAsDictionary(&dictionary))
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      continue;
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int key_code = 0;
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    dictionary->GetInteger("keyCode", &key_code);
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (key_code == 0)
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      continue;
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int modifiers = 0;
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    dictionary->GetInteger("modifiers", &modifiers);
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!KeyWhitelistingAllowed(key_code, modifiers)) {
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      LOG(WARNING) << "Key whitelisting forbidden: "
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   << "(" << key_code << "," << modifiers << ")";
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      continue;
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    whitelisted_keys_.insert(CombineKeyCodeAndModifiers(key_code, modifiers));
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool DevToolsEventForwarder::ForwardEvent(
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const content::NativeWebKeyboardEvent& event) {
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string event_type;
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (event.type) {
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case WebInputEvent::KeyDown:
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case WebInputEvent::RawKeyDown:
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      event_type = kKeyDownEventName;
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case WebInputEvent::KeyUp:
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      event_type = kKeyUpEventName;
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    default:
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return false;
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int key_code = VirtualKeyCodeWithoutLocation(event.windowsKeyCode);
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int key = CombineKeyCodeAndModifiers(key_code, event.modifiers);
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (whitelisted_keys_.find(key) == whitelisted_keys_.end())
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::DictionaryValue event_data;
245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_data.SetString("type", event_type);
246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_data.SetString("keyIdentifier", event.keyIdentifier);
247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_data.SetInteger("keyCode", key_code);
248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_data.SetInteger("modifiers", event.modifiers);
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  devtools_window_->CallClientFunction(
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "InspectorFrontendAPI.keyEventUnhandled", &event_data, NULL, NULL);
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint DevToolsEventForwarder::CombineKeyCodeAndModifiers(int key_code,
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                       int modifiers) {
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return key_code | (modifiers << 16);
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool DevToolsEventForwarder::KeyWhitelistingAllowed(int key_code,
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                    int modifiers) {
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return (ui::VKEY_F1 <= key_code && key_code <= ui::VKEY_F12) ||
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      modifiers != 0;
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Mapping copied from Blink's KeyboardEvent.cpp.
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint DevToolsEventForwarder::VirtualKeyCodeWithoutLocation(int key_code)
267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{
268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (key_code) {
269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_LCONTROL:
270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_RCONTROL:
271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return ui::VKEY_CONTROL;
272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_LSHIFT:
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_RSHIFT:
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return ui::VKEY_SHIFT;
275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_LMENU:
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_RMENU:
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return ui::VKEY_MENU;
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    default:
279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return key_code;
280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// DevToolsWindow::InspectedWebContentsObserver -------------------------------
284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DevToolsWindow::InspectedWebContentsObserver
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : public content::WebContentsObserver {
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  explicit InspectedWebContentsObserver(content::WebContents* web_contents);
2892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  virtual ~InspectedWebContentsObserver();
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  content::WebContents* web_contents() {
292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return WebContentsObserver::web_contents();
293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
2942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
2952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch private:
2962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DISALLOW_COPY_AND_ASSIGN(InspectedWebContentsObserver);
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow::InspectedWebContentsObserver::InspectedWebContentsObserver(
300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    content::WebContents* web_contents)
301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : WebContentsObserver(web_contents) {
302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochDevToolsWindow::InspectedWebContentsObserver::~InspectedWebContentsObserver() {
3052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
3062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// DevToolsWindow::FrontendWebContentsObserver --------------------------------
309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DevToolsWindow::FrontendWebContentsObserver
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : public content::WebContentsObserver {
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  explicit FrontendWebContentsObserver(DevToolsWindow* window);
3142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  virtual ~FrontendWebContentsObserver();
315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
3172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // contents::WebContentsObserver:
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void AboutToNavigateRenderView(
3192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      content::RenderViewHost* render_view_host) OVERRIDE;
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual void DocumentOnLoadCompletedInMainFrame(int32 page_id) OVERRIDE;
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE;
3222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DevToolsWindow* devtools_window_;
3242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DISALLOW_COPY_AND_ASSIGN(FrontendWebContentsObserver);
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow::FrontendWebContentsObserver::FrontendWebContentsObserver(
3281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DevToolsWindow* devtools_window)
3291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : WebContentsObserver(devtools_window->web_contents()),
3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      devtools_window_(devtools_window) {
331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DevToolsWindow::FrontendWebContentsObserver::WebContentsDestroyed(
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::WebContents* contents) {
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delete devtools_window_;
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochDevToolsWindow::FrontendWebContentsObserver::~FrontendWebContentsObserver() {
3392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
3402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DevToolsWindow::FrontendWebContentsObserver::AboutToNavigateRenderView(
342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    content::RenderViewHost* render_view_host) {
343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  content::DevToolsClientHost::SetupDevToolsFrontendClient(render_view_host);
344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void DevToolsWindow::FrontendWebContentsObserver::
3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DocumentOnLoadCompletedInMainFrame(int32 page_id) {
3481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  devtools_window_->DocumentOnLoadCompletedInMainFrame();
3491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// DevToolsWindow -------------------------------------------------------------
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace {
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochtypedef std::vector<DevToolsWindow*> DevToolsWindows;
3562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochbase::LazyInstance<DevToolsWindows>::Leaky g_instances =
3572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    LAZY_INSTANCE_INITIALIZER;
3582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static const char kFrontendHostId[] = "id";
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static const char kFrontendHostMethod[] = "method";
3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static const char kFrontendHostParams[] = "params";
3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)std::string SkColorToRGBAString(SkColor color) {
3642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // We avoid StringPrintf because it will use locale specific formatters for
3652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // the double (e.g. ',' instead of '.' in German).
3662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return "rgba(" + base::IntToString(SkColorGetR(color)) + "," +
3672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      base::IntToString(SkColorGetG(color)) + "," +
3682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      base::IntToString(SkColorGetB(color)) + "," +
3692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      base::DoubleToString(SkColorGetA(color) / 255.0) + ")";
370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::DictionaryValue* CreateFileSystemValue(
373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    DevToolsFileHelper::FileSystem file_system) {
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* file_system_value = new base::DictionaryValue();
375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  file_system_value->SetString("fileSystemName", file_system.file_system_name);
376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  file_system_value->SetString("rootURL", file_system.root_url);
377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  file_system_value->SetString("fileSystemPath", file_system.file_system_path);
378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return file_system_value;
379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace
382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char DevToolsWindow::kDevToolsApp[] = "DevToolsApp";
3842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
385a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow::~DevToolsWindow() {
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  content::DevToolsManager::GetInstance()->ClientHostClosing(
387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      frontend_host_.get());
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateBrowserToolbar();
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DevToolsWindows* instances = g_instances.Pointer();
3912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DevToolsWindows::iterator it(
3922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      std::find(instances->begin(), instances->end(), this));
3932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DCHECK(it != instances->end());
3942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  instances->erase(it);
3952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (IndexingJobsMap::const_iterator jobs_it(indexing_jobs_.begin());
397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       jobs_it != indexing_jobs_.end(); ++jobs_it) {
3982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    jobs_it->second->Stop();
399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
4002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  indexing_jobs_.clear();
401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string DevToolsWindow::GetDevToolsWindowPlacementPrefKey() {
4052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return std::string(prefs::kBrowserWindowPlacement) + "_" +
4062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      std::string(kDevToolsApp);
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
4107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DevToolsWindow::RegisterProfilePrefs(
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterDictionaryPref(
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kDevToolsEditedFiles,
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterDictionaryPref(
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kDevToolsFileSystemPaths,
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
4187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  registry->RegisterStringPref(
419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      prefs::kDevToolsAdbKey, std::string(),
4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterDictionaryPref(
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetDevToolsWindowPlacementPrefKey().c_str(),
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
4252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
4262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  registry->RegisterBooleanPref(
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      prefs::kDevToolsDiscoverUsbDevicesEnabled,
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      false,
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterBooleanPref(
4312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      prefs::kDevToolsPortForwardingEnabled,
4322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      false,
4332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  registry->RegisterBooleanPref(
43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      prefs::kDevToolsPortForwardingDefaultSet,
43658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      false,
43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
4382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  registry->RegisterDictionaryPref(
4392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      prefs::kDevToolsPortForwardingConfig,
4402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::GetDockedInstanceForInspectedTab(
4452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::WebContents* inspected_web_contents) {
4460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DevToolsWindow* window = GetInstanceForInspectedRenderViewHost(
4470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      inspected_web_contents->GetRenderViewHost());
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!window)
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Not yet loaded window is treated as docked, but we should not present it
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // until we decided on docking.
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool is_docked_set = window->load_state_ == kLoadCompleted ||
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window->load_state_ == kIsDockedSet;
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return window->is_docked_ && is_docked_set ? window : NULL;
4550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
4560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
4570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// static
4580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)DevToolsWindow* DevToolsWindow::GetInstanceForInspectedRenderViewHost(
4590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      content::RenderViewHost* inspected_rvh) {
4600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (!inspected_rvh || !DevToolsAgentHost::HasFor(inspected_rvh))
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetOrCreateFor(
4640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      inspected_rvh));
4650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return FindDevToolsWindow(agent.get());
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
469c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochDevToolsWindow* DevToolsWindow::GetInstanceForInspectedWebContents(
470c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    content::WebContents* inspected_web_contents) {
471c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!inspected_web_contents)
472c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return NULL;
473c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return GetInstanceForInspectedRenderViewHost(
474c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      inspected_web_contents->GetRenderViewHost());
475c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
476c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
477c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// static
4782385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochbool DevToolsWindow::IsDevToolsWindow(content::RenderViewHost* window_rvh) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AsDevToolsWindow(window_rvh) != NULL;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindowForWorker(
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DevToolsAgentHost* worker_agent) {
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DevToolsWindow* window = FindDevToolsWindow(worker_agent);
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!window) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window = DevToolsWindow::CreateDevToolsWindowForWorker(profile);
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Will disconnect the current client host if there is one.
4902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
4912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        worker_agent, window->frontend_host_.get());
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window->ScheduleShow(DevToolsToggleAction::Show());
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return window;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::CreateDevToolsWindowForWorker(
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile) {
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::RecordAction(base::UserMetricsAction("DevTools_InspectWorker"));
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return Create(profile, GURL(), NULL, true, false, false);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindow(
5062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::RenderViewHost* inspected_rvh) {
5070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return ToggleDevToolsWindow(
5080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      inspected_rvh, true, DevToolsToggleAction::Show());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindow(
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderViewHost* inspected_rvh,
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const DevToolsToggleAction& action) {
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ToggleDevToolsWindow(
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      inspected_rvh, true, action);
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindowForTest(
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderViewHost* inspected_rvh,
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_docked) {
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DevToolsWindow* window = OpenDevToolsWindow(inspected_rvh);
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window->SetIsDockedAndShowImmediatelyForTest(is_docked);
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return window;
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindowForTest(
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Browser* browser,
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_docked) {
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return OpenDevToolsWindowForTest(
5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      browser->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(),
5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      is_docked);
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow(
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser,
5400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const DevToolsToggleAction& action) {
5410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (action.type() == DevToolsToggleAction::kToggle &&
5420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      browser->is_devtools()) {
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser->tab_strip_model()->CloseAllTabs();
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return ToggleDevToolsWindow(
5482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      browser->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(),
5490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      action.type() == DevToolsToggleAction::kInspect, action);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsWindow::OpenExternalFrontend(
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Profile* profile,
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& frontend_url,
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::DevToolsAgentHost* agent_host) {
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DevToolsWindow* window = FindDevToolsWindow(agent_host);
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!window) {
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window = Create(profile, DevToolsUI::GetProxyURL(frontend_url), NULL,
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    false, true, false);
5612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        agent_host, window->frontend_host_.get());
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window->ScheduleShow(DevToolsToggleAction::Show());
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow(
5692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::RenderViewHost* inspected_rvh,
570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    bool force_open,
5710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const DevToolsToggleAction& action) {
572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent(
573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      DevToolsAgentHost::GetOrCreateFor(inspected_rvh));
5742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  content::DevToolsManager* manager = content::DevToolsManager::GetInstance();
575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DevToolsWindow* window = FindDevToolsWindow(agent.get());
576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool do_open = force_open;
577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!window) {
578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Profile* profile = Profile::FromBrowserContext(
579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        inspected_rvh->GetProcess()->GetBrowserContext());
580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::RecordAction(
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::UserMetricsAction("DevTools_InspectRenderer"));
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window = Create(profile, GURL(), inspected_rvh, false, false, true);
583a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    manager->RegisterDevToolsClientHostFor(agent.get(),
584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                           window->frontend_host_.get());
585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    do_open = true;
586a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
588a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Update toolbar to reflect DevTools changes.
589a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  window->UpdateBrowserToolbar();
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
591a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // If window is docked and visible, we hide it on toggle. If window is
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // undocked, we show (activate) it.
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!window->is_docked_ || do_open)
5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window->ScheduleShow(action);
595a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  else
596a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    window->CloseWindow();
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
598a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return window;
599a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
601a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
6022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::InspectElement(content::RenderViewHost* inspected_rvh,
603a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    int x,
604a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    int y) {
605a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent(
606a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      DevToolsAgentHost::GetOrCreateFor(inspected_rvh));
607a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  agent->InspectElement(x, y);
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool should_measure_time = FindDevToolsWindow(agent.get()) == NULL;
6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::TimeTicks start_time = base::TimeTicks::Now();
610a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // TODO(loislo): we should initiate DevTools window opening from within
611a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // renderer. Otherwise, we still can hit a race condition here.
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DevToolsWindow* window = OpenDevToolsWindow(inspected_rvh);
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (should_measure_time)
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window->inspect_element_start_time_ = start_time;
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::InspectedContentsClosing() {
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  intercepted_page_beforeunload_ = false;
6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This will prevent any activity after frontend is loaded.
6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  action_on_load_ = DevToolsToggleAction::NoOp();
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ignore_set_is_docked_ = true;
6224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  web_contents_->GetRenderViewHost()->ClosePage();
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochcontent::RenderViewHost* DevToolsWindow::GetRenderViewHost() {
626a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return web_contents_->GetRenderViewHost();
627a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const DevToolsContentsResizingStrategy&
6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DevToolsWindow::GetContentsResizingStrategy() const {
6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return contents_resizing_strategy_;
632a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
633a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gfx::Size DevToolsWindow::GetMinimumSize() const {
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Size kMinDevToolsSize = gfx::Size(230, 100);
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return kMinDevToolsSize;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::ScheduleShow(const DevToolsToggleAction& action) {
6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (load_state_ == kLoadCompleted) {
6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Show(action);
6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Action will be done only after load completed.
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  action_on_load_ = action;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!can_dock_) {
6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // No harm to show always-undocked window right away.
6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    is_docked_ = false;
6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Show(DevToolsToggleAction::Show());
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void DevToolsWindow::Show(const DevToolsToggleAction& action) {
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (action.type() == DevToolsToggleAction::kNoOp)
6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_) {
6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(can_dock_);
6612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    Browser* inspected_browser = NULL;
6622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    int inspected_tab_index = -1;
6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FindInspectedBrowserAndTabIndex(GetInspectedWebContents(),
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    &inspected_browser,
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    &inspected_tab_index);
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(inspected_browser);
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(inspected_tab_index != -1);
6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
669a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Tell inspected browser to update splitter and switch to inspected panel.
6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserWindow* inspected_window = inspected_browser->window();
6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    web_contents_->SetDelegate(this);
6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TabStripModel* tab_strip_model = inspected_browser->tab_strip_model();
6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tab_strip_model->ActivateTabAt(inspected_tab_index, true);
6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    inspected_window->UpdateDevTools();
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    web_contents_->GetView()->SetInitialFocus();
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    inspected_window->Show();
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // On Aura, focusing once is not enough. Do it again.
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Note that focusing only here but not before isn't enough either. We just
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // need to focus twice.
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    web_contents_->GetView()->SetInitialFocus();
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PrefsTabHelper::CreateForWebContents(web_contents_);
6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GetRenderViewHost()->SyncRendererPrefs();
6862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DoAction(action);
6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
691a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Avoid consecutive window switching if the devtools window has been opened
692a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // and the Inspect Element shortcut is pressed in the inspected tab.
693a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool should_show_window =
6940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      !browser_ || (action.type() != DevToolsToggleAction::kInspect);
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
696a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!browser_)
697a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CreateDevToolsBrowser();
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
699a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (should_show_window) {
700a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    browser_->window()->Show();
701a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    web_contents_->GetView()->SetInitialFocus();
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoAction(action);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
707f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
708f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool DevToolsWindow::HandleBeforeUnload(content::WebContents* frontend_contents,
709f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool proceed, bool* proceed_to_fire_unload) {
710f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DevToolsWindow* window = AsDevToolsWindow(
711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      frontend_contents->GetRenderViewHost());
712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!window)
713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
714f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!window->intercepted_page_beforeunload_)
715f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
716f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  window->BeforeUnloadFired(frontend_contents, proceed,
717f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      proceed_to_fire_unload);
718f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
719f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
720f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
721f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
722f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool DevToolsWindow::InterceptPageBeforeUnload(content::WebContents* contents) {
723f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DevToolsWindow* window =
724f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DevToolsWindow::GetInstanceForInspectedRenderViewHost(
725f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          contents->GetRenderViewHost());
726f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!window || window->intercepted_page_beforeunload_)
727f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
728f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Not yet loaded frontend will not handle beforeunload.
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (window->load_state_ != kLoadCompleted)
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
733f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  window->intercepted_page_beforeunload_ = true;
734f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Handle case of devtools inspecting another devtools instance by passing
735f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // the call up to the inspecting devtools instance.
736f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!DevToolsWindow::InterceptPageBeforeUnload(window->web_contents())) {
737c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    window->web_contents()->DispatchBeforeUnload(false);
738f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
739f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
740f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool DevToolsWindow::NeedsToInterceptBeforeUnload(
744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::WebContents* contents) {
745f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DevToolsWindow* window =
746f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DevToolsWindow::GetInstanceForInspectedRenderViewHost(
747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          contents->GetRenderViewHost());
748f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return window && !window->intercepted_page_beforeunload_;
749f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
750f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
751f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
752f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool DevToolsWindow::HasFiredBeforeUnloadEventForDevToolsBrowser(
753f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Browser* browser) {
754f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(browser->is_devtools());
755f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // When FastUnloadController is used, devtools frontend will be detached
756f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // from the browser window at this point which means we've already fired
757f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // beforeunload.
758f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (browser->tab_strip_model()->empty())
759f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
760f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  content::WebContents* contents =
761f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      browser->tab_strip_model()->GetWebContentsAt(0);
762f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DevToolsWindow* window = AsDevToolsWindow(contents->GetRenderViewHost());
763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!window)
764a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
765f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return window->intercepted_page_beforeunload_;
766f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
767f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
768f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
769f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DevToolsWindow::OnPageCloseCanceled(content::WebContents* contents) {
770f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DevToolsWindow *window =
771f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DevToolsWindow::GetInstanceForInspectedRenderViewHost(
772f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          contents->GetRenderViewHost());
773f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!window)
774f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
775f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  window->intercepted_page_beforeunload_ = false;
776f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Propagate to devtools opened on devtools if any.
777f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DevToolsWindow::OnPageCloseCanceled(window->web_contents());
778f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
779f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
780a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow::DevToolsWindow(Profile* profile,
781a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               const GURL& url,
7822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                               content::RenderViewHost* inspected_rvh,
7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               bool can_dock)
784a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : profile_(profile),
785a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      browser_(NULL),
7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      is_docked_(true),
7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      can_dock_(can_dock),
7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // This initialization allows external front-end to work without changes.
7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // We don't wait for docking call, but instead immediately show undocked.
7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Passing "dockSide=undocked" parameter ensures proper UI.
7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      load_state_(can_dock ? kNotLoaded : kIsDockedSet),
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      action_on_load_(DevToolsToggleAction::NoOp()),
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ignore_set_is_docked_(false),
794f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      intercepted_page_beforeunload_(false),
7954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_factory_(this) {
7962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  web_contents_ =
7972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      content::WebContents::Create(content::WebContents::CreateParams(profile));
7981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  frontend_contents_observer_.reset(new FrontendWebContentsObserver(this));
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents_->GetMutableRendererPrefs()->can_accept_load_drops = false;
8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Set up delegate, so we get fully-functional window immediately.
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // It will not appear in UI though until |load_state_ == kLoadCompleted|.
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents_->SetDelegate(this);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  web_contents_->GetController().LoadURL(url, content::Referrer(),
806f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      content::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
807a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
8082385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  frontend_host_.reset(content::DevToolsClientHost::CreateDevToolsFrontendHost(
8092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      web_contents_, this));
810a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  file_helper_.reset(new DevToolsFileHelper(web_contents_, profile));
8112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  file_system_indexer_ = new DevToolsFileSystemIndexer();
81223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
81323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      web_contents_);
814a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
815a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  g_instances.Get().push_back(this);
8162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
817a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Wipe out page icon so that the default application icon is used.
8182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  content::NavigationEntry* entry =
8192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      web_contents_->GetController().GetActiveEntry();
820a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  entry->GetFavicon().image = gfx::Image();
821a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  entry->GetFavicon().valid = true;
822a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
823a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Register on-load actions.
824a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  registrar_.Add(
8252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
826a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      content::Source<ThemeService>(
827a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          ThemeServiceFactory::GetForProfile(profile_)));
8282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
829a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // There is no inspected_rvh in case of shared workers.
830a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (inspected_rvh)
831a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    inspected_contents_observer_.reset(new InspectedWebContentsObserver(
8322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        content::WebContents::FromRenderViewHost(inspected_rvh)));
83358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
83458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  embedder_message_dispatcher_.reset(
835a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DevToolsEmbedderMessageDispatcher::createForDevToolsFrontend(this));
836c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_forwarder_.reset(new DevToolsEventForwarder(this));
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
839a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
840a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow* DevToolsWindow::Create(
841a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Profile* profile,
842a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const GURL& frontend_url,
8432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::RenderViewHost* inspected_rvh,
844424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    bool shared_worker_frontend,
845a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool external_frontend,
846a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool can_dock) {
847a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (inspected_rvh) {
848a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Check for a place to dock.
849a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Browser* browser = NULL;
850a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int tab;
851a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    content::WebContents* inspected_web_contents =
852a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        content::WebContents::FromRenderViewHost(inspected_rvh);
853a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!FindInspectedBrowserAndTabIndex(inspected_web_contents,
854a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                         &browser, &tab) ||
855a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        inspected_rvh->GetMainFrame()->IsCrossProcessSubframe() ||
856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        browser->is_type_popup()) {
857a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      can_dock = false;
858a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
859a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
860a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
861a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create WebContents with devtools.
8625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(GetDevToolsURL(profile, frontend_url,
863424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                          shared_worker_frontend,
864a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          external_frontend,
865a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          can_dock));
8665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new DevToolsWindow(profile, url, inspected_rvh, can_dock);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL DevToolsWindow::GetDevToolsURL(Profile* profile,
871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    const GURL& base_url,
872424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                    bool shared_worker_frontend,
873a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    bool external_frontend,
874a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    bool can_dock) {
8758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (base_url.SchemeIs("data"))
8768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return base_url;
8778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8782385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  std::string frontend_url(
8792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      base_url.is_empty() ? chrome::kChromeUIDevToolsURL : base_url.spec());
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThemeService* tp = ThemeServiceFactory::GetForProfile(profile);
8812385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DCHECK(tp);
8822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  std::string url_string(
8832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      frontend_url +
8842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      ((frontend_url.find("?") == std::string::npos) ? "?" : "&") +
8855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "dockSide=undocked" + // TODO(dgozman): remove this support in M38.
8862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      "&toolbarColor=" +
8872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_TOOLBAR)) +
8882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      "&textColor=" +
8892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)));
8902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (shared_worker_frontend)
8912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    url_string += "&isSharedWorker=true";
892424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (external_frontend)
893424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    url_string += "&remoteFrontend=true";
894a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (can_dock)
895a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    url_string += "&can_dock=true";
8962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (CommandLine::ForCurrentProcess()->HasSwitch(
8972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      switches::kEnableDevToolsExperiments))
8982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    url_string += "&experiments=true";
899f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  url_string += "&updateAppcache";
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL(url_string);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
903a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
904a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow* DevToolsWindow::FindDevToolsWindow(
905a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    DevToolsAgentHost* agent_host) {
9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DevToolsWindows* instances = g_instances.Pointer();
9072385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  content::DevToolsManager* manager = content::DevToolsManager::GetInstance();
9082385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  for (DevToolsWindows::iterator it(instances->begin()); it != instances->end();
9092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch       ++it) {
910a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (manager->GetDevToolsAgentHostFor((*it)->frontend_host_.get()) ==
911a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        agent_host)
912a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *it;
913a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
914a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return NULL;
915a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
917a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
9182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochDevToolsWindow* DevToolsWindow::AsDevToolsWindow(
9192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::RenderViewHost* window_rvh) {
920a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (g_instances == NULL)
921a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return NULL;
9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DevToolsWindows* instances = g_instances.Pointer();
9232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  for (DevToolsWindows::iterator it(instances->begin()); it != instances->end();
9242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch       ++it) {
925a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if ((*it)->web_contents_->GetRenderViewHost() == window_rvh)
926a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *it;
927a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
928a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return NULL;
929a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
930a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
931a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DevToolsWindow::Observe(int type,
932a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                             const content::NotificationSource& source,
933a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                             const content::NotificationDetails& details) {
934f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type);
935f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateTheme();
936a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
937a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
9382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochcontent::WebContents* DevToolsWindow::OpenURLFromTab(
9392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::WebContents* source,
9402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const content::OpenURLParams& params) {
9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(source == web_contents_);
9425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!params.url.SchemeIs(content::kChromeDevToolsScheme)) {
943a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    content::WebContents* inspected_web_contents = GetInspectedWebContents();
9442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return inspected_web_contents ?
9452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        inspected_web_contents->OpenURL(params) : NULL;
946a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
947a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
9482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  content::DevToolsManager* manager = content::DevToolsManager::GetInstance();
949a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent_host(
950a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      manager->GetDevToolsAgentHostFor(frontend_host_.get()));
951a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!agent_host.get())
952a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return NULL;
953a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  manager->ClientHostClosing(frontend_host_.get());
954a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  manager->RegisterDevToolsClientHostFor(agent_host.get(),
955a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         frontend_host_.get());
956a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
9575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::NavigationController::LoadURLParams load_url_params(params.url);
9585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents_->GetController().LoadURLWithParams(load_url_params);
9595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return web_contents_;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::AddNewContents(content::WebContents* source,
9632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                    content::WebContents* new_contents,
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WindowOpenDisposition disposition,
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const gfx::Rect& initial_pos,
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool user_gesture,
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool* was_blocked) {
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (inspected_web_contents) {
9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    inspected_web_contents->GetDelegate()->AddNewContents(
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        source, new_contents, disposition, initial_pos, user_gesture,
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        was_blocked);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
976a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DevToolsWindow::CloseContents(content::WebContents* source) {
9775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(is_docked_);
9785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This will prevent any activity after frontend is loaded.
9795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  action_on_load_ = DevToolsToggleAction::NoOp();
9805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ignore_set_is_docked_ = true;
9814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Update dev tools to reflect removed dev tools window.
9824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrowserWindow* inspected_window = GetInspectedBrowserWindow();
9834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (inspected_window)
9844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    inspected_window->UpdateDevTools();
9854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // In case of docked web_contents_, we own it so delete here.
986f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Embedding DevTools window will be deleted as a result of
987f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // WebContentsDestroyed callback.
9884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  delete web_contents_;
9894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
9904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::ContentsZoomChange(bool zoom_in) {
9925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(is_docked_);
9935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chrome_page_zoom::Zoom(web_contents(),
9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      zoom_in ? content::PAGE_ZOOM_IN : content::PAGE_ZOOM_OUT);
9955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
9965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DevToolsWindow::BeforeUnloadFired(content::WebContents* tab,
9984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       bool proceed,
9994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       bool* proceed_to_fire_unload) {
1000f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!intercepted_page_beforeunload_) {
1001f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Docked devtools window closed directly.
1002f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (proceed) {
1003f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      content::DevToolsManager::GetInstance()->ClientHostClosing(
1004f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          frontend_host_.get());
1005f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
1006f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *proceed_to_fire_unload = proceed;
1007f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
1008f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Inspected page is attempting to close.
1009f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::WebContents* inspected_web_contents = GetInspectedWebContents();
1010f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (proceed) {
1011c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      inspected_web_contents->DispatchBeforeUnload(false);
1012f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
1013f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      bool should_proceed;
1014f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      inspected_web_contents->GetDelegate()->BeforeUnloadFired(
1015f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          inspected_web_contents, false, &should_proceed);
1016f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK(!should_proceed);
1017f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
1018f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *proceed_to_fire_unload = false;
10194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1020a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1021a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DevToolsWindow::PreHandleKeyboardEvent(
10232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::WebContents* source,
10242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const content::NativeWebKeyboardEvent& event,
10252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    bool* is_keyboard_shortcut) {
10265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_) {
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserWindow* inspected_window = GetInspectedBrowserWindow();
10282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    if (inspected_window) {
10292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      return inspected_window->PreHandleKeyboardEvent(event,
10302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                                      is_keyboard_shortcut);
10312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    }
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::HandleKeyboardEvent(
10372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::WebContents* source,
10382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const content::NativeWebKeyboardEvent& event) {
10395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_) {
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event.windowsKeyCode == 0x08) {
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Do not navigate back in history on Windows (http://crbug.com/74156).
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserWindow* inspected_window = GetInspectedBrowserWindow();
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inspected_window)
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inspected_window->HandleKeyboardEvent(event);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1050a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)content::JavaScriptDialogManager* DevToolsWindow::GetJavaScriptDialogManager() {
1051a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
10522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return (inspected_web_contents && inspected_web_contents->GetDelegate()) ?
10532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      inspected_web_contents->GetDelegate()->GetJavaScriptDialogManager() :
10542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      content::WebContentsDelegate::GetJavaScriptDialogManager();
1055a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1057a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)content::ColorChooser* DevToolsWindow::OpenColorChooser(
10582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    content::WebContents* web_contents,
1059a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SkColor initial_color,
1060a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::vector<content::ColorSuggestion>& suggestions) {
1061a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return chrome::ShowColorChooser(web_contents, initial_color);
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::RunFileChooser(content::WebContents* web_contents,
10652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                    const content::FileChooserParams& params) {
1066a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FileSelectHelper::RunFileChooser(web_contents, params);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::WebContentsFocused(content::WebContents* contents) {
1070a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Browser* inspected_browser = NULL;
1071a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int inspected_tab_index = -1;
10725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_ && FindInspectedBrowserAndTabIndex(GetInspectedWebContents(),
1073a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                    &inspected_browser,
10742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                                    &inspected_tab_index))
1075a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    inspected_browser->window()->WebContentsFocused(contents);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool DevToolsWindow::PreHandleGestureEvent(
10795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::WebContents* source,
10805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const blink::WebGestureEvent& event) {
10815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Disable pinch zooming.
10825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return event.type == blink::WebGestureEvent::GesturePinchBegin ||
10835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.type == blink::WebGestureEvent::GesturePinchUpdate ||
10845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.type == blink::WebGestureEvent::GesturePinchEnd;
10855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
10865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
108758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DevToolsWindow::DispatchOnEmbedder(const std::string& message) {
10884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string method;
10894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::ListValue empty_params;
10904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::ListValue* params = &empty_params;
10914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::DictionaryValue* dict = NULL;
10934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message));
10944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!parsed_message ||
10954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      !parsed_message->GetAsDictionary(&dict) ||
10964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      !dict->GetString(kFrontendHostMethod, &method) ||
10974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      (dict->HasKey(kFrontendHostParams) &&
10984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          !dict->GetList(kFrontendHostParams, &params))) {
10994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    LOG(ERROR) << "Invalid message was sent to embedder: " << message;
11004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
11014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
11024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int id = 0;
11044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  dict->GetInteger(kFrontendHostId, &id);
11054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string error;
1107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  embedder_message_dispatcher_->Dispatch(method, params, &error);
11084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (id) {
11094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_ptr<base::Value> id_value(base::Value::CreateIntegerValue(id));
11104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_ptr<base::Value> error_value(base::Value::CreateStringValue(error));
11114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CallClientFunction("InspectorFrontendAPI.embedderMessageAck",
11124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                       id_value.get(), error_value.get(), NULL);
11134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
111458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
111558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::ActivateWindow() {
11175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_ && GetInspectedBrowserWindow())
11182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    web_contents_->GetView()->Focus();
11195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (!is_docked_ && !browser_->window()->IsActive())
11202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    browser_->window()->Activate();
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DevToolsWindow::ActivateContents(content::WebContents* contents) {
11245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_) {
11254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    content::WebContents* inspected_tab = this->GetInspectedWebContents();
11264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    inspected_tab->GetDelegate()->ActivateContents(inspected_tab);
11274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
11284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    browser_->window()->Activate();
11294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
11304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
11314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::CloseWindow() {
11335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(is_docked_);
11345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This will prevent any activity after frontend is loaded.
11355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  action_on_load_ = DevToolsToggleAction::NoOp();
11365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ignore_set_is_docked_ = true;
1137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  web_contents_->DispatchBeforeUnload(false);
11384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
11394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::SetContentsInsets(
11415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int top, int left, int bottom, int right) {
11425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Insets insets(top, left, bottom, right);
11435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetContentsResizingStrategy(insets, contents_resizing_strategy_.min_size());
11445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
11455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::SetContentsResizingStrategy(
11475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::Insets& insets, const gfx::Size& min_size) {
11485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DevToolsContentsResizingStrategy strategy(insets, min_size);
11495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (contents_resizing_strategy_.Equals(strategy))
11505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
11515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  contents_resizing_strategy_.CopyFrom(strategy);
11535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_) {
11545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Update inspected window.
11555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserWindow* inspected_window = GetInspectedBrowserWindow();
11565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (inspected_window)
11575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      inspected_window->UpdateDevTools();
11585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
11595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
11605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::InspectElementCompleted() {
11625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!inspect_element_start_time_.is_null()) {
11635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UMA_HISTOGRAM_TIMES("DevTools.InspectElement",
11645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::TimeTicks::Now() - inspect_element_start_time_);
11655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    inspect_element_start_time_ = base::TimeTicks();
11665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::MoveWindow(int x, int y) {
11705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_docked_) {
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect bounds = browser_->window()->GetBounds();
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds.Offset(x, y);
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser_->window()->SetBounds(bounds);
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::SetIsDockedAndShowImmediatelyForTest(bool is_docked) {
11785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!is_docked || can_dock_);
11795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (load_state_ == kLoadCompleted) {
11805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetIsDocked(is_docked);
11815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
11825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    is_docked_ = is_docked;
11835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Load is completed when both kIsDockedSet and kOnLoadFired happened.
11845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Note that kIsDockedSet may be already set when can_dock_ is false.
11855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    load_state_ = load_state_ == kOnLoadFired ? kLoadCompleted : kIsDockedSet;
11865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Note that action_on_load_ will be performed after the load is actually
11875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // completed. For now, just show the window.
11885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Show(DevToolsToggleAction::Show());
11895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (load_state_ == kLoadCompleted)
11905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LoadCompleted();
11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
11925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ignore_set_is_docked_ = true;
11935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
11945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::SetIsDocked(bool dock_requested) {
11965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ignore_set_is_docked_)
11975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
11985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(can_dock_ || !dock_requested);
12005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!can_dock_)
12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dock_requested = false;
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool was_docked = is_docked_;
12045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  is_docked_ = dock_requested;
12055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (load_state_ != kLoadCompleted) {
12075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // This is a first time call we waited for to initialize.
12085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    load_state_ = load_state_ == kOnLoadFired ? kLoadCompleted : kIsDockedSet;
12095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (load_state_ == kLoadCompleted)
12105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LoadCompleted();
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dock_requested == was_docked)
12155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dock_requested && !was_docked) {
12182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // Detach window from the external devtools browser. It will lead to
12192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // the browser object's close and delete. Remove observer first.
12202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    TabStripModel* tab_strip_model = browser_->tab_strip_model();
12212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    tab_strip_model->DetachWebContentsAt(
12222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        tab_strip_model->GetIndexOfWebContents(web_contents_));
12232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    browser_ = NULL;
12245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (!dock_requested && was_docked) {
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update inspected window to hide split and reset it.
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserWindow* inspected_window = GetInspectedBrowserWindow();
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inspected_window)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inspected_window->UpdateDevTools();
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Show(DevToolsToggleAction::Show());
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::OpenInNewTab(const std::string& url) {
12352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  content::OpenURLParams params(
12362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      GURL(url), content::Referrer(), NEW_FOREGROUND_TAB,
12372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      content::PAGE_TRANSITION_LINK, false);
12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (inspected_web_contents) {
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    inspected_web_contents->OpenURL(params);
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::HostDesktopType host_desktop_type;
12432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (browser_) {
12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_desktop_type = browser_->host_desktop_type();
12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // There should always be a browser when there are no inspected web
12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // contents.
12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_desktop_type = chrome::GetActiveDesktop();
12502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const BrowserList* browser_list =
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserList::GetInstance(host_desktop_type);
12542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (BrowserList::const_iterator it = browser_list->begin();
12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         it != browser_list->end(); ++it) {
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*it)->type() == Browser::TYPE_TABBED) {
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*it)->OpenURL(params);
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::SaveToFile(const std::string& url,
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const std::string& content,
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool save_as) {
12672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  file_helper_->Save(url, content, save_as,
12682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     base::Bind(&DevToolsWindow::FileSavedAs,
1269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                weak_factory_.GetWeakPtr(), url),
1270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     base::Bind(&DevToolsWindow::CanceledFileSaveAs,
12712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                weak_factory_.GetWeakPtr(), url));
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::AppendToFile(const std::string& url,
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::string& content) {
12762385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  file_helper_->Append(url, content,
12772385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                       base::Bind(&DevToolsWindow::AppendedTo,
12782385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                  weak_factory_.GetWeakPtr(), url));
12792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::RequestFileSystems() {
12825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
12832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  file_helper_->RequestFileSystems(base::Bind(
12842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      &DevToolsWindow::FileSystemsLoaded, weak_factory_.GetWeakPtr()));
12852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::AddFileSystem() {
12885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_helper_->AddFileSystem(
12902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      base::Bind(&DevToolsWindow::FileSystemAdded, weak_factory_.GetWeakPtr()),
12912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      base::Bind(&DevToolsWindow::ShowDevToolsConfirmInfoBar,
12922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                 weak_factory_.GetWeakPtr()));
12932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::RemoveFileSystem(const std::string& file_system_path) {
12965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
12972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_helper_->RemoveFileSystem(file_system_path);
12985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::StringValue file_system_path_value(file_system_path);
12992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.fileSystemRemoved",
13002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     &file_system_path_value, NULL, NULL);
13012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
13022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DevToolsWindow::UpgradeDraggedFileSystemPermissions(
1304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& file_system_url) {
13055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
1306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  file_helper_->UpgradeDraggedFileSystemPermissions(
1307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      file_system_url,
1308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&DevToolsWindow::FileSystemAdded, weak_factory_.GetWeakPtr()),
1309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&DevToolsWindow::ShowDevToolsConfirmInfoBar,
1310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 weak_factory_.GetWeakPtr()));
1311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
13132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::IndexPath(int request_id,
13142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                               const std::string& file_system_path) {
13150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
13165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
13172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (!file_helper_->IsFileSystemAdded(file_system_path)) {
13182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    IndexingDone(request_id, file_system_path);
13192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return;
13202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
1321ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  indexing_jobs_[request_id] =
1322ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>(
1323ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          file_system_indexer_->IndexPath(
1324ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch              file_system_path,
1325ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch              Bind(&DevToolsWindow::IndexingTotalWorkCalculated,
1326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   weak_factory_.GetWeakPtr(),
1327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   request_id,
1328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   file_system_path),
1329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch              Bind(&DevToolsWindow::IndexingWorked,
1330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   weak_factory_.GetWeakPtr(),
1331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   request_id,
1332ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   file_system_path),
1333ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch              Bind(&DevToolsWindow::IndexingDone,
1334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   weak_factory_.GetWeakPtr(),
1335ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   request_id,
1336ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   file_system_path)));
13372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
13382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
13392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::StopIndexing(int request_id) {
13400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
13412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  IndexingJobsMap::iterator it = indexing_jobs_.find(request_id);
13422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (it == indexing_jobs_.end())
13432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return;
13442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  it->second->Stop();
13452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  indexing_jobs_.erase(it);
13462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
13472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
13482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::SearchInPath(int request_id,
13492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                  const std::string& file_system_path,
13502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                  const std::string& query) {
13510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
13525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
13532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (!file_helper_->IsFileSystemAdded(file_system_path)) {
13542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    SearchCompleted(request_id, file_system_path, std::vector<std::string>());
13552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return;
13562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
13572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  file_system_indexer_->SearchInPath(file_system_path,
13582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                     query,
13592385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                     Bind(&DevToolsWindow::SearchCompleted,
13602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                          weak_factory_.GetWeakPtr(),
13612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                          request_id,
13622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                          file_system_path));
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::ZoomIn() {
13665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_IN);
13675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
13685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::ZoomOut() {
13705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_OUT);
13715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
13725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::ResetZoom() {
13745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_RESET);
13755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
13765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::FileSavedAs(const std::string& url) {
13785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::StringValue url_value(url);
13792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  CallClientFunction("InspectorFrontendAPI.savedURL", &url_value, NULL, NULL);
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void DevToolsWindow::CanceledFileSaveAs(const std::string& url) {
13835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::StringValue url_value(url);
1384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.canceledSaveURL",
1385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     &url_value, NULL, NULL);
1386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::AppendedTo(const std::string& url) {
13895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::StringValue url_value(url);
13902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  CallClientFunction("InspectorFrontendAPI.appendedToURL", &url_value, NULL,
13912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     NULL);
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::FileSystemsLoaded(
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<DevToolsFileHelper::FileSystem>& file_systems) {
13965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue file_systems_value;
13972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  for (size_t i = 0; i < file_systems.size(); ++i)
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_systems_value.Append(CreateFileSystemValue(file_systems[i]));
13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.fileSystemsLoaded",
14002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     &file_systems_value, NULL, NULL);
14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsWindow::FileSystemAdded(
14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DevToolsFileHelper::FileSystem& file_system) {
1405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<base::StringValue> error_string_value(
1406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new base::StringValue(std::string()));
1407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> file_system_value;
14082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!file_system.file_system_path.empty())
1409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    file_system_value.reset(CreateFileSystemValue(file_system));
14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CallClientFunction("InspectorFrontendAPI.fileSystemAdded",
1411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     error_string_value.get(), file_system_value.get(), NULL);
14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::IndexingTotalWorkCalculated(
14152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    int request_id,
14162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const std::string& file_system_path,
14172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    int total_work) {
14180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
14192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  base::FundamentalValue request_id_value(request_id);
14205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::StringValue file_system_path_value(file_system_path);
14212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  base::FundamentalValue total_work_value(total_work);
14222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  CallClientFunction("InspectorFrontendAPI.indexingTotalWorkCalculated",
14232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     &request_id_value, &file_system_path_value,
14242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     &total_work_value);
14252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
14262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
14272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::IndexingWorked(int request_id,
14282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                    const std::string& file_system_path,
14292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                    int worked) {
14300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
14312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  base::FundamentalValue request_id_value(request_id);
14325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::StringValue file_system_path_value(file_system_path);
14332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  base::FundamentalValue worked_value(worked);
14342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  CallClientFunction("InspectorFrontendAPI.indexingWorked", &request_id_value,
14352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     &file_system_path_value, &worked_value);
14362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
14372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
14382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::IndexingDone(int request_id,
14392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                  const std::string& file_system_path) {
14402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  indexing_jobs_.erase(request_id);
14410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
14422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  base::FundamentalValue request_id_value(request_id);
14435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::StringValue file_system_path_value(file_system_path);
14442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  CallClientFunction("InspectorFrontendAPI.indexingDone", &request_id_value,
14452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     &file_system_path_value, NULL);
14462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
14472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
14482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::SearchCompleted(
14492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    int request_id,
14502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const std::string& file_system_path,
14512385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const std::vector<std::string>& file_paths) {
14520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
14535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue file_paths_value;
1454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (std::vector<std::string>::const_iterator it(file_paths.begin());
1455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       it != file_paths.end(); ++it) {
14562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    file_paths_value.AppendString(*it);
14572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
14582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  base::FundamentalValue request_id_value(request_id);
14595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::StringValue file_system_path_value(file_system_path);
14602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  CallClientFunction("InspectorFrontendAPI.searchCompleted", &request_id_value,
14612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                     &file_system_path_value, &file_paths_value);
14622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
14632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsWindow::ShowDevToolsConfirmInfoBar(
1465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& message,
14662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const InfoBarCallback& callback) {
14672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DevToolsConfirmInfoBarDelegate::Create(
14685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      is_docked_ ?
14692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          InfoBarService::FromWebContents(GetInspectedWebContents()) :
14702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          InfoBarService::FromWebContents(web_contents_),
14712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      callback, message);
1472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DevToolsWindow::CreateDevToolsBrowser() {
1475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string wp_key = GetDevToolsWindowPlacementPrefKey();
1476a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PrefService* prefs = profile_->GetPrefs();
14775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* wp_pref = prefs->GetDictionary(wp_key.c_str());
1478a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!wp_pref || wp_pref->empty()) {
1479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    DictionaryPrefUpdate update(prefs, wp_key.c_str());
14805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* defaults = update.Get();
1481a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    defaults->SetInteger("left", 100);
1482a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    defaults->SetInteger("top", 100);
1483a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    defaults->SetInteger("right", 740);
1484a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    defaults->SetInteger("bottom", 740);
1485a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    defaults->SetBoolean("maximized", false);
1486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    defaults->SetBoolean("always_on_top", false);
1487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1488a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1489a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  browser_ = new Browser(Browser::CreateParams::CreateForDevTools(
14902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      profile_,
14912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      chrome::GetHostDesktopTypeForNativeView(
14922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          web_contents_->GetView()->GetNativeView())));
1493a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  browser_->tab_strip_model()->AddWebContents(
1494a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      web_contents_, -1, content::PAGE_TRANSITION_AUTO_TOPLEVEL,
1495a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      TabStripModel::ADD_ACTIVE);
1496a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  GetRenderViewHost()->SyncRendererPrefs();
1497a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static
1500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool DevToolsWindow::FindInspectedBrowserAndTabIndex(
1501a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    content::WebContents* inspected_web_contents, Browser** browser, int* tab) {
1502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!inspected_web_contents)
1503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
1504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    int tab_index = it->tab_strip_model()->GetIndexOfWebContents(
1507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        inspected_web_contents);
1508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (tab_index != TabStripModel::kNoTab) {
1509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      *browser = *it;
1510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      *tab = tab_index;
1511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return true;
1512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return false;
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1517a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() {
1518a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Browser* browser = NULL;
1519a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int tab;
1520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return FindInspectedBrowserAndTabIndex(GetInspectedWebContents(),
1521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                         &browser, &tab) ?
1522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      browser->window() : NULL;
152390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
152490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::DoAction(const DevToolsToggleAction& action) {
15265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (action.type()) {
15270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kShowConsole:
15282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      CallClientFunction("InspectorFrontendAPI.showConsole", NULL, NULL, NULL);
1529a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
15302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
15310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kInspect:
15322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      CallClientFunction("InspectorFrontendAPI.enterInspectElementMode", NULL,
15332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                         NULL, NULL);
15342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      break;
15352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
15360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kShow:
15370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kToggle:
1538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      // Do nothing.
1539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
15402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
15410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kReveal: {
15420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      const DevToolsToggleAction::RevealParams* params =
15435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          action.params();
15440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      CHECK(params);
15450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      base::StringValue url_value(params->url);
15460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      base::FundamentalValue line_value(static_cast<int>(params->line_number));
15470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      base::FundamentalValue column_value(
15480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          static_cast<int>(params->column_number));
15490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      CallClientFunction("InspectorFrontendAPI.revealSourceLine",
15500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                         &url_value,
15510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                         &line_value,
15520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                         &column_value);
15530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      break;
15540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
1555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    default:
1556a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      NOTREACHED();
15572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      break;
1558a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1559a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1560a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1561a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DevToolsWindow::UpdateTheme() {
1562a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_);
15632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DCHECK(tp);
15642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
15652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  std::string command("InspectorFrontendAPI.setToolbarColors(\"" +
15662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_TOOLBAR)) +
15672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      "\", \"" +
15682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)) +
15692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      "\")");
1570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  web_contents_->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(command));
1571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DevToolsWindow::AddDevToolsExtensionsToClient() {
1574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  content::WebContents* inspected_web_contents = GetInspectedWebContents();
1575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (inspected_web_contents) {
1576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    SessionTabHelper* session_tab_helper =
1577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        SessionTabHelper::FromWebContents(inspected_web_contents);
1578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (session_tab_helper) {
1579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::FundamentalValue tabId(session_tab_helper->session_id().id());
15802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      CallClientFunction("WebInspector.setInspectedTabId", &tabId, NULL, NULL);
1581a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
1582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
15832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Profile* profile =
1585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      Profile::FromBrowserContext(web_contents_->GetBrowserContext());
1586a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const ExtensionService* extension_service = extensions::ExtensionSystem::Get(
1587a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      profile->GetOriginalProfile())->extension_service();
1588a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!extension_service)
1589a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
15905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const extensions::ExtensionSet* extensions = extension_service->extensions();
1591a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue results;
15935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (extensions::ExtensionSet::const_iterator extension(extensions->begin());
1594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       extension != extensions->end(); ++extension) {
1595a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (extensions::ManifestURL::GetDevToolsPage(extension->get()).is_empty())
1596a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      continue;
15975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* extension_info = new base::DictionaryValue();
1598a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    extension_info->Set(
1599a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "startPage",
16005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new base::StringValue(
1601a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            extensions::ManifestURL::GetDevToolsPage(extension->get()).spec()));
16025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    extension_info->Set("name", new base::StringValue((*extension)->name()));
16032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    extension_info->Set(
16042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        "exposeExperimentalAPIs",
16052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        new base::FundamentalValue((*extension)->HasAPIPermission(
16062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            extensions::APIPermission::kExperimental)));
1607a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    results.Append(extension_info);
1608a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
16092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  CallClientFunction("WebInspector.addExtensions", &results, NULL, NULL);
1610a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1611a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1612a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DevToolsWindow::CallClientFunction(const std::string& function_name,
16135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const base::Value* arg1,
16145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const base::Value* arg2,
16155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const base::Value* arg3) {
1616a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string params;
1617a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (arg1) {
1618a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::string json;
1619a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::JSONWriter::Write(arg1, &json);
1620a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    params.append(json);
1621a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (arg2) {
1622a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::JSONWriter::Write(arg2, &json);
1623a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      params.append(", " + json);
16242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      if (arg3) {
16252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        base::JSONWriter::Write(arg3, &json);
16262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        params.append(", " + json);
16272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      }
1628a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 javascript =
16315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::ASCIIToUTF16(function_name + "(" + params + ");");
1632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  web_contents_->GetMainFrame()->ExecuteJavaScript(javascript);
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::UpdateBrowserToolbar() {
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserWindow* inspected_window = GetInspectedBrowserWindow();
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (inspected_window)
16383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    inspected_window->UpdateToolbar(NULL);
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1641a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)content::WebContents* DevToolsWindow::GetInspectedWebContents() {
16422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return inspected_contents_observer_ ?
16432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      inspected_contents_observer_->web_contents() : NULL;
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
16461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void DevToolsWindow::DocumentOnLoadCompletedInMainFrame() {
16475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We could be in kLoadCompleted state already if frontend reloads itself.
16485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (load_state_ != kLoadCompleted) {
16495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Load is completed when both kIsDockedSet and kOnLoadFired happened.
16505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Here we set kOnLoadFired.
16515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    load_state_ = load_state_ == kIsDockedSet ? kLoadCompleted : kOnLoadFired;
16525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
16535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (load_state_ == kLoadCompleted)
16545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LoadCompleted();
16555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
16565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::LoadCompleted() {
16585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Show(action_on_load_);
16595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  action_on_load_ = DevToolsToggleAction::NoOp();
16601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  UpdateTheme();
16611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  AddDevToolsExtensionsToClient();
16625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!load_completed_callback_.is_null()) {
16635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    load_completed_callback_.Run();
16645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    load_completed_callback_ = base::Closure();
16655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
16665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
16675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::SetLoadCompletedCallback(const base::Closure& closure) {
16695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (load_state_ == kLoadCompleted) {
16705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!closure.is_null())
16715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      closure.Run();
16725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
16735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
16745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  load_completed_callback_ = closure;
16751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1676c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1677c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid DevToolsWindow::SetWhitelistedShortcuts(
1678c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const std::string& message) {
1679c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_forwarder_->SetWhitelistedShortcuts(message);
1680c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1681c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1682c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool DevToolsWindow::ForwardKeyboardEvent(
1683c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const content::NativeWebKeyboardEvent& event) {
1684c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return event_forwarder_->ForwardEvent(event);
1685c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1686