|  | // Copyright 2018 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "chrome/browser/sync/session_sync_service_factory.h" | 
|  |  | 
|  | #include "base/memory/raw_ptr.h" | 
|  | #include "base/memory/singleton.h" | 
|  | #include "build/build_config.h" | 
|  | #include "chrome/browser/favicon/favicon_service_factory.h" | 
|  | #include "chrome/browser/history/history_service_factory.h" | 
|  | #include "chrome/browser/profiles/profile.h" | 
|  | #include "chrome/browser/sync/device_info_sync_service_factory.h" | 
|  | #include "chrome/browser/sync/glue/sync_start_util.h" | 
|  | #include "chrome/browser/sync/model_type_store_service_factory.h" | 
|  | #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router.h" | 
|  | #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h" | 
|  | #include "chrome/browser/ui/sync/browser_synced_window_delegates_getter.h" | 
|  | #include "chrome/common/channel_info.h" | 
|  | #include "chrome/common/url_constants.h" | 
|  | #include "components/dom_distiller/core/url_constants.h" | 
|  | #include "components/history/core/browser/history_service.h" | 
|  | #include "components/sync/model/model_type_store_service.h" | 
|  | #include "components/sync_device_info/device_info_sync_service.h" | 
|  | #include "components/sync_device_info/device_info_tracker.h" | 
|  | #include "components/sync_sessions/session_sync_prefs.h" | 
|  | #include "components/sync_sessions/session_sync_service_impl.h" | 
|  | #include "components/sync_sessions/sync_sessions_client.h" | 
|  | #include "content/public/common/url_utils.h" | 
|  |  | 
|  | #if BUILDFLAG(IS_ANDROID) | 
|  | #include "chrome/browser/sync/glue/synced_window_delegates_getter_android.h" | 
|  | #endif  // BUILDFLAG(IS_ANDROID) | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | bool ShouldSyncURLImpl(const GURL& url) { | 
|  | if (url == chrome::kChromeUIHistoryURL) { | 
|  | // Allow the chrome history page, home for "Tabs from other devices", so | 
|  | // it can trigger starting up the sync engine. | 
|  | return true; | 
|  | } | 
|  | return url.is_valid() && !content::HasWebUIScheme(url) && | 
|  | !url.SchemeIs(chrome::kChromeNativeScheme) && !url.SchemeIsFile() && | 
|  | !url.SchemeIs(dom_distiller::kDomDistillerScheme); | 
|  | } | 
|  |  | 
|  | // Chrome implementation of SyncSessionsClient. | 
|  | class SyncSessionsClientImpl : public sync_sessions::SyncSessionsClient { | 
|  | public: | 
|  | explicit SyncSessionsClientImpl(Profile* profile) | 
|  | : profile_(profile), session_sync_prefs_(profile->GetPrefs()) { | 
|  | window_delegates_getter_ = | 
|  | #if BUILDFLAG(IS_ANDROID) | 
|  | // Android doesn't have multi-profile support, so no need to pass the | 
|  | // profile in. | 
|  | std::make_unique<browser_sync::SyncedWindowDelegatesGetterAndroid>(); | 
|  | #else   // BUILDFLAG(IS_ANDROID) | 
|  | std::make_unique<browser_sync::BrowserSyncedWindowDelegatesGetter>( | 
|  | profile); | 
|  | #endif  // BUILDFLAG(IS_ANDROID) | 
|  | } | 
|  |  | 
|  | SyncSessionsClientImpl(const SyncSessionsClientImpl&) = delete; | 
|  | SyncSessionsClientImpl& operator=(const SyncSessionsClientImpl&) = delete; | 
|  |  | 
|  | ~SyncSessionsClientImpl() override = default; | 
|  |  | 
|  | // SyncSessionsClient implementation. | 
|  | sync_sessions::SessionSyncPrefs* GetSessionSyncPrefs() override { | 
|  | return &session_sync_prefs_; | 
|  | } | 
|  |  | 
|  | syncer::RepeatingModelTypeStoreFactory GetStoreFactory() override { | 
|  | return ModelTypeStoreServiceFactory::GetForProfile(profile_) | 
|  | ->GetStoreFactory(); | 
|  | } | 
|  |  | 
|  | void ClearAllOnDemandFavicons() override { | 
|  | history::HistoryService* history_service = | 
|  | HistoryServiceFactory::GetForProfile( | 
|  | profile_, ServiceAccessType::EXPLICIT_ACCESS); | 
|  | if (!history_service) { | 
|  | return; | 
|  | } | 
|  | history_service->ClearAllOnDemandFavicons(); | 
|  | } | 
|  |  | 
|  | bool ShouldSyncURL(const GURL& url) const override { | 
|  | return ShouldSyncURLImpl(url); | 
|  | } | 
|  |  | 
|  | bool IsRecentLocalCacheGuid(const std::string& cache_guid) const override { | 
|  | return DeviceInfoSyncServiceFactory::GetForProfile(profile_) | 
|  | ->GetDeviceInfoTracker() | 
|  | ->IsRecentLocalCacheGuid(cache_guid); | 
|  | } | 
|  |  | 
|  | sync_sessions::SyncedWindowDelegatesGetter* GetSyncedWindowDelegatesGetter() | 
|  | override { | 
|  | return window_delegates_getter_.get(); | 
|  | } | 
|  |  | 
|  | sync_sessions::LocalSessionEventRouter* GetLocalSessionEventRouter() | 
|  | override { | 
|  | syncer::SyncableService::StartSyncFlare flare( | 
|  | sync_start_util::GetFlareForSyncableService(profile_->GetPath())); | 
|  | sync_sessions::SyncSessionsWebContentsRouter* router = | 
|  | sync_sessions::SyncSessionsWebContentsRouterFactory::GetForProfile( | 
|  | profile_); | 
|  | // TODO(mastiz): Injecting a start flare as a side effect of what seems to | 
|  | // be a getter is error-prone. In fact, we seem to call this function very | 
|  | // early for the USS implementation. | 
|  | router->InjectStartSyncFlare(flare); | 
|  | return router; | 
|  | } | 
|  |  | 
|  | private: | 
|  | const raw_ptr<Profile> profile_; | 
|  | std::unique_ptr<sync_sessions::SyncedWindowDelegatesGetter> | 
|  | window_delegates_getter_; | 
|  | sync_sessions::SessionSyncPrefs session_sync_prefs_; | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | // static | 
|  | sync_sessions::SessionSyncService* SessionSyncServiceFactory::GetForProfile( | 
|  | Profile* profile) { | 
|  | return static_cast<sync_sessions::SessionSyncService*>( | 
|  | GetInstance()->GetServiceForBrowserContext(profile, true)); | 
|  | } | 
|  |  | 
|  | // static | 
|  | SessionSyncServiceFactory* SessionSyncServiceFactory::GetInstance() { | 
|  | return base::Singleton<SessionSyncServiceFactory>::get(); | 
|  | } | 
|  |  | 
|  | // static | 
|  | bool SessionSyncServiceFactory::ShouldSyncURLForTesting(const GURL& url) { | 
|  | return ShouldSyncURLImpl(url); | 
|  | } | 
|  |  | 
|  | SessionSyncServiceFactory::SessionSyncServiceFactory() | 
|  | : ProfileKeyedServiceFactory("SessionSyncService") { | 
|  | DependsOn(DeviceInfoSyncServiceFactory::GetInstance()); | 
|  | DependsOn(FaviconServiceFactory::GetInstance()); | 
|  | DependsOn(HistoryServiceFactory::GetInstance()); | 
|  | DependsOn(ModelTypeStoreServiceFactory::GetInstance()); | 
|  | DependsOn(sync_sessions::SyncSessionsWebContentsRouterFactory::GetInstance()); | 
|  | } | 
|  |  | 
|  | SessionSyncServiceFactory::~SessionSyncServiceFactory() = default; | 
|  |  | 
|  | KeyedService* SessionSyncServiceFactory::BuildServiceInstanceFor( | 
|  | content::BrowserContext* context) const { | 
|  | Profile* profile = Profile::FromBrowserContext(context); | 
|  | return new sync_sessions::SessionSyncServiceImpl( | 
|  | chrome::GetChannel(), std::make_unique<SyncSessionsClientImpl>(profile)); | 
|  | } |