Home | History | Annotate | Download | only in glue
      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.
      4 
      5 #ifndef CHROME_BROWSER_SYNC_GLUE_SYNCED_SESSION_TRACKER_H_
      6 #define CHROME_BROWSER_SYNC_GLUE_SYNCED_SESSION_TRACKER_H_
      7 
      8 #include <map>
      9 #include <set>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/basictypes.h"
     14 #include "base/memory/scoped_vector.h"
     15 #include "chrome/browser/sessions/session_id.h"
     16 #include "chrome/browser/sessions/session_types.h"
     17 #include "chrome/browser/sync/glue/synced_session.h"
     18 #include "chrome/browser/sync/sessions/tab_node_pool.h"
     19 
     20 namespace browser_sync {
     21 
     22 // Class to manage synced sessions. The tracker will own all SyncedSession
     23 // and SyncedSessionTab objects it creates, and deletes them appropriately on
     24 // destruction.
     25 // Note: SyncedSession objects are created for all synced sessions, including
     26 // the local session (whose tag we maintain separately).
     27 class SyncedSessionTracker {
     28  public:
     29   SyncedSessionTracker();
     30   ~SyncedSessionTracker();
     31 
     32   // We track and distinguish the local session from foreign sessions.
     33   void SetLocalSessionTag(const std::string& local_session_tag);
     34 
     35   // Fill a preallocated vector with all foreign sessions we're tracking (skips
     36   // the local session object). SyncedSession ownership remains within the
     37   // SyncedSessionTracker.
     38   // Returns true if we had foreign sessions to fill it with, false otherwise.
     39   bool LookupAllForeignSessions(std::vector<const SyncedSession*>* sessions)
     40       const;
     41 
     42   // Attempts to look up the session windows associatd with the session given
     43   // by |session_tag|. Ownership Of SessionWindows stays within the
     44   // SyncedSessionTracker.
     45   // If lookup succeeds:
     46   // - Fills windows with the SessionWindow pointers, returns true.
     47   // Else
     48   // - Returns false.
     49   bool LookupSessionWindows(const std::string& session_tag,
     50                             std::vector<const SessionWindow*>* windows) const;
     51 
     52   // Attempts to look up the tab associated with the given tag and tab id.
     53   // Ownership of the SessionTab remains within the SyncedSessionTracker.
     54   // If lookup succeeds:
     55   // - Sets tab to point to the SessionTab, and returns true.
     56   // Else
     57   // - Returns false, tab is set to NULL.
     58   bool LookupSessionTab(const std::string& session_tag,
     59                         SessionID::id_type tab_id,
     60                         const SessionTab** tab) const;
     61 
     62   // Allows retrieval of existing data for the local session. Unlike GetSession
     63   // this won't create-if-not-present.
     64   bool LookupLocalSession(const SyncedSession** output) const;
     65 
     66   // Returns a pointer to the SyncedSession object associated with
     67   // |session_tag|.  If none exists, creates one. Ownership of the
     68   // SyncedSession remains within the SyncedSessionTracker.
     69   SyncedSession* GetSession(const std::string& session_tag);
     70 
     71   // Deletes the session associated with |session_tag| if it exists.
     72   // Returns true if the session existed and was deleted, false otherwise.
     73   bool DeleteSession(const std::string& session_tag);
     74 
     75   // Resets the tracking information for the session specified by |session_tag|.
     76   // This involves clearing all the windows and tabs from the session, while
     77   // keeping pointers saved in the synced_window_map_ and synced_tab_map_.
     78   // Once reset, all calls to PutWindowInSession and PutTabInWindow will denote
     79   // that the requested windows and tabs are owned (by setting the boolean
     80   // in their SessionWindowWrapper/SessionTabWrapper to true) and add them back
     81   // to their session. The next call to CleanupSession(...) will delete those
     82   // windows and tabs not owned.
     83   void ResetSessionTracking(const std::string& session_tag);
     84 
     85   // Deletes those windows and tabs associated with |session_tag| that are no
     86   // longer owned.
     87   // See ResetSessionTracking(...).
     88   void CleanupSession(const std::string& session_tag);
     89 
     90   // Adds the window with id |window_id| to the session specified by
     91   // |session_tag|, and markes the window as being owned. If none existed for
     92   // that session, creates one. Similarly, if the session did not exist yet,
     93   // creates it. Ownership of the SessionWindow remains within the
     94   // SyncedSessionTracker.
     95   void PutWindowInSession(const std::string& session_tag,
     96                           SessionID::id_type window_id);
     97 
     98   // Adds the tab with id |tab_id| to the window |window_id|, and marks it as
     99   // being owned. If none existed for that session, creates one. Ownership of
    100   // the SessionTab remains within the SyncedSessionTracker.
    101   // Note: GetSession(..) must have already been called with |session_tag| to
    102   // ensure we having mapping information for this session.
    103   void PutTabInWindow(const std::string& session_tag,
    104                       SessionID::id_type window_id,
    105                       SessionID::id_type tab_id,
    106                       size_t tab_index);
    107 
    108   // Returns a pointer to the SessionTab object associated with |tab_id| for
    109   // the session specified with |session_tag|. If none exists, creates one.
    110   // Ownership of the SessionTab remains within the SyncedSessionTracker.
    111   // |tab_node_id| must be a valid node id for the node backing this tab.
    112   SessionTab* GetTab(const std::string& session_tag,
    113                      SessionID::id_type tab_id,
    114                      int tab_node_id);
    115 
    116   // Fills |tab_node_ids| with the tab node ids (see GetTab) for all the tabs*
    117   // associated with the session having tag |session_tag|.
    118   // Returns false if we don't have any record of the session.  If no tabs were
    119   // found as part of the session, the return value will be true but
    120   // |tab_node_ids| will be empty.
    121   //
    122   // * - note that this only returns the ids we're aware of; it's possible we
    123   // don't have the latest tab state from a foreign session and it's also
    124   // possible we just haven't updated the tab_node_id for a tab yet, so the
    125   // result list should not be treated as authoritative.
    126   bool LookupTabNodeIds(const std::string& session_tag,
    127                         std::set<int>* tab_node_ids);
    128 
    129   // Free the memory for all dynamically allocated objects and clear the
    130   // tracking structures.
    131   void Clear();
    132 
    133   bool Empty() const {
    134     return synced_tab_map_.empty() && synced_session_map_.empty();
    135   }
    136 
    137   // Includes both foreign sessions and the local session.
    138   size_t num_synced_sessions() const {
    139     return synced_session_map_.size();
    140   }
    141 
    142   // Returns the number of tabs associated with the specified session tag.
    143   size_t num_synced_tabs(const std::string& session_tag) const {
    144     SyncedTabMap::const_iterator iter = synced_tab_map_.find(session_tag);
    145     if (iter != synced_tab_map_.end()) {
    146       return iter->second.size();
    147     } else {
    148       return 0;
    149     }
    150   }
    151  private:
    152   // Datatypes for accessing session data. Neither of the *Wrappers actually
    153   // have ownership of the Windows/Tabs, they just provide id-based access to
    154   // them. The ownership remains within its containing session (for windows and
    155   // mapped tabs, unmapped tabs are owned by the unmapped_tabs_ container).
    156   // Note, we pair pointers with bools so that we can track what is owned and
    157   // what can be deleted (see ResetSessionTracking(..) and CleanupSession(..)
    158   // above).
    159   // The wrappers also serve as a convenient place to augment state stored in
    160   // SessionTab for sync purposes, such as |tab_node_id|.
    161   // IsOwned is used as a wrapper constructor parameter for readability.
    162   enum OwnedState {
    163     IS_OWNED,
    164     NOT_OWNED
    165   };
    166   struct SessionTabWrapper {
    167     SessionTabWrapper() : tab_ptr(NULL),
    168                           owned(false),
    169                           tab_node_id(TabNodePool::kInvalidTabNodeID) {}
    170     SessionTabWrapper(SessionTab* tab_ptr, OwnedState owned, int tab_node_id)
    171         : tab_ptr(tab_ptr),
    172           owned(owned == IS_OWNED),
    173           tab_node_id(tab_node_id) {}
    174     SessionTab* tab_ptr;
    175 
    176     // This is used as part of a mark-and-sweep approach to garbage
    177     // collection for closed tabs that are no longer "in use", or "owned".
    178     // ResetSessionTracking will clear |owned| bits, and if it is not claimed
    179     // by a window by the time CleanupSession is called it will be deleted.
    180     bool owned;
    181 
    182     // This lets us identify the sync node that is "backing" this tab in the
    183     // sync model, whether it is part of a local or foreign session. The
    184     // "tab node id" is described in session_specifics.proto.
    185     int tab_node_id;
    186   };
    187   typedef std::map<SessionID::id_type, SessionTabWrapper> IDToSessionTabMap;
    188   typedef std::map<std::string, IDToSessionTabMap> SyncedTabMap;
    189 
    190   struct SessionWindowWrapper {
    191     SessionWindowWrapper() : window_ptr(NULL), owned(false) {}
    192     SessionWindowWrapper(SessionWindow* window_ptr, OwnedState owned)
    193         : window_ptr(window_ptr),
    194           owned(owned == IS_OWNED) {}
    195     SessionWindow* window_ptr;
    196     bool owned;
    197   };
    198   typedef std::map<SessionID::id_type, SessionWindowWrapper>
    199       IDToSessionWindowMap;
    200   typedef std::map<std::string, IDToSessionWindowMap> SyncedWindowMap;
    201 
    202   typedef std::map<std::string, SyncedSession*> SyncedSessionMap;
    203 
    204   // Helper methods for deleting SessionWindows and SessionTabs without owners.
    205   bool DeleteOldSessionWindowIfNecessary(SessionWindowWrapper window_wrapper);
    206   bool DeleteOldSessionTabIfNecessary(SessionTabWrapper tab_wrapper);
    207 
    208   // Implementation for GetTab(...) above, permits invalid tab_node_id.
    209   SessionTab* GetTabImpl(const std::string& session_tag,
    210                          SessionID::id_type tab_id,
    211                          int tab_node_id);
    212 
    213   // Per client mapping of tab id's to their SessionTab objects.
    214   // Key: session tag.
    215   // Value: Tab id to SessionTabWrapper map.
    216   SyncedTabMap synced_tab_map_;
    217 
    218   // Per client mapping of the window id's to their SessionWindow objects.
    219   // Key: session_tag
    220   // Value: Window id to SessionWindowWrapper map.
    221   SyncedWindowMap synced_window_map_;
    222 
    223   // Per client mapping synced session objects.
    224   // Key: session tag.
    225   // Value: SyncedSession object pointer.
    226   SyncedSessionMap synced_session_map_;
    227 
    228   // The set of tabs that we have seen, and created SessionTab objects for, but
    229   // have not yet mapped to SyncedSessions. These are temporarily orphaned
    230   // tabs, and won't be deleted if we delete synced_session_map_, but are still
    231   // owned by the SyncedSessionTracker itself (and deleted on Clear()).
    232   std::set<SessionTab*> unmapped_tabs_;
    233 
    234   // The tag for this machine's local session, so we can distinguish the foreign
    235   // sessions.
    236   std::string local_session_tag_;
    237 
    238   DISALLOW_COPY_AND_ASSIGN(SyncedSessionTracker);
    239 };
    240 
    241 }  // namespace browser_sync
    242 
    243 #endif  // CHROME_BROWSER_SYNC_GLUE_SYNCED_SESSION_TRACKER_H_
    244