blob: 4771a10e1c1b0422d3e153a217cf765b0d2fcbc0 [file] [log] [blame]
// Copyright 2020 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 "components/feed/core/v2/public/feed_service.h"
#include <utility>
#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "build/build_config.h"
#include "components/feed/core/shared_prefs/pref_names.h"
#include "components/feed/core/v2/feed_network_impl.h"
#include "components/feed/core/v2/feed_store.h"
#include "components/feed/core/v2/feed_stream.h"
#include "components/feed/core/v2/metrics_reporter.h"
#include "components/feed/core/v2/refresh_task_scheduler.h"
#include "components/feed/feed_feature_list.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_service_observer.h"
#include "components/history/core/browser/history_types.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "net/base/network_change_notifier.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace feed {
namespace {
class EulaObserver : public web_resource::EulaAcceptedNotifier::Observer {
public:
explicit EulaObserver(FeedStream* feed_stream) : feed_stream_(feed_stream) {}
EulaObserver(EulaObserver&) = delete;
EulaObserver& operator=(const EulaObserver&) = delete;
// web_resource::EulaAcceptedNotifier::Observer.
void OnEulaAccepted() override { feed_stream_->OnEulaAccepted(); }
private:
FeedStream* feed_stream_;
};
} // namespace
namespace internal {
bool ShouldClearFeed(const history::DeletionInfo& deletion_info) {
// We ignore expirations since they're not user-initiated.
if (deletion_info.is_from_expiration())
return false;
// If a user deletes a single URL, we don't consider this a clear user
// intent to clear our data.
return deletion_info.IsAllHistory() ||
deletion_info.deleted_rows().size() > 1;
}
} // namespace internal
class FeedService::HistoryObserverImpl
: public history::HistoryServiceObserver {
public:
HistoryObserverImpl(history::HistoryService* history_service,
FeedStream* feed_stream)
: feed_stream_(feed_stream) {
// May be null for some profiles.
if (history_service)
history_service->AddObserver(this);
}
HistoryObserverImpl(const HistoryObserverImpl&) = delete;
HistoryObserverImpl& operator=(const HistoryObserverImpl&) = delete;
// history::HistoryServiceObserver.
void OnURLsDeleted(history::HistoryService* history_service,
const history::DeletionInfo& deletion_info) override {
if (internal::ShouldClearFeed(deletion_info))
feed_stream_->OnHistoryDeleted();
}
private:
FeedStream* feed_stream_;
};
class FeedService::NetworkDelegateImpl : public FeedNetworkImpl::Delegate {
public:
explicit NetworkDelegateImpl(FeedService::Delegate* service_delegate)
: service_delegate_(service_delegate) {}
NetworkDelegateImpl(const NetworkDelegateImpl&) = delete;
NetworkDelegateImpl& operator=(const NetworkDelegateImpl&) = delete;
// FeedNetworkImpl::Delegate.
std::string GetLanguageTag() override {
return service_delegate_->GetLanguageTag();
}
private:
FeedService::Delegate* service_delegate_;
};
class FeedService::StreamDelegateImpl : public FeedStream::Delegate {
public:
StreamDelegateImpl(PrefService* local_state,
FeedService::Delegate* service_delegate)
: service_delegate_(service_delegate), eula_notifier_(local_state) {}
StreamDelegateImpl(const StreamDelegateImpl&) = delete;
StreamDelegateImpl& operator=(const StreamDelegateImpl&) = delete;
void Initialize(FeedStream* feed_stream) {
eula_observer_ = std::make_unique<EulaObserver>(feed_stream);
eula_notifier_.Init(eula_observer_.get());
}
// FeedStream::Delegate.
bool IsEulaAccepted() override { return eula_notifier_.IsEulaAccepted(); }
bool IsOffline() override { return net::NetworkChangeNotifier::IsOffline(); }
DisplayMetrics GetDisplayMetrics() override {
return service_delegate_->GetDisplayMetrics();
}
std::string GetLanguageTag() override {
return service_delegate_->GetLanguageTag();
}
private:
FeedService::Delegate* service_delegate_;
web_resource::EulaAcceptedNotifier eula_notifier_;
std::unique_ptr<EulaObserver> eula_observer_;
std::unique_ptr<HistoryObserverImpl> history_observer_;
};
class FeedService::IdentityManagerObserverImpl
: public signin::IdentityManager::Observer {
public:
IdentityManagerObserverImpl(signin::IdentityManager* identity_manager,
FeedStream* stream)
: identity_manager_(identity_manager), feed_stream_(stream) {}
IdentityManagerObserverImpl(const IdentityManagerObserverImpl&) = delete;
IdentityManagerObserverImpl& operator=(const IdentityManagerObserverImpl&) =
delete;
~IdentityManagerObserverImpl() override {
identity_manager_->RemoveObserver(this);
}
void OnPrimaryAccountSet(
const CoreAccountInfo& primary_account_info) override {
feed_stream_->OnSignedIn();
}
void OnPrimaryAccountCleared(
const CoreAccountInfo& previous_primary_account_info) override {
feed_stream_->OnSignedOut();
}
private:
signin::IdentityManager* identity_manager_;
FeedStream* feed_stream_;
};
FeedService::FeedService(std::unique_ptr<FeedStream> stream)
: stream_(std::move(stream)) {}
FeedService::FeedService(
std::unique_ptr<Delegate> delegate,
std::unique_ptr<RefreshTaskScheduler> refresh_task_scheduler,
PrefService* profile_prefs,
PrefService* local_state,
std::unique_ptr<leveldb_proto::ProtoDatabase<feedstore::Record>> database,
signin::IdentityManager* identity_manager,
history::HistoryService* history_service,
offline_pages::PrefetchService* prefetch_service,
offline_pages::OfflinePageModel* offline_page_model,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
scoped_refptr<base::SequencedTaskRunner> background_task_runner,
const std::string& api_key,
const ChromeInfo& chrome_info)
: delegate_(std::move(delegate)),
refresh_task_scheduler_(std::move(refresh_task_scheduler)) {
stream_delegate_ =
std::make_unique<StreamDelegateImpl>(local_state, delegate_.get());
network_delegate_ = std::make_unique<NetworkDelegateImpl>(delegate_.get());
metrics_reporter_ = std::make_unique<MetricsReporter>(
base::DefaultTickClock::GetInstance(), profile_prefs);
feed_network_ = std::make_unique<FeedNetworkImpl>(
network_delegate_.get(), identity_manager, api_key, url_loader_factory,
base::DefaultTickClock::GetInstance(), profile_prefs,
chrome_info.channel);
store_ = std::make_unique<FeedStore>(std::move(database));
stream_ = std::make_unique<FeedStream>(
refresh_task_scheduler_.get(), metrics_reporter_.get(),
stream_delegate_.get(), profile_prefs, feed_network_.get(), store_.get(),
prefetch_service, offline_page_model, base::DefaultClock::GetInstance(),
base::DefaultTickClock::GetInstance(), chrome_info);
history_observer_ = std::make_unique<HistoryObserverImpl>(
history_service, static_cast<FeedStream*>(stream_.get()));
stream_delegate_->Initialize(static_cast<FeedStream*>(stream_.get()));
identity_manager_observer_ = std::make_unique<IdentityManagerObserverImpl>(
identity_manager, stream_.get());
identity_manager->AddObserver(identity_manager_observer_.get());
#if defined(OS_ANDROID)
application_status_listener_ =
base::android::ApplicationStatusListener::New(base::BindRepeating(
&FeedService::OnApplicationStateChange, base::Unretained(this)));
#endif
}
FeedService::~FeedService() = default;
FeedStreamApi* FeedService::GetStream() {
return stream_.get();
}
void FeedService::ClearCachedData() {
stream_->OnCacheDataCleared();
}
// static
bool FeedService::IsEnabled(const PrefService& pref_service) {
return base::FeatureList::IsEnabled(feed::kInterestFeedV2) &&
pref_service.GetBoolean(feed::prefs::kEnableSnippets);
}
#if defined(OS_ANDROID)
void FeedService::OnApplicationStateChange(
base::android::ApplicationState state) {
if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
// If we want to trigger an OnEnterForeground event, we'll need to be
// careful about the initial state of foregrounded_.
foregrounded_ = true;
}
if (foregrounded_ &&
state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES) {
foregrounded_ = false;
stream_->OnEnterBackground();
}
}
#endif
} // namespace feed