OLD | NEW |
(Empty) | |
| 1 // Copyright 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 IOS_CHROME_BROWSER_TABS_TAB_MODEL_H_ |
| 6 #define IOS_CHROME_BROWSER_TABS_TAB_MODEL_H_ |
| 7 |
| 8 #import <Foundation/Foundation.h> |
| 9 #import <UIKit/UIKit.h> |
| 10 |
| 11 #include <memory> |
| 12 |
| 13 #import "ios/web/public/navigation_manager.h" |
| 14 #include "ui/base/page_transition_types.h" |
| 15 |
| 16 class GURL; |
| 17 class SessionID; |
| 18 @class SessionServiceIOS; |
| 19 @class SessionWindowIOS; |
| 20 @class Tab; |
| 21 @protocol TabModelObserver; |
| 22 class TabModelSyncedWindowDelegate; |
| 23 class TabUsageRecorder; |
| 24 |
| 25 namespace ios { |
| 26 class ChromeBrowserState; |
| 27 } |
| 28 |
| 29 namespace web { |
| 30 struct Referrer; |
| 31 class WebState; |
| 32 } |
| 33 |
| 34 // A list of notifications about changes in the model or changes in tab |
| 35 // state. |
| 36 |
| 37 // A tab is about to load a URL. The tab in question is in the userInfo under |
| 38 // kTabModelTabKey. This may fire multiple times during a load, for example, on |
| 39 // redirects. |
| 40 extern NSString* const kTabModelTabWillStartLoadingNotification; |
| 41 // Notification sent when user navigates away from the current page. |
| 42 extern NSString* const kTabModelUserNavigatedNotification; |
| 43 // A tab started to load a URL. The tab in question is in the userInfo under |
| 44 // kTabModelTabKey. |
| 45 extern NSString* const kTabModelTabDidStartLoadingNotification; |
| 46 // A tab finished loading a URL. The tab in question is in the userInfo under |
| 47 // kTabModelTabKey. |
| 48 extern NSString* const kTabModelTabDidFinishLoadingNotification; |
| 49 // All tabs have finished their shutdown sequences. |
| 50 // NOTE: This notification is not sent when closing a single tab that happens |
| 51 // to be the last tab. |
| 52 extern NSString* const kTabModelAllTabsDidCloseNotification; |
| 53 // A tab has lost its status as the currently selected tab. The tab in question |
| 54 // is in the userInfo under kTabModelTabKey. |
| 55 extern NSString* const kTabModelTabDeselectedNotification; |
| 56 // A new tab has been created from a link. |
| 57 extern NSString* const kTabModelNewTabWillOpenNotification; |
| 58 |
| 59 // Keys for the userInfo included with the above notifications: |
| 60 |
| 61 // Key that indicates whether to open the next tab in the background. |
| 62 extern NSString* const kTabModelOpenInBackgroundKey; |
| 63 // Key for the tab. |
| 64 extern NSString* const kTabModelTabKey; |
| 65 // Key for the status of the page load. The value is a NSNumber. |
| 66 extern NSString* const kTabModelPageLoadSuccess; |
| 67 |
| 68 // --------------------------------------------------------------------------- |
| 69 |
| 70 namespace TabModelConstants { |
| 71 |
| 72 // Position the tab automatically. This value is used as index parameter in |
| 73 // methods that require an index when the caller doesn't have a preference |
| 74 // on the position where the tab will be open. |
| 75 NSUInteger const kTabPositionAutomatically = NSNotFound; |
| 76 |
| 77 } // namespace TabModelConstants |
| 78 |
| 79 // A model of a tab "strip". Although the UI representation may not be a |
| 80 // traditional strip at all, tabs are still accessed via an integral index. |
| 81 // The model knows about the currently selected tab in order to maintain |
| 82 // consistency between multiple views that need the current tab to be |
| 83 // synchronized. |
| 84 @interface TabModel : NSObject<NSFastEnumeration> |
| 85 |
| 86 // Currently active tab. |
| 87 @property(nonatomic, weak) Tab* currentTab; |
| 88 |
| 89 // The delegate for sync. |
| 90 @property(nonatomic, readonly) |
| 91 TabModelSyncedWindowDelegate* syncedWindowDelegate; |
| 92 |
| 93 // BrowserState associated with this TabModel. |
| 94 @property(nonatomic, readonly) ios::ChromeBrowserState* browserState; |
| 95 |
| 96 // Unique identifier of this browser for session restore. This ID is only |
| 97 // unique within the current session, and is not guaranteed to be unique |
| 98 // across sessions. |
| 99 @property(nonatomic, readonly) const SessionID& sessionID; |
| 100 |
| 101 // Records UMA metrics about Tab usage. |
| 102 @property(nonatomic, readonly) TabUsageRecorder* tabUsageRecorder; |
| 103 |
| 104 // Whether web usage is enabled (meaning web views can be created in its tabs). |
| 105 // Defaults to NO. |
| 106 // Note that generally this should be set via BVC, not directly. |
| 107 @property(nonatomic, assign) BOOL webUsageEnabled; |
| 108 |
| 109 // YES if this tab set is off the record. |
| 110 @property(nonatomic, readonly, getter=isOffTheRecord) BOOL offTheRecord; |
| 111 |
| 112 // NO if the model has at least one tab. |
| 113 @property(nonatomic, readonly, getter=isEmpty) BOOL empty; |
| 114 |
| 115 // Determines the number of tabs in the model. |
| 116 @property(nonatomic, readonly) NSUInteger count; |
| 117 |
| 118 // Returns the TabModel associated with |browserState|. May be null during |
| 119 // shutdown. |
| 120 + (instancetype)tabModelForBrowserState:(ios::ChromeBrowserState*)browserState; |
| 121 |
| 122 // Initializes tabs from a restored session. |-setCurrentTab| needs to be called |
| 123 // in order to display the views associated with the tabs. Waits until the views |
| 124 // are ready. |browserState| cannot be nil. |service| cannot be nil; this class |
| 125 // creates intermediate SessionWindowIOS objects which must be consumed by a |
| 126 // session service before they are deallocated. |window| can be nil to create |
| 127 // an empty TabModel. In that case no notification will be sent during object |
| 128 // creation. |
| 129 // |browserState| will have the initialized TabModel stored as user data. |
| 130 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window |
| 131 sessionService:(SessionServiceIOS*)service |
| 132 browserState:(ios::ChromeBrowserState*)browserState |
| 133 NS_DESIGNATED_INITIALIZER; |
| 134 |
| 135 - (instancetype)init NS_UNAVAILABLE; |
| 136 |
| 137 // Restores the given session window after a crash. If there is only one tab, |
| 138 // showing the NTP, then this tab is clobberred, otherwise, the tab from the |
| 139 // sessions are added at the end of the tab model. |
| 140 // Returns YES if the single NTP tab is closed. |
| 141 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window; |
| 142 |
| 143 // Uses the SessionServiceIOS to persist the tab model to disk, either |
| 144 // immediately or deferred based on the value of |immediately|. |
| 145 - (void)saveSessionImmediately:(BOOL)immediately; |
| 146 |
| 147 // Accesses the tab at the given index. |
| 148 - (Tab*)tabAtIndex:(NSUInteger)index; |
| 149 - (NSUInteger)indexOfTab:(Tab*)tab; |
| 150 |
| 151 // Returns the tab object associated from the given JS-level window name. |
| 152 - (Tab*)tabWithWindowName:(NSString*)windowName; |
| 153 |
| 154 // Returns the next Tab, starting after |tab|, spawned by the specified Tab, If |
| 155 // |after| is a valid tab, will only look at tabs following it (in tab ordering, |
| 156 // not order opened) in the list, even if it comes before |tab|. Returns nil if |
| 157 // no tab meets this constraint. |
| 158 - (Tab*)nextTabWithOpener:(Tab*)tab afterTab:(Tab*)afterTab; |
| 159 |
| 160 // TODO(crbug.com/661980): Make these |firstTabOpenedBy| and |lastTabOpenedBy| |
| 161 // better mimic what desktop chrome does. Or, better yet, use shared code. |
| 162 // Placing anew tab in its proper location along the tab strip is based on the |
| 163 // tab's 'opener' tab, the tab from which the new tab was opened. For the user, |
| 164 // that does not mean the tab in UI terms, but the page from which the new tab |
| 165 // is opened. Currently, to best provide this behavior, the session ID of the |
| 166 // tab is supplemented with its navigation index. If both those items match, it |
| 167 // is assumed that the tabs belong to the same owner's group. Note that using |
| 168 // navigation index is a limited solution, and may in some cases be incorrect, |
| 169 // as forward or back navigations (incrementing/decrementing the navigation |
| 170 // index) may result in incorrect tab pairings. |
| 171 |
| 172 // Returns the first tab in the model opened by the specified tab at its current |
| 173 // navigation index. The search starts at the beginning of the list and stops at |
| 174 // |tab|. Returns nil if no tab meets these constraints. |
| 175 - (Tab*)firstTabWithOpener:(Tab*)tab; |
| 176 // Returns the last tab in the model opened by the specified tab at its current |
| 177 // navigation index. The search starts at |tab|. Returns nil if no tab meets |
| 178 // these constraints. |
| 179 - (Tab*)lastTabWithOpener:(Tab*)tab; |
| 180 |
| 181 // Returns the tab which opened this tab, or nil if it's not a child. |
| 182 - (Tab*)openerOfTab:(Tab*)tab; |
| 183 |
| 184 // Add/modify tabs. |
| 185 |
| 186 // Either opens a tab at the specified URL and register its JS-supplied window |
| 187 // name if appropriate, or navigates the tab corresponding to |windowName| to |
| 188 // the given |URL|. Will also update the current tab if |inBackground| is NO. |
| 189 // |openedByDOM| is YES if the page was opened by DOM. The |index| parameter can |
| 190 // be set to TabModelConstants::kTabPositionAutomatically if the caller doesn't |
| 191 // have a preference for the position of the tab. |
| 192 - (Tab*)insertOrUpdateTabWithURL:(const GURL&)URL |
| 193 referrer:(const web::Referrer&)referrer |
| 194 transition:(ui::PageTransition)transition |
| 195 windowName:(NSString*)windowName |
| 196 opener:(Tab*)parentTab |
| 197 openedByDOM:(BOOL)openedByDOM |
| 198 atIndex:(NSUInteger)index |
| 199 inBackground:(BOOL)inBackground; |
| 200 |
| 201 // As above, but using WebLoadParams to specify various optional parameters. |
| 202 - (Tab*)insertOrUpdateTabWithLoadParams: |
| 203 (const web::NavigationManager::WebLoadParams&)params |
| 204 windowName:(NSString*)windowName |
| 205 opener:(Tab*)parentTab |
| 206 openedByDOM:(BOOL)openedByDOM |
| 207 atIndex:(NSUInteger)index |
| 208 inBackground:(BOOL)inBackground; |
| 209 |
| 210 // Opens a blank tab without URL and updates the current tab if |inBackground| |
| 211 // is NO. |
| 212 - (Tab*)insertBlankTabWithTransition:(ui::PageTransition)transition |
| 213 opener:(Tab*)parentTab |
| 214 openedByDOM:(BOOL)openedByDOM |
| 215 atIndex:(NSUInteger)index |
| 216 inBackground:(BOOL)inBackground; |
| 217 |
| 218 // Inserts a new tab at the given |index| with the session history specified by |
| 219 // |webState|. Does not go through the order controller as this is generally |
| 220 // used only for restoring a previous session and the index is fixed. |
| 221 - (Tab*)insertTabWithWebState:(std::unique_ptr<web::WebState>)webState |
| 222 atIndex:(NSUInteger)index; |
| 223 |
| 224 // Inserts |tab| at the given |index|. Broadcasts the proper notifications about |
| 225 // the change. The receiver should be set as the parentTabModel for |tab|; this |
| 226 // method doesn't check that. |
| 227 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index; |
| 228 |
| 229 // Moves |tab| to the given |index|. |index| must be valid for this tab model |
| 230 // (must be less than the current number of tabs). |tab| must already be in this |
| 231 // tab model. If |tab| is already at |index|, this method does nothing and will |
| 232 // not notify observers. |
| 233 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)index; |
| 234 |
| 235 // Replaces |oldTab| in the model with |newTab|. Closes the oldTab when |
| 236 // replacing it in the model unless |keepOldTabOpen|. |
| 237 - (void)replaceTab:(Tab*)oldTab |
| 238 withTab:(Tab*)newTab |
| 239 keepOldTabOpen:(BOOL)keepOldTabOpen; |
| 240 |
| 241 // Closes the tab at the given |index|. |index| must be valid. |
| 242 - (void)closeTabAtIndex:(NSUInteger)index; |
| 243 |
| 244 // Closes the given tab. |
| 245 - (void)closeTab:(Tab*)tab; |
| 246 |
| 247 // Closes ALL the tabs. |
| 248 - (void)closeAllTabs; |
| 249 |
| 250 // Halts all tabs (terminating active requests) without closing them. Used |
| 251 // when the app is shutting down. |
| 252 - (void)haltAllTabs; |
| 253 |
| 254 // Notifies observers that the given |tab| was changed. |
| 255 - (void)notifyTabChanged:(Tab*)tab; |
| 256 // Notifies observers that the snapshot for the given |tab| changed was changed |
| 257 // to |image|. |
| 258 - (void)notifyTabSnapshotChanged:(Tab*)tab withImage:(UIImage*)image; |
| 259 |
| 260 // Adds |observer| to the list of observers. |observer| is not retained. Does |
| 261 // nothing if |observer| is already in the list. Any added observers must be |
| 262 // explicitly removed before the TabModel is destroyed. |
| 263 - (void)addObserver:(id<TabModelObserver>)observer; |
| 264 |
| 265 // Removes |observer| from the list of observers. |
| 266 - (void)removeObserver:(id<TabModelObserver>)observer; |
| 267 |
| 268 // Resets all session counters. |
| 269 - (void)resetSessionMetrics; |
| 270 |
| 271 // Records tab session metrics. |
| 272 - (void)recordSessionMetrics; |
| 273 |
| 274 // Purges the web views on all the tabs and reloads the frontmost one if there |
| 275 // is one. This is used when a userdefault changes and the web views need to be |
| 276 // re-created to pick it up. |
| 277 - (void)resetAllWebViews; |
| 278 |
| 279 // Sets whether the tab model can communicate with the web. |
| 280 - (void)setWebUsageEnabled:(BOOL)webUsageEnabled; |
| 281 |
| 282 // Sets whether the user is primarily interacting with this tab model. |
| 283 - (void)setPrimary:(BOOL)primary; |
| 284 |
| 285 // Returns a set with the names of the files received from other applications |
| 286 // that are still referenced by an open or recently closed tab. |
| 287 - (NSSet*)currentlyReferencedExternalFiles; |
| 288 |
| 289 // Called when the browser state provided to this instance is being destroyed. |
| 290 // At this point the tab model will no longer ever be active, and will likely be |
| 291 // deallocated soon. |
| 292 - (void)browserStateDestroyed; |
| 293 // Called by the Tab to inform its parent that it has been closed. |
| 294 - (void)didCloseTab:(Tab*)closedTab; |
| 295 // Called by |tab| to inform the model that a navigation has taken place. |
| 296 // TODO(crbug.com/661983): once more of the navigation state has moved into WC, |
| 297 // replace this with WebStateObserver. |
| 298 - (void)navigationCommittedInTab:(Tab*)tab; |
| 299 |
| 300 @end |
| 301 |
| 302 @interface TabModel (PrivateForTestingOnly) |
| 303 |
| 304 // Opens a tab at the specified URL and register its JS-supplied window name if |
| 305 // appropriate. The newly created tab will not be the child of any other tab. |
| 306 // This does not go through the order controller. Used a page transition of |
| 307 // TYPED. |
| 308 - (Tab*)addTabWithURL:(const GURL&)URL |
| 309 referrer:(const web::Referrer&)referrer |
| 310 windowName:(NSString*)windowName; |
| 311 |
| 312 // Inserts a new tab at the given |index| with the given |URL| and |referrer|. |
| 313 // This does not go through the order controller. Uses a page transition of |
| 314 // TYPED. |
| 315 - (Tab*)insertTabWithURL:(const GURL&)URL |
| 316 referrer:(const web::Referrer&)referrer |
| 317 windowName:(NSString*)windowName |
| 318 opener:(Tab*)parentTab |
| 319 atIndex:(NSUInteger)index; |
| 320 |
| 321 @end |
| 322 |
| 323 #endif // IOS_CHROME_BROWSER_TABS_TAB_MODEL_H_ |
OLD | NEW |