OLD | NEW |
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 "chrome/browser/budget_service/budget_database.h" | 5 #include "chrome/browser/budget_service/budget_database.h" |
6 | 6 |
7 #include "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
8 #include "base/time/clock.h" | 8 #include "base/time/clock.h" |
9 #include "base/time/default_clock.h" | 9 #include "base/time/default_clock.h" |
10 #include "chrome/browser/budget_service/budget.pb.h" | 10 #include "chrome/browser/budget_service/budget.pb.h" |
11 #include "chrome/browser/engagement/site_engagement_score.h" | 11 #include "chrome/browser/engagement/site_engagement_score.h" |
12 #include "chrome/browser/engagement/site_engagement_service.h" | 12 #include "chrome/browser/engagement/site_engagement_service.h" |
13 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
14 #include "components/leveldb_proto/proto_database_impl.h" | 14 #include "components/leveldb_proto/proto_database_impl.h" |
15 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
16 #include "url/gurl.h" | 16 #include "url/gurl.h" |
| 17 #include "url/origin.h" |
17 | 18 |
18 using content::BrowserThread; | 19 using content::BrowserThread; |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 // UMA are logged for the database with this string as part of the name. | 23 // UMA are logged for the database with this string as part of the name. |
23 // They will be LevelDB.*.BudgetManager. Changes here should be synchronized | 24 // They will be LevelDB.*.BudgetManager. Changes here should be synchronized |
24 // with histograms.xml. | 25 // with histograms.xml. |
25 const char kDatabaseUMAName[] = "BudgetManager"; | 26 const char kDatabaseUMAName[] = "BudgetManager"; |
26 | 27 |
(...skipping 21 matching lines...) Expand all Loading... |
48 task_runner)), | 49 task_runner)), |
49 clock_(base::WrapUnique(new base::DefaultClock)), | 50 clock_(base::WrapUnique(new base::DefaultClock)), |
50 weak_ptr_factory_(this) { | 51 weak_ptr_factory_(this) { |
51 db_->Init(kDatabaseUMAName, database_dir, | 52 db_->Init(kDatabaseUMAName, database_dir, |
52 base::Bind(&BudgetDatabase::OnDatabaseInit, | 53 base::Bind(&BudgetDatabase::OnDatabaseInit, |
53 weak_ptr_factory_.GetWeakPtr())); | 54 weak_ptr_factory_.GetWeakPtr())); |
54 } | 55 } |
55 | 56 |
56 BudgetDatabase::~BudgetDatabase() {} | 57 BudgetDatabase::~BudgetDatabase() {} |
57 | 58 |
58 void BudgetDatabase::GetBudgetDetails(const GURL& origin, | 59 void BudgetDatabase::GetBudgetDetails(const url::Origin& origin, |
59 const GetBudgetCallback& callback) { | 60 const GetBudgetCallback& callback) { |
60 DCHECK_EQ(origin.GetOrigin(), origin); | |
61 | |
62 SyncCache(origin, | 61 SyncCache(origin, |
63 base::Bind(&BudgetDatabase::GetBudgetAfterSync, | 62 base::Bind(&BudgetDatabase::GetBudgetAfterSync, |
64 weak_ptr_factory_.GetWeakPtr(), origin, callback)); | 63 weak_ptr_factory_.GetWeakPtr(), origin, callback)); |
65 } | 64 } |
66 | 65 |
67 void BudgetDatabase::SpendBudget(const GURL& origin, | 66 void BudgetDatabase::SpendBudget(const url::Origin& origin, |
68 double amount, | 67 double amount, |
69 const StoreBudgetCallback& callback) { | 68 const StoreBudgetCallback& callback) { |
70 SyncCache(origin, base::Bind(&BudgetDatabase::SpendBudgetAfterSync, | 69 SyncCache(origin, base::Bind(&BudgetDatabase::SpendBudgetAfterSync, |
71 weak_ptr_factory_.GetWeakPtr(), origin, amount, | 70 weak_ptr_factory_.GetWeakPtr(), origin, amount, |
72 callback)); | 71 callback)); |
73 } | 72 } |
74 | 73 |
75 void BudgetDatabase::SetClockForTesting(std::unique_ptr<base::Clock> clock) { | 74 void BudgetDatabase::SetClockForTesting(std::unique_ptr<base::Clock> clock) { |
76 clock_ = std::move(clock); | 75 clock_ = std::move(clock); |
77 } | 76 } |
78 | 77 |
79 void BudgetDatabase::OnDatabaseInit(bool success) { | 78 void BudgetDatabase::OnDatabaseInit(bool success) { |
80 // TODO(harkness): Consider caching the budget database now? | 79 // TODO(harkness): Consider caching the budget database now? |
81 } | 80 } |
82 | 81 |
83 bool BudgetDatabase::IsCached(const GURL& origin) const { | 82 bool BudgetDatabase::IsCached(const url::Origin& origin) const { |
84 return budget_map_.find(origin.spec()) != budget_map_.end(); | 83 return budget_map_.find(origin) != budget_map_.end(); |
85 } | 84 } |
86 | 85 |
87 double BudgetDatabase::GetBudget(const GURL& origin) const { | 86 double BudgetDatabase::GetBudget(const url::Origin& origin) const { |
88 double total = 0; | 87 double total = 0; |
89 auto iter = budget_map_.find(origin.spec()); | 88 auto iter = budget_map_.find(origin); |
90 if (iter == budget_map_.end()) | 89 if (iter == budget_map_.end()) |
91 return total; | 90 return total; |
92 | 91 |
93 const BudgetInfo& info = iter->second; | 92 const BudgetInfo& info = iter->second; |
94 for (const BudgetChunk& chunk : info.chunks) | 93 for (const BudgetChunk& chunk : info.chunks) |
95 total += chunk.amount; | 94 total += chunk.amount; |
96 return total; | 95 return total; |
97 } | 96 } |
98 | 97 |
99 void BudgetDatabase::AddToCache( | 98 void BudgetDatabase::AddToCache( |
100 const GURL& origin, | 99 const url::Origin& origin, |
101 const AddToCacheCallback& callback, | 100 const AddToCacheCallback& callback, |
102 bool success, | 101 bool success, |
103 std::unique_ptr<budget_service::Budget> budget_proto) { | 102 std::unique_ptr<budget_service::Budget> budget_proto) { |
104 // If the database read failed, there's nothing to add to the cache. | 103 // If the database read failed, there's nothing to add to the cache. |
105 if (!success || !budget_proto) { | 104 if (!success || !budget_proto) { |
106 callback.Run(success); | 105 callback.Run(success); |
107 return; | 106 return; |
108 } | 107 } |
109 | 108 |
110 // If there were two simultaneous loads, don't overwrite the cache value, | 109 // If there were two simultaneous loads, don't overwrite the cache value, |
111 // which might have been updated after the previous load. | 110 // which might have been updated after the previous load. |
112 if (IsCached(origin)) { | 111 if (IsCached(origin)) { |
113 callback.Run(success); | 112 callback.Run(success); |
114 return; | 113 return; |
115 } | 114 } |
116 | 115 |
117 // Add the data to the cache, converting from the proto format to an STL | 116 // Add the data to the cache, converting from the proto format to an STL |
118 // format which is better for removing things from the list. | 117 // format which is better for removing things from the list. |
119 BudgetInfo& info = budget_map_[origin.spec()]; | 118 BudgetInfo& info = budget_map_[origin]; |
120 for (const auto& chunk : budget_proto->budget()) { | 119 for (const auto& chunk : budget_proto->budget()) { |
121 info.chunks.emplace_back(chunk.amount(), | 120 info.chunks.emplace_back(chunk.amount(), |
122 base::Time::FromInternalValue(chunk.expiration())); | 121 base::Time::FromInternalValue(chunk.expiration())); |
123 } | 122 } |
124 | 123 |
125 info.last_engagement_award = | 124 info.last_engagement_award = |
126 base::Time::FromInternalValue(budget_proto->engagement_last_updated()); | 125 base::Time::FromInternalValue(budget_proto->engagement_last_updated()); |
127 | 126 |
128 callback.Run(success); | 127 callback.Run(success); |
129 } | 128 } |
130 | 129 |
131 void BudgetDatabase::GetBudgetAfterSync(const GURL& origin, | 130 void BudgetDatabase::GetBudgetAfterSync(const url::Origin& origin, |
132 const GetBudgetCallback& callback, | 131 const GetBudgetCallback& callback, |
133 bool success) { | 132 bool success) { |
134 mojo::Array<blink::mojom::BudgetStatePtr> predictions; | 133 mojo::Array<blink::mojom::BudgetStatePtr> predictions; |
135 | 134 |
136 // If the database wasn't able to read the information, return the | 135 // If the database wasn't able to read the information, return the |
137 // failure and an empty predictions array. | 136 // failure and an empty predictions array. |
138 if (!success) { | 137 if (!success) { |
139 callback.Run(blink::mojom::BudgetServiceErrorType::DATABASE_ERROR, | 138 callback.Run(blink::mojom::BudgetServiceErrorType::DATABASE_ERROR, |
140 std::move(predictions)); | 139 std::move(predictions)); |
141 return; | 140 return; |
142 } | 141 } |
143 | 142 |
144 // Now, build up the BudgetExpection. This is different from the format | 143 // Now, build up the BudgetExpection. This is different from the format |
145 // in which the cache stores the data. The cache stores chunks of budget and | 144 // in which the cache stores the data. The cache stores chunks of budget and |
146 // when that budget expires. The mojo array describes a set of times | 145 // when that budget expires. The mojo array describes a set of times |
147 // and the budget at those times. | 146 // and the budget at those times. |
148 double total = GetBudget(origin); | 147 double total = GetBudget(origin); |
149 | 148 |
150 // Always add one entry at the front of the list for the total budget now. | 149 // Always add one entry at the front of the list for the total budget now. |
151 blink::mojom::BudgetStatePtr prediction(blink::mojom::BudgetState::New()); | 150 blink::mojom::BudgetStatePtr prediction(blink::mojom::BudgetState::New()); |
152 prediction->budget_at = total; | 151 prediction->budget_at = total; |
153 prediction->time = clock_->Now().ToDoubleT(); | 152 prediction->time = clock_->Now().ToDoubleT(); |
154 predictions.push_back(std::move(prediction)); | 153 predictions.push_back(std::move(prediction)); |
155 | 154 |
156 // Starting with the soonest expiring chunks, add entries for the | 155 // Starting with the soonest expiring chunks, add entries for the |
157 // expiration times going forward. | 156 // expiration times going forward. |
158 const BudgetChunks& chunks = budget_map_[origin.spec()].chunks; | 157 const BudgetChunks& chunks = budget_map_[origin].chunks; |
159 for (const auto& chunk : chunks) { | 158 for (const auto& chunk : chunks) { |
160 blink::mojom::BudgetStatePtr prediction(blink::mojom::BudgetState::New()); | 159 blink::mojom::BudgetStatePtr prediction(blink::mojom::BudgetState::New()); |
161 total -= chunk.amount; | 160 total -= chunk.amount; |
162 prediction->budget_at = total; | 161 prediction->budget_at = total; |
163 prediction->time = chunk.expiration.ToDoubleT(); | 162 prediction->time = chunk.expiration.ToDoubleT(); |
164 predictions.push_back(std::move(prediction)); | 163 predictions.push_back(std::move(prediction)); |
165 } | 164 } |
166 | 165 |
167 DCHECK_EQ(0, total); | 166 DCHECK_EQ(0, total); |
168 | 167 |
169 callback.Run(blink::mojom::BudgetServiceErrorType::NONE, | 168 callback.Run(blink::mojom::BudgetServiceErrorType::NONE, |
170 std::move(predictions)); | 169 std::move(predictions)); |
171 } | 170 } |
172 | 171 |
173 void BudgetDatabase::SpendBudgetAfterSync(const GURL& origin, | 172 void BudgetDatabase::SpendBudgetAfterSync(const url::Origin& origin, |
174 double amount, | 173 double amount, |
175 const StoreBudgetCallback& callback, | 174 const StoreBudgetCallback& callback, |
176 bool success) { | 175 bool success) { |
177 if (!success) { | 176 if (!success) { |
178 callback.Run(false /* success */); | 177 callback.Run(false /* success */); |
179 return; | 178 return; |
180 } | 179 } |
181 | 180 |
182 // Get the current SES score, to generate UMA. | 181 // Get the current SES score, to generate UMA. |
183 SiteEngagementService* service = SiteEngagementService::Get(profile_); | 182 SiteEngagementService* service = SiteEngagementService::Get(profile_); |
184 double score = service->GetScore(origin); | 183 double score = service->GetScore(GURL(origin.Serialize())); |
185 | 184 |
186 // Walk the list of budget chunks to see if the origin has enough budget. | 185 // Walk the list of budget chunks to see if the origin has enough budget. |
187 double total = 0; | 186 double total = 0; |
188 BudgetInfo& info = budget_map_[origin.spec()]; | 187 BudgetInfo& info = budget_map_[origin]; |
189 for (const BudgetChunk& chunk : info.chunks) | 188 for (const BudgetChunk& chunk : info.chunks) |
190 total += chunk.amount; | 189 total += chunk.amount; |
191 | 190 |
192 if (total < amount) { | 191 if (total < amount) { |
193 UMA_HISTOGRAM_COUNTS_100("PushMessaging.SESForNoBudgetOrigin", score); | 192 UMA_HISTOGRAM_COUNTS_100("PushMessaging.SESForNoBudgetOrigin", score); |
194 callback.Run(false /* success */); | 193 callback.Run(false /* success */); |
195 return; | 194 return; |
196 } else if (total < amount * 2) { | 195 } else if (total < amount * 2) { |
197 UMA_HISTOGRAM_COUNTS_100("PushMessaging.SESForLowBudgetOrigin", score); | 196 UMA_HISTOGRAM_COUNTS_100("PushMessaging.SESForLowBudgetOrigin", score); |
198 } | 197 } |
(...skipping 16 matching lines...) Expand all Loading... |
215 // Now that the cache is updated, write the data to the database. | 214 // Now that the cache is updated, write the data to the database. |
216 // TODO(harkness): Consider adding a second parameter to the callback so the | 215 // TODO(harkness): Consider adding a second parameter to the callback so the |
217 // caller can distinguish between not enough budget and a failed database | 216 // caller can distinguish between not enough budget and a failed database |
218 // write. | 217 // write. |
219 // TODO(harkness): If the database write fails, the cache will be out of sync | 218 // TODO(harkness): If the database write fails, the cache will be out of sync |
220 // with the database. Consider ways to mitigate this. | 219 // with the database. Consider ways to mitigate this. |
221 WriteCachedValuesToDatabase(origin, callback); | 220 WriteCachedValuesToDatabase(origin, callback); |
222 } | 221 } |
223 | 222 |
224 void BudgetDatabase::WriteCachedValuesToDatabase( | 223 void BudgetDatabase::WriteCachedValuesToDatabase( |
225 const GURL& origin, | 224 const url::Origin& origin, |
226 const StoreBudgetCallback& callback) { | 225 const StoreBudgetCallback& callback) { |
227 // Create the data structures that are passed to the ProtoDatabase. | 226 // Create the data structures that are passed to the ProtoDatabase. |
228 std::unique_ptr< | 227 std::unique_ptr< |
229 leveldb_proto::ProtoDatabase<budget_service::Budget>::KeyEntryVector> | 228 leveldb_proto::ProtoDatabase<budget_service::Budget>::KeyEntryVector> |
230 entries(new leveldb_proto::ProtoDatabase< | 229 entries(new leveldb_proto::ProtoDatabase< |
231 budget_service::Budget>::KeyEntryVector()); | 230 budget_service::Budget>::KeyEntryVector()); |
232 std::unique_ptr<std::vector<std::string>> keys_to_remove( | 231 std::unique_ptr<std::vector<std::string>> keys_to_remove( |
233 new std::vector<std::string>()); | 232 new std::vector<std::string>()); |
234 | 233 |
235 // Each operation can either update the existing budget or remove the origin's | 234 // Each operation can either update the existing budget or remove the origin's |
236 // budget information. | 235 // budget information. |
237 if (IsCached(origin)) { | 236 if (IsCached(origin)) { |
238 // Build the Budget proto object. | 237 // Build the Budget proto object. |
239 budget_service::Budget budget; | 238 budget_service::Budget budget; |
240 const BudgetInfo& info = budget_map_[origin.spec()]; | 239 const BudgetInfo& info = budget_map_[origin]; |
241 for (const auto& chunk : info.chunks) { | 240 for (const auto& chunk : info.chunks) { |
242 budget_service::BudgetChunk* budget_chunk = budget.add_budget(); | 241 budget_service::BudgetChunk* budget_chunk = budget.add_budget(); |
243 budget_chunk->set_amount(chunk.amount); | 242 budget_chunk->set_amount(chunk.amount); |
244 budget_chunk->set_expiration(chunk.expiration.ToInternalValue()); | 243 budget_chunk->set_expiration(chunk.expiration.ToInternalValue()); |
245 } | 244 } |
246 budget.set_engagement_last_updated( | 245 budget.set_engagement_last_updated( |
247 info.last_engagement_award.ToInternalValue()); | 246 info.last_engagement_award.ToInternalValue()); |
248 entries->push_back(std::make_pair(origin.spec(), budget)); | 247 entries->push_back(std::make_pair(origin.Serialize(), budget)); |
249 } else { | 248 } else { |
250 // If the origin doesn't exist in the cache, this is a remove operation. | 249 // If the origin doesn't exist in the cache, this is a remove operation. |
251 keys_to_remove->push_back(origin.spec()); | 250 keys_to_remove->push_back(origin.Serialize()); |
252 } | 251 } |
253 | 252 |
254 // Send the updates to the database. | 253 // Send the updates to the database. |
255 db_->UpdateEntries(std::move(entries), std::move(keys_to_remove), callback); | 254 db_->UpdateEntries(std::move(entries), std::move(keys_to_remove), callback); |
256 } | 255 } |
257 | 256 |
258 void BudgetDatabase::SyncCache(const GURL& origin, | 257 void BudgetDatabase::SyncCache(const url::Origin& origin, |
259 const SyncCacheCallback& callback) { | 258 const SyncCacheCallback& callback) { |
260 DCHECK_EQ(origin, origin.GetOrigin()); | |
261 | |
262 // If the origin isn't already cached, add it to the cache. | 259 // If the origin isn't already cached, add it to the cache. |
263 if (!IsCached(origin)) { | 260 if (!IsCached(origin)) { |
264 AddToCacheCallback add_callback = | 261 AddToCacheCallback add_callback = |
265 base::Bind(&BudgetDatabase::SyncLoadedCache, | 262 base::Bind(&BudgetDatabase::SyncLoadedCache, |
266 weak_ptr_factory_.GetWeakPtr(), origin, callback); | 263 weak_ptr_factory_.GetWeakPtr(), origin, callback); |
267 db_->GetEntry(origin.spec(), base::Bind(&BudgetDatabase::AddToCache, | 264 db_->GetEntry(origin.Serialize(), base::Bind(&BudgetDatabase::AddToCache, |
268 weak_ptr_factory_.GetWeakPtr(), | 265 weak_ptr_factory_.GetWeakPtr(), |
269 origin, add_callback)); | 266 origin, add_callback)); |
270 return; | 267 return; |
271 } | 268 } |
272 SyncLoadedCache(origin, callback, true /* success */); | 269 SyncLoadedCache(origin, callback, true /* success */); |
273 } | 270 } |
274 | 271 |
275 void BudgetDatabase::SyncLoadedCache(const GURL& origin, | 272 void BudgetDatabase::SyncLoadedCache(const url::Origin& origin, |
276 const SyncCacheCallback& callback, | 273 const SyncCacheCallback& callback, |
277 bool success) { | 274 bool success) { |
278 if (!success) { | 275 if (!success) { |
279 callback.Run(false /* success */); | 276 callback.Run(false /* success */); |
280 return; | 277 return; |
281 } | 278 } |
282 | 279 |
283 // Now, cleanup any expired budget chunks for the origin. | 280 // Now, cleanup any expired budget chunks for the origin. |
284 bool needs_write = CleanupExpiredBudget(origin); | 281 bool needs_write = CleanupExpiredBudget(origin); |
285 | 282 |
286 // Get the SES score and add engagement budget for the site. | 283 // Get the SES score and add engagement budget for the site. |
287 AddEngagementBudget(origin); | 284 AddEngagementBudget(origin); |
288 | 285 |
289 if (needs_write) | 286 if (needs_write) |
290 WriteCachedValuesToDatabase(origin, callback); | 287 WriteCachedValuesToDatabase(origin, callback); |
291 else | 288 else |
292 callback.Run(success); | 289 callback.Run(success); |
293 } | 290 } |
294 | 291 |
295 void BudgetDatabase::AddEngagementBudget(const GURL& origin) { | 292 void BudgetDatabase::AddEngagementBudget(const url::Origin& origin) { |
296 // Get the current SES score, which we'll use to set a new budget. | 293 // Get the current SES score, which we'll use to set a new budget. |
297 SiteEngagementService* service = SiteEngagementService::Get(profile_); | 294 SiteEngagementService* service = SiteEngagementService::Get(profile_); |
298 double score = service->GetScore(origin); | 295 double score = service->GetScore(GURL(origin.Serialize())); |
299 | 296 |
300 // By default we award the "full" award. Then that ratio is decreased if | 297 // By default we award the "full" award. Then that ratio is decreased if |
301 // there have been other awards recently. | 298 // there have been other awards recently. |
302 double ratio = 1.0; | 299 double ratio = 1.0; |
303 | 300 |
304 // Calculate how much budget should be awarded. If there is no entry in the | 301 // Calculate how much budget should be awarded. If there is no entry in the |
305 // cache then we award a full amount. | 302 // cache then we award a full amount. |
306 if (IsCached(origin)) { | 303 if (IsCached(origin)) { |
307 base::TimeDelta elapsed = | 304 base::TimeDelta elapsed = |
308 clock_->Now() - budget_map_[origin.spec()].last_engagement_award; | 305 clock_->Now() - budget_map_[origin].last_engagement_award; |
309 int elapsed_hours = elapsed.InHours(); | 306 int elapsed_hours = elapsed.InHours(); |
310 // Don't give engagement awards for periods less than an hour. | 307 // Don't give engagement awards for periods less than an hour. |
311 if (elapsed_hours < 1) | 308 if (elapsed_hours < 1) |
312 return; | 309 return; |
313 if (elapsed_hours < kBudgetDurationInHours) | 310 if (elapsed_hours < kBudgetDurationInHours) |
314 ratio = elapsed_hours / kBudgetDurationInHours; | 311 ratio = elapsed_hours / kBudgetDurationInHours; |
315 } | 312 } |
316 | 313 |
317 // Update the last_engagement_award to the current time. If the origin wasn't | 314 // Update the last_engagement_award to the current time. If the origin wasn't |
318 // already in the map, this adds a new entry for it. | 315 // already in the map, this adds a new entry for it. |
319 budget_map_[origin.spec()].last_engagement_award = clock_->Now(); | 316 budget_map_[origin].last_engagement_award = clock_->Now(); |
320 | 317 |
321 // Add a new chunk of budget for the origin at the default expiration time. | 318 // Add a new chunk of budget for the origin at the default expiration time. |
322 base::Time expiration = | 319 base::Time expiration = |
323 clock_->Now() + base::TimeDelta::FromHours(kBudgetDurationInHours); | 320 clock_->Now() + base::TimeDelta::FromHours(kBudgetDurationInHours); |
324 budget_map_[origin.spec()].chunks.emplace_back(ratio * score, expiration); | 321 budget_map_[origin].chunks.emplace_back(ratio * score, expiration); |
325 | 322 |
326 // Any time we award engagement budget, which is done at most once an hour | 323 // Any time we award engagement budget, which is done at most once an hour |
327 // whenever any budget action is taken, record the budget. | 324 // whenever any budget action is taken, record the budget. |
328 double budget = GetBudget(origin); | 325 double budget = GetBudget(origin); |
329 UMA_HISTOGRAM_COUNTS_100("PushMessaging.BackgroundBudget", budget); | 326 UMA_HISTOGRAM_COUNTS_100("PushMessaging.BackgroundBudget", budget); |
330 } | 327 } |
331 | 328 |
332 // Cleans up budget in the cache. Relies on the caller eventually writing the | 329 // Cleans up budget in the cache. Relies on the caller eventually writing the |
333 // cache back to the database. | 330 // cache back to the database. |
334 bool BudgetDatabase::CleanupExpiredBudget(const GURL& origin) { | 331 bool BudgetDatabase::CleanupExpiredBudget(const url::Origin& origin) { |
335 if (!IsCached(origin)) | 332 if (!IsCached(origin)) |
336 return false; | 333 return false; |
337 | 334 |
338 base::Time now = clock_->Now(); | 335 base::Time now = clock_->Now(); |
339 BudgetChunks& chunks = budget_map_[origin.spec()].chunks; | 336 BudgetChunks& chunks = budget_map_[origin].chunks; |
340 auto cleanup_iter = chunks.begin(); | 337 auto cleanup_iter = chunks.begin(); |
341 | 338 |
342 // This relies on the list of chunks being in timestamp order. | 339 // This relies on the list of chunks being in timestamp order. |
343 while (cleanup_iter != chunks.end() && cleanup_iter->expiration <= now) | 340 while (cleanup_iter != chunks.end() && cleanup_iter->expiration <= now) |
344 cleanup_iter = chunks.erase(cleanup_iter); | 341 cleanup_iter = chunks.erase(cleanup_iter); |
345 | 342 |
346 // If the entire budget is empty now AND there have been no engagements | 343 // If the entire budget is empty now AND there have been no engagements |
347 // in the last kBudgetDurationInHours hours, remove this from the cache. | 344 // in the last kBudgetDurationInHours hours, remove this from the cache. |
348 if (chunks.empty() && | 345 if (chunks.empty() && |
349 budget_map_[origin.spec()].last_engagement_award < | 346 budget_map_[origin].last_engagement_award < |
350 clock_->Now() - base::TimeDelta::FromHours(kBudgetDurationInHours)) { | 347 clock_->Now() - base::TimeDelta::FromHours(kBudgetDurationInHours)) { |
351 budget_map_.erase(origin.spec()); | 348 budget_map_.erase(origin); |
352 return true; | 349 return true; |
353 } | 350 } |
354 | 351 |
355 // Although some things may have expired, there are some chunks still valid. | 352 // Although some things may have expired, there are some chunks still valid. |
356 // Don't write to the DB now, write either when all chunks expire or when the | 353 // Don't write to the DB now, write either when all chunks expire or when the |
357 // origin spends some budget. | 354 // origin spends some budget. |
358 return false; | 355 return false; |
359 } | 356 } |
OLD | NEW |