Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: components/offline_pages/downloads/download_ui_adapter.cc

Issue 2264233002: Fix a crash in DownloadUIAddapter that happens when Java bridge is created/removed quickly while (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/offline_pages/downloads/download_ui_adapter.h" 5 #include "components/offline_pages/downloads/download_ui_adapter.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/guid.h" 8 #include "base/guid.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
(...skipping 11 matching lines...) Expand all
22 DownloadUIAdapter::ItemInfo::ItemInfo(const OfflinePageItem& page) 22 DownloadUIAdapter::ItemInfo::ItemInfo(const OfflinePageItem& page)
23 : ui_item(base::MakeUnique<DownloadUIItem>(page)), 23 : ui_item(base::MakeUnique<DownloadUIItem>(page)),
24 offline_id(page.offline_id), 24 offline_id(page.offline_id),
25 offline_url(page.GetOfflineURL()) {} 25 offline_url(page.GetOfflineURL()) {}
26 26
27 DownloadUIAdapter::ItemInfo::~ItemInfo() {} 27 DownloadUIAdapter::ItemInfo::~ItemInfo() {}
28 28
29 DownloadUIAdapter::DownloadUIAdapter(OfflinePageModel* model) 29 DownloadUIAdapter::DownloadUIAdapter(OfflinePageModel* model)
30 : model_(model), 30 : model_(model),
31 is_loaded_(false), 31 is_loaded_(false),
32 observers_count_(0),
32 weak_ptr_factory_(this) { 33 weak_ptr_factory_(this) {
33 } 34 }
34 35
35 DownloadUIAdapter::~DownloadUIAdapter() { } 36 DownloadUIAdapter::~DownloadUIAdapter() { }
36 37
37 // static 38 // static
38 DownloadUIAdapter* DownloadUIAdapter::FromOfflinePageModel( 39 DownloadUIAdapter* DownloadUIAdapter::FromOfflinePageModel(
39 OfflinePageModel* offline_page_model) { 40 OfflinePageModel* offline_page_model) {
40 DownloadUIAdapter* adapter = static_cast<DownloadUIAdapter*>( 41 DownloadUIAdapter* adapter = static_cast<DownloadUIAdapter*>(
41 offline_page_model->GetUserData(kDownloadUIAdapterKey)); 42 offline_page_model->GetUserData(kDownloadUIAdapterKey));
42 if (!adapter) { 43 if (!adapter) {
43 adapter = new DownloadUIAdapter(offline_page_model); 44 adapter = new DownloadUIAdapter(offline_page_model);
44 offline_page_model->SetUserData(kDownloadUIAdapterKey, adapter); 45 offline_page_model->SetUserData(kDownloadUIAdapterKey, adapter);
45 } 46 }
46 return adapter; 47 return adapter;
47 } 48 }
48 49
49 void DownloadUIAdapter::AddObserver(Observer* observer) { 50 void DownloadUIAdapter::AddObserver(Observer* observer) {
50 DCHECK(observer); 51 DCHECK(observer);
51 if (!observers_.might_have_observers()) 52 if (observers_count_ == 0)
52 LoadCache(); 53 LoadCache();
53 observers_.AddObserver(observer); 54 observers_.AddObserver(observer);
55 ++observers_count_;
54 // If the items are already loaded, post the notification right away. 56 // If the items are already loaded, post the notification right away.
55 // Don't just invoke it from here to avoid reentrancy in the client. 57 // Don't just invoke it from here to avoid reentrancy in the client.
56 if (is_loaded_) { 58 if (is_loaded_) {
57 base::ThreadTaskRunnerHandle::Get()->PostTask( 59 base::ThreadTaskRunnerHandle::Get()->PostTask(
58 FROM_HERE, base::Bind(&DownloadUIAdapter::NotifyItemsLoaded, 60 FROM_HERE, base::Bind(&DownloadUIAdapter::NotifyItemsLoaded,
59 weak_ptr_factory_.GetWeakPtr(), 61 weak_ptr_factory_.GetWeakPtr(),
60 base::Unretained(observer))); 62 base::Unretained(observer)));
61 } 63 }
62 } 64 }
63 65
64 void DownloadUIAdapter::RemoveObserver(Observer* observer) { 66 void DownloadUIAdapter::RemoveObserver(Observer* observer) {
65 observers_.RemoveObserver(observer); 67 observers_.RemoveObserver(observer);
68 --observers_count_;
66 // Once the last observer is gone, clear cached data. 69 // Once the last observer is gone, clear cached data.
67 if (!observers_.might_have_observers()) 70 if (observers_count_ == 0)
68 ClearCache(); 71 ClearCache();
69 } 72 }
70 73
71 void DownloadUIAdapter::OfflinePageModelLoaded(OfflinePageModel* model) { 74 void DownloadUIAdapter::OfflinePageModelLoaded(OfflinePageModel* model) {
72 // This signal is not used here. 75 // This signal is not used here.
73 } 76 }
74 77
75 void DownloadUIAdapter::OfflinePageModelChanged(OfflinePageModel* model) { 78 void DownloadUIAdapter::OfflinePageModelChanged(OfflinePageModel* model) {
76 DCHECK(model == model_); 79 DCHECK(model == model_);
77 model_->GetAllPages( 80 model_->GetAllPages(
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 GURL DownloadUIAdapter::GetOfflineUrlByGuid( 128 GURL DownloadUIAdapter::GetOfflineUrlByGuid(
126 const std::string& guid) const { 129 const std::string& guid) const {
127 // TODO(dimich): when requests are also in the cache, filter them out. 130 // TODO(dimich): when requests are also in the cache, filter them out.
128 // Requests do not yet have offline URL. 131 // Requests do not yet have offline URL.
129 DownloadUIItems::const_iterator it = items_.find(guid); 132 DownloadUIItems::const_iterator it = items_.find(guid);
130 if (it != items_.end()) 133 if (it != items_.end())
131 return it->second->offline_url; 134 return it->second->offline_url;
132 return GURL(); 135 return GURL();
133 } 136 }
134 137
138 // Note that several LoadCache calls may be issued before the async GetAllPages
139 // comes back.
135 void DownloadUIAdapter::LoadCache() { 140 void DownloadUIAdapter::LoadCache() {
136 DCHECK(!is_loaded_);
137 // TODO(dimich): Add fetching from RequestQueue as well. 141 // TODO(dimich): Add fetching from RequestQueue as well.
138 model_->AddObserver(this); 142 model_->AddObserver(this);
dewittj 2016/08/22 21:54:07 I think you'll want to AddObserver after the GetAl
139 model_->GetAllPages( 143 model_->GetAllPages(
dewittj 2016/08/22 21:54:07 do you want a loading_ indicator so you don't GetA
140 base::Bind(&DownloadUIAdapter::OnOfflinePagesLoaded, 144 base::Bind(&DownloadUIAdapter::OnOfflinePagesLoaded,
141 weak_ptr_factory_.GetWeakPtr())); 145 weak_ptr_factory_.GetWeakPtr()));
142 } 146 }
143 147
144 void DownloadUIAdapter::ClearCache() { 148 void DownloadUIAdapter::ClearCache() {
145 model_->RemoveObserver(this); 149 model_->RemoveObserver(this);
146 items_.clear(); 150 items_.clear();
147 is_loaded_ = false; 151 is_loaded_ = false;
148 } 152 }
149 153
150 void DownloadUIAdapter::OnOfflinePagesLoaded( 154 void DownloadUIAdapter::OnOfflinePagesLoaded(
151 const MultipleOfflinePageItemResult& pages) { 155 const MultipleOfflinePageItemResult& pages) {
156 // If multiple observers register quickly, the cache might be already loaded
157 // by the previous LoadCache call. At the same time, if all observers already
158 // left, there is no reason to populate the cache.
159 if (is_loaded_ || observers_count_ == 0)
160 return;
152 for (const auto& page : pages) { 161 for (const auto& page : pages) {
153 if (IsVisibleInUI(page.client_id)) { 162 if (IsVisibleInUI(page.client_id)) {
154 std::string guid = page.client_id.id; 163 std::string guid = page.client_id.id;
155 DCHECK(items_.find(guid) == items_.end()); 164 DCHECK(items_.find(guid) == items_.end());
156 items_[guid] = base::MakeUnique<ItemInfo>(page); 165 items_[guid] = base::MakeUnique<ItemInfo>(page);
157 } 166 }
158 } 167 }
159 is_loaded_ = true; 168 is_loaded_ = true;
160 FOR_EACH_OBSERVER(Observer, observers_, ItemsLoaded()); 169 FOR_EACH_OBSERVER(Observer, observers_, ItemsLoaded());
161 } 170 }
(...skipping 30 matching lines...) Expand all
192 // TODO(dimich): Consider adding UMA to record user actions. 201 // TODO(dimich): Consider adding UMA to record user actions.
193 } 202 }
194 203
195 bool DownloadUIAdapter::IsVisibleInUI(const ClientId& client_id) { 204 bool DownloadUIAdapter::IsVisibleInUI(const ClientId& client_id) {
196 const std::string& name_space = client_id.name_space; 205 const std::string& name_space = client_id.name_space;
197 return (name_space == kAsyncNamespace || name_space == kDownloadNamespace) && 206 return (name_space == kAsyncNamespace || name_space == kDownloadNamespace) &&
198 base::IsValidGUID(client_id.id); 207 base::IsValidGUID(client_id.id);
199 } 208 }
200 209
201 } // namespace offline_pages 210 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698