Chromium Code Reviews| Index: chrome/browser/android/offline_pages/suggestions_observer.cc |
| diff --git a/chrome/browser/android/offline_pages/suggestions_observer.cc b/chrome/browser/android/offline_pages/suggestions_observer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5f3e71ae0d3a70559b3ab16f5ac9a089dab1f338 |
| --- /dev/null |
| +++ b/chrome/browser/android/offline_pages/suggestions_observer.cc |
| @@ -0,0 +1,145 @@ |
| +// Copyright 2017 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 "chrome/browser/android/offline_pages/suggestions_observer.h" |
| + |
| +#include <unordered_set> |
| + |
| +#include "base/memory/ptr_util.h" |
| +#include "base/threading/thread_task_runner_handle.h" |
| +#include "chrome/browser/android/offline_pages/prefetch_service_factory.h" |
| +#include "components/ntp_snippets/category.h" |
| +#include "components/ntp_snippets/category_status.h" |
| +#include "components/offline_pages/core/client_namespace_constants.h" |
| +#include "components/offline_pages/core/offline_page_feature.h" |
| +#include "components/offline_pages/core/prefetch/prefetch_service_impl.h" |
| + |
| +using ntp_snippets::Category; |
| +using ntp_snippets::ContentSuggestion; |
| + |
| +namespace offline_pages { |
| + |
| +int kOfflinePageSuggestionsObserverUserDataKey; |
|
carlosk
2017/04/18 00:36:09
Shouldn't this be inside the anonymous namespace t
dewittj
2017/04/18 18:20:25
Done.
|
| + |
| +namespace { |
|
carlosk
2017/04/18 00:36:09
Are anonymous namespaces within named namespaces a
dewittj
2017/04/18 18:20:25
I'm not sure what you are trying to ask. In my ex
carlosk
2017/04/18 20:17:22
Acknowledged.
|
| + |
| +ClientId CreateClientIDFromSuggestionId(const ContentSuggestion::ID& id) { |
| + return ClientId(kSuggestedArticlesNamespace, id.id_within_category()); |
| +} |
| + |
| +// The default delegate that contains external dependencies for the Offline Page |
| +// Suggestions Observer. This is unused in tests, which implement their own |
| +// Delegate. |
| +class DefaultDelegate : public SuggestionsObserver::Delegate { |
| + public: |
| + explicit DefaultDelegate(ntp_snippets::ContentSuggestionsService* service); |
| + ~DefaultDelegate() override = default; |
| + |
| + const std::vector<ContentSuggestion>& GetSuggestions( |
| + const Category& category) override; |
| + PrefetchService* GetPrefetchService( |
| + content::BrowserContext* context) override; |
| + |
| + private: |
| + ntp_snippets::ContentSuggestionsService* service_; |
| +}; |
| + |
| +DefaultDelegate::DefaultDelegate( |
| + ntp_snippets::ContentSuggestionsService* service) |
| + : service_(service) {} |
| + |
| +const std::vector<ContentSuggestion>& DefaultDelegate::GetSuggestions( |
| + const Category& category) { |
| + return service_->GetSuggestionsForCategory(category); |
| +} |
| + |
| +PrefetchService* DefaultDelegate::GetPrefetchService( |
| + content::BrowserContext* context) { |
| + return PrefetchServiceFactory::GetForBrowserContext(context); |
| +} |
| + |
| +} // namespace |
| + |
| +// static |
| +void SuggestionsObserver::ObserveContentSuggestionsService( |
| + content::BrowserContext* browser_context, |
| + ntp_snippets::ContentSuggestionsService* service) { |
| + if (!offline_pages::IsPrefetchingOfflinePagesEnabled()) |
| + return; |
| + |
| + auto category = |
| + Category::FromKnownCategory(ntp_snippets::KnownCategories::ARTICLES); |
| + auto suggestions_observer = base::MakeUnique<SuggestionsObserver>( |
| + browser_context, category, base::MakeUnique<DefaultDelegate>(service)); |
| + service->AddObserver(suggestions_observer.get()); |
| + service->SetUserData(&kOfflinePageSuggestionsObserverUserDataKey, |
| + suggestions_observer.release()); |
|
carlosk
2017/04/18 00:36:09
Is it impossible to use std::move here?
dewittj
2017/04/18 18:20:25
Done. Note that the obvious way seemed to fail bec
|
| +} |
| + |
| +SuggestionsObserver::SuggestionsObserver( |
| + content::BrowserContext* browser_context, |
| + const Category& category, |
| + std::unique_ptr<Delegate> delegate) |
| + : browser_context_(browser_context), |
| + category_(category), |
| + delegate_(std::move(delegate)) {} |
| + |
| +SuggestionsObserver::~SuggestionsObserver() = default; |
| + |
| +void SuggestionsObserver::OnNewSuggestions(Category category) { |
| + if (category != category_ || |
| + category_status_ != ntp_snippets::CategoryStatus::AVAILABLE) { |
| + return; |
| + } |
| + |
| + const std::vector<ContentSuggestion>& suggestions = |
| + delegate_->GetSuggestions(category_); |
| + if (suggestions.empty()) |
| + return; |
| + |
| + std::vector<PrefetchService::PrefetchURL> prefetch_urls; |
| + for (auto& suggestion : suggestions) { |
| + prefetch_urls.push_back( |
| + {CreateClientIDFromSuggestionId(suggestion.id()), suggestion.url()}); |
| + } |
| + |
| + PrefetchService* service = delegate_->GetPrefetchService(browser_context_); |
| + service->OnNewURLsToPrefetch(prefetch_urls); |
| +} |
| + |
| +void SuggestionsObserver::OnCategoryStatusChanged( |
| + Category category, |
| + ntp_snippets::CategoryStatus new_status) { |
| + if (category != category_ || category_status_ == new_status) |
| + return; |
| + |
| + category_status_ = new_status; |
| + |
| + if (category_status_ == |
| + ntp_snippets::CategoryStatus::CATEGORY_EXPLICITLY_DISABLED || |
| + category_status_ == |
| + ntp_snippets::CategoryStatus::ALL_SUGGESTIONS_EXPLICITLY_DISABLED) { |
| + PrefetchService* service = delegate_->GetPrefetchService(browser_context_); |
| + service->RemoveAllUnprocessedPrefetchURLs(kSuggestedArticlesNamespace); |
| + } |
| +} |
| + |
| +void SuggestionsObserver::OnSuggestionInvalidated( |
| + const ContentSuggestion::ID& suggestion_id) { |
| + PrefetchService* service = delegate_->GetPrefetchService(browser_context_); |
| + service->RemovePrefetchURLsByClientId( |
| + CreateClientIDFromSuggestionId(suggestion_id)); |
| +} |
| + |
| +void SuggestionsObserver::OnFullRefreshRequired() { |
| + PrefetchService* service = delegate_->GetPrefetchService(browser_context_); |
| + service->RemoveAllUnprocessedPrefetchURLs(kSuggestedArticlesNamespace); |
|
jianli
2017/04/17 21:52:58
Are all PrefetchService operations asynchronous? I
dewittj
2017/04/17 22:22:18
They are, but hopefully they will be serialized us
|
| + OnNewSuggestions(category_); |
| +} |
| + |
| +void SuggestionsObserver::ContentSuggestionsServiceShutdown() { |
| + // No need to do anything here, we will just stop getting events. |
| +} |
| + |
| +} // namespace offline_pages |