NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / devtools / devtools_window.h
blobfd7f43010b36322a1cc0a0b435d257963057f9b4
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_contents_resizing_strategy.h"
16 #include "chrome/browser/devtools/devtools_embedder_message_dispatcher.h"
17 #include "chrome/browser/devtools/devtools_file_helper.h"
18 #include "chrome/browser/devtools/devtools_file_system_indexer.h"
19 #include "chrome/browser/devtools/devtools_toggle_action.h"
20 #include "content/public/browser/devtools_client_host.h"
21 #include "content/public/browser/devtools_frontend_host_delegate.h"
22 #include "content/public/browser/notification_observer.h"
23 #include "content/public/browser/notification_registrar.h"
24 #include "content/public/browser/web_contents_delegate.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 // content::DevToolsFrontendHostDelegate:
116 virtual void InspectedContentsClosing() OVERRIDE;
118 content::WebContents* web_contents() { return web_contents_; }
119 Browser* browser() { return browser_; } // For tests.
121 content::RenderViewHost* GetRenderViewHost();
123 // Inspected WebContents is placed over DevTools WebContents in docked mode.
124 // The following method returns the resizing strategy of inspected
125 // WebContents relative to DevTools WebContents.
126 const DevToolsContentsResizingStrategy& GetContentsResizingStrategy() const;
128 // Minimum size of the docked DevTools WebContents. This includes
129 // the overlaying inspected WebContents size.
130 gfx::Size GetMinimumSize() const;
132 // Sets closure to be called after load is done. If already loaded, calls
133 // closure immediately.
134 void SetLoadCompletedCallback(const base::Closure& closure);
136 // BeforeUnload interception ////////////////////////////////////////////////
138 // In order to preserve any edits the user may have made in devtools, the
139 // beforeunload event of the inspected page is hooked - devtools gets the
140 // first shot at handling beforeunload and presents a dialog to the user. If
141 // the user accepts the dialog then the script is given a chance to handle
142 // it. This way 2 dialogs may be displayed: one from the devtools asking the
143 // user to confirm that they're ok with their devtools edits going away and
144 // another from the webpage as the result of its beforeunload handler.
145 // The following set of methods handle beforeunload event flow through
146 // devtools window. When the |contents| with devtools opened on them are
147 // getting closed, the following sequence of calls takes place:
148 // 1. |DevToolsWindow::InterceptPageBeforeUnload| is called and indicates
149 // whether devtools intercept the beforeunload event.
150 // If InterceptPageBeforeUnload() returns true then the following steps
151 // will take place; otherwise only step 4 will be reached and none of the
152 // corresponding functions in steps 2 & 3 will get called.
153 // 2. |DevToolsWindow::InterceptPageBeforeUnload| fires beforeunload event
154 // for devtools frontend, which will asynchronously call
155 // |WebContentsDelegate::BeforeUnloadFired| method.
156 // In case of docked devtools window, devtools are set as a delegate for
157 // its frontend, so method |DevToolsWindow::BeforeUnloadFired| will be
158 // called directly.
159 // If devtools window is undocked it's not set as the delegate so the call
160 // to BeforeUnloadFired is proxied through HandleBeforeUnload() rather
161 // than getting called directly.
162 // 3a. If |DevToolsWindow::BeforeUnloadFired| is called with |proceed|=false
163 // it calls throught to the content's BeforeUnloadFired(), which from the
164 // WebContents perspective looks the same as the |content|'s own
165 // beforeunload dialog having had it's 'stay on this page' button clicked.
166 // 3b. If |proceed| = true, then it fires beforeunload event on |contents|
167 // and everything proceeds as it normally would without the Devtools
168 // interception.
169 // 4. If the user cancels the dialog put up by either the WebContents or
170 // devtools frontend, then |contents|'s |BeforeUnloadFired| callback is
171 // called with the proceed argument set to false, this causes
172 // |DevToolsWindow::OnPageCloseCancelled| to be called.
174 // Devtools window in undocked state is not set as a delegate of
175 // its frontend. Instead, an instance of browser is set as the delegate, and
176 // thus beforeunload event callback from devtools frontend is not delivered
177 // to the instance of devtools window, which is solely responsible for
178 // managing custom beforeunload event flow.
179 // This is a helper method to route callback from
180 // |Browser::BeforeUnloadFired| back to |DevToolsWindow::BeforeUnloadFired|.
181 // * |proceed| - true if the user clicked 'ok' in the beforeunload dialog,
182 // false otherwise.
183 // * |proceed_to_fire_unload| - output parameter, whether we should continue
184 // to fire the unload event or stop things here.
185 // Returns true if devtools window is in a state of intercepting beforeunload
186 // event and if it will manage unload process on its own.
187 static bool HandleBeforeUnload(content::WebContents* contents,
188 bool proceed,
189 bool* proceed_to_fire_unload);
191 // Returns true if this contents beforeunload event was intercepted by
192 // devtools and false otherwise. If the event was intercepted, caller should
193 // not fire beforeunlaod event on |contents| itself as devtools window will
194 // take care of it, otherwise caller should continue handling the event as
195 // usual.
196 static bool InterceptPageBeforeUnload(content::WebContents* contents);
198 // Returns true if devtools browser has already fired its beforeunload event
199 // as a result of beforeunload event interception.
200 static bool HasFiredBeforeUnloadEventForDevToolsBrowser(Browser* browser);
202 // Returns true if devtools window would like to hook beforeunload event
203 // of this |contents|.
204 static bool NeedsToInterceptBeforeUnload(content::WebContents* contents);
206 // Notify devtools window that closing of |contents| was cancelled
207 // by user.
208 static void OnPageCloseCanceled(content::WebContents* contents);
210 private:
211 friend class DevToolsControllerTest;
212 friend class DevToolsSanityTest;
213 friend class BrowserWindowControllerTest;
215 // DevTools initialization typically follows this way:
216 // - Toggle/Open: client call;
217 // - Create;
218 // - ScheduleShow: setup window to be functional, but not yet show;
219 // - DocumentOnLoadCompletedInMainFrame: frontend loaded;
220 // - SetIsDocked: frontend decided on docking state;
221 // - OnLoadCompleted: ready to present frontend;
222 // - Show: actually placing frontend WebContents to a Browser or docked place;
223 // - DoAction: perform action passed in Toggle/Open.
224 enum LoadState {
225 kNotLoaded,
226 kOnLoadFired, // Implies SetIsDocked was not yet called.
227 kIsDockedSet, // Implies DocumentOnLoadCompleted was not yet called.
228 kLoadCompleted
231 DevToolsWindow(Profile* profile,
232 const GURL& frontend_url,
233 content::RenderViewHost* inspected_rvh,
234 bool can_dock);
236 static DevToolsWindow* Create(Profile* profile,
237 const GURL& frontend_url,
238 content::RenderViewHost* inspected_rvh,
239 bool shared_worker_frontend,
240 bool external_frontend,
241 bool can_dock);
242 static GURL GetDevToolsURL(Profile* profile,
243 const GURL& base_url,
244 bool shared_worker_frontend,
245 bool external_frontend,
246 bool can_dock);
247 static DevToolsWindow* FindDevToolsWindow(content::DevToolsAgentHost*);
248 static DevToolsWindow* AsDevToolsWindow(content::RenderViewHost*);
249 static DevToolsWindow* CreateDevToolsWindowForWorker(Profile* profile);
250 static bool FindInspectedBrowserAndTabIndex(
251 content::WebContents* inspected_web_contents, Browser**, int* tab);
252 static DevToolsWindow* ToggleDevToolsWindow(
253 content::RenderViewHost* inspected_rvh,
254 bool force_open,
255 const DevToolsToggleAction& action);
257 // content::NotificationObserver:
258 virtual void Observe(int type,
259 const content::NotificationSource& source,
260 const content::NotificationDetails& details) OVERRIDE;
262 // content::WebContentsDelegate:
263 virtual content::WebContents* OpenURLFromTab(
264 content::WebContents* source,
265 const content::OpenURLParams& params) OVERRIDE;
266 virtual void AddNewContents(content::WebContents* source,
267 content::WebContents* new_contents,
268 WindowOpenDisposition disposition,
269 const gfx::Rect& initial_pos,
270 bool user_gesture,
271 bool* was_blocked) OVERRIDE;
272 virtual void CloseContents(content::WebContents* source) OVERRIDE;
273 virtual void ContentsZoomChange(bool zoom_in) OVERRIDE;
274 virtual void BeforeUnloadFired(content::WebContents* tab,
275 bool proceed,
276 bool* proceed_to_fire_unload) OVERRIDE;
277 virtual bool PreHandleKeyboardEvent(
278 content::WebContents* source,
279 const content::NativeWebKeyboardEvent& event,
280 bool* is_keyboard_shortcut) OVERRIDE;
281 virtual void HandleKeyboardEvent(
282 content::WebContents* source,
283 const content::NativeWebKeyboardEvent& event) OVERRIDE;
284 virtual content::JavaScriptDialogManager*
285 GetJavaScriptDialogManager() OVERRIDE;
286 virtual content::ColorChooser* OpenColorChooser(
287 content::WebContents* web_contents,
288 SkColor color,
289 const std::vector<content::ColorSuggestion>& suggestions) OVERRIDE;
290 virtual void RunFileChooser(
291 content::WebContents* web_contents,
292 const content::FileChooserParams& params) OVERRIDE;
293 virtual void WebContentsFocused(content::WebContents* contents) OVERRIDE;
294 virtual bool PreHandleGestureEvent(
295 content::WebContents* source,
296 const blink::WebGestureEvent& event) OVERRIDE;
298 // content::DevToolsFrontendHostDelegate override:
299 virtual void DispatchOnEmbedder(const std::string& message) OVERRIDE;
301 // DevToolsEmbedderMessageDispatcher::Delegate overrides:
302 virtual void ActivateWindow() OVERRIDE;
303 virtual void ActivateContents(content::WebContents* contents) OVERRIDE;
304 virtual void CloseWindow() OVERRIDE;
305 virtual void SetContentsInsets(
306 int left, int top, int right, int bottom) OVERRIDE;
307 virtual void SetContentsResizingStrategy(
308 const gfx::Insets& insets, const gfx::Size& min_size) OVERRIDE;
309 virtual void InspectElementCompleted() OVERRIDE;
310 virtual void MoveWindow(int x, int y) OVERRIDE;
311 virtual void SetIsDocked(bool is_docked) OVERRIDE;
312 virtual void OpenInNewTab(const std::string& url) OVERRIDE;
313 virtual void SaveToFile(const std::string& url,
314 const std::string& content,
315 bool save_as) OVERRIDE;
316 virtual void AppendToFile(const std::string& url,
317 const std::string& content) OVERRIDE;
318 virtual void RequestFileSystems() OVERRIDE;
319 virtual void AddFileSystem() OVERRIDE;
320 virtual void RemoveFileSystem(const std::string& file_system_path) OVERRIDE;
321 virtual void UpgradeDraggedFileSystemPermissions(
322 const std::string& file_system_url) OVERRIDE;
323 virtual void IndexPath(int request_id,
324 const std::string& file_system_path) OVERRIDE;
325 virtual void StopIndexing(int request_id) OVERRIDE;
326 virtual void SearchInPath(int request_id,
327 const std::string& file_system_path,
328 const std::string& query) OVERRIDE;
329 virtual void ZoomIn() OVERRIDE;
330 virtual void ZoomOut() OVERRIDE;
331 virtual void ResetZoom() OVERRIDE;
333 // DevToolsFileHelper callbacks.
334 void FileSavedAs(const std::string& url);
335 void CanceledFileSaveAs(const std::string& url);
336 void AppendedTo(const std::string& url);
337 void FileSystemsLoaded(
338 const std::vector<DevToolsFileHelper::FileSystem>& file_systems);
339 void FileSystemAdded(const DevToolsFileHelper::FileSystem& file_system);
340 void IndexingTotalWorkCalculated(int request_id,
341 const std::string& file_system_path,
342 int total_work);
343 void IndexingWorked(int request_id,
344 const std::string& file_system_path,
345 int worked);
346 void IndexingDone(int request_id, const std::string& file_system_path);
347 void SearchCompleted(int request_id,
348 const std::string& file_system_path,
349 const std::vector<std::string>& file_paths);
350 void ShowDevToolsConfirmInfoBar(const base::string16& message,
351 const InfoBarCallback& callback);
353 void CreateDevToolsBrowser();
354 BrowserWindow* GetInspectedBrowserWindow();
355 void ScheduleShow(const DevToolsToggleAction& action);
356 void Show(const DevToolsToggleAction& action);
357 void DoAction(const DevToolsToggleAction& action);
358 void LoadCompleted();
359 void SetIsDockedAndShowImmediatelyForTest(bool is_docked);
360 void UpdateTheme();
361 void AddDevToolsExtensionsToClient();
362 void CallClientFunction(const std::string& function_name,
363 const base::Value* arg1,
364 const base::Value* arg2,
365 const base::Value* arg3);
366 void UpdateBrowserToolbar();
367 content::WebContents* GetInspectedWebContents();
368 void DocumentOnLoadCompletedInMainFrame();
370 class InspectedWebContentsObserver;
371 scoped_ptr<InspectedWebContentsObserver> inspected_contents_observer_;
372 class FrontendWebContentsObserver;
373 friend class FrontendWebContentsObserver;
374 scoped_ptr<FrontendWebContentsObserver> frontend_contents_observer_;
376 Profile* profile_;
377 content::WebContents* web_contents_;
378 Browser* browser_;
379 bool is_docked_;
380 bool can_dock_;
381 LoadState load_state_;
382 DevToolsToggleAction action_on_load_;
383 bool ignore_set_is_docked_;
384 content::NotificationRegistrar registrar_;
385 scoped_ptr<content::DevToolsClientHost> frontend_host_;
386 scoped_ptr<DevToolsFileHelper> file_helper_;
387 scoped_refptr<DevToolsFileSystemIndexer> file_system_indexer_;
388 typedef std::map<
389 int,
390 scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob> >
391 IndexingJobsMap;
392 IndexingJobsMap indexing_jobs_;
393 DevToolsContentsResizingStrategy contents_resizing_strategy_;
394 // True if we're in the process of handling a beforeunload event originating
395 // from the inspected webcontents, see InterceptPageBeforeUnload for details.
396 bool intercepted_page_beforeunload_;
397 base::Closure load_completed_callback_;
399 scoped_ptr<DevToolsEmbedderMessageDispatcher> embedder_message_dispatcher_;
400 base::WeakPtrFactory<DevToolsWindow> weak_factory_;
401 base::TimeTicks inspect_element_start_time_;
402 DISALLOW_COPY_AND_ASSIGN(DevToolsWindow);
405 #endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_WINDOW_H_