- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / sessions2 / sessions_sync_manager.h
1 // Copyright 2013 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_SESSIONS2_SESSIONS_SYNC_MANAGER_H_
6 #define CHROME_BROWSER_SYNC_SESSIONS2_SESSIONS_SYNC_MANAGER_H_
7
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <vector>
12
13 #include "base/basictypes.h"
14 #include "base/gtest_prod_util.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/time/time.h"
17 #include "chrome/browser/sessions/session_id.h"
18 #include "chrome/browser/sessions/session_types.h"
19 #include "chrome/browser/sync/glue/device_info.h"
20 #include "chrome/browser/sync/glue/favicon_cache.h"
21 #include "chrome/browser/sync/glue/synced_session.h"
22 #include "chrome/browser/sync/glue/synced_session_tracker.h"
23 #include "chrome/browser/sync/sessions2/tab_node_pool2.h"
24 #include "chrome/browser/sync/sync_prefs.h"
25 #include "sync/api/syncable_service.h"
26
27 class Profile;
28
29 namespace syncer {
30 class SyncErrorFactory;
31 }
32
33 namespace sync_pb {
34 class SessionHeader;
35 class SessionSpecifics;
36 class SessionTab;
37 class SessionWindow;
38 class TabNavigation;
39 }  // namespace sync_pb
40
41 namespace browser_sync {
42
43 class DataTypeErrorHandler;
44 class SyncedTabDelegate;
45 class SyncedWindowDelegate;
46
47 // Contains all logic for associating the Chrome sessions model and
48 // the sync sessions model.
49 class SessionsSyncManager : public syncer::SyncableService {
50  public:
51   // Isolates SessionsSyncManager from having to depend on sync internals.
52   class SyncInternalApiDelegate {
53    public:
54     // Returns sync's representation of the local device info.
55     // Return value is an empty scoped_ptr if the device info is unavailable.
56     virtual scoped_ptr<DeviceInfo> GetLocalDeviceInfo() const = 0;
57
58     // Used for creation of the machine tag for this local session.
59     virtual std::string GetCacheGuid() const = 0;
60   };
61
62   SessionsSyncManager(Profile* profile,
63                       scoped_ptr<SyncPrefs> sync_prefs,
64                       SyncInternalApiDelegate* delegate);
65   virtual ~SessionsSyncManager();
66
67   // A local navigation event took place that affects the synced session
68   // for this instance of Chrome.
69   void OnLocalTabModified(const SyncedTabDelegate& modified_tab,
70                           syncer::SyncError* error);
71
72   // When a Browser window is opened, we want to know so we can make sure our
73   // bookkeeping of open windows / sessions on this device is up-to-date.
74   void OnBrowserOpened();
75
76   // A local navigation occurred that triggered updates to favicon data for
77   // each URL in |updated_page_urls|.  This is routed through Sessions Sync so
78   // that we can filter (exclude) favicon updates for pages that aren't
79   // currently part of the set of local open tabs, and pass relevant updates
80   // on to FaviconCache for out-of-band favicon syncing.
81   void ForwardRelevantFaviconUpdatesToFaviconCache(
82       const std::set<GURL>& updated_favicon_page_urls);
83
84   // Returns the tag used to uniquely identify this machine's session in the
85   // sync model.
86   const std::string& current_machine_tag() const {
87     DCHECK(!current_machine_tag_.empty());
88     return current_machine_tag_;
89   }
90
91   // Builds a list of all foreign sessions. Caller does NOT own SyncedSession
92   // objects.
93   // Returns true if foreign sessions were found, false otherwise.
94   bool GetAllForeignSessions(std::vector<const SyncedSession*>* sessions);
95
96   // If a valid favicon for the page at |url| is found, fills |favicon_png| with
97   // the png-encoded image and returns true. Else, returns false.
98   bool GetSyncedFaviconForPageURL(
99       const std::string& page_url,
100       scoped_refptr<base::RefCountedMemory>* favicon_png) const;
101
102   // syncer::SyncableService implementation.
103   virtual syncer::SyncMergeResult MergeDataAndStartSyncing(
104       syncer::ModelType type,
105       const syncer::SyncDataList& initial_sync_data,
106       scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
107       scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE;
108   virtual void StopSyncing(syncer::ModelType type) OVERRIDE;
109   virtual syncer::SyncDataList GetAllSyncData(
110       syncer::ModelType type) const OVERRIDE;
111   virtual syncer::SyncError ProcessSyncChanges(
112       const tracked_objects::Location& from_here,
113       const syncer::SyncChangeList& change_list) OVERRIDE;
114
115   // Return the virtual URL of the current tab, even if it's pending.
116   static GURL GetCurrentVirtualURL(const SyncedTabDelegate& tab_delegate);
117
118   // Return the favicon url of the current tab, even if it's pending.
119   static GURL GetCurrentFaviconURL(const SyncedTabDelegate& tab_delegate);
120
121  private:
122   // Keep all the links to local tab data in one place. A tab_node_id and tab
123   // must be passed at creation. The tab_node_id is not mutable, although
124   // all other fields are.
125   class TabLink {
126    public:
127     TabLink(int tab_node_id, const SyncedTabDelegate* tab)
128       : tab_node_id_(tab_node_id),
129         tab_(tab) {}
130
131     void set_tab(const SyncedTabDelegate* tab) { tab_ = tab; }
132     void set_url(const GURL& url) { url_ = url; }
133
134     int tab_node_id() const { return tab_node_id_; }
135     const SyncedTabDelegate* tab() const { return tab_; }
136     const GURL& url() const { return url_; }
137
138    private:
139     // The id for the sync node this tab is stored in.
140     const int tab_node_id_;
141
142     // The tab object itself.
143     const SyncedTabDelegate* tab_;
144
145     // The currently visible url of the tab (used for syncing favicons).
146     GURL url_;
147
148     DISALLOW_COPY_AND_ASSIGN(TabLink);
149   };
150
151   // Container for accessing local tab data by tab id.
152   typedef std::map<SessionID::id_type, linked_ptr<TabLink> > TabLinksMap;
153
154   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, PopulateSessionHeader);
155   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, PopulateSessionWindow);
156   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, ValidTabs);
157   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, SetSessionTabFromDelegate);
158   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, BlockedNavigations);
159   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, DeleteForeignSession);
160   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
161                            SaveUnassociatedNodesForReassociation);
162   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, MergeDeletesCorruptNode);
163   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
164                            MergeLocalSessionExistingTabs);
165   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
166                            CheckPrerenderedWebContentsSwap);
167   FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
168                            AssociateWindowsDontReloadTabs);
169
170   void InitializeCurrentMachineTag();
171
172   // Load and add window or tab data for a foreign session to our internal
173   // tracking.
174   void UpdateTrackerWithForeignSession(
175       const sync_pb::SessionSpecifics& specifics,
176       const base::Time& modification_time);
177
178   // Returns true if |sync_data| contained a header node for the current
179   // machine, false otherwise.
180   bool InitFromSyncModel(const syncer::SyncDataList& sync_data,
181                          syncer::SyncChangeList* new_changes);
182
183   // Helper to construct a deletion SyncChange for a *tab node*.
184   // Caller should check IsValid() on the returned change, as it's possible
185   // this node could not be deleted.
186   syncer::SyncChange TombstoneTab(const sync_pb::SessionSpecifics& tab);
187
188   // Helper method to load the favicon data from the tab specifics. If the
189   // favicon is valid, stores the favicon data into the favicon cache.
190   void RefreshFaviconVisitTimesFromForeignTab(
191       const sync_pb::SessionTab& tab, const base::Time& modification_time);
192
193   // Removes a foreign session from our internal bookkeeping.
194   // Returns true if the session was found and deleted, false if no data was
195   // found for that session.  This will *NOT* trigger sync deletions. See
196   // DeleteForeignSession below.
197   bool DisassociateForeignSession(const std::string& foreign_session_tag);
198
199   // Delete a foreign session and all its sync data.
200   // |change_output| *must* be provided as a link to the SyncChange pipeline
201   // that exists in the caller's context. This function will append necessary
202   // changes for processing later.
203   void DeleteForeignSession(const std::string& tag,
204                             syncer::SyncChangeList* change_output);
205
206   // Used to populate a session header from the session specifics header
207   // provided.
208   static void PopulateSessionHeaderFromSpecifics(
209       const sync_pb::SessionHeader& header_specifics,
210       base::Time mtime,
211       SyncedSession* session_header);
212
213   // Builds |session_window| from the session specifics window
214   // provided and updates the SessionTracker with foreign session data created.
215   void BuildSyncedSessionFromSpecifics(
216       const std::string& session_tag,
217       const sync_pb::SessionWindow& specifics,
218       base::Time mtime,
219       SessionWindow* session_window);
220
221   // Resync local window information. Updates the local sessions header node
222   // with the status of open windows and the order of tabs they contain. Should
223   // only be called for changes that affect a window, not a change within a
224   // single tab.
225   //
226   // RELOAD_TABS will additionally cause a resync of all tabs (same as calling
227   // AssociateTabs with a vector of all tabs).
228   //
229   // Returns: false if the local session's sync nodes were deleted and
230   // reassociation is necessary, true otherwise.
231   //
232   // |change_output| *must* be provided as a link to the SyncChange pipeline
233   // that exists in the caller's context. This function will append necessary
234   // changes for processing later.
235   enum ReloadTabsOption {
236     RELOAD_TABS,
237     DONT_RELOAD_TABS
238   };
239   void AssociateWindows(ReloadTabsOption option,
240                         syncer::SyncChangeList* change_output);
241
242   // Loads and reassociates the local tabs referenced in |tabs|.
243   // |change_output| *must* be provided as a link to the SyncChange pipeline
244   // that exists in the caller's context. This function will append necessary
245   // changes for processing later.
246   void AssociateTab(SyncedTabDelegate* const tab,
247                     syncer::SyncChangeList* change_output);
248
249   // Control which local tabs we're interested in syncing.
250   // Ensures the profile matches sync's profile and that the tab has valid
251   // entries.
252   bool ShouldSyncTab(const SyncedTabDelegate& tab) const;
253   static bool ShouldSyncWindow(const SyncedWindowDelegate* window);
254
255   // Set |session_tab| from |tab_delegate| and |mtime|.
256   static void SetSessionTabFromDelegate(
257       const SyncedTabDelegate& tab_delegate,
258       base::Time mtime,
259       SessionTab* session_tab);
260
261   // Populates |specifics| based on the data in |tab_delegate|.
262   void LocalTabDelegateToSpecifics(const SyncedTabDelegate& tab_delegate,
263                                    sync_pb::SessionSpecifics* specifics);
264
265   // It's possible that when we associate windows, tabs aren't all loaded
266   // into memory yet (e.g on android) and we don't have a WebContents. In this
267   // case we can't do a full association, but we still want to update tab IDs
268   // as they may have changed after a session was restored.  This method
269   // compares new_tab_id against the previously persisted tab ID (from
270   // our TabNodePool) and updates it if it differs.
271   // TODO(tim): Bug 98892. We should be able to test this for this on android
272   // even though we didn't have tests for old API-based sessions sync.
273   void UpdateTabIdIfNecessary(const SyncedTabDelegate& tab_delegate,
274                               SessionID::id_type new_tab_id,
275                               syncer::SyncChangeList* change_output);
276
277   // Mapping of current open (local) tabs to their sync identifiers.
278   TabLinksMap local_tab_map_;
279
280   SyncedSessionTracker session_tracker_;
281   FaviconCache favicon_cache_;
282
283   // Pool of used/available sync nodes associated with local tabs.
284   TabNodePool2 local_tab_pool_;
285
286   scoped_ptr<SyncPrefs> sync_prefs_;
287
288   const Profile* const profile_;
289
290   scoped_ptr<syncer::SyncErrorFactory> error_handler_;
291   scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
292
293   const SyncInternalApiDelegate* const delegate_;
294
295   // Unique client tag.
296   std::string current_machine_tag_;
297
298   // User-visible machine name.
299   std::string current_session_name_;
300
301   // SyncID for the sync node containing all the window information for this
302   // client.
303   int local_session_header_node_id_;
304
305   DISALLOW_COPY_AND_ASSIGN(SessionsSyncManager);
306 };
307
308 }  // namespace browser_sync
309
310 #endif  // CHROME_BROWSER_SYNC_SESSIONS2_SESSIONS_SYNC_MANAGER_H_