| Index: components/offline_pages/core/downloads/download_ui_adapter.cc
|
| diff --git a/components/offline_pages/core/downloads/download_ui_adapter.cc b/components/offline_pages/core/downloads/download_ui_adapter.cc
|
| index 193bfdb7f67e09a4addddcbdb3ad36468e7edb4e..118efd999d448fbfa05af0708044a97edab37698 100644
|
| --- a/components/offline_pages/core/downloads/download_ui_adapter.cc
|
| +++ b/components/offline_pages/core/downloads/download_ui_adapter.cc
|
| @@ -9,6 +9,8 @@
|
| #include "base/logging.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| +#include "components/offline_pages/core/background/request_coordinator.h"
|
| +#include "components/offline_pages/core/background/save_page_request.h"
|
| #include "components/offline_pages/core/client_namespace_constants.h"
|
| #include "components/offline_pages/core/client_policy_controller.h"
|
| #include "components/offline_pages/core/downloads/download_ui_item.h"
|
| @@ -16,36 +18,34 @@
|
|
|
| namespace offline_pages {
|
|
|
| -namespace {
|
| -const char kDownloadUIAdapterKey[] = "download-ui-adapter";
|
| -}
|
| -
|
| DownloadUIAdapter::ItemInfo::ItemInfo(const OfflinePageItem& page)
|
| : ui_item(base::MakeUnique<DownloadUIItem>(page)),
|
| - offline_id(page.offline_id) {}
|
| + is_request(false),
|
| + offline_id(page.offline_id),
|
| + client_id(page.client_id),
|
| + temporarily_hidden(false) {}
|
| +
|
| +DownloadUIAdapter::ItemInfo::ItemInfo(const SavePageRequest& request)
|
| + : ui_item(base::MakeUnique<DownloadUIItem>(request)),
|
| + is_request(true),
|
| + offline_id(request.request_id()),
|
| + client_id(request.client_id()),
|
| + temporarily_hidden(false) {}
|
|
|
| DownloadUIAdapter::ItemInfo::~ItemInfo() {}
|
|
|
| -DownloadUIAdapter::DownloadUIAdapter(OfflinePageModel* model)
|
| +DownloadUIAdapter::DownloadUIAdapter(OfflinePageModel* model,
|
| + RequestCoordinator* request_coordinator,
|
| + std::unique_ptr<Delegate> delegate)
|
| : model_(model),
|
| + request_coordinator_(request_coordinator),
|
| + delegate_(std::move(delegate)),
|
| state_(State::NOT_LOADED),
|
| observers_count_(0),
|
| weak_ptr_factory_(this) {}
|
|
|
| DownloadUIAdapter::~DownloadUIAdapter() {}
|
|
|
| -// static
|
| -DownloadUIAdapter* DownloadUIAdapter::FromOfflinePageModel(
|
| - OfflinePageModel* offline_page_model) {
|
| - DownloadUIAdapter* adapter = static_cast<DownloadUIAdapter*>(
|
| - offline_page_model->GetUserData(kDownloadUIAdapterKey));
|
| - if (!adapter) {
|
| - adapter = new DownloadUIAdapter(offline_page_model);
|
| - offline_page_model->SetUserData(kDownloadUIAdapterKey, adapter);
|
| - }
|
| - return adapter;
|
| -}
|
| -
|
| void DownloadUIAdapter::AddObserver(Observer* observer) {
|
| DCHECK(observer);
|
| if (observers_.HasObserver(observer))
|
| @@ -82,48 +82,98 @@ void DownloadUIAdapter::OfflinePageModelLoaded(OfflinePageModel* model) {
|
| void DownloadUIAdapter::OfflinePageAdded(OfflinePageModel* model,
|
| const OfflinePageItem& added_page) {
|
| DCHECK(model == model_);
|
| - if (!IsVisibleInUI(added_page.client_id))
|
| + if (!delegate_->IsVisibleInUI(added_page.client_id))
|
| return;
|
|
|
| - const std::string& guid = added_page.client_id.id;
|
| - DCHECK(items_.find(guid) == items_.end());
|
| -
|
| - items_[guid] = base::MakeUnique<ItemInfo>(added_page);
|
| - const DownloadUIItem& item = *(items_[guid]->ui_item);
|
| - for (Observer& observer : observers_)
|
| - observer.ItemAdded(item);
|
| + AddItemHelper(base::MakeUnique<ItemInfo>(added_page));
|
| }
|
|
|
| void DownloadUIAdapter::OfflinePageDeleted(int64_t offline_id,
|
| const ClientId& client_id) {
|
| - if (!IsVisibleInUI(client_id))
|
| + if (!delegate_->IsVisibleInUI(client_id))
|
| return;
|
| - std::string guid = client_id.id;
|
| - DownloadUIItems::const_iterator it = items_.find(guid);
|
| - if (it == items_.end())
|
| + DeleteItemHelper(client_id.id);
|
| +}
|
| +
|
| +// RequestCoordinator::Observer
|
| +void DownloadUIAdapter::OnAdded(const SavePageRequest& added_request) {
|
| + if (!delegate_->IsVisibleInUI(added_request.client_id()))
|
| return;
|
| - items_.erase(it);
|
| +
|
| + AddItemHelper(base::MakeUnique<ItemInfo>(added_request));
|
| +}
|
| +
|
| +// RequestCoordinator::Observer
|
| +void DownloadUIAdapter::OnCompleted(
|
| + const SavePageRequest& request,
|
| + RequestNotifier::BackgroundSavePageResult status) {
|
| + if (!delegate_->IsVisibleInUI(request.client_id()))
|
| + return;
|
| +
|
| + // If request completed successfully, report ItemUpdated when a page is added
|
| + // to the model. If the request failed, tell UI that the item is gone.
|
| + if (status == RequestNotifier::BackgroundSavePageResult::SUCCESS)
|
| + return;
|
| + DeleteItemHelper(request.client_id().id);
|
| +}
|
| +
|
| +// RequestCoordinator::Observer
|
| +void DownloadUIAdapter::OnChanged(const SavePageRequest& request) {
|
| + if (!delegate_->IsVisibleInUI(request.client_id()))
|
| + return;
|
| +
|
| + std::string guid = request.client_id().id;
|
| + items_[guid] = base::MakeUnique<ItemInfo>(request);
|
| +
|
| + if (state_ != State::LOADED)
|
| + return;
|
| +
|
| + const DownloadUIItem& download_ui_item = *(items_[guid]->ui_item);
|
| for (Observer& observer : observers_)
|
| - observer.ItemDeleted(guid);
|
| + observer.ItemUpdated(download_ui_item);
|
| +}
|
| +
|
| +void DownloadUIAdapter::TemporaryHiddenStatusChanged(
|
| + const ClientId& client_id) {
|
| + bool hidden = delegate_->IsTemporarilyHiddenInUI(client_id);
|
| +
|
| + for (const auto& item : items_) {
|
| + if (item.second->client_id == client_id) {
|
| + if (item.second->temporarily_hidden == hidden)
|
| + continue;
|
| + item.second->temporarily_hidden = hidden;
|
| + if (hidden) {
|
| + for (Observer& observer : observers_)
|
| + observer.ItemDeleted(item.second->ui_item->guid);
|
| + } else {
|
| + for (Observer& observer : observers_)
|
| + observer.ItemAdded(*item.second->ui_item.get());
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
| std::vector<const DownloadUIItem*> DownloadUIAdapter::GetAllItems() const {
|
| std::vector<const DownloadUIItem*> result;
|
| - for (const auto& item : items_)
|
| + for (const auto& item : items_) {
|
| + if (delegate_->IsTemporarilyHiddenInUI(item.second->client_id))
|
| + continue;
|
| result.push_back(item.second->ui_item.get());
|
| + }
|
| return result;
|
| }
|
|
|
| const DownloadUIItem* DownloadUIAdapter::GetItem(
|
| const std::string& guid) const {
|
| DownloadUIItems::const_iterator it = items_.find(guid);
|
| - if (it == items_.end())
|
| + if (it == items_.end() ||
|
| + delegate_->IsTemporarilyHiddenInUI(it->second->client_id)) {
|
| return nullptr;
|
| + }
|
| return it->second->ui_item.get();
|
| }
|
|
|
| void DownloadUIAdapter::DeleteItem(const std::string& guid) {
|
| - // TODO(dimich): Also remove pending request from RequestQueue.
|
| DownloadUIItems::const_iterator it = items_.find(guid);
|
| if (it == items_.end())
|
| return;
|
| @@ -136,8 +186,6 @@ void DownloadUIAdapter::DeleteItem(const std::string& guid) {
|
| }
|
|
|
| int64_t DownloadUIAdapter::GetOfflineIdByGuid(const std::string& guid) const {
|
| - // TODO(dimich): when requests are also in the cache, filter them out.
|
| - // Requests do not yet have offline ID.
|
| DownloadUIItems::const_iterator it = items_.find(guid);
|
| if (it != items_.end())
|
| return it->second->offline_id;
|
| @@ -147,8 +195,7 @@ int64_t DownloadUIAdapter::GetOfflineIdByGuid(const std::string& guid) const {
|
| // Note that several LoadCache calls may be issued before the async GetAllPages
|
| // comes back.
|
| void DownloadUIAdapter::LoadCache() {
|
| - // TODO(dimich): Add fetching from RequestQueue as well.
|
| - state_ = State::LOADING;
|
| + state_ = State::LOADING_PAGES;
|
| model_->GetAllPages(base::Bind(&DownloadUIAdapter::OnOfflinePagesLoaded,
|
| weak_ptr_factory_.GetWeakPtr()));
|
| }
|
| @@ -167,16 +214,46 @@ void DownloadUIAdapter::OnOfflinePagesLoaded(
|
| // If multiple observers register quickly, the cache might be already loaded
|
| // by the previous LoadCache call. At the same time, if all observers already
|
| // left, there is no reason to populate the cache.
|
| - if (state_ != State::LOADING)
|
| + if (state_ != State::LOADING_PAGES)
|
| return;
|
| for (const auto& page : pages) {
|
| - if (IsVisibleInUI(page.client_id)) {
|
| + if (delegate_->IsVisibleInUI(page.client_id)) {
|
| std::string guid = page.client_id.id;
|
| DCHECK(items_.find(guid) == items_.end());
|
| - items_[guid] = base::MakeUnique<ItemInfo>(page);
|
| + std::unique_ptr<ItemInfo> item = base::MakeUnique<ItemInfo>(page);
|
| + item->temporarily_hidden =
|
| + delegate_->IsTemporarilyHiddenInUI(page.client_id);
|
| + items_[guid] = std::move(item);
|
| }
|
| }
|
| model_->AddObserver(this);
|
| +
|
| + state_ = State::LOADING_REQUESTS;
|
| + request_coordinator_->GetAllRequests(base::Bind(
|
| + &DownloadUIAdapter::OnRequestsLoaded, weak_ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void DownloadUIAdapter::OnRequestsLoaded(
|
| + std::vector<std::unique_ptr<SavePageRequest>> requests) {
|
| + // If multiple observers register quickly, the cache might be already loaded
|
| + // by the previous LoadCache call. At the same time, if all observers already
|
| + // left, there is no reason to populate the cache.
|
| + if (state_ != State::LOADING_REQUESTS)
|
| + return;
|
| +
|
| + for (const auto& request : requests) {
|
| + if (delegate_->IsVisibleInUI(request->client_id())) {
|
| + std::string guid = request->client_id().id;
|
| + DCHECK(items_.find(guid) == items_.end());
|
| + std::unique_ptr<ItemInfo> item =
|
| + base::MakeUnique<ItemInfo>(*request.get());
|
| + item->temporarily_hidden =
|
| + delegate_->IsTemporarilyHiddenInUI(request->client_id());
|
| + items_[guid] = std::move(item);
|
| + }
|
| + }
|
| + request_coordinator_->AddObserver(this);
|
| +
|
| state_ = State::LOADED;
|
| for (Observer& observer : observers_)
|
| observer.ItemsLoaded();
|
| @@ -192,10 +269,43 @@ void DownloadUIAdapter::OnDeletePagesDone(DeletePageResult result) {
|
| // TODO(dimich): Consider adding UMA to record user actions.
|
| }
|
|
|
| -bool DownloadUIAdapter::IsVisibleInUI(const ClientId& client_id) {
|
| - const std::string& name_space = client_id.name_space;
|
| - return model_->GetPolicyController()->IsSupportedByDownload(name_space) &&
|
| - base::IsValidGUID(client_id.id);
|
| +void DownloadUIAdapter::AddItemHelper(std::unique_ptr<ItemInfo> item_info) {
|
| + const std::string& guid = item_info->ui_item->guid;
|
| +
|
| + DownloadUIItems::const_iterator it = items_.find(guid);
|
| + // In case when request is completed and morphed into a page, this comes as
|
| + // new page added and request completed. We ignore request completion
|
| + // notification and when page is added, fire 'updated' instead of 'added'.
|
| + bool request_to_page_transition =
|
| + (it != items_.end() && it->second->is_request && !item_info->is_request);
|
| +
|
| + items_[guid] = std::move(item_info);
|
| +
|
| + if (state_ != State::LOADED)
|
| + return;
|
| +
|
| + DownloadUIItem* download_ui_item = items_[guid]->ui_item.get();
|
| + if (request_to_page_transition) {
|
| + download_ui_item->download_state = DownloadUIItem::DownloadState::COMPLETE;
|
| + for (Observer& observer : observers_)
|
| + observer.ItemUpdated(*download_ui_item);
|
| + } else {
|
| + for (Observer& observer : observers_)
|
| + observer.ItemAdded(*download_ui_item);
|
| + }
|
| +}
|
| +
|
| +void DownloadUIAdapter::DeleteItemHelper(const std::string& guid) {
|
| + DownloadUIItems::const_iterator it = items_.find(guid);
|
| + if (it == items_.end())
|
| + return;
|
| + items_.erase(it);
|
| +
|
| + if (state_ != State::LOADED)
|
| + return;
|
| +
|
| + for (Observer& observer : observers_)
|
| + observer.ItemDeleted(guid);
|
| }
|
|
|
| } // namespace offline_pages
|
|
|