blob: 4c13c67b2b8dab4c5bca43ff4394fe29f9381427 [file] [log] [blame]
[email protected]f9b6c092012-07-09 19:32:281// 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.
4
5#ifndef CHROME_BROWSER_UI_UNLOAD_CONTROLLER_H_
6#define CHROME_BROWSER_UI_UNLOAD_CONTROLLER_H_
[email protected]f9b6c092012-07-09 19:32:287
8#include <set>
9
10#include "base/memory/weak_ptr.h"
11#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
12#include "content/public/browser/notification_observer.h"
13#include "content/public/browser/notification_registrar.h"
14
15class Browser;
[email protected]f9b6c092012-07-09 19:32:2816class TabStripModel;
17
18namespace content {
19class NotificationSource;
20class NotifictaionDetails;
21class WebContents;
22}
23
24namespace chrome {
25
26class UnloadController : public content::NotificationObserver,
27 public TabStripModelObserver {
28 public:
29 explicit UnloadController(Browser* browser);
30 virtual ~UnloadController();
31
32 // Returns true if |contents| can be cleanly closed. When |browser_| is being
33 // closed, this function will return false to indicate |contents| should not
34 // be cleanly closed, since the fast shutdown path will just kill its
35 // renderer.
36 bool CanCloseContents(content::WebContents* contents);
37
38 // Called when a BeforeUnload handler is fired for |contents|. |proceed|
39 // indicates the user's response to the Y/N BeforeUnload handler dialog. If
40 // this parameter is false, any pending attempt to close the whole browser
41 // will be canceled. Returns true if Unload handlers should be fired. When the
42 // |browser_| is being closed, Unload handlers for any particular WebContents
43 // will not be run until every WebContents being closed has a chance to run
44 // its BeforeUnloadHandler.
45 bool BeforeUnloadFired(content::WebContents* contents, bool proceed);
46
47 bool is_attempting_to_close_browser() const {
48 return is_attempting_to_close_browser_;
49 }
50
51 // Called in response to a request to close |browser_|'s window. Returns true
[email protected]656d0992013-04-19 12:12:3652 // when there are no remaining unload handlers to be run.
[email protected]f9b6c092012-07-09 19:32:2853 bool ShouldCloseWindow();
54
55 // Returns true if |browser_| has any tabs that have BeforeUnload handlers
56 // that have not been fired. This method is non-const because it builds a list
57 // of tabs that need their BeforeUnloadHandlers fired.
58 // TODO(beng): This seems like it could be private but it is used by
59 // AreAllBrowsersCloseable() in application_lifetime.cc. It seems
60 // very similar to ShouldCloseWindow() and some consolidation
61 // could be pursued.
62 bool TabsNeedBeforeUnloadFired();
63
64 private:
65 typedef std::set<content::WebContents*> UnloadListenerSet;
66
67 // Overridden from content::NotificationObserver:
68 virtual void Observe(int type,
69 const content::NotificationSource& source,
70 const content::NotificationDetails& details) OVERRIDE;
71
72 // Overridden from TabStripModelObserver:
[email protected]409ea2972012-11-10 19:54:4373 virtual void TabInsertedAt(content::WebContents* contents,
[email protected]f9b6c092012-07-09 19:32:2874 int index,
75 bool foreground) OVERRIDE;
[email protected]e89cfcb2012-11-11 14:47:2476 virtual void TabDetachedAt(content::WebContents* contents,
77 int index) OVERRIDE;
[email protected]f9b6c092012-07-09 19:32:2878 virtual void TabReplacedAt(TabStripModel* tab_strip_model,
[email protected]b624ddc2012-11-15 18:04:1379 content::WebContents* old_contents,
80 content::WebContents* new_contents,
[email protected]f9b6c092012-07-09 19:32:2881 int index) OVERRIDE;
82 virtual void TabStripEmpty() OVERRIDE;
83
[email protected]409ea2972012-11-10 19:54:4384 void TabAttachedImpl(content::WebContents* contents);
[email protected]e89cfcb2012-11-11 14:47:2485 void TabDetachedImpl(content::WebContents* contents);
[email protected]f9b6c092012-07-09 19:32:2886
87 // Processes the next tab that needs it's beforeunload/unload event fired.
88 void ProcessPendingTabs();
89
[email protected]656d0992013-04-19 12:12:3690 // Whether we've completed firing all the tabs' beforeunload/unload events.
91 bool HasCompletedUnloadProcessing() const;
92
[email protected]f9b6c092012-07-09 19:32:2893 // Clears all the state associated with processing tabs' beforeunload/unload
94 // events since the user cancelled closing the window.
95 void CancelWindowClose();
96
97 // Removes |web_contents| from the passed |set|.
98 // Returns whether the tab was in the set in the first place.
99 bool RemoveFromSet(UnloadListenerSet* set,
100 content::WebContents* web_contents);
101
102 // Cleans up state appropriately when we are trying to close the browser and
103 // the tab has finished firing its unload handler. We also use this in the
104 // cases where a tab crashes or hangs even if the beforeunload/unload haven't
105 // successfully fired. If |process_now| is true |ProcessPendingTabs| is
106 // invoked immediately, otherwise it is invoked after a delay (PostTask).
107 //
108 // Typically you'll want to pass in true for |process_now|. Passing in true
109 // may result in deleting |tab|. If you know that shouldn't happen (because of
110 // the state of the stack), pass in false.
111 void ClearUnloadState(content::WebContents* web_contents, bool process_now);
112
113 Browser* browser_;
114
115 content::NotificationRegistrar registrar_;
116
[email protected]656d0992013-04-19 12:12:36117 // Tracks tabs that need there beforeunload event fired before we can
[email protected]f9b6c092012-07-09 19:32:28118 // close the browser. Only gets populated when we try to close the browser.
119 UnloadListenerSet tabs_needing_before_unload_fired_;
120
[email protected]656d0992013-04-19 12:12:36121 // Tracks tabs that need there unload event fired before we can
[email protected]f9b6c092012-07-09 19:32:28122 // close the browser. Only gets populated when we try to close the browser.
123 UnloadListenerSet tabs_needing_unload_fired_;
124
125 // Whether we are processing the beforeunload and unload events of each tab
126 // in preparation for closing the browser. UnloadController owns this state
127 // rather than Browser because unload handlers are the only reason that a
128 // Browser window isn't just immediately closed.
129 bool is_attempting_to_close_browser_;
130
[email protected]f9b6c092012-07-09 19:32:28131 base::WeakPtrFactory<UnloadController> weak_factory_;
132
133 DISALLOW_COPY_AND_ASSIGN(UnloadController);
134};
135
136} // namespace chrome
137
138#endif // CHROME_BROWSER_UI_UNLOAD_CONTROLLER_H_