summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/tab_closeable_state_watcher.h
blob: facadc5c0fec15f5d143713796a585a2aa5f20f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_CHROMEOS_TAB_CLOSEABLE_STATE_WATCHER_H_
#define CHROME_BROWSER_CHROMEOS_TAB_CLOSEABLE_STATE_WATCHER_H_
#pragma once

#include <vector>

#include "chrome/browser/browser_list.h"
#include "chrome/browser/tab_closeable_state_watcher.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/common/notification_registrar.h"

namespace chromeos {

// This class overrides ::TabCloseableStateWatcher to allow or disallow tabs or
// browsers to be closed based on increase or decrease in number of tabs or
// browsers.  We only do this on Chromeos and only for non-tests.
// 1) A tab, and hence its containing browser, is not closeable if the tab is
// the last NewTabPage in the last normal non-incognito browser and user is not
// signing off.
// 2) Otherwise, if user closes a normal non-incognito browser or the last tab
// in it, the browser stays open, the existing tabs are closed, and a new
// NewTabPage is opened.
// 3) Or, if user closes a normal incognito browser or the last tab in it, the
// browser closes, a new non-incognito normal browser is opened with a
// NewTabPage (which, by rule 1, will not be closeable).

class TabCloseableStateWatcher : public ::TabCloseableStateWatcher,
                                 public BrowserList::Observer,
                                 public NotificationObserver {
 public:
  TabCloseableStateWatcher();
  virtual ~TabCloseableStateWatcher();

  // TabCloseableStateWatcher implementation:
  virtual bool CanCloseTab(const Browser* browser) const;
  virtual bool CanCloseBrowser(Browser* browser);
  virtual void OnWindowCloseCanceled(Browser* browser);

 private:
  enum BrowserActionType {
    NONE = 0,         // Nothing to do.
    OPEN_WINDOW = 1,  // Opens a regular (i.e. non-incognito) normal browser.
    OPEN_NTP = 2,     // Opens a NewTabPage.
  };

  // BrowserList::Observer implementation:
  virtual void OnBrowserAdded(const Browser* browser);
  virtual void OnBrowserRemoving(const Browser* browser);

  // NotificationObserver implementation:
  virtual void Observe(NotificationType type, const NotificationSource& source,
                       const NotificationDetails& details);

  // Called by private class TabStripWatcher for TabStripModelObserver
  // notifications.
  // |closing_last_tab| is true if the tab strip is closing the last tab.
  virtual void OnTabStripChanged(const Browser* browser, bool closing_last_tab);

  // Utility functions.

  // Checks the closeable state of tab.  If it has changed, updates it and
  // notifies all normal browsers.
  // |browser_to_check| is the browser whose closeable state the caller is
  // interested in; can be NULL if caller is interested in all browsers, e.g.
  // when a browser is being removed and there's no specific browser to check.
  void CheckAndUpdateState(const Browser* browser_to_check);

  // Sets the new closeable state and fires notification.
  void SetCloseableState(bool closeable);

  // Returns true if closing of |browser| is permitted.
  // |action_type| is the action to take regardless if browser is closeable.
  bool CanCloseBrowserImpl(const Browser* browser,
                           BrowserActionType* action_type) const;

  // Data members.

  // This is true if tab can be closed; it's updated in CheckAndUpdateState and
  // when sign-off notification is received.
  bool can_close_tab_;

  // This is true when sign-off notification is received; it lets us know to
  // allow closing of all tabs and browsers in this situation.
  bool signing_off_;

  NotificationRegistrar notification_registrar_;

  // TabStripWatcher is a TabStripModelObserver that funnels all interesting
  // methods to TabCloseableStateWatcher::OnTabStripChanged. TabStripWatcher is
  // needed so we know which browser the TabStripModelObserver method relates
  // to.
  class TabStripWatcher : public TabStripModelObserver {
   public:
    TabStripWatcher(TabCloseableStateWatcher* main_watcher,
                    const Browser* browser);
    virtual ~TabStripWatcher();

    // TabStripModelObserver implementation:
    virtual void TabInsertedAt(TabContents* contents, int index,
                               bool foreground);
    virtual void TabClosingAt(TabContents* contents, int index);
    virtual void TabDetachedAt(TabContents* contents, int index);
    virtual void TabChangedAt(TabContents* contents, int index,
                              TabChangeType change_type);

    const Browser* browser() const {
      return browser_;
    }

   private:
    TabCloseableStateWatcher* main_watcher_;
    const Browser* browser_;

    DISALLOW_COPY_AND_ASSIGN(TabStripWatcher);
  };

  friend class TabStripWatcher;

  std::vector<TabStripWatcher*> tabstrip_watchers_;

  DISALLOW_COPY_AND_ASSIGN(TabCloseableStateWatcher);
};

}  // namespace chromeos

#endif  // CHROME_BROWSER_CHROMEOS_TAB_CLOSEABLE_STATE_WATCHER_H_