Chromium Code Reviews| 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..483ee49e27caffc5940b49c1f66349fdb0682f40 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,29 +82,80 @@ 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) { |
|
fgorski
2017/01/20 17:03:01
nit: git cl format
Dmitry Titov
2017/01/27 04:26:24
Done.
|
| + if (!delegate_->IsVisibleInUI(request.client_id())) |
| + return; |
| + |
| + // If request completed sucecssfully, 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::OnTemporaryHidenStatusChanged( |
| + const ClientId& client_id, bool hidden) { |
| + // Generate ItemAdded/ItemDeleted notifications when items change their |
| + // hidden status. |
| + |
| + // Sanity check. The items that are not visible in UI can not be temporarily |
| + // hidden. |
| + DCHECK(delegate_->IsVisibleInUI(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 { |
| @@ -123,7 +174,6 @@ const DownloadUIItem* DownloadUIAdapter::GetItem( |
| } |
| 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,40 @@ 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); |
| } |
| } |
| 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()); |
| + items_[guid] = base::MakeUnique<ItemInfo>(*request.get()); |
| + } |
| + } |
| + request_coordinator_->AddObserver(this); |
| + |
| state_ = State::LOADED; |
| for (Observer& observer : observers_) |
| observer.ItemsLoaded(); |
| @@ -192,10 +263,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; |
| + |
| + const DownloadUIItem& download_ui_item = *(items_[guid]->ui_item); |
| + if (request_to_page_transition) { |
| + 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); |
| + |
|
fgorski
2017/01/20 17:03:01
nit: remove empty line.
Dmitry Titov
2017/01/27 04:26:24
Done.
|
| } |
| } // namespace offline_pages |