blob: 106104f978a20e2556d80d1b05a69a522081c419 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/sessions/core/session_id.h"
#include "components/sessions/core/session_types.h"
#include "components/sync/base/sync_prefs.h"
#include "components/sync/device_info/device_info.h"
#include "components/sync/model/syncable_service.h"
#include "components/sync_sessions/abstract_sessions_sync_manager.h"
#include "components/sync_sessions/favicon_cache.h"
#include "components/sync_sessions/local_session_event_handler_impl.h"
#include "components/sync_sessions/lost_navigations_recorder.h"
#include "components/sync_sessions/open_tabs_ui_delegate_impl.h"
#include "components/sync_sessions/sessions_global_id_mapper.h"
#include "components/sync_sessions/synced_session.h"
#include "components/sync_sessions/synced_session_tracker.h"
namespace syncer {
class LocalDeviceInfoProvider;
class SyncErrorFactory;
} // namespace syncer
namespace sync_pb {
class SessionSpecifics;
class SessionTab;
} // namespace sync_pb
namespace extensions {
class ExtensionSessionsTest;
} // namespace extensions
namespace sync_sessions {
// Contains all logic for associating the Chrome sessions model and
// the sync sessions model.
class SessionsSyncManager : public AbstractSessionsSyncManager,
public syncer::SyncableService,
public LocalSessionEventHandlerImpl::Delegate {
SessionsSyncManager(SyncSessionsClient* sessions_client,
syncer::SessionSyncPrefs* sync_prefs,
syncer::LocalDeviceInfoProvider* local_device,
const base::RepeatingClosure& sessions_updated_callback);
~SessionsSyncManager() override;
// AbstractSessionsSyncManager implementation.
void ScheduleGarbageCollection() override;
FaviconCache* GetFaviconCache() override;
SessionsGlobalIdMapper* GetGlobalIdMapper() override;
OpenTabsUIDelegate* GetOpenTabsUIDelegate() override;
void OnSessionRestoreComplete() override;
syncer::SyncableService* GetSyncableService() override;
syncer::ModelTypeSyncBridge* GetModelTypeSyncBridge() override;
// syncer::SyncableService implementation.
syncer::SyncMergeResult MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
std::unique_ptr<syncer::SyncErrorFactory> error_handler) override;
void StopSyncing(syncer::ModelType type) override;
syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
syncer::SyncError ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
// LocalSessionEventHandlerImpl::Delegate implementation.
CreateLocalSessionWriteBatch() override;
void TrackLocalNavigationId(base::Time timestamp, int unique_id) override;
void OnPageFaviconUpdated(const GURL& page_url) override;
void OnFaviconVisited(const GURL& page_url, const GURL& favicon_url) override;
// Returns the tag used to uniquely identify this machine's session in the
// sync model.
const std::string& current_machine_tag() const {
return current_machine_tag_;
const std::string GetCurrentSessionNameForTest() const {
return current_session_name_;
// Triggers garbage collection of stale sessions (as defined by
// |stale_session_threshold_days_|). This is called every time we see new
// sessions data downloaded (sync cycles complete).
void DoGarbageCollection();
friend class extensions::ExtensionSessionsTest;
friend class SessionsSyncManagerTest;
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, BlockedNavigations);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, DeleteForeignSession);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, MergeDeletesBadHash);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, SwappedOutOnRestore);
void InitializeCurrentMachineTag(const std::string& cache_guid);
// Returns true if |sync_data| contained a header node for the current
// machine, false otherwise. |new_changes| is a link to the SyncChange
// pipeline that exists in the caller's context. This function will append
// necessary changes for processing later.
bool InitFromSyncModel(const syncer::SyncDataList& sync_data,
syncer::SyncChangeList* new_changes);
// Helper to construct a deletion SyncChange for a *tab node*.
// Caller should check IsValid() on the returned change, as it's possible
// this node could not be deleted.
syncer::SyncChange TombstoneTab(const sync_pb::SessionSpecifics& tab);
// Removes a foreign session from our internal bookkeeping.
// Returns true if the session was found and deleted, false if no data was
// found for that session. This will *NOT* trigger sync deletions. See
// DeleteForeignSession below.
bool DisassociateForeignSession(const std::string& foreign_session_tag);
// Delete a foreign session and all its sync data.
// |change_output| *must* be provided as a link to the SyncChange pipeline
// that exists in the caller's context. This function will append necessary
// changes for processing later.
void DeleteForeignSessionInternal(const std::string& tag,
syncer::SyncChangeList* change_output);
// Same as above but it also notifies the processor.
void DeleteForeignSessionFromUI(const std::string& tag);
// Stops and re-starts syncing to rebuild association mappings. Returns true
// when re-starting succeeds.
// See |local_tab_pool_out_of_sync_|.
bool RebuildAssociations();
// Calculates the tag hash from a specifics object. Calculating the hash is
// something we typically want to avoid doing in the model type like this.
// However, the only place that understands how to generate a tag from the
// specifics is the model type, ie us. We need to generate the tag because it
// is not passed over the wire for remote data. The use case this function was
// created for is detecting bad tag hashes from remote data, see
static std::string TagHashFromSpecifics(
const sync_pb::SessionSpecifics& specifics);
void ProcessLocalSessionSyncChanges(
const syncer::SyncChangeList& change_list);
// The client of this sync sessions datatype.
SyncSessionsClient* const sessions_client_;
SyncedSessionTracker session_tracker_;
SessionsGlobalIdMapper global_id_mapper_;
FaviconCache favicon_cache_;
OpenTabsUIDelegateImpl open_tabs_ui_delegate_;
// Instantiated when sync is enabled.
std::unique_ptr<LocalSessionEventHandlerImpl> local_session_event_handler_;
// Tracks whether our local representation of which sync nodes map to what
// tabs (belonging to the current local session) is inconsistent. This can
// happen if a foreign client deems our session as "stale" and decides to
// delete it. Rather than respond by bullishly re-creating our nodes
// immediately, which could lead to ping-pong sequences, we give the benefit
// of the doubt and hold off until another local navigation occurs, which
// proves that we are still relevant.
bool local_tab_pool_out_of_sync_;
syncer::SessionSyncPrefs* sync_prefs_;
std::unique_ptr<syncer::SyncErrorFactory> error_handler_;
std::unique_ptr<syncer::SyncChangeProcessor> sync_processor_;
// Local device info provider, owned by ProfileSyncService.
const syncer::LocalDeviceInfoProvider* const local_device_;
// Unique client tag.
std::string current_machine_tag_;
// User-visible machine name to populate header.
std::string current_session_name_;
// Number of days without activity after which we consider a session to be
// stale and a candidate for garbage collection.
int stale_session_threshold_days_;
// Callback to inform interested observer that new sessions data has arrived.
base::RepeatingClosure sessions_updated_callback_;
} // namespace sync_sessions