Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / sync / glue / session_model_associator.h
blobfceb6bd387c73592adcdee2f9a5e71784c919706
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.
5 #ifndef CHROME_BROWSER_SYNC_GLUE_SESSION_MODEL_ASSOCIATOR_H_
6 #define CHROME_BROWSER_SYNC_GLUE_SESSION_MODEL_ASSOCIATOR_H_
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <vector>
13 #include "base/basictypes.h"
14 #include "base/compiler_specific.h"
15 #include "base/gtest_prod_util.h"
16 #include "base/memory/linked_ptr.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/threading/non_thread_safe.h"
19 #include "base/time/time.h"
20 #include "chrome/browser/sessions/session_id.h"
21 #include "chrome/browser/sessions/session_service.h"
22 #include "chrome/browser/sessions/session_types.h"
23 #include "chrome/browser/sync/glue/favicon_cache.h"
24 #include "chrome/browser/sync/glue/model_associator.h"
25 #include "chrome/browser/sync/glue/synced_session_tracker.h"
26 #include "chrome/browser/sync/glue/tab_node_pool.h"
27 #include "chrome/browser/sync/open_tabs_ui_delegate.h"
28 #include "sync/internal_api/public/base/model_type.h"
30 class PrefServiceSyncable;
31 class Profile;
32 class ProfileSyncService;
34 namespace syncer {
35 class ReadNode;
36 class WriteTransaction;
37 } // namespace syncer
39 namespace sync_pb {
40 class SessionHeader;
41 class SessionSpecifics;
42 class SessionTab;
43 class SessionWindow;
44 class TabNavigation;
45 } // namespace sync_pb
47 namespace browser_sync {
49 class DataTypeErrorHandler;
50 class DeviceInfo;
51 class SyncedTabDelegate;
52 class SyncedWindowDelegate;
54 // Contains all logic for associating the Chrome sessions model and
55 // the sync sessions model.
56 class SessionModelAssociator
57 : public AssociatorInterface,
58 public OpenTabsUIDelegate,
59 public base::SupportsWeakPtr<SessionModelAssociator>,
60 public base::NonThreadSafe {
61 public:
62 // Does not take ownership of sync_service.
63 SessionModelAssociator(ProfileSyncService* sync_service,
64 DataTypeErrorHandler* error_handler);
65 SessionModelAssociator(ProfileSyncService* sync_service,
66 bool setup_for_test);
67 virtual ~SessionModelAssociator();
69 // The has_nodes out parameter is set to true if the sync model has
70 // nodes other than the permanent tagged nodes. The method may
71 // return false if an error occurred.
72 virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes) OVERRIDE;
74 // AssociatorInterface implementation.
75 virtual void AbortAssociation() OVERRIDE {
76 // No implementation needed, this associator runs on the main thread.
79 // See ModelAssociator interface.
80 virtual bool CryptoReadyIfNecessary() OVERRIDE;
82 // Returns sync id for the given session tag.
83 // Returns syncer::kInvalidId if the sync node is not found for the given
84 // tag
85 virtual int64 GetSyncIdFromSessionTag(const std::string& tag);
87 // Resync local window information. Updates the local sessions header node
88 // with the status of open windows and the order of tabs they contain. Should
89 // only be called for changes that affect a window, not a change within a
90 // single tab.
92 // If |reload_tabs| is true, will also resync all tabs (same as calling
93 // AssociateTabs with a vector of all tabs).
94 // |error| gets set if any association error occurred.
95 // Returns: false if the local session's sync nodes were deleted and
96 // reassociation is necessary, true otherwise.
97 bool AssociateWindows(bool reload_tabs, syncer::SyncError* error);
99 // Loads and reassociates the local tabs referenced in |tabs|.
100 // |error| gets set if any association error occurred.
101 // Returns: false if the local session's sync nodes were deleted and
102 // reassociation is necessary, true otherwise.
103 bool AssociateTabs(const std::vector<SyncedTabDelegate*>& tabs,
104 syncer::SyncError* error);
106 // Reassociates a single tab with the sync model. Will check if the tab
107 // already is associated with a sync node and allocate one if necessary.
108 // |error| gets set if any association error occurred.
109 // |tab| will be updated with sync id if necessary.
110 // Returns: false if the local session's sync nodes were deleted and
111 // reassociation is necessary, true otherwise.
112 bool AssociateTab(SyncedTabDelegate* const tab, syncer::SyncError* error);
114 // Load any foreign session info stored in sync db and update the sync db
115 // with local client data. Processes/reuses any sync nodes owned by this
116 // client and creates any further sync nodes needed to store local header and
117 // tab info.
118 virtual syncer::SyncError AssociateModels(
119 syncer::SyncMergeResult* local_merge_result,
120 syncer::SyncMergeResult* syncer_merge_result) OVERRIDE;
122 // Clear local sync data buffers. Does not delete sync nodes to avoid
123 // tombstones. TODO(zea): way to eventually delete orphaned nodes.
124 virtual syncer::SyncError DisassociateModels() OVERRIDE;
126 // Returns the tag used to uniquely identify this machine's session in the
127 // sync model.
128 const std::string& GetCurrentMachineTag() const {
129 DCHECK(!current_machine_tag_.empty());
130 return current_machine_tag_;
133 // Load and associate window and tab data for a foreign session.
134 void AssociateForeignSpecifics(const sync_pb::SessionSpecifics& specifics,
135 const base::Time& modification_time);
137 // Removes a foreign session from our internal bookkeeping.
138 // Returns true if the session was found and deleted, false if no data was
139 // found for that session.
140 bool DisassociateForeignSession(const std::string& foreign_session_tag);
142 // Attempts to asynchronously refresh the sessions sync data. If new data is
143 // received, the FOREIGN_SESSIONS_UPDATED notification is sent. No
144 // notification will be sent otherwise. This method is not guaranteed to
145 // trigger a sync cycle.
146 void AttemptSessionsDataRefresh() const;
148 // Triggers garbage collection of stale sessions (as defined by
149 // |stale_session_threshold_days_|). This is called automatically every
150 // time we start up (via AssociateModels).
151 void DeleteStaleSessions();
153 // Set the threshold of inactivity (in days) at which we consider sessions
154 // stale.
155 void SetStaleSessionThreshold(size_t stale_session_threshold_days);
157 // Control which local tabs we're interested in syncing.
158 // Ensures the profile matches sync's profile and that the tab has valid
159 // entries.
160 bool ShouldSyncTab(const SyncedTabDelegate& tab) const;
162 // Compare |urls| against |local_tab_map_|'s urls to see if any tabs with
163 // outstanding favicon loads can be fulfilled.
164 void FaviconsUpdated(const std::set<GURL>& urls);
166 // Returns the syncable model type.
167 static syncer::ModelType model_type() { return syncer::SESSIONS; }
169 // Testing only. Will cause the associator to call MessageLoop::Quit()
170 // when a local change is made, or when timeout occurs, whichever is
171 // first.
172 void BlockUntilLocalChangeForTest(base::TimeDelta timeout);
174 // OpenTabsUIDelegate implementation.
175 virtual bool GetSyncedFaviconForPageURL(
176 const std::string& pageurl,
177 scoped_refptr<base::RefCountedMemory>* favicon_png) const OVERRIDE;
178 virtual bool GetAllForeignSessions(
179 std::vector<const SyncedSession*>* sessions) OVERRIDE;
180 virtual bool GetForeignSession(
181 const std::string& tag,
182 std::vector<const SessionWindow*>* windows) OVERRIDE;
183 virtual bool GetForeignTab(const std::string& tag,
184 const SessionID::id_type tab_id,
185 const SessionTab** tab) OVERRIDE;
186 virtual void DeleteForeignSession(const std::string& tag) OVERRIDE;
187 virtual bool GetLocalSession(const SyncedSession* * local_session) OVERRIDE;
189 void SetCurrentMachineTagForTesting(const std::string& machine_tag) {
190 current_machine_tag_ = machine_tag;
193 // Gets the device info for a given session tag.
194 scoped_ptr<browser_sync::DeviceInfo> GetDeviceInfoForSessionTag(
195 const std::string& session_tag);
197 FaviconCache* GetFaviconCache();
199 private:
200 friend class SyncSessionModelAssociatorTest;
201 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, WriteSessionToNode);
202 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
203 WriteFilledSessionToNode);
204 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
205 WriteForeignSessionToNode);
206 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, TabNodePoolEmpty);
207 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, TabNodePoolNonEmpty);
208 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, ValidTabs);
209 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, ExistingTabs);
210 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, MissingLocalTabNode);
211 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
212 TabPoolFreeNodeLimits);
213 FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
214 TabNodePoolDeleteUnassociatedNodes);
215 FRIEND_TEST_ALL_PREFIXES(SyncSessionModelAssociatorTest,
216 PopulateSessionHeader);
217 FRIEND_TEST_ALL_PREFIXES(SyncSessionModelAssociatorTest,
218 PopulateSessionWindow);
219 FRIEND_TEST_ALL_PREFIXES(SyncSessionModelAssociatorTest, PopulateSessionTab);
220 FRIEND_TEST_ALL_PREFIXES(SyncSessionModelAssociatorTest,
221 TabNodePool);
223 // Keep all the links to local tab data in one place. A tab_node_id and tab
224 // must be passed at creation. The tab_node_id is not mutable after, although
225 // all other fields are.
226 class TabLink {
227 public:
228 TabLink(int tab_node_id, const SyncedTabDelegate* tab)
229 : tab_node_id_(tab_node_id),
230 tab_(tab) {}
232 void set_tab(const SyncedTabDelegate* tab) { tab_ = tab; }
233 void set_url(const GURL& url) { url_ = url; }
235 int tab_node_id() const { return tab_node_id_; }
236 const SyncedTabDelegate* tab() const { return tab_; }
237 const GURL& url() const { return url_; }
239 private:
240 DISALLOW_COPY_AND_ASSIGN(TabLink);
242 // The id for the sync node this tab is stored in.
243 const int tab_node_id_;
245 // The tab object itself.
246 const SyncedTabDelegate* tab_;
248 // The currently visible url of the tab (used for syncing favicons).
249 GURL url_;
252 // Container for accessing local tab data by tab id.
253 typedef std::map<SessionID::id_type, linked_ptr<TabLink> > TabLinksMap;
255 // Determine if a window is of a type we're interested in syncing.
256 static bool ShouldSyncWindow(const SyncedWindowDelegate* window);
258 // Initializes the tag corresponding to this machine.
259 void InitializeCurrentMachineTag(syncer::WriteTransaction* trans);
261 // Updates the server data based upon the current client session. If no node
262 // corresponding to this machine exists in the sync model, one is created.
263 // Returns true on success, false if association failed.
264 bool UpdateSyncModelDataFromClient(syncer::SyncError* error);
266 // Pulls the current sync model from the sync database and returns true upon
267 // update of the client model. Will associate any foreign sessions as well as
268 // keep track of any local tab nodes, adding them to our free tab node pool.
269 bool UpdateAssociationsFromSyncModel(const syncer::ReadNode& root,
270 syncer::WriteTransaction* trans,
271 syncer::SyncError* error);
273 // Return the virtual URL of the current tab, even if it's pending.
274 static GURL GetCurrentVirtualURL(const SyncedTabDelegate& tab_delegate);
276 // Return the favicon url of the current tab, even if it's pending.
277 static GURL GetCurrentFaviconURL(const SyncedTabDelegate& tab_delegate);
279 // Fills a tab sync node with data from a WebContents object. Updates
280 // |tab_link| with the current url if it's valid and triggers a favicon
281 // load if the url has changed.
282 // Returns true on success, false if we need to reassociate due to corruption.
283 bool WriteTabContentsToSyncModel(TabLink* tab_link,
284 syncer::SyncError* error);
286 // Set |session_tab| from |tab_delegate| and |mtime|.
287 static void SetSessionTabFromDelegate(
288 const SyncedTabDelegate& tab_delegate,
289 base::Time mtime,
290 SessionTab* session_tab);
292 // Used to populate a session header from the session specifics header
293 // provided.
294 static void PopulateSessionHeaderFromSpecifics(
295 const sync_pb::SessionHeader& header_specifics,
296 base::Time mtime,
297 SyncedSession* session_header);
299 // Used to populate a session window from the session specifics window
300 // provided. Tracks any foreign session data created through |tracker|.
301 static void PopulateSessionWindowFromSpecifics(
302 const std::string& foreign_session_tag,
303 const sync_pb::SessionWindow& window,
304 base::Time mtime,
305 SessionWindow* session_window,
306 SyncedSessionTracker* tracker);
308 // Helper method to load the favicon data from the tab specifics. If the
309 // favicon is valid, stores the favicon data into the favicon cache.
310 void LoadForeignTabFavicon(const sync_pb::SessionTab& tab);
312 // Returns true if this tab belongs to this profile and belongs to a window,
313 // false otherwise.
314 bool IsValidTab(const SyncedTabDelegate& tab) const;
316 // Having a valid entry is defined as the url being valid and and having a
317 // syncable scheme (non chrome:// and file:// url's). In other words, we don't
318 // want to sync a tab that is nothing but chrome:// and file:// navigations or
319 // invalid url's.
320 bool TabHasValidEntry(const SyncedTabDelegate& tab) const;
322 // Update the tab id of the node associated with |tab_node_id| to
323 // |new_tab_id|.
324 void UpdateTabIdIfNecessary(int tab_node_id,
325 SessionID::id_type new_tab_id);
327 // For testing only.
328 void QuitLoopForSubtleTesting();
330 // Unique client tag.
331 std::string current_machine_tag_;
333 // User-visible machine name.
334 std::string current_session_name_;
336 // Pool of all used/available sync nodes associated with local tabs.
337 TabNodePool local_tab_pool_;
339 // SyncID for the sync node containing all the window information for this
340 // client.
341 int64 local_session_syncid_;
343 // Mapping of current open (local) tabs to their sync identifiers.
344 TabLinksMap local_tab_map_;
346 SyncedSessionTracker synced_session_tracker_;
348 // Weak pointer.
349 ProfileSyncService* sync_service_;
351 // Number of days without activity after which we consider a session to be
352 // stale and a candidate for garbage collection.
353 size_t stale_session_threshold_days_;
355 // To avoid certain checks not applicable to tests.
356 bool setup_for_test_;
358 // During integration tests, we sometimes need to block until a local change
359 // is made.
360 bool waiting_for_change_;
362 // Profile being synced. Weak pointer.
363 Profile* const profile_;
365 DataTypeErrorHandler* error_handler_;
367 // Our favicon cache.
368 FaviconCache favicon_cache_;
370 base::WeakPtrFactory<SessionModelAssociator> test_weak_factory_;
372 DISALLOW_COPY_AND_ASSIGN(SessionModelAssociator);
375 } // namespace browser_sync
377 #endif // CHROME_BROWSER_SYNC_GLUE_SESSION_MODEL_ASSOCIATOR_H_