No longer register app window placement preference keys on
[chromium-blink-merge.git] / chrome / browser / devtools / devtools_window.h
blob7e75c52edc9d32876844f098a309f013b602b04c
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_
6 #define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_
8 #include "chrome/browser/devtools/devtools_contents_resizing_strategy.h"
9 #include "chrome/browser/devtools/devtools_toggle_action.h"
10 #include "chrome/browser/devtools/devtools_ui_bindings.h"
11 #include "content/public/browser/web_contents_delegate.h"
12 #include "content/public/browser/web_contents_observer.h"
14 class Browser;
15 class BrowserWindow;
16 class DevToolsWindowTesting;
17 class DevToolsEventForwarder;
19 namespace content {
20 class DevToolsAgentHost;
21 struct NativeWebKeyboardEvent;
22 class RenderViewHost;
25 namespace user_prefs {
26 class PrefRegistrySyncable;
29 class DevToolsWindow : public DevToolsUIBindings::Delegate,
30 public content::WebContentsDelegate {
31 public:
32 class ObserverWithAccessor : public content::WebContentsObserver {
33 public:
34 explicit ObserverWithAccessor(content::WebContents* web_contents);
35 virtual ~ObserverWithAccessor();
37 private:
38 DISALLOW_COPY_AND_ASSIGN(ObserverWithAccessor);
41 static const char kDevToolsApp[];
43 virtual ~DevToolsWindow();
45 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
47 // Return the DevToolsWindow for the given WebContents if one exists,
48 // otherwise NULL.
49 static DevToolsWindow* GetInstanceForInspectedWebContents(
50 content::WebContents* inspected_web_contents);
52 // Return the docked DevTools WebContents for the given inspected WebContents
53 // if one exists and should be shown in browser window, otherwise NULL.
54 // This method will return only fully initialized window ready to be
55 // presented in UI.
56 // If |out_strategy| is not NULL, it will contain resizing strategy.
57 // For immediately-ready-to-use but maybe not yet fully initialized DevTools
58 // use |GetInstanceForInspectedRenderViewHost| instead.
59 static content::WebContents* GetInTabWebContents(
60 content::WebContents* inspected_tab,
61 DevToolsContentsResizingStrategy* out_strategy);
63 static bool IsDevToolsWindow(content::WebContents* web_contents);
65 // Open or reveal DevTools window, and perform the specified action.
66 static DevToolsWindow* OpenDevToolsWindow(
67 content::WebContents* inspected_web_contents,
68 const DevToolsToggleAction& action);
70 // Open or reveal DevTools window, with no special action.
71 static DevToolsWindow* OpenDevToolsWindow(
72 content::WebContents* inspected_web_contents);
74 // Perform specified action for current WebContents inside a |browser|.
75 // This may close currently open DevTools window.
76 static DevToolsWindow* ToggleDevToolsWindow(
77 Browser* browser,
78 const DevToolsToggleAction& action);
80 // External frontend is always undocked.
81 static void OpenExternalFrontend(
82 Profile* profile,
83 const std::string& frontend_uri,
84 const scoped_refptr<content::DevToolsAgentHost>& agent_host,
85 bool isWorker);
87 // Worker frontend is always undocked.
88 static DevToolsWindow* OpenDevToolsWindowForWorker(
89 Profile* profile,
90 const scoped_refptr<content::DevToolsAgentHost>& worker_agent);
92 static void InspectElement(content::WebContents* inspected_web_contents,
93 int x,
94 int y);
96 // Sets closure to be called after load is done. If already loaded, calls
97 // closure immediately.
98 void SetLoadCompletedCallback(const base::Closure& closure);
100 // Forwards an unhandled keyboard event to the DevTools frontend.
101 bool ForwardKeyboardEvent(const content::NativeWebKeyboardEvent& event);
103 // BeforeUnload interception ////////////////////////////////////////////////
105 // In order to preserve any edits the user may have made in devtools, the
106 // beforeunload event of the inspected page is hooked - devtools gets the
107 // first shot at handling beforeunload and presents a dialog to the user. If
108 // the user accepts the dialog then the script is given a chance to handle
109 // it. This way 2 dialogs may be displayed: one from the devtools asking the
110 // user to confirm that they're ok with their devtools edits going away and
111 // another from the webpage as the result of its beforeunload handler.
112 // The following set of methods handle beforeunload event flow through
113 // devtools window. When the |contents| with devtools opened on them are
114 // getting closed, the following sequence of calls takes place:
115 // 1. |DevToolsWindow::InterceptPageBeforeUnload| is called and indicates
116 // whether devtools intercept the beforeunload event.
117 // If InterceptPageBeforeUnload() returns true then the following steps
118 // will take place; otherwise only step 4 will be reached and none of the
119 // corresponding functions in steps 2 & 3 will get called.
120 // 2. |DevToolsWindow::InterceptPageBeforeUnload| fires beforeunload event
121 // for devtools frontend, which will asynchronously call
122 // |WebContentsDelegate::BeforeUnloadFired| method.
123 // In case of docked devtools window, devtools are set as a delegate for
124 // its frontend, so method |DevToolsWindow::BeforeUnloadFired| will be
125 // called directly.
126 // If devtools window is undocked it's not set as the delegate so the call
127 // to BeforeUnloadFired is proxied through HandleBeforeUnload() rather
128 // than getting called directly.
129 // 3a. If |DevToolsWindow::BeforeUnloadFired| is called with |proceed|=false
130 // it calls throught to the content's BeforeUnloadFired(), which from the
131 // WebContents perspective looks the same as the |content|'s own
132 // beforeunload dialog having had it's 'stay on this page' button clicked.
133 // 3b. If |proceed| = true, then it fires beforeunload event on |contents|
134 // and everything proceeds as it normally would without the Devtools
135 // interception.
136 // 4. If the user cancels the dialog put up by either the WebContents or
137 // devtools frontend, then |contents|'s |BeforeUnloadFired| callback is
138 // called with the proceed argument set to false, this causes
139 // |DevToolsWindow::OnPageCloseCancelled| to be called.
141 // Devtools window in undocked state is not set as a delegate of
142 // its frontend. Instead, an instance of browser is set as the delegate, and
143 // thus beforeunload event callback from devtools frontend is not delivered
144 // to the instance of devtools window, which is solely responsible for
145 // managing custom beforeunload event flow.
146 // This is a helper method to route callback from
147 // |Browser::BeforeUnloadFired| back to |DevToolsWindow::BeforeUnloadFired|.
148 // * |proceed| - true if the user clicked 'ok' in the beforeunload dialog,
149 // false otherwise.
150 // * |proceed_to_fire_unload| - output parameter, whether we should continue
151 // to fire the unload event or stop things here.
152 // Returns true if devtools window is in a state of intercepting beforeunload
153 // event and if it will manage unload process on its own.
154 static bool HandleBeforeUnload(content::WebContents* contents,
155 bool proceed,
156 bool* proceed_to_fire_unload);
158 // Returns true if this contents beforeunload event was intercepted by
159 // devtools and false otherwise. If the event was intercepted, caller should
160 // not fire beforeunlaod event on |contents| itself as devtools window will
161 // take care of it, otherwise caller should continue handling the event as
162 // usual.
163 static bool InterceptPageBeforeUnload(content::WebContents* contents);
165 // Returns true if devtools browser has already fired its beforeunload event
166 // as a result of beforeunload event interception.
167 static bool HasFiredBeforeUnloadEventForDevToolsBrowser(Browser* browser);
169 // Returns true if devtools window would like to hook beforeunload event
170 // of this |contents|.
171 static bool NeedsToInterceptBeforeUnload(content::WebContents* contents);
173 // Notify devtools window that closing of |contents| was cancelled
174 // by user.
175 static void OnPageCloseCanceled(content::WebContents* contents);
177 private:
178 friend class DevToolsWindowTesting;
180 // DevTools lifecycle typically follows this way:
181 // - Toggle/Open: client call;
182 // - Create;
183 // - ScheduleShow: setup window to be functional, but not yet show;
184 // - DocumentOnLoadCompletedInMainFrame: frontend loaded;
185 // - SetIsDocked: frontend decided on docking state;
186 // - OnLoadCompleted: ready to present frontend;
187 // - Show: actually placing frontend WebContents to a Browser or docked place;
188 // - DoAction: perform action passed in Toggle/Open;
189 // - ...;
190 // - CloseWindow: initiates before unload handling;
191 // - CloseContents: destroys frontend;
192 // - DevToolsWindow is dead once it's main_web_contents dies.
193 enum LifeStage {
194 kNotLoaded,
195 kOnLoadFired, // Implies SetIsDocked was not yet called.
196 kIsDockedSet, // Implies DocumentOnLoadCompleted was not yet called.
197 kLoadCompleted,
198 kClosing
201 DevToolsWindow(Profile* profile,
202 const GURL& frontend_url,
203 content::WebContents* inspected_web_contents,
204 bool can_dock);
206 static DevToolsWindow* Create(Profile* profile,
207 const GURL& frontend_url,
208 content::WebContents* inspected_web_contents,
209 bool shared_worker_frontend,
210 bool external_frontend,
211 bool can_dock,
212 const std::string& settings);
213 static GURL GetDevToolsURL(Profile* profile,
214 const GURL& base_url,
215 bool shared_worker_frontend,
216 bool external_frontend,
217 bool can_dock,
218 const std::string& settings);
219 static DevToolsWindow* FindDevToolsWindow(content::DevToolsAgentHost*);
220 static DevToolsWindow* AsDevToolsWindow(content::WebContents*);
221 static DevToolsWindow* CreateDevToolsWindowForWorker(Profile* profile);
222 static DevToolsWindow* ToggleDevToolsWindow(
223 content::WebContents* web_contents,
224 bool force_open,
225 const DevToolsToggleAction& action,
226 const std::string& settings);
228 // content::WebContentsDelegate:
229 virtual content::WebContents* OpenURLFromTab(
230 content::WebContents* source,
231 const content::OpenURLParams& params) OVERRIDE;
232 virtual void ActivateContents(content::WebContents* contents) OVERRIDE;
233 virtual void AddNewContents(content::WebContents* source,
234 content::WebContents* new_contents,
235 WindowOpenDisposition disposition,
236 const gfx::Rect& initial_pos,
237 bool user_gesture,
238 bool* was_blocked) OVERRIDE;
239 virtual void WebContentsCreated(content::WebContents* source_contents,
240 int opener_render_frame_id,
241 const base::string16& frame_name,
242 const GURL& target_url,
243 content::WebContents* new_contents) OVERRIDE;
244 virtual void CloseContents(content::WebContents* source) OVERRIDE;
245 virtual void ContentsZoomChange(bool zoom_in) OVERRIDE;
246 virtual void BeforeUnloadFired(content::WebContents* tab,
247 bool proceed,
248 bool* proceed_to_fire_unload) OVERRIDE;
249 virtual bool PreHandleKeyboardEvent(
250 content::WebContents* source,
251 const content::NativeWebKeyboardEvent& event,
252 bool* is_keyboard_shortcut) OVERRIDE;
253 virtual void HandleKeyboardEvent(
254 content::WebContents* source,
255 const content::NativeWebKeyboardEvent& event) OVERRIDE;
256 virtual content::JavaScriptDialogManager*
257 GetJavaScriptDialogManager() OVERRIDE;
258 virtual content::ColorChooser* OpenColorChooser(
259 content::WebContents* web_contents,
260 SkColor color,
261 const std::vector<content::ColorSuggestion>& suggestions) OVERRIDE;
262 virtual void RunFileChooser(
263 content::WebContents* web_contents,
264 const content::FileChooserParams& params) OVERRIDE;
265 virtual void WebContentsFocused(content::WebContents* contents) OVERRIDE;
266 virtual bool PreHandleGestureEvent(
267 content::WebContents* source,
268 const blink::WebGestureEvent& event) OVERRIDE;
270 // content::DevToolsUIBindings::Delegate overrides
271 virtual void ActivateWindow() OVERRIDE;
272 virtual void CloseWindow() OVERRIDE;
273 virtual void SetInspectedPageBounds(const gfx::Rect& rect) OVERRIDE;
274 virtual void InspectElementCompleted() OVERRIDE;
275 virtual void MoveWindow(int x, int y) OVERRIDE;
276 virtual void SetIsDocked(bool is_docked) OVERRIDE;
277 virtual void OpenInNewTab(const std::string& url) OVERRIDE;
278 virtual void SetWhitelistedShortcuts(const std::string& message) OVERRIDE;
279 virtual void InspectedContentsClosing() OVERRIDE;
280 virtual void OnLoadCompleted() OVERRIDE;
281 virtual InfoBarService* GetInfoBarService() OVERRIDE;
282 virtual void RenderProcessGone() OVERRIDE;
284 void CreateDevToolsBrowser();
285 BrowserWindow* GetInspectedBrowserWindow();
286 void ScheduleShow(const DevToolsToggleAction& action);
287 void Show(const DevToolsToggleAction& action);
288 void DoAction(const DevToolsToggleAction& action);
289 void LoadCompleted();
290 void UpdateBrowserToolbar();
291 void UpdateBrowserWindow();
292 content::WebContents* GetInspectedWebContents();
294 scoped_ptr<ObserverWithAccessor> inspected_contents_observer_;
296 Profile* profile_;
297 content::WebContents* main_web_contents_;
298 content::WebContents* toolbox_web_contents_;
299 DevToolsUIBindings* bindings_;
300 Browser* browser_;
301 bool is_docked_;
302 const bool can_dock_;
303 LifeStage life_stage_;
304 DevToolsToggleAction action_on_load_;
305 DevToolsContentsResizingStrategy contents_resizing_strategy_;
306 // True if we're in the process of handling a beforeunload event originating
307 // from the inspected webcontents, see InterceptPageBeforeUnload for details.
308 bool intercepted_page_beforeunload_;
309 base::Closure load_completed_callback_;
310 base::Closure close_callback_;
312 base::TimeTicks inspect_element_start_time_;
313 scoped_ptr<DevToolsEventForwarder> event_forwarder_;
315 friend class DevToolsEventForwarder;
316 DISALLOW_COPY_AND_ASSIGN(DevToolsWindow);
319 #endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_