OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/extensions/extension_storage_monitor.h" | 5 #include "chrome/browser/extensions/extension_storage_monitor.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 // threshold than installed extensions and apps. Once a threshold is exceeded, | 47 // threshold than installed extensions and apps. Once a threshold is exceeded, |
48 // it will be doubled to throttle notifications. | 48 // it will be doubled to throttle notifications. |
49 const int64 kMBytes = 1024 * 1024; | 49 const int64 kMBytes = 1024 * 1024; |
50 const int64 kEphemeralAppInitialThreshold = 250 * kMBytes; | 50 const int64 kEphemeralAppInitialThreshold = 250 * kMBytes; |
51 const int64 kExtensionInitialThreshold = 1000 * kMBytes; | 51 const int64 kExtensionInitialThreshold = 1000 * kMBytes; |
52 | 52 |
53 // Notifications have an ID so that we can update them. | 53 // Notifications have an ID so that we can update them. |
54 const char kNotificationIdFormat[] = "ExtensionStorageMonitor-$1-$2"; | 54 const char kNotificationIdFormat[] = "ExtensionStorageMonitor-$1-$2"; |
55 const char kSystemNotifierId[] = "ExtensionStorageMonitor"; | 55 const char kSystemNotifierId[] = "ExtensionStorageMonitor"; |
56 | 56 |
| 57 // A preference that stores the next threshold for displaying a notification |
| 58 // when an extension or app consumes excessive disk space. This will not be |
| 59 // set until the extension/app reaches the initial threshold. |
| 60 const char kPrefNextStorageThreshold[] = "next_storage_threshold"; |
| 61 |
| 62 // If this preference is set to true, notifications will be suppressed when an |
| 63 // extension or app consumes excessive disk space. |
| 64 const char kPrefDisableStorageNotifications[] = "disable_storage_notifications"; |
| 65 |
| 66 bool ShouldMonitorStorageFor(const Extension* extension) { |
| 67 // Only monitor storage for extensions that are granted unlimited storage. |
| 68 // Do not monitor storage for component extensions. |
| 69 return extension->HasAPIPermission(APIPermission::kUnlimitedStorage) && |
| 70 extension->location() != Manifest::COMPONENT; |
| 71 } |
| 72 |
57 } // namespace | 73 } // namespace |
58 | 74 |
59 // StorageEventObserver monitors the storage usage of extensions and lives on | 75 // StorageEventObserver monitors the storage usage of extensions and lives on |
60 // the IO thread. When a threshold is exceeded, a message will be posted to the | 76 // the IO thread. When a threshold is exceeded, a message will be posted to the |
61 // UI thread, which displays the notification. | 77 // UI thread, which displays the notification. |
62 class StorageEventObserver | 78 class StorageEventObserver |
63 : public base::RefCountedThreadSafe< | 79 : public base::RefCountedThreadSafe< |
64 StorageEventObserver, | 80 StorageEventObserver, |
65 BrowserThread::DeleteOnIOThread>, | 81 BrowserThread::DeleteOnIOThread>, |
66 public quota::StorageObserver { | 82 public quota::StorageObserver { |
(...skipping 20 matching lines...) Expand all Loading... |
87 state.next_threshold = next_threshold; | 103 state.next_threshold = next_threshold; |
88 | 104 |
89 quota::StorageObserver::MonitorParams params( | 105 quota::StorageObserver::MonitorParams params( |
90 kMonitorStorageType, | 106 kMonitorStorageType, |
91 origin, | 107 origin, |
92 base::TimeDelta::FromSeconds(rate), | 108 base::TimeDelta::FromSeconds(rate), |
93 false); | 109 false); |
94 quota_manager->AddStorageObserver(this, params); | 110 quota_manager->AddStorageObserver(this, params); |
95 } | 111 } |
96 | 112 |
| 113 // Updates the threshold for an extension already being monitored. |
| 114 void UpdateThresholdForExtension(const std::string& extension_id, |
| 115 int64 next_threshold) { |
| 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 117 |
| 118 for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); |
| 119 it != origin_state_map_.end(); |
| 120 ++it) { |
| 121 if (it->second.extension_id == extension_id) { |
| 122 it->second.next_threshold = next_threshold; |
| 123 break; |
| 124 } |
| 125 } |
| 126 } |
| 127 |
97 // Deregister as an observer for the extension's storage events. | 128 // Deregister as an observer for the extension's storage events. |
98 void StopObservingForExtension(const std::string& extension_id) { | 129 void StopObservingForExtension(const std::string& extension_id) { |
99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
100 | 131 |
101 for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); | 132 for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); |
102 it != origin_state_map_.end(); ) { | 133 it != origin_state_map_.end(); ) { |
103 if (it->second.extension_id == extension_id) { | 134 if (it->second.extension_id == extension_id) { |
104 quota::StorageObserver::Filter filter(kMonitorStorageType, it->first); | 135 quota::StorageObserver::Filter filter(kMonitorStorageType, it->first); |
105 it->second.quota_manager->RemoveStorageObserverForFilter(this, filter); | 136 it->second.quota_manager->RemoveStorageObserverForFilter(this, filter); |
106 origin_state_map_.erase(it++); | 137 origin_state_map_.erase(it++); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 return ExtensionStorageMonitorFactory::GetForBrowserContext(context); | 205 return ExtensionStorageMonitorFactory::GetForBrowserContext(context); |
175 } | 206 } |
176 | 207 |
177 ExtensionStorageMonitor::ExtensionStorageMonitor( | 208 ExtensionStorageMonitor::ExtensionStorageMonitor( |
178 content::BrowserContext* context) | 209 content::BrowserContext* context) |
179 : enable_for_all_extensions_(false), | 210 : enable_for_all_extensions_(false), |
180 initial_extension_threshold_(kExtensionInitialThreshold), | 211 initial_extension_threshold_(kExtensionInitialThreshold), |
181 initial_ephemeral_threshold_(kEphemeralAppInitialThreshold), | 212 initial_ephemeral_threshold_(kEphemeralAppInitialThreshold), |
182 observer_rate_(kStorageEventRateSec), | 213 observer_rate_(kStorageEventRateSec), |
183 context_(context), | 214 context_(context), |
| 215 extension_prefs_(ExtensionPrefs::Get(context)), |
| 216 extension_registry_observer_(this), |
184 weak_ptr_factory_(this) { | 217 weak_ptr_factory_(this) { |
185 registrar_.Add(this, | 218 DCHECK(extension_prefs_); |
186 chrome::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED, | 219 |
187 content::Source<content::BrowserContext>(context_)); | |
188 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 220 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
189 content::Source<content::BrowserContext>(context_)); | 221 content::Source<content::BrowserContext>(context_)); |
190 | 222 |
191 ExtensionRegistry* registry = ExtensionRegistry::Get(context_); | 223 extension_registry_observer_.Add(ExtensionRegistry::Get(context_)); |
192 DCHECK(registry); | |
193 registry->AddObserver(this); | |
194 } | 224 } |
195 | 225 |
196 ExtensionStorageMonitor::~ExtensionStorageMonitor() {} | 226 ExtensionStorageMonitor::~ExtensionStorageMonitor() {} |
197 | 227 |
198 void ExtensionStorageMonitor::Observe( | 228 void ExtensionStorageMonitor::Observe( |
199 int type, | 229 int type, |
200 const content::NotificationSource& source, | 230 const content::NotificationSource& source, |
201 const content::NotificationDetails& details) { | 231 const content::NotificationDetails& details) { |
202 switch (type) { | 232 switch (type) { |
203 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED: { | |
204 const Extension* extension = | |
205 content::Details<const Extension>(details).ptr(); | |
206 RemoveNotificationForExtension(extension->id()); | |
207 break; | |
208 } | |
209 case chrome::NOTIFICATION_PROFILE_DESTROYED: { | 233 case chrome::NOTIFICATION_PROFILE_DESTROYED: { |
210 StopMonitoringAll(); | 234 StopMonitoringAll(); |
211 break; | 235 break; |
212 } | 236 } |
213 default: | 237 default: |
214 NOTREACHED(); | 238 NOTREACHED(); |
215 } | 239 } |
216 } | 240 } |
217 | 241 |
218 void ExtensionStorageMonitor::OnExtensionLoaded( | 242 void ExtensionStorageMonitor::OnExtensionLoaded( |
219 content::BrowserContext* browser_context, | 243 content::BrowserContext* browser_context, |
220 const Extension* extension) { | 244 const Extension* extension) { |
221 DCHECK(extension); | |
222 StartMonitoringStorage(extension); | 245 StartMonitoringStorage(extension); |
223 } | 246 } |
224 | 247 |
225 void ExtensionStorageMonitor::OnExtensionUnloaded( | 248 void ExtensionStorageMonitor::OnExtensionUnloaded( |
226 content::BrowserContext* browser_context, | 249 content::BrowserContext* browser_context, |
227 const Extension* extension, | 250 const Extension* extension, |
228 UnloadedExtensionInfo::Reason reason) { | 251 UnloadedExtensionInfo::Reason reason) { |
229 DCHECK(extension); | |
230 StopMonitoringStorage(extension->id()); | 252 StopMonitoringStorage(extension->id()); |
231 } | 253 } |
232 | 254 |
| 255 void ExtensionStorageMonitor::OnExtensionWillBeInstalled( |
| 256 content::BrowserContext* browser_context, |
| 257 const Extension* extension, |
| 258 bool is_update, |
| 259 bool from_ephemeral, |
| 260 const std::string& old_name) { |
| 261 // If an ephemeral app was promoted to a regular installed app, we may need to |
| 262 // increase its next threshold. |
| 263 if (!from_ephemeral || !ShouldMonitorStorageFor(extension)) |
| 264 return; |
| 265 |
| 266 if (!enable_for_all_extensions_) { |
| 267 // If monitoring is not enabled for installed extensions, just stop |
| 268 // monitoring. |
| 269 SetNextStorageThreshold(extension->id(), 0); |
| 270 StopMonitoringStorage(extension->id()); |
| 271 return; |
| 272 } |
| 273 |
| 274 int64 next_threshold = GetNextStorageThresholdFromPrefs(extension->id()); |
| 275 if (next_threshold <= initial_extension_threshold_) { |
| 276 // Clear the next threshold in the prefs. This effectively raises it to |
| 277 // |initial_extension_threshold_|. If the current threshold is already |
| 278 // higher than this, leave it as is. |
| 279 SetNextStorageThreshold(extension->id(), 0); |
| 280 |
| 281 if (storage_observer_.get()) { |
| 282 BrowserThread::PostTask( |
| 283 BrowserThread::IO, |
| 284 FROM_HERE, |
| 285 base::Bind(&StorageEventObserver::UpdateThresholdForExtension, |
| 286 storage_observer_, |
| 287 extension->id(), |
| 288 initial_extension_threshold_)); |
| 289 } |
| 290 } |
| 291 } |
| 292 |
| 293 void ExtensionStorageMonitor::OnExtensionUninstalled( |
| 294 content::BrowserContext* browser_context, |
| 295 const Extension* extension) { |
| 296 RemoveNotificationForExtension(extension->id()); |
| 297 } |
| 298 |
233 std::string ExtensionStorageMonitor::GetNotificationId( | 299 std::string ExtensionStorageMonitor::GetNotificationId( |
234 const std::string& extension_id) { | 300 const std::string& extension_id) { |
235 std::vector<std::string> placeholders; | 301 std::vector<std::string> placeholders; |
236 placeholders.push_back(context_->GetPath().BaseName().MaybeAsASCII()); | 302 placeholders.push_back(context_->GetPath().BaseName().MaybeAsASCII()); |
237 placeholders.push_back(extension_id); | 303 placeholders.push_back(extension_id); |
238 | 304 |
239 return ReplaceStringPlaceholders(kNotificationIdFormat, placeholders, NULL); | 305 return ReplaceStringPlaceholders(kNotificationIdFormat, placeholders, NULL); |
240 } | 306 } |
241 | 307 |
242 void ExtensionStorageMonitor::OnStorageThresholdExceeded( | 308 void ExtensionStorageMonitor::OnStorageThresholdExceeded( |
243 const std::string& extension_id, | 309 const std::string& extension_id, |
244 int64 next_threshold, | 310 int64 next_threshold, |
245 int64 current_usage) { | 311 int64 current_usage) { |
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
247 | 313 |
248 const Extension* extension = ExtensionRegistry::Get(context_)-> | 314 const Extension* extension = ExtensionRegistry::Get(context_)-> |
249 GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); | 315 GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); |
250 if (!extension) | 316 if (!extension) |
251 return; | 317 return; |
252 | 318 |
253 ExtensionPrefs* prefs = ExtensionPrefs::Get(context_); | 319 if (GetNextStorageThreshold(extension->id()) < next_threshold) |
254 DCHECK(prefs); | 320 SetNextStorageThreshold(extension->id(), next_threshold); |
255 prefs->SetNextStorageThreshold(extension->id(), next_threshold); | |
256 | 321 |
257 const int kIconSize = message_center::kNotificationIconSize; | 322 const int kIconSize = message_center::kNotificationIconSize; |
258 ExtensionResource resource = IconsInfo::GetIconResource( | 323 ExtensionResource resource = IconsInfo::GetIconResource( |
259 extension, kIconSize, ExtensionIconSet::MATCH_BIGGER); | 324 extension, kIconSize, ExtensionIconSet::MATCH_BIGGER); |
260 ImageLoader::Get(context_)->LoadImageAsync( | 325 ImageLoader::Get(context_)->LoadImageAsync( |
261 extension, resource, gfx::Size(kIconSize, kIconSize), | 326 extension, resource, gfx::Size(kIconSize, kIconSize), |
262 base::Bind(&ExtensionStorageMonitor::OnImageLoaded, | 327 base::Bind(&ExtensionStorageMonitor::OnImageLoaded, |
263 weak_ptr_factory_.GetWeakPtr(), | 328 weak_ptr_factory_.GetWeakPtr(), |
264 extension_id, | 329 extension_id, |
265 current_usage)); | 330 current_usage)); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 } | 390 } |
326 default: | 391 default: |
327 NOTREACHED(); | 392 NOTREACHED(); |
328 } | 393 } |
329 } | 394 } |
330 | 395 |
331 void ExtensionStorageMonitor::DisableStorageMonitoring( | 396 void ExtensionStorageMonitor::DisableStorageMonitoring( |
332 const std::string& extension_id) { | 397 const std::string& extension_id) { |
333 StopMonitoringStorage(extension_id); | 398 StopMonitoringStorage(extension_id); |
334 | 399 |
335 ExtensionPrefs* prefs = ExtensionPrefs::Get(context_); | 400 SetStorageNotificationEnabled(extension_id, false); |
336 DCHECK(prefs); | |
337 prefs->SetStorageNotificationEnabled(extension_id, false); | |
338 | 401 |
339 message_center::MessageCenter::Get()->RemoveNotification( | 402 message_center::MessageCenter::Get()->RemoveNotification( |
340 GetNotificationId(extension_id), false); | 403 GetNotificationId(extension_id), false); |
341 } | 404 } |
342 | 405 |
343 void ExtensionStorageMonitor::StartMonitoringStorage( | 406 void ExtensionStorageMonitor::StartMonitoringStorage( |
344 const Extension* extension) { | 407 const Extension* extension) { |
345 if (!extension->HasAPIPermission(APIPermission::kUnlimitedStorage)) | 408 if (!ShouldMonitorStorageFor(extension)) |
346 return; | 409 return; |
347 | 410 |
348 // Do not monitor storage for component extensions. | |
349 if (extension->location() == Manifest::COMPONENT) | |
350 return; | |
351 | |
352 ExtensionPrefs* prefs = ExtensionPrefs::Get(context_); | |
353 DCHECK(prefs); | |
354 | |
355 // First apply this feature only to experimental ephemeral apps. If it works | 411 // First apply this feature only to experimental ephemeral apps. If it works |
356 // well, roll it out to all extensions and apps. | 412 // well, roll it out to all extensions and apps. |
357 bool is_ephemeral = prefs->IsEphemeralApp(extension->id()); | 413 if (!enable_for_all_extensions_ && |
358 if (!is_ephemeral && !enable_for_all_extensions_) | 414 !extension_prefs_->IsEphemeralApp(extension->id())) { |
359 return; | 415 return; |
| 416 } |
360 | 417 |
361 if (!prefs->IsStorageNotificationEnabled(extension->id())) | 418 if (!IsStorageNotificationEnabled(extension->id())) |
362 return; | 419 return; |
363 | 420 |
364 // Lazily create the storage monitor proxy on the IO thread. | 421 // Lazily create the storage monitor proxy on the IO thread. |
365 if (!storage_observer_.get()) { | 422 if (!storage_observer_.get()) { |
366 storage_observer_ = | 423 storage_observer_ = |
367 new StorageEventObserver(weak_ptr_factory_.GetWeakPtr()); | 424 new StorageEventObserver(weak_ptr_factory_.GetWeakPtr()); |
368 } | 425 } |
369 | 426 |
370 GURL site_url = | 427 GURL site_url = |
371 extensions::util::GetSiteForExtensionId(extension->id(), context_); | 428 extensions::util::GetSiteForExtensionId(extension->id(), context_); |
372 content::StoragePartition* storage_partition = | 429 content::StoragePartition* storage_partition = |
373 content::BrowserContext::GetStoragePartitionForSite(context_, site_url); | 430 content::BrowserContext::GetStoragePartitionForSite(context_, site_url); |
374 DCHECK(storage_partition); | 431 DCHECK(storage_partition); |
375 scoped_refptr<quota::QuotaManager> quota_manager( | 432 scoped_refptr<quota::QuotaManager> quota_manager( |
376 storage_partition->GetQuotaManager()); | 433 storage_partition->GetQuotaManager()); |
377 | 434 |
378 GURL storage_origin(site_url.GetOrigin()); | 435 GURL storage_origin(site_url.GetOrigin()); |
379 if (extension->is_hosted_app()) | 436 if (extension->is_hosted_app()) |
380 storage_origin = AppLaunchInfo::GetLaunchWebURL(extension).GetOrigin(); | 437 storage_origin = AppLaunchInfo::GetLaunchWebURL(extension).GetOrigin(); |
381 | 438 |
382 int next_threshold = prefs->GetNextStorageThreshold(extension->id()); | |
383 if (next_threshold == 0) { | |
384 // The next threshold is written to the prefs after the initial threshold is | |
385 // exceeded. | |
386 next_threshold = is_ephemeral ? initial_ephemeral_threshold_ | |
387 : initial_extension_threshold_; | |
388 } | |
389 | |
390 BrowserThread::PostTask( | 439 BrowserThread::PostTask( |
391 BrowserThread::IO, | 440 BrowserThread::IO, |
392 FROM_HERE, | 441 FROM_HERE, |
393 base::Bind(&StorageEventObserver::StartObservingForExtension, | 442 base::Bind(&StorageEventObserver::StartObservingForExtension, |
394 storage_observer_, | 443 storage_observer_, |
395 quota_manager, | 444 quota_manager, |
396 extension->id(), | 445 extension->id(), |
397 storage_origin, | 446 storage_origin, |
398 next_threshold, | 447 GetNextStorageThreshold(extension->id()), |
399 observer_rate_)); | 448 observer_rate_)); |
400 } | 449 } |
401 | 450 |
402 void ExtensionStorageMonitor::StopMonitoringStorage( | 451 void ExtensionStorageMonitor::StopMonitoringStorage( |
403 const std::string& extension_id) { | 452 const std::string& extension_id) { |
404 if (!storage_observer_.get()) | 453 if (!storage_observer_.get()) |
405 return; | 454 return; |
406 | 455 |
407 BrowserThread::PostTask( | 456 BrowserThread::PostTask( |
408 BrowserThread::IO, | 457 BrowserThread::IO, |
409 FROM_HERE, | 458 FROM_HERE, |
410 base::Bind(&StorageEventObserver::StopObservingForExtension, | 459 base::Bind(&StorageEventObserver::StopObservingForExtension, |
411 storage_observer_, | 460 storage_observer_, |
412 extension_id)); | 461 extension_id)); |
413 } | 462 } |
414 | 463 |
415 void ExtensionStorageMonitor::StopMonitoringAll() { | 464 void ExtensionStorageMonitor::StopMonitoringAll() { |
416 ExtensionRegistry* registry = ExtensionRegistry::Get(context_); | 465 extension_registry_observer_.RemoveAll(); |
417 DCHECK(registry); | |
418 registry->RemoveObserver(this); | |
419 | 466 |
420 RemoveAllNotifications(); | 467 RemoveAllNotifications(); |
421 | 468 |
422 if (!storage_observer_.get()) | 469 if (!storage_observer_.get()) |
423 return; | 470 return; |
424 | 471 |
425 BrowserThread::PostTask( | 472 BrowserThread::PostTask( |
426 BrowserThread::IO, | 473 BrowserThread::IO, |
427 FROM_HERE, | 474 FROM_HERE, |
428 base::Bind(&StorageEventObserver::StopObserving, storage_observer_)); | 475 base::Bind(&StorageEventObserver::StopObserving, storage_observer_)); |
(...skipping 18 matching lines...) Expand all Loading... |
447 | 494 |
448 message_center::MessageCenter* center = message_center::MessageCenter::Get(); | 495 message_center::MessageCenter* center = message_center::MessageCenter::Get(); |
449 DCHECK(center); | 496 DCHECK(center); |
450 for (std::set<std::string>::iterator it = notified_extension_ids_.begin(); | 497 for (std::set<std::string>::iterator it = notified_extension_ids_.begin(); |
451 it != notified_extension_ids_.end(); ++it) { | 498 it != notified_extension_ids_.end(); ++it) { |
452 center->RemoveNotification(GetNotificationId(*it), false); | 499 center->RemoveNotification(GetNotificationId(*it), false); |
453 } | 500 } |
454 notified_extension_ids_.clear(); | 501 notified_extension_ids_.clear(); |
455 } | 502 } |
456 | 503 |
| 504 int64 ExtensionStorageMonitor::GetNextStorageThreshold( |
| 505 const std::string& extension_id) const { |
| 506 int next_threshold = GetNextStorageThresholdFromPrefs(extension_id); |
| 507 if (next_threshold == 0) { |
| 508 // The next threshold is written to the prefs after the initial threshold is |
| 509 // exceeded. |
| 510 next_threshold = extension_prefs_->IsEphemeralApp(extension_id) |
| 511 ? initial_ephemeral_threshold_ |
| 512 : initial_extension_threshold_; |
| 513 } |
| 514 return next_threshold; |
| 515 } |
| 516 |
| 517 void ExtensionStorageMonitor::SetNextStorageThreshold( |
| 518 const std::string& extension_id, |
| 519 int64 next_threshold) { |
| 520 extension_prefs_->UpdateExtensionPref( |
| 521 extension_id, |
| 522 kPrefNextStorageThreshold, |
| 523 next_threshold > 0 |
| 524 ? new base::StringValue(base::Int64ToString(next_threshold)) |
| 525 : NULL); |
| 526 } |
| 527 |
| 528 int64 ExtensionStorageMonitor::GetNextStorageThresholdFromPrefs( |
| 529 const std::string& extension_id) const { |
| 530 std::string next_threshold_str; |
| 531 if (extension_prefs_->ReadPrefAsString( |
| 532 extension_id, kPrefNextStorageThreshold, &next_threshold_str)) { |
| 533 int64 next_threshold; |
| 534 if (base::StringToInt64(next_threshold_str, &next_threshold)) |
| 535 return next_threshold; |
| 536 } |
| 537 |
| 538 // A return value of zero indicates that the initial threshold has not yet |
| 539 // been reached. |
| 540 return 0; |
| 541 } |
| 542 |
| 543 bool ExtensionStorageMonitor::IsStorageNotificationEnabled( |
| 544 const std::string& extension_id) const { |
| 545 bool disable_notifications; |
| 546 if (extension_prefs_->ReadPrefAsBoolean(extension_id, |
| 547 kPrefDisableStorageNotifications, |
| 548 &disable_notifications)) { |
| 549 return !disable_notifications; |
| 550 } |
| 551 |
| 552 return true; |
| 553 } |
| 554 |
| 555 void ExtensionStorageMonitor::SetStorageNotificationEnabled( |
| 556 const std::string& extension_id, |
| 557 bool enable_notifications) { |
| 558 extension_prefs_->UpdateExtensionPref( |
| 559 extension_id, |
| 560 kPrefDisableStorageNotifications, |
| 561 enable_notifications ? NULL : new base::FundamentalValue(true)); |
| 562 } |
| 563 |
457 } // namespace extensions | 564 } // namespace extensions |
OLD | NEW |