OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/previews/core/previews_black_list.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/memory/ptr_util.h" | |
9 #include "base/optional.h" | |
10 #include "base/time/clock.h" | |
11 #include "base/time/time.h" | |
12 #include "components/previews/core/previews_black_list_item.h" | |
13 #include "components/previews/core/previews_experiments.h" | |
14 #include "url/gurl.h" | |
15 | |
16 namespace previews { | |
17 | |
18 PreviewsBlackList::PreviewsBlackList( | |
19 std::unique_ptr<PreviewsOptOutStore> opt_out_store, | |
20 std::unique_ptr<base::Clock> clock) | |
21 : loaded_(false), | |
22 opt_out_store_(std::move(opt_out_store)), | |
23 clock_(std::move(clock)), | |
24 weak_factory_(this) { | |
25 if (opt_out_store_) { | |
26 opt_out_store_->LoadBlackList(base::Bind( | |
27 &PreviewsBlackList::LoadBlackListDone, weak_factory_.GetWeakPtr())); | |
28 } else { | |
29 LoadBlackListDone(base::MakeUnique<BlackListItemMap>()); | |
30 } | |
31 } | |
32 | |
33 PreviewsBlackList::~PreviewsBlackList() {} | |
34 | |
35 void PreviewsBlackList::AddPreviewNavigation(const GURL& url, | |
36 bool opt_out, | |
37 PreviewsType type) { | |
38 DCHECK(thread_checker_.CalledOnValidThread()); | |
39 DCHECK(url.has_host()); | |
40 // If the |black_list_item_map_| has been loaded from |opt_out_store_|, | |
41 // synchronous operations will be accurate. Otherwise, queue the task to run | |
42 // asynchronously. | |
43 if (loaded_) { | |
44 AddPreviewNavigationSync(url, opt_out, type); | |
45 } else { | |
46 QueuePendingTask(base::Bind(&PreviewsBlackList::AddPreviewNavigationSync, | |
47 base::Unretained(this), url, opt_out, type)); | |
48 } | |
49 } | |
50 | |
51 void PreviewsBlackList::AddPreviewNavigationSync(const GURL& url, | |
52 bool opt_out, | |
53 PreviewsType type) { | |
54 DCHECK(thread_checker_.CalledOnValidThread()); | |
55 DCHECK(url.has_host()); | |
56 DCHECK(loaded_); | |
57 std::string host_name = url.host(); | |
58 base::Time now = clock_->Now(); | |
59 PreviewsBlackListItem* item = GetBlackListItem(host_name); | |
60 if (!item) { | |
61 item = CreateBlackListItem(host_name); | |
62 } | |
63 item->AddPreviewNavigation(opt_out, now); | |
64 DCHECK_LE(black_list_item_map_->size(), | |
65 params::MaxInMemoryHostsInBlackList()); | |
66 if (!opt_out_store_) | |
67 return; | |
68 opt_out_store_->AddPreviewNavigation(opt_out, host_name, type, now); | |
69 } | |
70 | |
71 bool PreviewsBlackList::IsLoadedAndAllowed(const GURL& url, | |
72 PreviewsType type) const { | |
73 DCHECK(thread_checker_.CalledOnValidThread()); | |
74 DCHECK(url.has_host()); | |
75 std::string host_name = url.host(); | |
tbansal1
2016/09/22 21:12:27
nit: you can move this statement after the if-cond
RyanSturm
2016/09/23 17:23:24
Done.
| |
76 if (!loaded_) | |
77 return false; | |
78 PreviewsBlackListItem* black_list_item = GetBlackListItem(host_name); | |
79 return !black_list_item || !black_list_item->IsBlackListed(clock_->Now()); | |
80 } | |
81 | |
82 void PreviewsBlackList::QueuePendingTask(QueueClosure callback) { | |
83 DCHECK(thread_checker_.CalledOnValidThread()); | |
84 DCHECK(!loaded_); | |
85 DCHECK(!callback.is_null()); | |
86 pending_callbacks_.emplace(callback); | |
87 } | |
88 | |
89 void PreviewsBlackList::LoadBlackListDone( | |
90 std::unique_ptr<BlackListItemMap> black_list_item_map) { | |
91 DCHECK(thread_checker_.CalledOnValidThread()); | |
92 DCHECK_LE(black_list_item_map->size(), params::MaxInMemoryHostsInBlackList()); | |
93 loaded_ = true; | |
94 black_list_item_map_ = std::move(black_list_item_map); | |
95 | |
96 // Run all pending tasks. |loaded_| may change if ClearBlackList is queued. | |
97 while (pending_callbacks_.size() > 0 && loaded_) { | |
98 pending_callbacks_.front().Run(); | |
99 pending_callbacks_.pop(); | |
100 } | |
101 } | |
102 | |
103 PreviewsBlackListItem* PreviewsBlackList::GetBlackListItem( | |
104 const std::string& host_name) const { | |
105 DCHECK(thread_checker_.CalledOnValidThread()); | |
106 DCHECK(loaded_); | |
107 BlackListItemMap::iterator iter = black_list_item_map_->find(host_name); | |
108 if (iter != black_list_item_map_->end()) | |
109 return iter->second.get(); | |
110 return nullptr; | |
111 } | |
112 | |
113 PreviewsBlackListItem* PreviewsBlackList::CreateBlackListItem( | |
114 const std::string& host_name) { | |
115 DCHECK(thread_checker_.CalledOnValidThread()); | |
116 DCHECK(loaded_); | |
117 DCHECK(black_list_item_map_->find(host_name) == black_list_item_map_->end()); | |
tbansal1
2016/09/22 21:12:27
s/DCHECK/DHECK_EQ/
or
DCHECK(!GetBlackListItem(hos
RyanSturm
2016/09/23 17:23:24
Done.
| |
118 if (black_list_item_map_->size() >= params::MaxInMemoryHostsInBlackList()) | |
119 EvictOldestOptOut(); | |
120 DCHECK_LT(black_list_item_map_->size(), | |
121 params::MaxInMemoryHostsInBlackList()); | |
122 PreviewsBlackListItem* black_list_item = new PreviewsBlackListItem( | |
123 params::MaxStoredHistoryLengthForBlackList(), | |
124 params::BlackListOptOutThreshold(), params::BlackListDuration()); | |
125 black_list_item_map_->operator[](host_name) = | |
126 base::WrapUnique(black_list_item); | |
127 return black_list_item; | |
128 } | |
129 | |
130 void PreviewsBlackList::EvictOldestOptOut() { | |
131 DCHECK(thread_checker_.CalledOnValidThread()); | |
132 DCHECK(loaded_); | |
133 // TODO(ryansturm): Add UMA. crbug.com/647717 | |
134 BlackListItemMap::iterator item_to_delete = black_list_item_map_->end(); | |
135 base::Time oldest_opt_out = clock_->Now(); | |
136 for (BlackListItemMap::iterator iter = black_list_item_map_->begin(); | |
137 iter != black_list_item_map_->end(); ++iter) { | |
138 if (!iter->second->most_recent_opt_out_time()) { | |
139 // If there is no opt out time, this is a good choice to evict. | |
140 item_to_delete = iter; | |
141 break; | |
142 } | |
143 if (iter->second->most_recent_opt_out_time().value() < oldest_opt_out) { | |
144 oldest_opt_out = iter->second->most_recent_opt_out_time().value(); | |
145 item_to_delete = iter; | |
146 } | |
147 } | |
148 black_list_item_map_->erase(item_to_delete); | |
149 } | |
150 | |
151 } // namespace previews | |
OLD | NEW |