Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3790)

Unified Diff: chrome/browser/sync/glue/session_model_associator.h

Issue 5705004: [SYNC] Sessions datatype refactor. Most things related to sessions under-the-... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Rebase Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sync/glue/session_model_associator.h
===================================================================
--- chrome/browser/sync/glue/session_model_associator.h (revision 70604)
+++ chrome/browser/sync/glue/session_model_associator.h (working copy)
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_SYNC_GLUE_SESSION_MODEL_ASSOCIATOR_H_
#pragma once
+#include <map>
#include <string>
#include <vector>
@@ -13,13 +14,19 @@
#include "base/gtest_prod_util.h"
#include "base/observer_list.h"
#include "base/scoped_vector.h"
+#include "base/string_util.h"
#include "base/threading/non_thread_safe.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/sessions/session_id.h"
#include "chrome/browser/sessions/session_service.h"
#include "chrome/browser/sessions/session_types.h"
#include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/glue/foreign_session_tracker.h"
#include "chrome/browser/sync/glue/model_associator.h"
#include "chrome/browser/sync/protocol/session_specifics.pb.h"
#include "chrome/browser/sync/syncable/model_type.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/notification_registrar.h"
class Profile;
@@ -41,170 +48,357 @@
// Contains all logic for associating the Chrome sessions model and
// the sync sessions model.
-// In the case of sessions, our local model is nothing but a buffer (specifics_)
-// that gets overwritten everytime there is an update. From it, we build a new
-// foreign session windows list each time |GetSessionData| is called by the
-// ForeignSessionHandler.
class SessionModelAssociator
- : public PerDataTypeAssociatorInterface<sync_pb::SessionSpecifics,
- std::string>,
+ : public PerDataTypeAssociatorInterface<TabContents, size_t>,
public base::NonThreadSafe {
public:
-
// Does not take ownership of sync_service.
explicit SessionModelAssociator(ProfileSyncService* sync_service);
virtual ~SessionModelAssociator();
+ // The has_nodes out parameter is set to true if the sync model has
+ // nodes other than the permanent tagged nodes. The method may
+ // return false if an error occurred.
+ virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes);
+
// AssociatorInterface and PerDataTypeAssociator Interface implementation.
virtual void AbortAssociation() {
- // No implementation needed, this associator runs on the main
- // thread.
+ // No implementation needed, this associator runs on the main thread.
}
- // Dummy method, we do everything all-at-once in UpdateFromSyncModel.
- virtual void Associate(const sync_pb::SessionSpecifics* specifics,
- int64 sync_id) {
- }
+ // Returns sync id for the given chrome model id.
+ // Returns sync_api::kInvalidId if the sync node is not found for the given
+ // chrome id.
+ virtual int64 GetSyncIdFromChromeId(const size_t& id);
- // Updates the sync model with the local client data. (calls
- // UpdateFromSyncModel)
- virtual bool AssociateModels();
+ // Returns sync id for the given session tag.
+ // Returns sync_api::kInvalidId if the sync node is not found for the given
+ // tag
+ virtual int64 GetSyncIdFromSessionTag(const std::string& tag);
- // The has_nodes out parameter is set to true if the chrome model
- // has user-created nodes. The method may return false if an error
- // occurred.
- virtual bool ChromeModelHasUserCreatedNodes(bool* has_nodes);
+ // Not used.
+ virtual const TabContents* GetChromeNodeFromSyncId(int64 sync_id) {
+ NOTREACHED();
+ return NULL;
+ }
- // Dummy method, we do everything all-at-once in UpdateFromSyncModel.
- virtual void Disassociate(int64 sync_id) {
+ // Not used.
+ bool InitSyncNodeFromChromeId(const size_t& id,
+ sync_api::BaseNode* sync_node) {
+ NOTREACHED();
+ return false;
}
- // Clear specifics_ buffer and notify foreign session handlers.
- virtual bool DisassociateModels();
+ // Resync local window information. Updates the local sessions header node
+ // with the status of open windows and the order of tabs they contain. Should
+ // only be called for changes that affect a window, not a change within a
+ // single tab.
+ //
+ // If |reload_tabs| is true, will also resync all tabs (same as calling
+ // ReassociateTabs with a vector of all tabs).
+ void ReassociateWindows(bool reload_tabs);
- // Returns the chrome session specifics for the given sync id.
- // Returns NULL if no specifics are found for the given sync id.
- virtual const sync_pb::SessionSpecifics* GetChromeNodeFromSyncId(
- int64 sync_id);
+ // Loads and reassociates the local tabs referenced in |tabs|.
+ void ReassociateTabs(const std::vector<TabContents*>& tabs);
- // Returns whether a node with the given permanent tag was found and update
- // |sync_id| with that node's id.
- virtual bool GetSyncIdForTaggedNode(const std::string* tag, int64* sync_id);
+ // Reassociates a single tab with the sync model. Will check if the tab
+ // already is associated with a sync node and allocate one if necessary.
+ void ReassociateTab(const TabContents& tab);
- // Returns sync id for the given chrome model id.
- // Returns sync_api::kInvalidId if the sync node is not found for the given
- // chrome id.
- virtual int64 GetSyncIdFromChromeId(const std::string& id);
+ // Associate a local tab and it's sync node. Will overwrite the contents of
+ // the sync node with new specifics built from the tab.
+ virtual void Associate(const TabContents* tab, int64 sync_id);
+ // Looks up the specified sync node, and marks that tab as closed, then marks
+ // the node as free and deletes association.
+ virtual void Disassociate(int64 sync_id);
+ // Load any foreign session info stored in sync db and update the sync db
+ // with local client data. Processes/reuses any sync nodes owned by this
+ // client and creates any further sync nodes needed to store local header and
+ // tab info.
+ virtual bool AssociateModels();
+
// Initializes the given sync node from the given chrome node id.
// Returns false if no sync node was found for the given chrome node id or
// if the initialization of sync node fails.
virtual bool InitSyncNodeFromChromeId(const std::string& id,
sync_api::BaseNode* sync_node);
- // The has_nodes out parameter is set to true if the sync model has
- // nodes other than the permanent tagged nodes. The method may
- // return false if an error occurred.
- virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes);
+ // Clear local sync data buffers. Does not delete sync nodes to avoid
+ // tombstones. TODO(zea): way to eventually delete orphaned nodes.
+ virtual bool DisassociateModels();
// Returns the tag used to uniquely identify this machine's session in the
// sync model.
- std::string GetCurrentMachineTag();
+ inline const std::string& GetCurrentMachineTag() {
+ DCHECK(!current_machine_tag_.empty());
+ return current_machine_tag_;
+ }
- // Updates the server data based upon the current client session. If no node
- // corresponding to this machine exists in the sync model, one is created.
- void UpdateSyncModelDataFromClient();
+ // Load and associate window and tab data for a foreign session
+ bool AssociateForeignSpecifics(const sync_pb::SessionSpecifics& specifics,
+ int64 modification_time);
- // Pulls the current sync model from the sync database and returns true upon
- // update of the client model. Called by SessionChangeProcessor.
- // Note that the specifics_ vector is reset and built from scratch each time.
- bool UpdateFromSyncModel(const sync_api::BaseTransaction* trans);
+ // Removes a foreign session from our internal bookkeeping.
+ void DisassociateForeignSession(const std::string& foreign_session_tag);
- // Helper for UpdateFromSyncModel. Appends sync data to a vector of specifics.
- bool QuerySyncModel(const sync_api::BaseTransaction* trans,
- std::vector<const sync_pb::SessionSpecifics*>& specifics);
+ // Builds a list of all foreign sessions.
+ // Caller does NOT own ForeignSession objects.
+ bool GetAllForeignSessions(std::vector<const ForeignSession*>* sessions);
- // Builds sessions from buffered specifics data
- bool GetSessionData(std::vector<ForeignSession*>* sessions);
+ // Loads all windows for foreign session with session tag |tag|.
+ // Caller does NOT own ForeignSession objects.
+ bool GetForeignSession(const std::string& tag,
+ std::vector<SessionWindow*>* windows);
- // Helper method to generate session specifics from session windows.
- void FillSpecificsFromSessions(std::vector<SessionWindow*>* windows,
- sync_pb::SessionSpecifics* session);
+ // Looks up the foreign tab identified by |tab_id| and belonging to foreign
+ // session |tag|.
+ // Caller does NOT own the SessionTab object.
+ bool GetForeignTab(const std::string& tag,
+ const SessionID::id_type tab_id,
+ const SessionTab** tab);
- // Helper method for converting session specifics to windows.
- void AppendForeignSessionFromSpecifics(
- const sync_pb::SessionSpecifics* specifics,
- std::vector<ForeignSession*>* session);
+ // Specifies whether the window has tabs to sync. The new tab page does not
+ // count. If no tabs to sync, it returns true, otherwise false;
+ static bool SessionWindowHasNoTabsToSync(const SessionWindow& window);
- // Fills the given empty vector with foreign session windows to restore.
- // If the vector is returned empty, then the session data could not be
- // converted back into windows.
- void AppendForeignSessionWithID(int64 id,
- std::vector<ForeignSession*>* session,
- sync_api::BaseTransaction* trans);
+ // Control which local tabs we're interested in syncing.
+ // Ensures the profile matches sync's profile and that the tab has at least
+ // one navigation entry and is not an empty tab.
+ bool IsValidTab(const TabContents& tab);
+ // Control which foreign tabs we're interested in displaying.
+ // Checks that the tab has navigations and is not a new tab.
+ // Note: a new tab page with back/forward history is valid.
+ static bool IsValidSessionTab(const SessionTab& tab);
+
// Returns the syncable model type.
static syncable::ModelType model_type() { return syncable::SESSIONS; }
private:
FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, WriteSessionToNode);
FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
+ WriteFilledSessionToNode);
+ FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
WriteForeignSessionToNode);
+ FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, TabNodePoolEmpty);
+ FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, TabNodePoolNonEmpty);
+ FRIEND_TEST_ALL_PREFIXES(SessionModelAssociatorTest, PopulateSessionWindow);
+ FRIEND_TEST_ALL_PREFIXES(SessionModelAssociatorTest, PopulateSessionTab);
- // Returns the session service from |sync_service_|.
- SessionService* GetSessionService();
+ // Keep all the links to local tab data in one place.
+ class TabLinks {
+ public:
+ // To support usage as second value in maps we need default and copy
+ // constructors.
+ TabLinks()
+ : sync_id_(0),
+ session_tab_(NULL),
+ tab_(NULL) {}
+ // We only ever have either a SessionTab (for foreign tabs), or a
+ // TabContents (for local tabs).
+ TabLinks(int64 sync_id, const TabContents* tab)
+ : sync_id_(sync_id),
+ session_tab_(NULL) {
+ tab_ = const_cast<TabContents*>(tab);
+ }
+ TabLinks(int64 sync_id, const SessionTab* session_tab)
+ : sync_id_(sync_id),
+ tab_(NULL) {
+ session_tab_ = const_cast<SessionTab*>(session_tab);
+ }
+
+ inline const int64 sync_id() const { return sync_id_; }
+ inline const SessionTab* session_tab() const { return session_tab_; }
+ inline const TabContents* tab() const { return tab_; }
+ private:
+ int64 sync_id_;
+ SessionTab* session_tab_;
+ TabContents* tab_;
+ };
+
+ // A pool for managing free/used tab sync nodes. Performs lazy creation
+ // of sync nodes when necessary.
+ class TabNodePool {
+ public:
+ explicit TabNodePool(ProfileSyncService* sync_service);
+
+ // Add a previously allocated tab sync node to our pool. Increases the size
+ // of tab_syncid_pool_ by one and marks the new tab node as free.
+ // Note: this should only be called when we discover tab sync nodes from
+ // previous sessions, not for freeing tab nodes we created through
+ // GetFreeTabNode (use FreeTabNode below for that).
+ void AddTabNode(int64 sync_id);
+
+ // Returns the sync_id for the next free tab node. If none are available,
+ // creates a new tab node.
+ // Note: We make use of the following "id's"
+ // - a sync_id: an int64 used in |sync_api::InitByIdLookup|
+ // - a tab_id: created by session service, unique to this client
+ // - a tab_node_id: the id for a particular sync tab node. This is used
+ // to generate the sync tab node tag through:
+ // tab_tag = StringPrintf("%s_%ui", local_session_tag, tab_node_id);
+ // tab_node_id and sync_id are both unique to a particular sync node. The
+ // difference is that tab_node_id is controlled by the model associator and
+ // is used when creating a new sync node, which returns the sync_id, created
+ // by the sync db.
+ int64 GetFreeTabNode();
+
+ // Return a tab node to our free pool.
+ // Note: the difference between FreeTabNode and AddTabNode is that
+ // FreeTabNode does not modify the size of |tab_syncid_pool_|, while
+ // AddTabNode increases it by one. In the case of FreeTabNode, the size of
+ // the |tab_syncid_pool_| should always be equal to the amount of tab nodes
+ // associated with this machine.
+ void FreeTabNode(int64 sync_id);
+
+ // Clear tab pool.
+ inline void clear() { tab_syncid_pool_.clear(); }
+
+ // Return the number of tab nodes this client currently has allocated
+ // (including both free and used nodes)
+ inline size_t capacity() const { return tab_syncid_pool_.size(); }
+
+ // Return empty status (all tab nodes are in use).
+ inline bool empty() const { return tab_pool_fp_ == -1; }
+
+ // Return full status (no tab nodes are in use).
+ inline bool full() {
+ return tab_pool_fp_ == static_cast<int64>(tab_syncid_pool_.size())-1;
+ }
+
+ inline void set_machine_tag(const std::string& machine_tag) {
+ machine_tag_ = machine_tag;
+ }
+ private:
+ // Pool of all available syncid's for tab's we have created.
+ std::vector<int64> tab_syncid_pool_;
+
+ // Free pointer for tab pool. Only those node id's, up to and including the
+ // one indexed by the free pointer, are valid and free. The rest of the
+ // |tab_syncid_pool_| is invalid because the nodes are in use.
+ // To get the next free node, use tab_syncid_pool_[tab_pool_fp_--].
+ int64 tab_pool_fp_;
+
+ // The machiine tag associated with this tab pool. Used in the title of new
+ // sync nodes.
+ std::string machine_tag_;
+
+ // Our sync service profile (for making changes to the sync db)
+ ProfileSyncService* sync_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(TabNodePool);
+ };
+
+ // Datatypes for accessing local tab data.
+ typedef std::map<SessionID::id_type, TabLinks> TabLinksMap;
+
+ // Delete all foreign session/window/tab objects allocated dynamically.
+ // This is comprised of ForeignSession*, IDToSessionTabMap*, and any orphaned
+ // SessionTab*'s.
+ void DeleteForeignSessions();
+
+ // Determine if a window is of a type we're interested in syncing.
+ static bool ShouldSyncWindowType(const Browser::Type& type);
+
+ // Build a sync tag from tab_node_id.
+ static inline std::string TabIdToTag(
+ const std::string machine_tag,
+ size_t tab_node_id) {
+ return StringPrintf("%s %lu",
+ machine_tag.c_str(), static_cast<unsigned long>(tab_node_id));
+ }
+
// Initializes the tag corresponding to this machine.
- // Note: creates a syncable::BaseTransaction.
- void InitializeCurrentMachineTag();
+ void InitializeCurrentMachineTag(sync_api::WriteTransaction* trans);
- // Populates the navigation portion of the session specifics.
- void PopulateSessionSpecificsNavigation(const TabNavigation* navigation,
- sync_pb::TabNavigation* tab_navigation);
+ // Updates the server data based upon the current client session. If no node
+ // corresponding to this machine exists in the sync model, one is created.
+ void UpdateSyncModelDataFromClient();
- // Populates the tab portion of the session specifics.
- void PopulateSessionSpecificsTab(const SessionTab* tab,
- sync_pb::SessionTab* session_tab);
+ // Pulls the current sync model from the sync database and returns true upon
+ // update of the client model. Will associate any foreign sessions as well as
+ // keep track of any local tab nodes, adding them to our free tab node pool.
+ bool UpdateAssociationsFromSyncModel(const sync_api::ReadNode& root,
+ const sync_api::BaseTransaction* trans);
- // Populates the window portion of the session specifics.
- void PopulateSessionSpecificsWindow(const SessionWindow* window,
- sync_pb::SessionWindow* session_window);
+ // Fills a tab sync node with data from a TabContents object.
+ // (from a local navigation event)
+ bool WriteTabContentsToSyncModel(const TabContents& tab,
+ const int64 sync_id,
+ sync_api::WriteTransaction* trans);
- // Specifies whether the window has tabs to sync. The new tab page does not
- // count. If no tabs to sync, it returns true, otherwise false;
- bool WindowHasNoTabsToSync(const SessionWindow* window);
+ // Used to populate a session window from the session specifics window
+ // provided. Tracks any foreign session data created through |tracker|.
+ static void PopulateSessionWindowFromSpecifics(
+ std::string foreign_session_tag,
+ const sync_pb::SessionWindow& window,
+ const int64 mtime,
+ SessionWindow* session_window,
+ ForeignSessionTracker* tracker);
+ // Used to populate a session tab from the session specifics tab provided.
+ static void PopulateSessionTabFromSpecifics(const sync_pb::SessionTab& tab,
+ const int64 mtime,
+ SessionTab* session_tab);
+
+ // Used to populate a session tab from the session specifics tab provided.
+ static void AppendSessionTabNavigation(
+ const sync_pb::TabNavigation& navigation,
+ std::vector<TabNavigation>* navigations);
+
+ // Populates the navigation portion of the session specifics.
+ static void PopulateSessionSpecificsNavigation(
+ const TabNavigation* navigation,
+ sync_pb::TabNavigation* tab_navigation);
+
+ // Returns the session service from |sync_service_|.
+ SessionService* GetSessionService();
+
// Internal method used in the callback to obtain the current session.
// We don't own |windows|.
void OnGotSession(int handle, std::vector<SessionWindow*>* windows);
- // Used to populate a session tab from the session specifics tab provided.
- void AppendSessionTabNavigation(std::vector<TabNavigation>* navigations,
- const sync_pb::TabNavigation* navigation);
+ // Populate a session specifics header from a list of SessionWindows
+ void PopulateSessionSpecificsHeader(
+ const std::vector<SessionWindow*>& windows,
+ sync_pb::SessionHeader* header_s);
- // Used to populate a session tab from the session specifics tab provided.
- void PopulateSessionTabFromSpecifics(SessionTab* session_tab,
- const sync_pb::SessionTab* tab, SessionID id);
+ // Populates the window portion of the session specifics.
+ void PopulateSessionSpecificsWindow(const SessionWindow& window,
+ sync_pb::SessionWindow* session_window);
- // Used to populate a session window from the session specifics window
- // provided.
- void PopulateSessionWindowFromSpecifics(SessionWindow* session_window,
- const sync_pb::SessionWindow* window);
+ // Syncs all the tabs in |window| with the local sync db. Will allocate tab
+ // nodes if needed.
+ bool SyncLocalWindowToSyncModel(const SessionWindow& window);
- // Updates the current session on the server. Creates a node for this machine
- // if there is not one already.
- bool UpdateSyncModel(sync_pb::SessionSpecifics* session_data,
- sync_api::WriteTransaction* trans,
- const sync_api::ReadNode* root);
- // Stores the machine tag.
+ // Fills a tab sync node with data from a SessionTab object.
+ // (from ReadCurrentSessions)
+ bool WriteSessionTabToSyncModel(const SessionTab& tab,
+ const int64 sync_id,
+ sync_api::WriteTransaction* trans);
+
+ // Populates the tab portion of the session specifics.
+ void PopulateSessionSpecificsTab(const SessionTab& tab,
+ sync_pb::SessionTab* session_tab);
+
+ // Local client name.
std::string current_machine_tag_;
- // Stores the current set of foreign session specifics.
- // Used by ForeignSessionHandler through |GetSessionData|.
- // Built by |QuerySyncModel| via |UpdateFromSyncModel|.
- std::vector<const sync_pb::SessionSpecifics*> specifics_;
+ // Pool of all used/available sync nodes associated with tabs.
+ TabNodePool tab_pool_;
+ // SyncID for the sync node containing all the window information for this
+ // client.
+ int64 local_session_syncid_;
+
+ // Mapping of current open (local) tabs to their sync identifiers.
+ TabLinksMap tab_map_;
+
+ ForeignSessionTracker foreign_session_tracker_;
+
// Weak pointer.
ProfileSyncService* sync_service_;
« no previous file with comments | « chrome/browser/sync/glue/session_change_processor.cc ('k') | chrome/browser/sync/glue/session_model_associator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698