1 // Copyright 2012 The Chromium Authors
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_APP_CONTROLLER_MAC_H_
6 #define CHROME_BROWSER_APP_CONTROLLER_MAC_H_
8 #include "base/memory/raw_ptr.h"
9 #include "base/scoped_observation.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "components/sessions/core/session_id.h"
12 #include "components/sessions/core/tab_restore_service.h"
13 #include "components/sessions/core/tab_restore_service_observer.h"
17 #import <AuthenticationServices/AuthenticationServices.h>
18 #import <Cocoa/Cocoa.h>
23 #include "base/files/file_path.h"
24 #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
25 #include "components/prefs/pref_change_registrar.h"
27 class BookmarkMenuBridge;
29 class HistoryMenuBridge;
37 // The application controller object, created by loading the MainMenu nib.
38 // This handles things like responding to menus when there are no windows
39 // open, etc and acts as the NSApplication delegate.
40 @interface AppController
41 : NSObject <NSUserInterfaceValidations,
43 NSApplicationDelegate,
44 ASWebAuthenticationSessionWebBrowserSessionHandling>
46 // The app-wide singleton AppController. Guaranteed to be the delegate of NSApp
47 // inside of Chromium (not inside of app shims; see AppShimDelegate). Guaranteed
49 @property(readonly, nonatomic, class) AppController* sharedController;
51 @property(readonly, nonatomic) BOOL startupComplete;
52 @property(readonly, nonatomic) Profile* lastProfileIfLoaded;
54 // DEPRECATED: use lastProfileIfLoaded instead.
55 // TODO(https://crbug.com/1176734): May be blocking, migrate all callers to
56 // |-lastProfileIfLoaded|.
57 @property(readonly, nonatomic) Profile* lastProfile;
59 // Do not create new instances of AppController; use the `sharedController`
60 // property so that the invariants of there always being exactly one
61 // AppController and that that instance is the NSApp delegate always hold true.
62 - (instancetype)init NS_UNAVAILABLE;
64 // This method is called very early in application startup after the main menu
66 - (void)mainMenuCreated;
68 - (void)didEndMainMessageLoop;
70 // Try to close all browser windows, and if that succeeds then quit.
71 - (BOOL)tryToTerminateApplication:(NSApplication*)app;
73 // Stop trying to terminate the application. That is, prevent the final browser
74 // window closure from causing the application to quit.
75 - (void)stopTryingToTerminateApplication:(NSApplication*)app;
77 // Run the quit confirmation panel and return whether or not to continue
79 - (BOOL)runConfirmQuitPanel;
81 // Indicate that the system is powering off or logging out.
82 - (void)willPowerOff:(NSNotification*)inNotification;
84 // Returns true if there is a modal window (either window- or application-
85 // modal) blocking the active browser. Note that tab modal dialogs (HTTP auth
86 // sheets) will not count as blocking the browser. But things like open/save
87 // dialogs that are window modal will block the browser.
88 - (BOOL)keyWindowIsModal;
90 // Called when the user picks a menu item when there are no key windows, or when
91 // there is no foreground browser window. Calls through to the browser object to
92 // execute the command. This assumes that the command is supported and doesn't
93 // check, otherwise it should have been disabled in the UI in
94 // |-validateUserInterfaceItem:|.
95 - (void)commandDispatch:(id)sender;
97 // Helper function called by -commandDispatch:, to actually execute the command.
98 // This runs after -commandDispatch: has obtained a pointer to the last Profile
99 // (which possibly requires an async Profile load).
100 - (void)executeCommand:(id)sender withProfile:(Profile*)profile;
102 // Show the preferences window, or bring it to the front if it's already
104 - (IBAction)showPreferences:(id)sender;
105 - (IBAction)showPreferencesForProfile:(Profile*)profile;
107 // Redirect in the menu item from the expected target of "File's
108 // Owner" (NSApplication) for a Branded About Box
109 - (IBAction)orderFrontStandardAboutPanel:(id)sender;
110 - (IBAction)orderFrontStandardAboutPanelForProfile:(Profile*)profile;
112 // Toggles the "Confirm to Quit" preference.
113 - (IBAction)toggleConfirmToQuit:(id)sender;
115 // Delegate method to return the dock menu.
116 - (NSMenu*)applicationDockMenu:(NSApplication*)sender;
118 // Get the URLs that Launch Services expects the browser to open at startup.
119 - (const std::vector<GURL>&)startupUrls;
121 - (BookmarkMenuBridge*)bookmarkMenuBridge;
122 - (HistoryMenuBridge*)historyMenuBridge;
123 - (TabMenuBridge*)tabMenuBridge;
125 // Initializes the AppShimMenuController. This enables changing the menu bar for
127 - (void)initAppShimMenuController;
129 // Called when the user has changed browser windows, meaning the backing profile
130 // may have changed. This can cause a rebuild of the user-data menus. This is a
131 // no-op if the new profile is the same as the current one. This can be either
132 // the original or the incognito profile.
133 - (void)setLastProfile:(Profile*)profile;
135 // Returns the last active ColorProvider.
136 - (const ui::ColorProvider&)lastActiveColorProvider;
138 // This is called when the system wide light or dark mode changes.
139 - (void)nativeThemeDidChange;
141 // Certain NSMenuItems [Close Tab and Close Window] have different
142 // keyEquivalents depending on context. This must be invoked in two locations:
143 // * In menuNeedsUpdate:, which is called prior to showing the NSMenu.
144 // * In CommandDispatcher, which independently searches for a matching
146 - (void)updateMenuItemKeyEquivalents;
148 // Returns YES if `window` is a normal, tabbed, non-app browser window.
149 // Serves as a swizzle point for unit tests to avoid creating Browser
151 - (BOOL)windowHasBrowserTabs:(NSWindow*)window;
154 - (void)setCloseWindowMenuItemForTesting:(NSMenuItem*)menuItem;
155 - (void)setCloseTabMenuItemForTesting:(NSMenuItem*)menuItem;
156 - (void)setLastProfileForTesting:(Profile*)profile;
162 // Functions that may be accessed from non-Objective-C C/C++ code.
164 namespace app_controller_mac {
166 // True if we are currently handling an IDC_NEW_{TAB,WINDOW} command. Used in
167 // SessionService::Observe() to get around windows/linux and mac having
168 // different models of application lifetime.
169 bool IsOpeningNewWindow();
171 // Create a guest profile if one is needed. Afterwards, even if the profile
172 // already existed, notify the AppController of the profile in use.
173 void CreateGuestProfileIfNeeded();
175 // Called when Enterprise startup dialog is close and repost
176 // applicationDidFinished notification.
177 void EnterpriseStartupDialogClosed();
179 // Tells RunInSafeProfile() or RunInSpecificSafeProfile() what to do if the
180 // profile cannot be loaded from disk.
181 enum ProfileLoadFailureBehavior {
182 // Silently fail, and run |callback| with nullptr.
184 // Show the profile picker, and run |callback| with nullptr.
185 kShowProfilePickerOnFailure,
188 // Tries to load the profile returned by |-safeProfileForNewWindows:|. If it
189 // succeeds, calls |callback| with it.
191 // |callback| must be valid.
192 void RunInLastProfileSafely(base::OnceCallback<void(Profile*)> callback,
193 ProfileLoadFailureBehavior on_failure);
195 // Tries to load the profile in |profile_dir|. If it succeeds, calls
196 // |callback| with it. If the profile was already loaded, |callback| runs
199 // |callback| must be valid.
200 void RunInProfileSafely(const base::FilePath& profile_dir,
201 base::OnceCallback<void(Profile*)> callback,
202 ProfileLoadFailureBehavior on_failure);
204 // Waits for the TabRestoreService to have loaded its entries, then calls
205 // OpenWindowWithRestoredTabs().
208 class TabRestorer : public sessions::TabRestoreServiceObserver {
210 // Restore the most recent tab in |profile|, e.g. for Cmd+Shift+T.
211 static void RestoreMostRecent(Profile* profile);
213 // Restore a specific tab in |profile|, e.g. for a History menu item.
214 // |session_id| can be a |TabRestoreService::Entry::id|, or a
215 // |TabRestoreEntryService::Entry::original_id|.
216 static void RestoreByID(Profile* profile, SessionID session_id);
218 ~TabRestorer() override;
220 // sessions::TabRestoreServiceObserver:
221 void TabRestoreServiceDestroyed(
222 sessions::TabRestoreService* service) override;
223 void TabRestoreServiceLoaded(sessions::TabRestoreService* service) override;
226 TabRestorer(Profile* profile, SessionID session_id);
228 // Performs the tab restore. Called either in TabRestoreServiceLoaded(), or
229 // directly from RestoreMostRecent()/RestoreByID() if the service was already
231 static void DoRestoreTab(Profile* profile, SessionID session_id);
233 base::ScopedObservation<sessions::TabRestoreService,
234 sessions::TabRestoreServiceObserver>
236 raw_ptr<Profile> profile_;
237 SessionID session_id_;
240 } // namespace app_controller_mac
242 #endif // CHROME_BROWSER_APP_CONTROLLER_MAC_H_