Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / devtools / devtools_window.h
blob6a8e85fd5134f77bc11819873399d257a4ea9494
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 <string>
9 #include <vector>
11 #include "base/basictypes.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/strings/string16.h"
15 #include "chrome/browser/devtools/devtools_embedder_message_dispatcher.h"
16 #include "chrome/browser/devtools/devtools_file_helper.h"
17 #include "chrome/browser/devtools/devtools_file_system_indexer.h"
18 #include "chrome/browser/devtools/devtools_toggle_action.h"
19 #include "content/public/browser/devtools_client_host.h"
20 #include "content/public/browser/devtools_frontend_host_delegate.h"
21 #include "content/public/browser/notification_observer.h"
22 #include "content/public/browser/notification_registrar.h"
23 #include "content/public/browser/web_contents_delegate.h"
24 #include "ui/gfx/insets.h"
25 #include "ui/gfx/size.h"
27 class Browser;
28 class BrowserWindow;
29 class DevToolsControllerTest;
30 class Profile;
32 namespace base {
33 class Value;
36 namespace content {
37 class DevToolsAgentHost;
38 class DevToolsClientHost;
39 struct FileChooserParams;
40 class RenderViewHost;
41 class WebContents;
44 namespace IPC {
45 class Message;
48 namespace user_prefs {
49 class PrefRegistrySyncable;
52 class DevToolsWindow : private content::NotificationObserver,
53 private content::WebContentsDelegate,
54 private content::DevToolsFrontendHostDelegate,
55 private DevToolsEmbedderMessageDispatcher::Delegate {
56 public:
57 typedef base::Callback<void(bool)> InfoBarCallback;
59 static const char kDevToolsApp[];
61 virtual ~DevToolsWindow();
63 static std::string GetDevToolsWindowPlacementPrefKey();
64 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
66 // Return the DevToolsWindow for the given RenderViewHost if one exists,
67 // otherwise NULL.
68 static DevToolsWindow* GetInstanceForInspectedRenderViewHost(
69 content::RenderViewHost* inspected_rvh);
71 // Return the DevToolsWindow for the given WebContents if one exists and is
72 // docked, otherwise NULL. This method will return only fully initialized
73 // window ready to be presented in UI.
74 // For immediately-ready-to-use but maybe not yet fully initialized DevTools
75 // use |GetInstanceForInspectedRenderViewHost| instead.
76 static DevToolsWindow* GetDockedInstanceForInspectedTab(
77 content::WebContents* inspected_tab);
79 static bool IsDevToolsWindow(content::RenderViewHost* window_rvh);
81 // Open or reveal DevTools window, and perform the specified action.
82 static DevToolsWindow* OpenDevToolsWindow(
83 content::RenderViewHost* inspected_rvh,
84 const DevToolsToggleAction& action);
86 // Open or reveal DevTools window, with no special action.
87 static DevToolsWindow* OpenDevToolsWindow(
88 content::RenderViewHost* inspected_rvh);
90 static DevToolsWindow* OpenDevToolsWindowForTest(
91 content::RenderViewHost* inspected_rvh, bool is_docked);
92 static DevToolsWindow* OpenDevToolsWindowForTest(
93 Browser* browser, bool is_docked);
95 // Perform specified action for current WebContents inside a |browser|.
96 // This may close currently open DevTools window.
97 static DevToolsWindow* ToggleDevToolsWindow(
98 Browser* browser,
99 const DevToolsToggleAction& action);
101 // External frontend is always undocked.
102 static void OpenExternalFrontend(
103 Profile* profile,
104 const std::string& frontend_uri,
105 content::DevToolsAgentHost* agent_host);
107 // Worker frontend is always undocked.
108 static DevToolsWindow* OpenDevToolsWindowForWorker(
109 Profile* profile,
110 content::DevToolsAgentHost* worker_agent);
112 static void InspectElement(
113 content::RenderViewHost* inspected_rvh, int x, int y);
115 static int GetMinimizedHeight();
117 // content::DevToolsFrontendHostDelegate:
118 virtual void InspectedContentsClosing() OVERRIDE;
120 content::WebContents* web_contents() { return web_contents_; }
121 Browser* browser() { return browser_; } // For tests.
123 content::RenderViewHost* GetRenderViewHost();
125 // Inspected WebContents is placed over DevTools WebContents in docked mode.
126 // The following methods return the insets of inspected WebContents
127 // relative to DevTools WebContents.
128 gfx::Insets GetContentsInsets() const;
130 // Minimum size of the docked DevTools WebContents. This includes
131 // the overlaying inspected WebContents size.
132 gfx::Size GetMinimumSize() const;
134 // BeforeUnload interception ////////////////////////////////////////////////
136 // In order to preserve any edits the user may have made in devtools, the
137 // beforeunload event of the inspected page is hooked - devtools gets the
138 // first shot at handling beforeunload and presents a dialog to the user. If
139 // the user accepts the dialog then the script is given a chance to handle
140 // it. This way 2 dialogs may be displayed: one from the devtools asking the
141 // user to confirm that they're ok with their devtools edits going away and
142 // another from the webpage as the result of its beforeunload handler.
143 // The following set of methods handle beforeunload event flow through
144 // devtools window. When the |contents| with devtools opened on them are
145 // getting closed, the following sequence of calls takes place:
146 // 1. |DevToolsWindow::InterceptPageBeforeUnload| is called and indicates
147 // whether devtools intercept the beforeunload event.
148 // If InterceptPageBeforeUnload() returns true then the following steps
149 // will take place; otherwise only step 4 will be reached and none of the
150 // corresponding functions in steps 2 & 3 will get called.
151 // 2. |DevToolsWindow::InterceptPageBeforeUnload| fires beforeunload event
152 // for devtools frontend, which will asynchronously call
153 // |WebContentsDelegate::BeforeUnloadFired| method.
154 // In case of docked devtools window, devtools are set as a delegate for
155 // its frontend, so method |DevToolsWindow::BeforeUnloadFired| will be
156 // called directly.
157 // If devtools window is undocked it's not set as the delegate so the call
158 // to BeforeUnloadFired is proxied through HandleBeforeUnload() rather
159 // than getting called directly.
160 // 3a. If |DevToolsWindow::BeforeUnloadFired| is called with |proceed|=false
161 // it calls throught to the content's BeforeUnloadFired(), which from the
162 // WebContents perspective looks the same as the |content|'s own
163 // beforeunload dialog having had it's 'stay on this page' button clicked.
164 // 3b. If |proceed| = true, then it fires beforeunload event on |contents|
165 // and everything proceeds as it normally would without the Devtools
166 // interception.
167 // 4. If the user cancels the dialog put up by either the WebContents or
168 // devtools frontend, then |contents|'s |BeforeUnloadFired| callback is
169 // called with the proceed argument set to false, this causes
170 // |DevToolsWindow::OnPageCloseCancelled| to be called.
172 // Devtools window in undocked state is not set as a delegate of
173 // its frontend. Instead, an instance of browser is set as the delegate, and
174 // thus beforeunload event callback from devtools frontend is not delivered
175 // to the instance of devtools window, which is solely responsible for
176 // managing custom beforeunload event flow.
177 // This is a helper method to route callback from
178 // |Browser::BeforeUnloadFired| back to |DevToolsWindow::BeforeUnloadFired|.
179 // * |proceed| - true if the user clicked 'ok' in the beforeunload dialog,
180 // false otherwise.
181 // * |proceed_to_fire_unload| - output parameter, whether we should continue
182 // to fire the unload event or stop things here.
183 // Returns true if devtools window is in a state of intercepting beforeunload
184 // event and if it will manage unload process on its own.
185 static bool HandleBeforeUnload(content::WebContents* contents,
186 bool proceed,
187 bool* proceed_to_fire_unload);
189 // Returns true if this contents beforeunload event was intercepted by
190 // devtools and false otherwise. If the event was intercepted, caller should
191 // not fire beforeunlaod event on |contents| itself as devtools window will
192 // take care of it, otherwise caller should continue handling the event as
193 // usual.
194 static bool InterceptPageBeforeUnload(content::WebContents* contents);
196 // Returns true if devtools browser has already fired its beforeunload event
197 // as a result of beforeunload event interception.
198 static bool HasFiredBeforeUnloadEventForDevToolsBrowser(Browser* browser);
200 // Returns true if devtools window would like to hook beforeunload event
201 // of this |contents|.
202 static bool NeedsToInterceptBeforeUnload(content::WebContents* contents);
204 // Notify devtools window that closing of |contents| was cancelled
205 // by user.
206 static void OnPageCloseCanceled(content::WebContents* contents);
208 private:
209 friend class DevToolsControllerTest;
210 friend class DevToolsSanityTest;
211 friend class BrowserWindowControllerTest;
213 // DevTools initialization typically follows this way:
214 // - Toggle/Open: client call;
215 // - Create;
216 // - ScheduleShow: setup window to be functional, but not yet show;
217 // - DocumentOnLoadCompletedInMainFrame: frontend loaded;
218 // - SetIsDocked: frontend decided on docking state;
219 // - OnLoadCompleted: ready to present frontend;
220 // - Show: actually placing frontend WebContents to a Browser or docked place;
221 // - DoAction: perform action passed in Toggle/Open.
222 enum LoadState {
223 kNotLoaded,
224 kOnLoadFired, // Implies SetIsDocked was not yet called.
225 kIsDockedSet, // Implies DocumentOnLoadCompleted was not yet called.
226 kLoadCompleted
229 DevToolsWindow(Profile* profile,
230 const GURL& frontend_url,
231 content::RenderViewHost* inspected_rvh,
232 bool can_dock);
234 static DevToolsWindow* Create(Profile* profile,
235 const GURL& frontend_url,
236 content::RenderViewHost* inspected_rvh,
237 bool shared_worker_frontend,
238 bool external_frontend,
239 bool can_dock);
240 static GURL GetDevToolsURL(Profile* profile,
241 const GURL& base_url,
242 bool shared_worker_frontend,
243 bool external_frontend,
244 bool can_dock);
245 static DevToolsWindow* FindDevToolsWindow(content::DevToolsAgentHost*);
246 static DevToolsWindow* AsDevToolsWindow(content::RenderViewHost*);
247 static DevToolsWindow* CreateDevToolsWindowForWorker(Profile* profile);
248 static bool IsDockedFromString(const std::string& dock_side);
249 static bool FindInspectedBrowserAndTabIndex(
250 content::WebContents* inspected_web_contents, Browser**, int* tab);
251 static DevToolsWindow* ToggleDevToolsWindow(
252 content::RenderViewHost* inspected_rvh,
253 bool force_open,
254 const DevToolsToggleAction& action);
256 // content::NotificationObserver:
257 virtual void Observe(int type,
258 const content::NotificationSource& source,
259 const content::NotificationDetails& details) OVERRIDE;
261 // content::WebContentsDelegate:
262 virtual content::WebContents* OpenURLFromTab(
263 content::WebContents* source,
264 const content::OpenURLParams& params) OVERRIDE;
265 virtual void AddNewContents(content::WebContents* source,
266 content::WebContents* new_contents,
267 WindowOpenDisposition disposition,
268 const gfx::Rect& initial_pos,
269 bool user_gesture,
270 bool* was_blocked) OVERRIDE;
271 virtual void CloseContents(content::WebContents* source) OVERRIDE;
272 virtual void BeforeUnloadFired(content::WebContents* tab,
273 bool proceed,
274 bool* proceed_to_fire_unload) OVERRIDE;
275 virtual bool PreHandleKeyboardEvent(
276 content::WebContents* source,
277 const content::NativeWebKeyboardEvent& event,
278 bool* is_keyboard_shortcut) OVERRIDE;
279 virtual void HandleKeyboardEvent(
280 content::WebContents* source,
281 const content::NativeWebKeyboardEvent& event) OVERRIDE;
282 virtual content::JavaScriptDialogManager*
283 GetJavaScriptDialogManager() OVERRIDE;
284 virtual content::ColorChooser* OpenColorChooser(
285 content::WebContents* web_contents,
286 SkColor color,
287 const std::vector<content::ColorSuggestion>& suggestions) OVERRIDE;
288 virtual void RunFileChooser(
289 content::WebContents* web_contents,
290 const content::FileChooserParams& params) OVERRIDE;
291 virtual void WebContentsFocused(content::WebContents* contents) OVERRIDE;
293 // content::DevToolsFrontendHostDelegate override:
294 virtual void DispatchOnEmbedder(const std::string& message) OVERRIDE;
296 // DevToolsEmbedderMessageDispatcher::Delegate overrides:
297 virtual void ActivateWindow() OVERRIDE;
298 virtual void ActivateContents(content::WebContents* contents) OVERRIDE;
299 virtual void CloseWindow() OVERRIDE;
300 virtual void SetContentsInsets(
301 int left, int top, int right, int bottom) OVERRIDE;
302 virtual void MoveWindow(int x, int y) OVERRIDE;
303 virtual void SetDockSide(const std::string& side) OVERRIDE;
304 virtual void SetIsDocked(bool is_docked) OVERRIDE;
305 virtual void OpenInNewTab(const std::string& url) OVERRIDE;
306 virtual void SaveToFile(const std::string& url,
307 const std::string& content,
308 bool save_as) OVERRIDE;
309 virtual void AppendToFile(const std::string& url,
310 const std::string& content) OVERRIDE;
311 virtual void RequestFileSystems() OVERRIDE;
312 virtual void AddFileSystem() OVERRIDE;
313 virtual void RemoveFileSystem(const std::string& file_system_path) OVERRIDE;
314 virtual void UpgradeDraggedFileSystemPermissions(
315 const std::string& file_system_url) OVERRIDE;
316 virtual void IndexPath(int request_id,
317 const std::string& file_system_path) OVERRIDE;
318 virtual void StopIndexing(int request_id) OVERRIDE;
319 virtual void SearchInPath(int request_id,
320 const std::string& file_system_path,
321 const std::string& query) OVERRIDE;
323 // DevToolsFileHelper callbacks.
324 void FileSavedAs(const std::string& url);
325 void CanceledFileSaveAs(const std::string& url);
326 void AppendedTo(const std::string& url);
327 void FileSystemsLoaded(
328 const std::vector<DevToolsFileHelper::FileSystem>& file_systems);
329 void FileSystemAdded(const DevToolsFileHelper::FileSystem& file_system);
330 void IndexingTotalWorkCalculated(int request_id,
331 const std::string& file_system_path,
332 int total_work);
333 void IndexingWorked(int request_id,
334 const std::string& file_system_path,
335 int worked);
336 void IndexingDone(int request_id, const std::string& file_system_path);
337 void SearchCompleted(int request_id,
338 const std::string& file_system_path,
339 const std::vector<std::string>& file_paths);
340 void ShowDevToolsConfirmInfoBar(const base::string16& message,
341 const InfoBarCallback& callback);
343 void CreateDevToolsBrowser();
344 BrowserWindow* GetInspectedBrowserWindow();
345 void ScheduleShow(const DevToolsToggleAction& action);
346 void Show(const DevToolsToggleAction& action);
347 void DoAction(const DevToolsToggleAction& action);
348 void LoadCompleted();
349 void SetIsDockedAndShowImmediatelyForTest(bool is_docked);
350 void UpdateTheme();
351 void AddDevToolsExtensionsToClient();
352 void CallClientFunction(const std::string& function_name,
353 const base::Value* arg1,
354 const base::Value* arg2,
355 const base::Value* arg3);
356 void UpdateBrowserToolbar();
357 content::WebContents* GetInspectedWebContents();
358 void DocumentOnLoadCompletedInMainFrame();
360 class InspectedWebContentsObserver;
361 scoped_ptr<InspectedWebContentsObserver> inspected_contents_observer_;
362 class FrontendWebContentsObserver;
363 friend class FrontendWebContentsObserver;
364 scoped_ptr<FrontendWebContentsObserver> frontend_contents_observer_;
366 Profile* profile_;
367 content::WebContents* web_contents_;
368 Browser* browser_;
369 bool is_docked_;
370 bool can_dock_;
371 LoadState load_state_;
372 DevToolsToggleAction action_on_load_;
373 bool ignore_set_is_docked_for_test_;
374 content::NotificationRegistrar registrar_;
375 scoped_ptr<content::DevToolsClientHost> frontend_host_;
376 scoped_ptr<DevToolsFileHelper> file_helper_;
377 scoped_refptr<DevToolsFileSystemIndexer> file_system_indexer_;
378 typedef std::map<
379 int,
380 scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob> >
381 IndexingJobsMap;
382 IndexingJobsMap indexing_jobs_;
383 gfx::Insets contents_insets_;
384 // True if we're in the process of handling a beforeunload event originating
385 // from the inspected webcontents, see InterceptPageBeforeUnload for details.
386 bool intercepted_page_beforeunload_;
388 scoped_ptr<DevToolsEmbedderMessageDispatcher> embedder_message_dispatcher_;
389 base::WeakPtrFactory<DevToolsWindow> weak_factory_;
390 DISALLOW_COPY_AND_ASSIGN(DevToolsWindow);
393 #endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_