session_model_associator.h revision ddb351dbec246cf1fab5ec20d2d5520909041de1
1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file. 4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#ifndef CHROME_BROWSER_SYNC_GLUE_SESSION_MODEL_ASSOCIATOR_H_ 6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#define CHROME_BROWSER_SYNC_GLUE_SESSION_MODEL_ASSOCIATOR_H_ 7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#pragma once 8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 93f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include <map> 10bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <string> 11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <vector> 12bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 13bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/basictypes.h" 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/format_macros.h" 15bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/gtest_prod_util.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_vector.h" 17bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/observer_list.h" 183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/string_util.h" 193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/non_thread_safe.h" 203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/utf_string_conversions.h" 213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/browser/sessions/session_id.h" 22bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/sessions/session_service.h" 23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/sessions/session_types.h" 24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/sync/engine/syncapi.h" 253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/browser/sync/glue/foreign_session_tracker.h" 26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/sync/glue/model_associator.h" 27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/sync/protocol/session_specifics.pb.h" 28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/sync/syncable/model_type.h" 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h" 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass Profile; 33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass ProfileSyncService; 34bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace sync_api { 36bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass ReadNode; 37bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass WriteNode; 38bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass WriteTransaction; 39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} // namespace sync_api 40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace sync_pb { 42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass SessionSpecifics; 43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} // namespace sync_pb 44bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 45bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace browser_sync { 46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstatic const char kSessionsTag[] = "google_chrome_sessions"; 48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Contains all logic for associating the Chrome sessions model and 50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// the sync sessions model. 513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenclass SessionModelAssociator 523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen : public PerDataTypeAssociatorInterface<TabContents, size_t>, 533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen public base::NonThreadSafe { 54bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen public: 55bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Does not take ownership of sync_service. 56bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen explicit SessionModelAssociator(ProfileSyncService* sync_service); 57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SessionModelAssociator(ProfileSyncService* sync_service, 58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool setup_for_test); 59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual ~SessionModelAssociator(); 60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // The has_nodes out parameter is set to true if the sync model has 623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // nodes other than the permanent tagged nodes. The method may 633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // return false if an error occurred. 643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes); 653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // AssociatorInterface and PerDataTypeAssociator Interface implementation. 67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual void AbortAssociation() { 683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // No implementation needed, this associator runs on the main thread. 69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // See ModelAssociator interface. 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual bool CryptoReadyIfNecessary(); 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Returns sync id for the given chrome model id. 753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Returns sync_api::kInvalidId if the sync node is not found for the given 763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // chrome id. 773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual int64 GetSyncIdFromChromeId(const size_t& id); 78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Returns sync id for the given session tag. 803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Returns sync_api::kInvalidId if the sync node is not found for the given 813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // tag 823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual int64 GetSyncIdFromSessionTag(const std::string& tag); 83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Not used. 8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual const TabContents* GetChromeNodeFromSyncId(int64 sync_id); 86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Not used. 8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual bool InitSyncNodeFromChromeId(const size_t& id, 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sync_api::BaseNode* sync_node); 90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Resync local window information. Updates the local sessions header node 923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // with the status of open windows and the order of tabs they contain. Should 933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // only be called for changes that affect a window, not a change within a 943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // single tab. 953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // 963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // If |reload_tabs| is true, will also resync all tabs (same as calling 973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // ReassociateTabs with a vector of all tabs). 983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void ReassociateWindows(bool reload_tabs); 993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Loads and reassociates the local tabs referenced in |tabs|. 1013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void ReassociateTabs(const std::vector<TabContents*>& tabs); 1023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Reassociates a single tab with the sync model. Will check if the tab 1043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // already is associated with a sync node and allocate one if necessary. 1053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void ReassociateTab(const TabContents& tab); 1063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Associate a local tab and it's sync node. Will overwrite the contents of 1083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // the sync node with new specifics built from the tab. 1093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void Associate(const TabContents* tab, int64 sync_id); 1103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Looks up the specified sync node, and marks that tab as closed, then marks 1123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // the node as free and deletes association. 1133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void Disassociate(int64 sync_id); 1143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Load any foreign session info stored in sync db and update the sync db 1163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // with local client data. Processes/reuses any sync nodes owned by this 1173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // client and creates any further sync nodes needed to store local header and 1183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // tab info. 1193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual bool AssociateModels(); 120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Initializes the given sync node from the given chrome node id. 122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Returns false if no sync node was found for the given chrome node id or 123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // if the initialization of sync node fails. 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual bool InitSyncNodeFromChromeId(const std::string& id, 12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen sync_api::BaseNode* sync_node); 126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 1273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Clear local sync data buffers. Does not delete sync nodes to avoid 1283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // tombstones. TODO(zea): way to eventually delete orphaned nodes. 1293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual bool DisassociateModels(); 130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Returns the tag used to uniquely identify this machine's session in the 132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // sync model. 1333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inline const std::string& GetCurrentMachineTag() { 1343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(!current_machine_tag_.empty()); 1353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return current_machine_tag_; 1363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 1383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Load and associate window and tab data for a foreign session 1393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool AssociateForeignSpecifics(const sync_pb::SessionSpecifics& specifics, 1403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int64 modification_time); 141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Removes a foreign session from our internal bookkeeping. 1433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void DisassociateForeignSession(const std::string& foreign_session_tag); 1443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Builds a list of all foreign sessions. 1463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Caller does NOT own ForeignSession objects. 1473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool GetAllForeignSessions(std::vector<const ForeignSession*>* sessions); 148bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 1493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Loads all windows for foreign session with session tag |tag|. 1503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Caller does NOT own ForeignSession objects. 1513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool GetForeignSession(const std::string& tag, 1523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen std::vector<SessionWindow*>* windows); 153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Looks up the foreign tab identified by |tab_id| and belonging to foreign 1553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // session |tag|. 1563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Caller does NOT own the SessionTab object. 1573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool GetForeignTab(const std::string& tag, 1583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const SessionID::id_type tab_id, 1593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const SessionTab** tab); 160bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 1613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Specifies whether the window has tabs to sync. The new tab page does not 1623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // count. If no tabs to sync, it returns true, otherwise false; 1633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static bool SessionWindowHasNoTabsToSync(const SessionWindow& window); 164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Control which local tabs we're interested in syncing. 1663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Ensures the profile matches sync's profile and that the tab has at least 1673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // one navigation entry and is not an empty tab. 1683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool IsValidTab(const TabContents& tab); 169bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 1703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Control which foreign tabs we're interested in displaying. 1713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Checks that the tab has navigations and is not a new tab. 1723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Note: a new tab page with back/forward history is valid. 1733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static bool IsValidSessionTab(const SessionTab& tab); 174bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 175bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Returns the syncable model type. 176bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen static syncable::ModelType model_type() { return syncable::SESSIONS; } 177bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 178bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen private: 179bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, WriteSessionToNode); 180bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, 1813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen WriteFilledSessionToNode); 1823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, 183bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen WriteForeignSessionToNode); 1843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, TabNodePoolEmpty); 1853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, TabNodePoolNonEmpty); 1863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen FRIEND_TEST_ALL_PREFIXES(SessionModelAssociatorTest, PopulateSessionWindow); 1873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen FRIEND_TEST_ALL_PREFIXES(SessionModelAssociatorTest, PopulateSessionTab); 1883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Keep all the links to local tab data in one place. 1903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen class TabLinks { 1913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen public: 1923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // To support usage as second value in maps we need default and copy 1933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // constructors. 1943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TabLinks() 1953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen : sync_id_(0), 1963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen session_tab_(NULL), 1973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen tab_(NULL) {} 1983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // We only ever have either a SessionTab (for foreign tabs), or a 2003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // TabContents (for local tabs). 2013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TabLinks(int64 sync_id, const TabContents* tab) 2023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen : sync_id_(sync_id), 2033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen session_tab_(NULL) { 2043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen tab_ = const_cast<TabContents*>(tab); 2053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 2063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TabLinks(int64 sync_id, const SessionTab* session_tab) 2073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen : sync_id_(sync_id), 2083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen tab_(NULL) { 2093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen session_tab_ = const_cast<SessionTab*>(session_tab); 2103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 2113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inline int64 sync_id() const { return sync_id_; } 2133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inline const SessionTab* session_tab() const { return session_tab_; } 2143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inline const TabContents* tab() const { return tab_; } 2153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen private: 2163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int64 sync_id_; 2173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen SessionTab* session_tab_; 2183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TabContents* tab_; 2193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen }; 2203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // A pool for managing free/used tab sync nodes. Performs lazy creation 2223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // of sync nodes when necessary. 2233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen class TabNodePool { 2243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen public: 2253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen explicit TabNodePool(ProfileSyncService* sync_service); 22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ~TabNodePool(); 2273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Add a previously allocated tab sync node to our pool. Increases the size 2293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // of tab_syncid_pool_ by one and marks the new tab node as free. 2303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Note: this should only be called when we discover tab sync nodes from 2313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // previous sessions, not for freeing tab nodes we created through 2323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // GetFreeTabNode (use FreeTabNode below for that). 2333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void AddTabNode(int64 sync_id); 2343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Returns the sync_id for the next free tab node. If none are available, 2363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // creates a new tab node. 2373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Note: We make use of the following "id's" 2383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // - a sync_id: an int64 used in |sync_api::InitByIdLookup| 2393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // - a tab_id: created by session service, unique to this client 2403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // - a tab_node_id: the id for a particular sync tab node. This is used 2413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // to generate the sync tab node tag through: 2423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // tab_tag = StringPrintf("%s_%ui", local_session_tag, tab_node_id); 2433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // tab_node_id and sync_id are both unique to a particular sync node. The 2443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // difference is that tab_node_id is controlled by the model associator and 2453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // is used when creating a new sync node, which returns the sync_id, created 2463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // by the sync db. 2473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int64 GetFreeTabNode(); 2483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Return a tab node to our free pool. 2503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Note: the difference between FreeTabNode and AddTabNode is that 2513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // FreeTabNode does not modify the size of |tab_syncid_pool_|, while 2523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // AddTabNode increases it by one. In the case of FreeTabNode, the size of 2533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // the |tab_syncid_pool_| should always be equal to the amount of tab nodes 2543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // associated with this machine. 2553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void FreeTabNode(int64 sync_id); 2563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Clear tab pool. 2583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inline void clear() { tab_syncid_pool_.clear(); } 2593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Return the number of tab nodes this client currently has allocated 2613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // (including both free and used nodes) 2623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inline size_t capacity() const { return tab_syncid_pool_.size(); } 2633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Return empty status (all tab nodes are in use). 2653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inline bool empty() const { return tab_pool_fp_ == -1; } 2663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Return full status (no tab nodes are in use). 2683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inline bool full() { 2693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return tab_pool_fp_ == static_cast<int64>(tab_syncid_pool_.size())-1; 2703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 2713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inline void set_machine_tag(const std::string& machine_tag) { 2733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen machine_tag_ = machine_tag; 2743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 2753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen private: 2763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Pool of all available syncid's for tab's we have created. 2773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen std::vector<int64> tab_syncid_pool_; 2783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Free pointer for tab pool. Only those node id's, up to and including the 2803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // one indexed by the free pointer, are valid and free. The rest of the 2813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // |tab_syncid_pool_| is invalid because the nodes are in use. 2823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // To get the next free node, use tab_syncid_pool_[tab_pool_fp_--]. 2833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int64 tab_pool_fp_; 2843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // The machiine tag associated with this tab pool. Used in the title of new 2863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // sync nodes. 2873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen std::string machine_tag_; 2883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Our sync service profile (for making changes to the sync db) 2903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ProfileSyncService* sync_service_; 2913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DISALLOW_COPY_AND_ASSIGN(TabNodePool); 2933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen }; 2943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Datatypes for accessing local tab data. 2963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen typedef std::map<SessionID::id_type, TabLinks> TabLinksMap; 2973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 2983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Delete all foreign session/window/tab objects allocated dynamically. 2993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // This is comprised of ForeignSession*, IDToSessionTabMap*, and any orphaned 3003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // SessionTab*'s. 3013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void DeleteForeignSessions(); 3023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Determine if a window is of a type we're interested in syncing. 3043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static bool ShouldSyncWindowType(const Browser::Type& type); 3053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Build a sync tag from tab_node_id. 3073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static inline std::string TabIdToTag( 3083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const std::string machine_tag, 3093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen size_t tab_node_id) { 310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return StringPrintf("%s %"PRIuS"", 311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen machine_tag.c_str(), tab_node_id); 3123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 313bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 314bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Initializes the tag corresponding to this machine. 3153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void InitializeCurrentMachineTag(sync_api::WriteTransaction* trans); 316bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 3173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Updates the server data based upon the current client session. If no node 3183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // corresponding to this machine exists in the sync model, one is created. 3193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void UpdateSyncModelDataFromClient(); 320bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 3213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Pulls the current sync model from the sync database and returns true upon 3223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // update of the client model. Will associate any foreign sessions as well as 3233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // keep track of any local tab nodes, adding them to our free tab node pool. 3243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool UpdateAssociationsFromSyncModel(const sync_api::ReadNode& root, 3253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const sync_api::BaseTransaction* trans); 326bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 3273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Fills a tab sync node with data from a TabContents object. 3283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // (from a local navigation event) 329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool WriteTabContentsToSyncModel(const Browser& browser, 330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const TabContents& tab, 3313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const int64 sync_id, 3323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen sync_api::WriteTransaction* trans); 3333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Used to populate a session window from the session specifics window 3353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // provided. Tracks any foreign session data created through |tracker|. 3363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static void PopulateSessionWindowFromSpecifics( 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& foreign_session_tag, 3383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const sync_pb::SessionWindow& window, 3393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const int64 mtime, 3403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen SessionWindow* session_window, 3413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ForeignSessionTracker* tracker); 3423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Used to populate a session tab from the session specifics tab provided. 3443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static void PopulateSessionTabFromSpecifics(const sync_pb::SessionTab& tab, 3453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const int64 mtime, 3463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen SessionTab* session_tab); 347bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 3483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Used to populate a session tab from the session specifics tab provided. 3493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static void AppendSessionTabNavigation( 3503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const sync_pb::TabNavigation& navigation, 3513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen std::vector<TabNavigation>* navigations); 3523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Populates the navigation portion of the session specifics. 3543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static void PopulateSessionSpecificsNavigation( 3553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const TabNavigation* navigation, 3563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen sync_pb::TabNavigation* tab_navigation); 3573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Returns the session service from |sync_service_|. 3593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen SessionService* GetSessionService(); 360bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 361bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Internal method used in the callback to obtain the current session. 362bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // We don't own |windows|. 363bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen void OnGotSession(int handle, std::vector<SessionWindow*>* windows); 364bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 3653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Populate a session specifics header from a list of SessionWindows 3663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void PopulateSessionSpecificsHeader( 3673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const std::vector<SessionWindow*>& windows, 3683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen sync_pb::SessionHeader* header_s); 369bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 3703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Populates the window portion of the session specifics. 3713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void PopulateSessionSpecificsWindow(const SessionWindow& window, 3723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen sync_pb::SessionWindow* session_window); 373bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 3743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Syncs all the tabs in |window| with the local sync db. Will allocate tab 3753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // nodes if needed. 3763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool SyncLocalWindowToSyncModel(const SessionWindow& window); 3773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Fills a tab sync node with data from a SessionTab object. 3793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // (from ReadCurrentSessions) 3803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool WriteSessionTabToSyncModel(const SessionTab& tab, 3813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const int64 sync_id, 3823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen sync_api::WriteTransaction* trans); 3833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Populates the tab portion of the session specifics. 3853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void PopulateSessionSpecificsTab(const SessionTab& tab, 3863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen sync_pb::SessionTab* session_tab); 3873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Local client name. 389bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen std::string current_machine_tag_; 390bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 3913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Pool of all used/available sync nodes associated with tabs. 3923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TabNodePool tab_pool_; 3933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // SyncID for the sync node containing all the window information for this 3953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // client. 3963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int64 local_session_syncid_; 3973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 3983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Mapping of current open (local) tabs to their sync identifiers. 3993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TabLinksMap tab_map_; 4003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 4013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ForeignSessionTracker foreign_session_tracker_; 402731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 403bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Weak pointer. 404bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ProfileSyncService* sync_service_; 405bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 406bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Consumer used to obtain the current session. 407bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen CancelableRequestConsumer consumer_; 408bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 409dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // To avoid certain checks not applicable to tests. 410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool setup_for_test_; 411dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 412bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DISALLOW_COPY_AND_ASSIGN(SessionModelAssociator); 413bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}; 414bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 415bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} // namespace browser_sync 416bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 417bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif // CHROME_BROWSER_SYNC_GLUE_SESSION_MODEL_ASSOCIATOR_H_ 418