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)
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/json/json_reader.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/time/time.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chrome_page_zoom.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/file_select_helper.h"
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/infobars/infobar_service.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/prefs/pref_service_syncable.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_tab_helper.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/browser_dialogs.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/webui/devtools_ui.h"
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/ui/zoom/zoom_controller.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/render_messages.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "content/public/browser/browser_thread.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/devtools_agent_host.h"
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/browser/native_web_keyboard_event.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/render_frame_host.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/render_widget_host_view.h"
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/browser/user_metrics.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_client.h"
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/url_constants.h"
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/web/WebInputEvent.h"
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/page_transition_types.h"
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/keycodes/keyboard_codes.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)using base::DictionaryValue;
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochusing blink::WebInputEvent;
540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)using content::BrowserThread;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DevToolsAgentHost;
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing content::WebContents;
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace {
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liutypedef std::vector<DevToolsWindow*> DevToolsWindows;
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubase::LazyInstance<DevToolsWindows>::Leaky g_instances =
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LAZY_INSTANCE_INITIALIZER;
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic const char kKeyUpEventName[] = "keyup";
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic const char kKeyDownEventName[] = "keydown";
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool FindInspectedBrowserAndTabIndex(
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    WebContents* inspected_web_contents, Browser** browser, int* tab) {
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!inspected_web_contents)
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int tab_index = it->tab_strip_model()->GetIndexOfWebContents(
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        inspected_web_contents);
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (tab_index != TabStripModel::kNoTab) {
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      *browser = *it;
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      *tab = tab_index;
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return true;
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return false;
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// DevToolsToolboxDelegate ----------------------------------------------------
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass DevToolsToolboxDelegate
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : public content::WebContentsObserver,
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      public content::WebContentsDelegate {
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public:
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DevToolsToolboxDelegate(
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      WebContents* toolbox_contents,
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DevToolsWindow::ObserverWithAccessor* web_contents_observer);
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual ~DevToolsToolboxDelegate();
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual content::WebContents* OpenURLFromTab(
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      content::WebContents* source,
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const content::OpenURLParams& params) OVERRIDE;
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual bool PreHandleKeyboardEvent(
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      content::WebContents* source,
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const content::NativeWebKeyboardEvent& event,
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      bool* is_keyboard_shortcut) OVERRIDE;
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void HandleKeyboardEvent(
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      content::WebContents* source,
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const content::NativeWebKeyboardEvent& event) OVERRIDE;
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void WebContentsDestroyed() OVERRIDE;
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private:
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  BrowserWindow* GetInspectedBrowserWindow();
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DevToolsWindow::ObserverWithAccessor* inspected_contents_observer_;
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(DevToolsToolboxDelegate);
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
113116680a4aac90f2aa7413d9095a592090648e557Ben MurdochDevToolsToolboxDelegate::DevToolsToolboxDelegate(
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    WebContents* toolbox_contents,
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DevToolsWindow::ObserverWithAccessor* web_contents_observer)
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : WebContentsObserver(toolbox_contents),
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      inspected_contents_observer_(web_contents_observer) {
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
120116680a4aac90f2aa7413d9095a592090648e557Ben MurdochDevToolsToolboxDelegate::~DevToolsToolboxDelegate() {
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdochcontent::WebContents* DevToolsToolboxDelegate::OpenURLFromTab(
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::WebContents* source,
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const content::OpenURLParams& params) {
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(source == web_contents());
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!params.url.SchemeIs(content::kChromeDevToolsScheme))
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  content::NavigationController::LoadURLParams load_url_params(params.url);
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  source->GetController().LoadURLWithParams(load_url_params);
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return source;
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool DevToolsToolboxDelegate::PreHandleKeyboardEvent(
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::WebContents* source,
136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const content::NativeWebKeyboardEvent& event,
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool* is_keyboard_shortcut) {
138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  BrowserWindow* window = GetInspectedBrowserWindow();
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (window)
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return window->PreHandleKeyboardEvent(event, is_keyboard_shortcut);
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return false;
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid DevToolsToolboxDelegate::HandleKeyboardEvent(
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::WebContents* source,
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const content::NativeWebKeyboardEvent& event) {
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (event.windowsKeyCode == 0x08) {
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Do not navigate back in history on Windows (http://crbug.com/74156).
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  BrowserWindow* window = GetInspectedBrowserWindow();
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (window)
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    window->HandleKeyboardEvent(event);
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid DevToolsToolboxDelegate::WebContentsDestroyed() {
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  delete this;
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
160116680a4aac90f2aa7413d9095a592090648e557Ben MurdochBrowserWindow* DevToolsToolboxDelegate::GetInspectedBrowserWindow() {
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  WebContents* inspected_contents =
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      inspected_contents_observer_->web_contents();
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!inspected_contents)
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Browser* browser = NULL;
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int tab = 0;
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (FindInspectedBrowserAndTabIndex(inspected_contents, &browser, &tab))
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return browser->window();
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return NULL;
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// DevToolsEventForwarder -----------------------------------------------------
1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass DevToolsEventForwarder {
177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  explicit DevToolsEventForwarder(DevToolsWindow* window)
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     : devtools_window_(window) {}
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Registers whitelisted shortcuts with the forwarder.
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Only registered keys will be forwarded to the DevTools frontend.
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void SetWhitelistedShortcuts(const std::string& message);
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Forwards a keyboard event to the DevTools frontend if it is whitelisted.
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Returns |true| if the event has been forwarded, |false| otherwise.
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool ForwardEvent(const content::NativeWebKeyboardEvent& event);
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  static int VirtualKeyCodeWithoutLocation(int key_code);
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  static bool KeyWhitelistingAllowed(int key_code, int modifiers);
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  static int CombineKeyCodeAndModifiers(int key_code, int modifiers);
193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DevToolsWindow* devtools_window_;
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::set<int> whitelisted_keys_;
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DISALLOW_COPY_AND_ASSIGN(DevToolsEventForwarder);
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid DevToolsEventForwarder::SetWhitelistedShortcuts(
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const std::string& message) {
202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message));
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::ListValue* shortcut_list;
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!parsed_message->GetAsList(&shortcut_list))
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return;
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::ListValue::iterator it = shortcut_list->begin();
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (; it != shortcut_list->end(); ++it) {
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::DictionaryValue* dictionary;
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!(*it)->GetAsDictionary(&dictionary))
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      continue;
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int key_code = 0;
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    dictionary->GetInteger("keyCode", &key_code);
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (key_code == 0)
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      continue;
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int modifiers = 0;
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    dictionary->GetInteger("modifiers", &modifiers);
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!KeyWhitelistingAllowed(key_code, modifiers)) {
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      LOG(WARNING) << "Key whitelisting forbidden: "
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   << "(" << key_code << "," << modifiers << ")";
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      continue;
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    whitelisted_keys_.insert(CombineKeyCodeAndModifiers(key_code, modifiers));
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool DevToolsEventForwarder::ForwardEvent(
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const content::NativeWebKeyboardEvent& event) {
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string event_type;
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (event.type) {
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case WebInputEvent::KeyDown:
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case WebInputEvent::RawKeyDown:
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      event_type = kKeyDownEventName;
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case WebInputEvent::KeyUp:
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      event_type = kKeyUpEventName;
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    default:
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return false;
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int key_code = VirtualKeyCodeWithoutLocation(event.windowsKeyCode);
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int key = CombineKeyCodeAndModifiers(key_code, event.modifiers);
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (whitelisted_keys_.find(key) == whitelisted_keys_.end())
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::DictionaryValue event_data;
247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_data.SetString("type", event_type);
248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_data.SetString("keyIdentifier", event.keyIdentifier);
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_data.SetInteger("keyCode", key_code);
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_data.SetInteger("modifiers", event.modifiers);
2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  devtools_window_->bindings_->CallClientFunction(
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "InspectorFrontendAPI.keyEventUnhandled", &event_data, NULL, NULL);
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint DevToolsEventForwarder::CombineKeyCodeAndModifiers(int key_code,
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                       int modifiers) {
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return key_code | (modifiers << 16);
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool DevToolsEventForwarder::KeyWhitelistingAllowed(int key_code,
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                    int modifiers) {
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return (ui::VKEY_F1 <= key_code && key_code <= ui::VKEY_F12) ||
264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      modifiers != 0;
265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Mapping copied from Blink's KeyboardEvent.cpp.
268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint DevToolsEventForwarder::VirtualKeyCodeWithoutLocation(int key_code)
269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{
270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (key_code) {
271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_LCONTROL:
272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_RCONTROL:
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return ui::VKEY_CONTROL;
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_LSHIFT:
275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_RSHIFT:
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return ui::VKEY_SHIFT;
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_LMENU:
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ui::VKEY_RMENU:
279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return ui::VKEY_MENU;
280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    default:
281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return key_code;
282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// DevToolsWindow::ObserverWithAccessor -------------------------------
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
287116680a4aac90f2aa7413d9095a592090648e557Ben MurdochDevToolsWindow::ObserverWithAccessor::ObserverWithAccessor(
2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* web_contents)
289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : WebContentsObserver(web_contents) {
290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
292116680a4aac90f2aa7413d9095a592090648e557Ben MurdochDevToolsWindow::ObserverWithAccessor::~ObserverWithAccessor() {
2932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
2942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// DevToolsWindow -------------------------------------------------------------
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst char DevToolsWindow::kDevToolsApp[] = "DevToolsApp";
2982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow::~DevToolsWindow() {
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  life_stage_ = kClosing;
301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UpdateBrowserWindow();
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateBrowserToolbar();
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (toolbox_web_contents_)
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    delete toolbox_web_contents_;
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DevToolsWindows* instances = g_instances.Pointer();
3092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DevToolsWindows::iterator it(
3102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      std::find(instances->begin(), instances->end(), this));
3112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DCHECK(it != instances->end());
3122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  instances->erase(it);
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!close_callback_.is_null()) {
315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    close_callback_.Run();
316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    close_callback_ = base::Closure();
317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DevToolsWindow::RegisterProfilePrefs(
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterDictionaryPref(
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kDevToolsEditedFiles,
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterDictionaryPref(
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kDevToolsFileSystemPaths,
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  registry->RegisterStringPref(
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      prefs::kDevToolsAdbKey, std::string(),
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  registry->RegisterBooleanPref(
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      prefs::kDevToolsDiscoverUsbDevicesEnabled,
3350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      true,
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterBooleanPref(
3382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      prefs::kDevToolsPortForwardingEnabled,
3392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      false,
3402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  registry->RegisterBooleanPref(
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      prefs::kDevToolsPortForwardingDefaultSet,
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      false,
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
3452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  registry->RegisterDictionaryPref(
3462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      prefs::kDevToolsPortForwardingConfig,
3472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)content::WebContents* DevToolsWindow::GetInTabWebContents(
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    WebContents* inspected_web_contents,
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DevToolsContentsResizingStrategy* out_strategy) {
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DevToolsWindow* window = GetInstanceForInspectedWebContents(
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      inspected_web_contents);
356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!window || window->life_stage_ == kClosing)
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Not yet loaded window is treated as docked, but we should not present it
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // until we decided on docking.
361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool is_docked_set = window->life_stage_ == kLoadCompleted ||
362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      window->life_stage_ == kIsDockedSet;
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!is_docked_set)
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return NULL;
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Undocked window should have toolbox web contents.
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!window->is_docked_ && !window->toolbox_web_contents_)
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return NULL;
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (out_strategy)
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    out_strategy->CopyFrom(window->contents_resizing_strategy_);
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return window->is_docked_ ? window->main_web_contents_ :
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      window->toolbox_web_contents_;
3750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
3760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// static
378c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochDevToolsWindow* DevToolsWindow::GetInstanceForInspectedWebContents(
3795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* inspected_web_contents) {
380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!inspected_web_contents || g_instances == NULL)
381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return NULL;
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DevToolsWindows* instances = g_instances.Pointer();
383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (DevToolsWindows::iterator it(instances->begin()); it != instances->end();
384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       ++it) {
385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if ((*it)->GetInspectedWebContents() == inspected_web_contents)
386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return *it;
387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return NULL;
389c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
390c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
391c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// static
392116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool DevToolsWindow::IsDevToolsWindow(content::WebContents* web_contents) {
393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!web_contents || g_instances == NULL)
394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DevToolsWindows* instances = g_instances.Pointer();
396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (DevToolsWindows::iterator it(instances->begin()); it != instances->end();
397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       ++it) {
398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if ((*it)->main_web_contents_ == web_contents ||
399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        (*it)->toolbox_web_contents_ == web_contents)
400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return true;
401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return false;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindowForWorker(
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<DevToolsAgentHost>& worker_agent) {
4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DevToolsWindow* window = FindDevToolsWindow(worker_agent.get());
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!window) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window = DevToolsWindow::CreateDevToolsWindowForWorker(profile);
41203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    window->bindings_->AttachTo(worker_agent);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window->ScheduleShow(DevToolsToggleAction::Show());
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return window;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::CreateDevToolsWindowForWorker(
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile) {
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::RecordAction(base::UserMetricsAction("DevTools_InspectWorker"));
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return Create(profile, GURL(), NULL, true, false, false, "");
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindow(
4276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    content::WebContents* inspected_web_contents) {
4280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return ToggleDevToolsWindow(
4296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      inspected_web_contents, true, DevToolsToggleAction::Show(), "");
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DevToolsWindow* DevToolsWindow::OpenDevToolsWindow(
4346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    content::WebContents* inspected_web_contents,
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const DevToolsToggleAction& action) {
4366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return ToggleDevToolsWindow(inspected_web_contents, true, action, "");
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow(
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser,
4420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const DevToolsToggleAction& action) {
4430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (action.type() == DevToolsToggleAction::kToggle &&
4440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      browser->is_devtools()) {
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser->tab_strip_model()->CloseAllTabs();
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return ToggleDevToolsWindow(
4506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      browser->tab_strip_model()->GetActiveWebContents(),
4516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      action.type() == DevToolsToggleAction::kInspect,
4526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      action, "");
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsWindow::OpenExternalFrontend(
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Profile* profile,
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& frontend_url,
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<content::DevToolsAgentHost>& agent_host,
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool isWorker) {
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DevToolsWindow* window = FindDevToolsWindow(agent_host.get());
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!window) {
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window = Create(profile, DevToolsUI::GetProxyURL(frontend_url), NULL,
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    isWorker, true, false, "");
46503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    window->bindings_->AttachTo(agent_host);
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window->ScheduleShow(DevToolsToggleAction::Show());
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow(
4726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    content::WebContents* inspected_web_contents,
473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    bool force_open,
474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const DevToolsToggleAction& action,
475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& settings) {
476a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent(
4776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      DevToolsAgentHost::GetOrCreateFor(inspected_web_contents));
478a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DevToolsWindow* window = FindDevToolsWindow(agent.get());
479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool do_open = force_open;
480a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!window) {
481a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Profile* profile = Profile::FromBrowserContext(
4826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        inspected_web_contents->GetBrowserContext());
483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::RecordAction(
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::UserMetricsAction("DevTools_InspectRenderer"));
485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    window = Create(
4866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        profile, GURL(), inspected_web_contents, false, false, true, settings);
48703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    window->bindings_->AttachTo(agent.get());
488a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    do_open = true;
489a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
491a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Update toolbar to reflect DevTools changes.
492a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  window->UpdateBrowserToolbar();
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
494a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // If window is docked and visible, we hide it on toggle. If window is
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // undocked, we show (activate) it.
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!window->is_docked_ || do_open)
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window->ScheduleShow(action);
498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  else
499a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    window->CloseWindow();
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return window;
502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
5056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DevToolsWindow::InspectElement(
5066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    content::WebContents* inspected_web_contents,
5076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int x,
5086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int y) {
509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent(
5106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      DevToolsAgentHost::GetOrCreateFor(inspected_web_contents));
511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  agent->InspectElement(x, y);
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool should_measure_time = FindDevToolsWindow(agent.get()) == NULL;
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::TimeTicks start_time = base::TimeTicks::Now();
514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // TODO(loislo): we should initiate DevTools window opening from within
515a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // renderer. Otherwise, we still can hit a race condition here.
5166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DevToolsWindow* window = OpenDevToolsWindow(inspected_web_contents);
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (should_measure_time)
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window->inspect_element_start_time_ = start_time;
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::ScheduleShow(const DevToolsToggleAction& action) {
522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (life_stage_ == kLoadCompleted) {
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Show(action);
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Action will be done only after load completed.
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  action_on_load_ = action;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!can_dock_) {
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // No harm to show always-undocked window right away.
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    is_docked_ = false;
5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Show(DevToolsToggleAction::Show());
5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void DevToolsWindow::Show(const DevToolsToggleAction& action) {
538116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (life_stage_ == kClosing)
539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
540116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (action.type() == DevToolsToggleAction::kNoOp)
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_) {
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(can_dock_);
5462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    Browser* inspected_browser = NULL;
5472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    int inspected_tab_index = -1;
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FindInspectedBrowserAndTabIndex(GetInspectedWebContents(),
5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    &inspected_browser,
5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    &inspected_tab_index);
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(inspected_browser);
5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(inspected_tab_index != -1);
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Tell inspected browser to update splitter and switch to inspected panel.
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserWindow* inspected_window = inspected_browser->window();
556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    main_web_contents_->SetDelegate(this);
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TabStripModel* tab_strip_model = inspected_browser->tab_strip_model();
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tab_strip_model->ActivateTabAt(inspected_tab_index, true);
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    inspected_window->UpdateDevTools();
562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    main_web_contents_->SetInitialFocus();
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    inspected_window->Show();
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // On Aura, focusing once is not enough. Do it again.
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Note that focusing only here but not before isn't enough either. We just
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // need to focus twice.
567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    main_web_contents_->SetInitialFocus();
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PrefsTabHelper::CreateForWebContents(main_web_contents_);
570cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    main_web_contents_->GetRenderViewHost()->SyncRendererPrefs();
5712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DoAction(action);
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Avoid consecutive window switching if the devtools window has been opened
577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // and the Inspect Element shortcut is pressed in the inspected tab.
578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool should_show_window =
5790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      !browser_ || (action.type() != DevToolsToggleAction::kInspect);
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
581a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!browser_)
582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    CreateDevToolsBrowser();
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (should_show_window) {
585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    browser_->window()->Show();
586cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    main_web_contents_->SetInitialFocus();
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (toolbox_web_contents_)
589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UpdateBrowserWindow();
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoAction(action);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
594f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
5955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool DevToolsWindow::HandleBeforeUnload(WebContents* frontend_contents,
596f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool proceed, bool* proceed_to_fire_unload) {
597116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DevToolsWindow* window = AsDevToolsWindow(frontend_contents);
598a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!window)
599a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!window->intercepted_page_beforeunload_)
601f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  window->BeforeUnloadFired(frontend_contents, proceed,
603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      proceed_to_fire_unload);
604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
6085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool DevToolsWindow::InterceptPageBeforeUnload(WebContents* contents) {
609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DevToolsWindow* window =
610116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DevToolsWindow::GetInstanceForInspectedWebContents(contents);
611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!window || window->intercepted_page_beforeunload_)
612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Not yet loaded frontend will not handle beforeunload.
615116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (window->life_stage_ != kLoadCompleted)
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  window->intercepted_page_beforeunload_ = true;
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Handle case of devtools inspecting another devtools instance by passing
620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // the call up to the inspecting devtools instance.
621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!DevToolsWindow::InterceptPageBeforeUnload(window->main_web_contents_)) {
622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    window->main_web_contents_->DispatchBeforeUnload(false);
623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool DevToolsWindow::NeedsToInterceptBeforeUnload(
6295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* contents) {
630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DevToolsWindow* window =
631116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DevToolsWindow::GetInstanceForInspectedWebContents(contents);
632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return window && !window->intercepted_page_beforeunload_;
633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool DevToolsWindow::HasFiredBeforeUnloadEventForDevToolsBrowser(
637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Browser* browser) {
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(browser->is_devtools());
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // When FastUnloadController is used, devtools frontend will be detached
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // from the browser window at this point which means we've already fired
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // beforeunload.
642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (browser->tab_strip_model()->empty())
643f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
6445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WebContents* contents =
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      browser->tab_strip_model()->GetWebContentsAt(0);
646116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DevToolsWindow* window = AsDevToolsWindow(contents);
647a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!window)
648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
649f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return window->intercepted_page_beforeunload_;
650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
651f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
6535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::OnPageCloseCanceled(WebContents* contents) {
654f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DevToolsWindow *window =
655116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DevToolsWindow::GetInstanceForInspectedWebContents(contents);
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!window)
657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  window->intercepted_page_beforeunload_ = false;
659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Propagate to devtools opened on devtools if any.
660cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DevToolsWindow::OnPageCloseCanceled(window->main_web_contents_);
661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
663a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow::DevToolsWindow(Profile* profile,
664a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               const GURL& url,
6656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                               content::WebContents* inspected_web_contents,
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               bool can_dock)
667a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : profile_(profile),
668cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      main_web_contents_(
669cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          WebContents::Create(WebContents::CreateParams(profile))),
670cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      toolbox_web_contents_(NULL),
6715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bindings_(NULL),
672a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      browser_(NULL),
6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      is_docked_(true),
6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      can_dock_(can_dock),
6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // This initialization allows external front-end to work without changes.
6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // We don't wait for docking call, but instead immediately show undocked.
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Passing "dockSide=undocked" parameter ensures proper UI.
678116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      life_stage_(can_dock ? kNotLoaded : kIsDockedSet),
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      action_on_load_(DevToolsToggleAction::NoOp()),
6805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      intercepted_page_beforeunload_(false) {
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Set up delegate, so we get fully-functional window immediately.
682116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // It will not appear in UI though until |life_stage_ == kLoadCompleted|.
683cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  main_web_contents_->SetDelegate(this);
68403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
68503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  main_web_contents_->GetController().LoadURL(
68603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      DevToolsUIBindings::ApplyThemeToURL(profile, url), content::Referrer(),
6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
68803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
68903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bindings_ = DevToolsUIBindings::ForWebContents(main_web_contents_);
69003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(bindings_);
69103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Bindings take ownership over devtools as its delegate.
6935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bindings_->SetDelegate(this);
694116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // DevTools uses chrome_page_zoom::Zoom(), so main_web_contents_ requires a
695116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // ZoomController.
696116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ZoomController::CreateForWebContents(main_web_contents_);
697116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ZoomController::FromWebContents(main_web_contents_)
698116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ->SetShowsNotificationBubble(false);
699a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
700a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  g_instances.Get().push_back(this);
7012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
7026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // There is no inspected_web_contents in case of various workers.
7036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (inspected_web_contents)
7046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    inspected_contents_observer_.reset(
7056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        new ObserverWithAccessor(inspected_web_contents));
7065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Initialize docked page to be of the right size.
7085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (can_dock_ && inspected_web_contents) {
7095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    content::RenderWidgetHostView* inspected_view =
7105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        inspected_web_contents->GetRenderWidgetHostView();
7115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (inspected_view && main_web_contents_->GetRenderWidgetHostView()) {
7125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      gfx::Size size = inspected_view->GetViewBounds().size();
7135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      main_web_contents_->GetRenderWidgetHostView()->SetSize(size);
7145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
7155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
7165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
717c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_forwarder_.reset(new DevToolsEventForwarder(this));
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
720a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
721a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow* DevToolsWindow::Create(
722a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Profile* profile,
723a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const GURL& frontend_url,
7246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    content::WebContents* inspected_web_contents,
725424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    bool shared_worker_frontend,
726a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool external_frontend,
727116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool can_dock,
728116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& settings) {
7296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (inspected_web_contents) {
730a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Check for a place to dock.
731a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Browser* browser = NULL;
732a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int tab;
733a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!FindInspectedBrowserAndTabIndex(inspected_web_contents,
734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                         &browser, &tab) ||
735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        browser->is_type_popup()) {
736a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      can_dock = false;
737a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
738a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
739a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
740a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Create WebContents with devtools.
7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url(GetDevToolsURL(profile, frontend_url,
742424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                          shared_worker_frontend,
743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          external_frontend,
744116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          can_dock, settings));
7456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return new DevToolsWindow(profile, url, inspected_web_contents, can_dock);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL DevToolsWindow::GetDevToolsURL(Profile* profile,
750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    const GURL& base_url,
751424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                    bool shared_worker_frontend,
752a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    bool external_frontend,
753116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    bool can_dock,
754116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    const std::string& settings) {
7555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Compatibility errors are encoded with data urls, pass them
7565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // through with no decoration.
7578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (base_url.SchemeIs("data"))
7588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return base_url;
7598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  std::string frontend_url(
7612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      base_url.is_empty() ? chrome::kChromeUIDevToolsURL : base_url.spec());
7622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  std::string url_string(
7632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      frontend_url +
7645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ((frontend_url.find("?") == std::string::npos) ? "?" : "&"));
7652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (shared_worker_frontend)
7662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    url_string += "&isSharedWorker=true";
767424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (external_frontend)
768424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    url_string += "&remoteFrontend=true";
769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (can_dock)
770a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    url_string += "&can_dock=true";
771116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (settings.size())
772116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    url_string += "&settings=" + settings;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL(url_string);
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
776a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
777a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DevToolsWindow* DevToolsWindow::FindDevToolsWindow(
778a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    DevToolsAgentHost* agent_host) {
779116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!agent_host || g_instances == NULL)
780116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DevToolsWindows* instances = g_instances.Pointer();
7822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  for (DevToolsWindows::iterator it(instances->begin()); it != instances->end();
7832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch       ++it) {
78403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if ((*it)->bindings_->IsAttachedTo(agent_host))
785a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *it;
786a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
787a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return NULL;
788a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
790a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
7912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochDevToolsWindow* DevToolsWindow::AsDevToolsWindow(
792116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::WebContents* web_contents) {
793116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!web_contents || g_instances == NULL)
794a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return NULL;
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DevToolsWindows* instances = g_instances.Pointer();
7962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  for (DevToolsWindows::iterator it(instances->begin()); it != instances->end();
7972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch       ++it) {
798116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if ((*it)->main_web_contents_ == web_contents)
799a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return *it;
800a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
801a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return NULL;
802a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
803a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
8045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuWebContents* DevToolsWindow::OpenURLFromTab(
8055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* source,
8062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const content::OpenURLParams& params) {
807cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(source == main_web_contents_);
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!params.url.SchemeIs(content::kChromeDevToolsScheme)) {
8095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* inspected_web_contents = GetInspectedWebContents();
8102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return inspected_web_contents ?
8112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        inspected_web_contents->OpenURL(params) : NULL;
812a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
813a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
81403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bindings_->Reattach();
815a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::NavigationController::LoadURLParams load_url_params(params.url);
817cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  main_web_contents_->GetController().LoadURLWithParams(load_url_params);
818cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return main_web_contents_;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::ActivateContents(WebContents* contents) {
8225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (is_docked_) {
8235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* inspected_tab = GetInspectedWebContents();
8245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    inspected_tab->GetDelegate()->ActivateContents(inspected_tab);
8255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
8265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    browser_->window()->Activate();
8275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
8285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
8295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::AddNewContents(WebContents* source,
8315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                    WebContents* new_contents,
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    WindowOpenDisposition disposition,
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const gfx::Rect& initial_pos,
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool user_gesture,
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bool* was_blocked) {
836cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (new_contents == toolbox_web_contents_) {
837cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    toolbox_web_contents_->SetDelegate(
838116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        new DevToolsToolboxDelegate(toolbox_web_contents_,
839116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    inspected_contents_observer_.get()));
8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (main_web_contents_->GetRenderWidgetHostView() &&
8415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        toolbox_web_contents_->GetRenderWidgetHostView()) {
8425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      gfx::Size size =
8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          main_web_contents_->GetRenderWidgetHostView()->GetViewBounds().size();
844cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      toolbox_web_contents_->GetRenderWidgetHostView()->SetSize(size);
8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
846cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UpdateBrowserWindow();
847cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
848cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
849cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
8505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WebContents* inspected_web_contents = GetInspectedWebContents();
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (inspected_web_contents) {
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    inspected_web_contents->GetDelegate()->AddNewContents(
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        source, new_contents, disposition, initial_pos, user_gesture,
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        was_blocked);
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DevToolsWindow::WebContentsCreated(WebContents* source_contents,
859cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        int opener_render_frame_id,
860cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        const base::string16& frame_name,
861cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        const GURL& target_url,
862cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        WebContents* new_contents) {
863cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (target_url.SchemeIs(content::kChromeDevToolsScheme) &&
864cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      target_url.query().find("toolbox=true") != std::string::npos) {
865cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CHECK(can_dock_);
866cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    toolbox_web_contents_ = new_contents;
867cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
868cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
869cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
8705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::CloseContents(WebContents* source) {
8715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(is_docked_);
872116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  life_stage_ = kClosing;
873cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UpdateBrowserWindow();
874cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // In case of docked main_web_contents_, we own it so delete here.
875f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Embedding DevTools window will be deleted as a result of
876cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // DevToolsUIBindings destruction.
877cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  delete main_web_contents_;
8784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
8794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::ContentsZoomChange(bool zoom_in) {
8815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(is_docked_);
882cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chrome_page_zoom::Zoom(main_web_contents_,
8835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      zoom_in ? content::PAGE_ZOOM_IN : content::PAGE_ZOOM_OUT);
8845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::BeforeUnloadFired(WebContents* tab,
8874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       bool proceed,
8884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       bool* proceed_to_fire_unload) {
889f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!intercepted_page_beforeunload_) {
890f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Docked devtools window closed directly.
89103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (proceed)
89203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      bindings_->Detach();
893f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *proceed_to_fire_unload = proceed;
894f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
895f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Inspected page is attempting to close.
8965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* inspected_web_contents = GetInspectedWebContents();
897f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (proceed) {
898c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      inspected_web_contents->DispatchBeforeUnload(false);
899f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
900f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      bool should_proceed;
901f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      inspected_web_contents->GetDelegate()->BeforeUnloadFired(
902f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          inspected_web_contents, false, &should_proceed);
903f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK(!should_proceed);
904f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
905f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *proceed_to_fire_unload = false;
9064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
907a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
908a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DevToolsWindow::PreHandleKeyboardEvent(
9105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* source,
9112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const content::NativeWebKeyboardEvent& event,
9122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    bool* is_keyboard_shortcut) {
913116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  BrowserWindow* inspected_window = GetInspectedBrowserWindow();
914116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (inspected_window) {
915116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return inspected_window->PreHandleKeyboardEvent(event,
916116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                    is_keyboard_shortcut);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid DevToolsWindow::HandleKeyboardEvent(
9225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* source,
9232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const content::NativeWebKeyboardEvent& event) {
924116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (event.windowsKeyCode == 0x08) {
925116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Do not navigate back in history on Windows (http://crbug.com/74156).
926116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
928116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  BrowserWindow* inspected_window = GetInspectedBrowserWindow();
929116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (inspected_window)
930116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    inspected_window->HandleKeyboardEvent(event);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
933a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)content::JavaScriptDialogManager* DevToolsWindow::GetJavaScriptDialogManager() {
9345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WebContents* inspected_web_contents = GetInspectedWebContents();
9352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return (inspected_web_contents && inspected_web_contents->GetDelegate()) ?
9362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      inspected_web_contents->GetDelegate()->GetJavaScriptDialogManager() :
9372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      content::WebContentsDelegate::GetJavaScriptDialogManager();
938a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
940a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)content::ColorChooser* DevToolsWindow::OpenColorChooser(
9415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* web_contents,
942a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SkColor initial_color,
943a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::vector<content::ColorSuggestion>& suggestions) {
944a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return chrome::ShowColorChooser(web_contents, initial_color);
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::RunFileChooser(WebContents* web_contents,
9482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                    const content::FileChooserParams& params) {
949a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FileSelectHelper::RunFileChooser(web_contents, params);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::WebContentsFocused(WebContents* contents) {
953a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Browser* inspected_browser = NULL;
954a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int inspected_tab_index = -1;
9555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_ && FindInspectedBrowserAndTabIndex(GetInspectedWebContents(),
956a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                    &inspected_browser,
9572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                                    &inspected_tab_index))
958a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    inspected_browser->window()->WebContentsFocused(contents);
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool DevToolsWindow::PreHandleGestureEvent(
9625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WebContents* source,
9635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const blink::WebGestureEvent& event) {
9645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Disable pinch zooming.
9655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return event.type == blink::WebGestureEvent::GesturePinchBegin ||
9665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.type == blink::WebGestureEvent::GesturePinchUpdate ||
9675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.type == blink::WebGestureEvent::GesturePinchEnd;
9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
9695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::ActivateWindow() {
9715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_docked_ && GetInspectedBrowserWindow())
972cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    main_web_contents_->Focus();
9735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (!is_docked_ && !browser_->window()->IsActive())
9742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    browser_->window()->Activate();
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::CloseWindow() {
9785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(is_docked_);
979116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  life_stage_ = kClosing;
980cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  main_web_contents_->DispatchBeforeUnload(false);
9814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
9824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
983cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DevToolsWindow::SetInspectedPageBounds(const gfx::Rect& rect) {
984cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DevToolsContentsResizingStrategy strategy(rect);
985cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (contents_resizing_strategy_.Equals(strategy))
986cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
987cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
988cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  contents_resizing_strategy_.CopyFrom(strategy);
989cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UpdateBrowserWindow();
9905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
9915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::InspectElementCompleted() {
9935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!inspect_element_start_time_.is_null()) {
9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UMA_HISTOGRAM_TIMES("DevTools.InspectElement",
9955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::TimeTicks::Now() - inspect_element_start_time_);
9965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    inspect_element_start_time_ = base::TimeTicks();
9975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::MoveWindow(int x, int y) {
10015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_docked_) {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect bounds = browser_->window()->GetBounds();
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds.Offset(x, y);
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser_->window()->SetBounds(bounds);
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::SetIsDocked(bool dock_requested) {
1009116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (life_stage_ == kClosing)
10105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(can_dock_ || !dock_requested);
10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!can_dock_)
10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dock_requested = false;
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool was_docked = is_docked_;
10175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  is_docked_ = dock_requested;
10185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1019116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (life_stage_ != kLoadCompleted) {
10205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // This is a first time call we waited for to initialize.
1021116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    life_stage_ = life_stage_ == kOnLoadFired ? kLoadCompleted : kIsDockedSet;
1022116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (life_stage_ == kLoadCompleted)
10235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LoadCompleted();
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dock_requested == was_docked)
10285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1029c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dock_requested && !was_docked) {
10312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // Detach window from the external devtools browser. It will lead to
10322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // the browser object's close and delete. Remove observer first.
10332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    TabStripModel* tab_strip_model = browser_->tab_strip_model();
10342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    tab_strip_model->DetachWebContentsAt(
1035cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        tab_strip_model->GetIndexOfWebContents(main_web_contents_));
10362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    browser_ = NULL;
10375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (!dock_requested && was_docked) {
1038cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UpdateBrowserWindow();
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Show(DevToolsToggleAction::Show());
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::OpenInNewTab(const std::string& url) {
10452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  content::OpenURLParams params(
10462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      GURL(url), content::Referrer(), NEW_FOREGROUND_TAB,
10471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ui::PAGE_TRANSITION_LINK, false);
10485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WebContents* inspected_web_contents = GetInspectedWebContents();
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (inspected_web_contents) {
10502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    inspected_web_contents->OpenURL(params);
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::HostDesktopType host_desktop_type;
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (browser_) {
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_desktop_type = browser_->host_desktop_type();
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // There should always be a browser when there are no inspected web
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // contents.
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_desktop_type = chrome::GetActiveDesktop();
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const BrowserList* browser_list =
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserList::GetInstance(host_desktop_type);
10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (BrowserList::const_iterator it = browser_list->begin();
10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         it != browser_list->end(); ++it) {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*it)->type() == Browser::TYPE_TABBED) {
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*it)->OpenURL(params);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::SetWhitelistedShortcuts(
10755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& message) {
10765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  event_forwarder_->SetWhitelistedShortcuts(message);
1077f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1078f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::InspectedContentsClosing() {
10805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  intercepted_page_beforeunload_ = false;
1081116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  life_stage_ = kClosing;
1082cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  main_web_contents_->GetRenderViewHost()->ClosePage();
10832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
10842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1085010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)InfoBarService* DevToolsWindow::GetInfoBarService() {
1086010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return is_docked_ ?
1087010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      InfoBarService::FromWebContents(GetInspectedWebContents()) :
1088cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      InfoBarService::FromWebContents(main_web_contents_);
1089010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
1090010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1091010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DevToolsWindow::RenderProcessGone() {
1092cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Docked DevToolsWindow owns its main_web_contents_ and must delete it.
1093cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Undocked main_web_contents_ are owned and handled by browser.
1094cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // see crbug.com/369932
1095010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (is_docked_)
1096cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CloseContents(main_web_contents_);
1097010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
1098010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
10995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid DevToolsWindow::OnLoadCompleted() {
11005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // First seed inspected tab id for extension APIs.
11015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WebContents* inspected_web_contents = GetInspectedWebContents();
11025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (inspected_web_contents) {
11035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SessionTabHelper* session_tab_helper =
11045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SessionTabHelper::FromWebContents(inspected_web_contents);
11055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (session_tab_helper) {
11065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::FundamentalValue tabId(session_tab_helper->session_id().id());
11075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bindings_->CallClientFunction("WebInspector.setInspectedTabId",
11085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          &tabId, NULL, NULL);
11095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
11102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
1111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (life_stage_ == kClosing)
1113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
1114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
11155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // We could be in kLoadCompleted state already if frontend reloads itself.
1116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (life_stage_ != kLoadCompleted) {
11175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Load is completed when both kIsDockedSet and kOnLoadFired happened.
11185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Here we set kOnLoadFired.
1119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    life_stage_ = life_stage_ == kIsDockedSet ? kLoadCompleted : kOnLoadFired;
11202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
1121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (life_stage_ == kLoadCompleted)
11225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LoadCompleted();
1123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DevToolsWindow::CreateDevToolsBrowser() {
1126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PrefService* prefs = profile_->GetPrefs();
11271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!prefs->GetDictionary(prefs::kAppWindowPlacement)->HasKey(kDevToolsApp)) {
11281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DictionaryPrefUpdate update(prefs, prefs::kAppWindowPlacement);
11291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::DictionaryValue* wp_prefs = update.Get();
11301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::DictionaryValue* dev_tools_defaults = new base::DictionaryValue;
11311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    wp_prefs->Set(kDevToolsApp, dev_tools_defaults);
11321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dev_tools_defaults->SetInteger("left", 100);
11331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dev_tools_defaults->SetInteger("top", 100);
11341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dev_tools_defaults->SetInteger("right", 740);
11351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dev_tools_defaults->SetInteger("bottom", 740);
11361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dev_tools_defaults->SetBoolean("maximized", false);
11371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dev_tools_defaults->SetBoolean("always_on_top", false);
1138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  browser_ = new Browser(Browser::CreateParams::CreateForDevTools(
11412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      profile_,
11422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      chrome::GetHostDesktopTypeForNativeView(
1143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          main_web_contents_->GetNativeView())));
1144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  browser_->tab_strip_model()->AddWebContents(
11451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      main_web_contents_, -1, ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
1146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      TabStripModel::ADD_ACTIVE);
1147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  main_web_contents_->GetRenderViewHost()->SyncRendererPrefs();
1148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() {
1151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Browser* browser = NULL;
1152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int tab;
1153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return FindInspectedBrowserAndTabIndex(GetInspectedWebContents(),
1154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                         &browser, &tab) ?
1155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      browser->window() : NULL;
115690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
115790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::DoAction(const DevToolsToggleAction& action) {
11595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (action.type()) {
11600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kShowConsole:
11615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bindings_->CallClientFunction(
11625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          "InspectorFrontendAPI.showConsole", NULL, NULL, NULL);
1163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
11642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
11650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kInspect:
11665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bindings_->CallClientFunction(
11675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          "InspectorFrontendAPI.enterInspectElementMode", NULL, NULL, NULL);
11682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      break;
11692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
11700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kShow:
11710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kToggle:
1172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      // Do nothing.
1173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
11742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
11750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case DevToolsToggleAction::kReveal: {
11760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      const DevToolsToggleAction::RevealParams* params =
11775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          action.params();
11780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      CHECK(params);
11790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      base::StringValue url_value(params->url);
11800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      base::FundamentalValue line_value(static_cast<int>(params->line_number));
11810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      base::FundamentalValue column_value(
11820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          static_cast<int>(params->column_number));
11835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bindings_->CallClientFunction("InspectorFrontendAPI.revealSourceLine",
11845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                    &url_value, &line_value, &column_value);
11850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      break;
11860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
1187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    default:
1188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      NOTREACHED();
11892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      break;
1190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DevToolsWindow::UpdateBrowserToolbar() {
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserWindow* inspected_window = GetInspectedBrowserWindow();
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (inspected_window)
11963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    inspected_window->UpdateToolbar(NULL);
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DevToolsWindow::UpdateBrowserWindow() {
1200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BrowserWindow* inspected_window = GetInspectedBrowserWindow();
1201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (inspected_window)
1202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    inspected_window->UpdateDevTools();
1203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
12055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuWebContents* DevToolsWindow::GetInspectedWebContents() {
12061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return inspected_contents_observer_
12071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci             ? inspected_contents_observer_->web_contents()
12081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci             : NULL;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
12115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::LoadCompleted() {
12125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Show(action_on_load_);
12135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  action_on_load_ = DevToolsToggleAction::NoOp();
12145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!load_completed_callback_.is_null()) {
12155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    load_completed_callback_.Run();
12165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    load_completed_callback_ = base::Closure();
12175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
12195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DevToolsWindow::SetLoadCompletedCallback(const base::Closure& closure) {
1221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (life_stage_ == kLoadCompleted || life_stage_ == kClosing) {
12225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!closure.is_null())
12235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      closure.Run();
12245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
12255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  load_completed_callback_ = closure;
12271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool DevToolsWindow::ForwardKeyboardEvent(
1230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const content::NativeWebKeyboardEvent& event) {
1231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return event_forwarder_->ForwardEvent(event);
1232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1233