1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file. 4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/extension_storage_monitor.h" 6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <map> 8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/strings/string_number_conversions.h" 10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/strings/string_util.h" 11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/strings/utf_string_conversions.h" 12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/chrome_notification_types.h" 1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/extension_storage_monitor_factory.h" 15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/extension_util.h" 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/browser/browser_context.h" 20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/browser/browser_thread.h" 21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/browser/notification_details.h" 22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/browser/notification_source.h" 23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/browser/storage_partition.h" 24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/browser/extension_prefs.h" 25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/browser/extension_registry.h" 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/browser/extension_system.h" 276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/browser/image_loader.h" 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/uninstall_reason.h" 29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension.h" 30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h" 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h" 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/quota/quota_manager.h" 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/quota/storage_observer.h" 34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/base/l10n/l10n_util.h" 35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/message_center/message_center.h" 36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/message_center/notifier_settings.h" 37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/message_center/views/constants.h" 38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochusing content::BrowserThread; 40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace extensions { 42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace { 44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// The rate at which we would like to observe storage events. 46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int kStorageEventRateSec = 30; 47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// The storage type to monitor. 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const storage::StorageType kMonitorStorageType = 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) storage::kStorageTypePersistent; 51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Set the thresholds for the first notification. Ephemeral apps have a lower 53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// threshold than installed extensions and apps. Once a threshold is exceeded, 54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// it will be doubled to throttle notifications. 55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int64 kMBytes = 1024 * 1024; 56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int64 kEphemeralAppInitialThreshold = 250 * kMBytes; 57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int64 kExtensionInitialThreshold = 1000 * kMBytes; 58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Notifications have an ID so that we can update them. 60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kNotificationIdFormat[] = "ExtensionStorageMonitor-$1-$2"; 61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kSystemNotifierId[] = "ExtensionStorageMonitor"; 62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// A preference that stores the next threshold for displaying a notification 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// when an extension or app consumes excessive disk space. This will not be 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// set until the extension/app reaches the initial threshold. 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kPrefNextStorageThreshold[] = "next_storage_threshold"; 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// If this preference is set to true, notifications will be suppressed when an 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// extension or app consumes excessive disk space. 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kPrefDisableStorageNotifications[] = "disable_storage_notifications"; 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ShouldMonitorStorageFor(const Extension* extension) { 7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Only monitor storage for extensions that are granted unlimited storage. 7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Do not monitor storage for component extensions. 7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return extension->permissions_data()->HasAPIPermission( 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermission::kUnlimitedStorage) && 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->location() != Manifest::COMPONENT; 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const Extension* GetExtensionById(content::BrowserContext* context, 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& extension_id) { 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return ExtensionRegistry::Get(context)->GetExtensionById( 8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_id, ExtensionRegistry::EVERYTHING); 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} // namespace 87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// StorageEventObserver monitors the storage usage of extensions and lives on 89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// the IO thread. When a threshold is exceeded, a message will be posted to the 90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// UI thread, which displays the notification. 91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass StorageEventObserver 9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : public base::RefCountedThreadSafe<StorageEventObserver, 9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::DeleteOnIOThread>, 9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public storage::StorageObserver { 95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public: 96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch explicit StorageEventObserver( 97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::WeakPtr<ExtensionStorageMonitor> storage_monitor) 98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch : storage_monitor_(storage_monitor) { 99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Register as an observer for the extension's storage events. 102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void StartObservingForExtension( 10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<storage::QuotaManager> quota_manager, 104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string& extension_id, 105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const GURL& site_url, 106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 next_threshold, 107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int rate) { 108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(quota_manager.get()); 110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GURL origin = site_url.GetOrigin(); 112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StorageState& state = origin_state_map_[origin]; 113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch state.quota_manager = quota_manager; 114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch state.extension_id = extension_id; 115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch state.next_threshold = next_threshold; 116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) storage::StorageObserver::MonitorParams params( 11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) kMonitorStorageType, origin, base::TimeDelta::FromSeconds(rate), false); 119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch quota_manager->AddStorageObserver(this, params); 120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Updates the threshold for an extension already being monitored. 12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void UpdateThresholdForExtension(const std::string& extension_id, 12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int64 next_threshold) { 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); 12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != origin_state_map_.end(); 12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ++it) { 13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (it->second.extension_id == extension_id) { 13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it->second.next_threshold = next_threshold; 13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) break; 13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Deregister as an observer for the extension's storage events. 138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void StopObservingForExtension(const std::string& extension_id) { 139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); 142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch it != origin_state_map_.end(); ) { 143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (it->second.extension_id == extension_id) { 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) storage::StorageObserver::Filter filter(kMonitorStorageType, it->first); 145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch it->second.quota_manager->RemoveStorageObserverForFilter(this, filter); 146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch origin_state_map_.erase(it++); 147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } else { 148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ++it; 149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Stop observing all storage events. Called during shutdown. 154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void StopObserving() { 155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); 158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch it != origin_state_map_.end(); ++it) { 159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch it->second.quota_manager->RemoveStorageObserver(this); 160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch origin_state_map_.clear(); 162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private: 165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch friend class base::DeleteHelper<StorageEventObserver>; 166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch friend struct content::BrowserThread::DeleteOnThread< 167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch content::BrowserThread::IO>; 168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch struct StorageState { 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<storage::QuotaManager> quota_manager; 171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch std::string extension_id; 172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 next_threshold; 173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StorageState() : next_threshold(0) {} 175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }; 176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch typedef std::map<GURL, StorageState> OriginStorageStateMap; 177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch virtual ~StorageEventObserver() { 179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(origin_state_map_.empty()); 180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StopObserving(); 181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // storage::StorageObserver implementation. 184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch virtual void OnStorageEvent(const Event& event) OVERRIDE { 185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OriginStorageStateMap::iterator state = 186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch origin_state_map_.find(event.filter.origin); 187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (state == origin_state_map_.end()) 188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (event.usage >= state->second.next_threshold) { 191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch while (event.usage >= state->second.next_threshold) 192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch state->second.next_threshold *= 2; 193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BrowserThread::PostTask( 195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BrowserThread::UI, 196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FROM_HERE, 197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&ExtensionStorageMonitor::OnStorageThresholdExceeded, 198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch storage_monitor_, 199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch state->second.extension_id, 200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch state->second.next_threshold, 201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch event.usage)); 202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OriginStorageStateMap origin_state_map_; 206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::WeakPtr<ExtensionStorageMonitor> storage_monitor_; 207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}; 208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// ExtensionStorageMonitor 210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// static 212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochExtensionStorageMonitor* ExtensionStorageMonitor::Get( 213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch content::BrowserContext* context) { 214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return ExtensionStorageMonitorFactory::GetForBrowserContext(context); 215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochExtensionStorageMonitor::ExtensionStorageMonitor( 218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch content::BrowserContext* context) 219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch : enable_for_all_extensions_(false), 220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch initial_extension_threshold_(kExtensionInitialThreshold), 221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch initial_ephemeral_threshold_(kEphemeralAppInitialThreshold), 222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch observer_rate_(kStorageEventRateSec), 223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch context_(context), 22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_prefs_(ExtensionPrefs::Get(context)), 22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_registry_observer_(this), 226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch weak_ptr_factory_(this) { 22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(extension_prefs_); 22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch content::Source<content::BrowserContext>(context_)); 231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_registry_observer_.Add(ExtensionRegistry::Get(context_)); 233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochExtensionStorageMonitor::~ExtensionStorageMonitor() {} 236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::Observe( 238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int type, 239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const content::NotificationSource& source, 240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const content::NotificationDetails& details) { 241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch switch (type) { 242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch case chrome::NOTIFICATION_PROFILE_DESTROYED: { 243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StopMonitoringAll(); 244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch break; 245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch default: 247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch NOTREACHED(); 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::OnExtensionLoaded( 252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch content::BrowserContext* browser_context, 253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const Extension* extension) { 254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StartMonitoringStorage(extension); 255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::OnExtensionUnloaded( 258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch content::BrowserContext* browser_context, 2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const Extension* extension, 2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch UnloadedExtensionInfo::Reason reason) { 261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StopMonitoringStorage(extension->id()); 262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ExtensionStorageMonitor::OnExtensionWillBeInstalled( 26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) content::BrowserContext* browser_context, 26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Extension* extension, 26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool is_update, 26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool from_ephemeral, 26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& old_name) { 27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // If an ephemeral app was promoted to a regular installed app, we may need to 27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // increase its next threshold. 27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!from_ephemeral || !ShouldMonitorStorageFor(extension)) 27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!enable_for_all_extensions_) { 27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // If monitoring is not enabled for installed extensions, just stop 27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // monitoring. 27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SetNextStorageThreshold(extension->id(), 0); 27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) StopMonitoringStorage(extension->id()); 28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int64 next_threshold = GetNextStorageThresholdFromPrefs(extension->id()); 28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (next_threshold <= initial_extension_threshold_) { 28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Clear the next threshold in the prefs. This effectively raises it to 28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // |initial_extension_threshold_|. If the current threshold is already 28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // higher than this, leave it as is. 28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SetNextStorageThreshold(extension->id(), 0); 28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (storage_observer_.get()) { 29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::PostTask( 29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::IO, 29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&StorageEventObserver::UpdateThresholdForExtension, 29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) storage_observer_, 29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->id(), 29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) initial_extension_threshold_)); 29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 30146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 30246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ExtensionStorageMonitor::OnExtensionUninstalled( 30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) content::BrowserContext* browser_context, 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const Extension* extension, 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UninstallReason reason) { 30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RemoveNotificationForExtension(extension->id()); 30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 30946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ExtensionStorageMonitor::ExtensionUninstallAccepted() { 31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(!uninstall_extension_id_.empty()); 31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Extension* extension = GetExtensionById(context_, 31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uninstall_extension_id_); 31446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uninstall_extension_id_.clear(); 31546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!extension) 31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 31846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ExtensionService* service = 31946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ExtensionSystem::Get(context_)->extension_service(); 32046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(service); 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch service->UninstallExtension( 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension->id(), 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UNINSTALL_REASON_STORAGE_THRESHOLD_EXCEEDED, 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&base::DoNothing), 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NULL); 32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ExtensionStorageMonitor::ExtensionUninstallCanceled() { 32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uninstall_extension_id_.clear(); 33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 33146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 332c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstd::string ExtensionStorageMonitor::GetNotificationId( 333c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string& extension_id) { 334c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch std::vector<std::string> placeholders; 335c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch placeholders.push_back(context_->GetPath().BaseName().MaybeAsASCII()); 336c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch placeholders.push_back(extension_id); 337c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 338c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return ReplaceStringPlaceholders(kNotificationIdFormat, placeholders, NULL); 339c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 340c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 341c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::OnStorageThresholdExceeded( 342c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string& extension_id, 343c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 next_threshold, 344c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 current_usage) { 345c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 346c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 34746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Extension* extension = GetExtensionById(context_, extension_id); 348c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!extension) 349c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 350c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (GetNextStorageThreshold(extension->id()) < next_threshold) 35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SetNextStorageThreshold(extension->id(), next_threshold); 353c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 354c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const int kIconSize = message_center::kNotificationIconSize; 355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ExtensionResource resource = IconsInfo::GetIconResource( 356c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch extension, kIconSize, ExtensionIconSet::MATCH_BIGGER); 357c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ImageLoader::Get(context_)->LoadImageAsync( 358c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch extension, resource, gfx::Size(kIconSize, kIconSize), 359c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&ExtensionStorageMonitor::OnImageLoaded, 360c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch weak_ptr_factory_.GetWeakPtr(), 361c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch extension_id, 362c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch current_usage)); 363c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 364c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 365c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::OnImageLoaded( 366c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string& extension_id, 367c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 current_usage, 368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const gfx::Image& image) { 36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Extension* extension = GetExtensionById(context_, extension_id); 370c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!extension) 371c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 372c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 373c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Remove any existing notifications to force a new notification to pop up. 374c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch std::string notification_id(GetNotificationId(extension_id)); 375c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_center::MessageCenter::Get()->RemoveNotification( 376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notification_id, false); 377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 378c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_center::RichNotificationData notification_data; 379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notification_data.buttons.push_back(message_center::ButtonInfo( 380c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch l10n_util::GetStringUTF16(extension->is_app() ? 381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch IDS_EXTENSION_STORAGE_MONITOR_BUTTON_DISMISS_APP : 382c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch IDS_EXTENSION_STORAGE_MONITOR_BUTTON_DISMISS_EXTENSION))); 38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) notification_data.buttons.push_back(message_center::ButtonInfo( 38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) l10n_util::GetStringUTF16(extension->is_app() ? 38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) IDS_EXTENSION_STORAGE_MONITOR_BUTTON_UNINSTALL_APP : 38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) IDS_EXTENSION_STORAGE_MONITOR_BUTTON_UNINSTALL_EXTENSION))); 387c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 388c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch gfx::Image notification_image(image); 389c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (notification_image.IsEmpty()) { 390c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notification_image = 3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu extension->is_app() ? gfx::Image(util::GetDefaultAppIcon()) 3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : gfx::Image(util::GetDefaultExtensionIcon()); 393c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 394c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 395c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<message_center::Notification> notification; 396c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notification.reset(new message_center::Notification( 397c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_center::NOTIFICATION_TYPE_SIMPLE, 398c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notification_id, 399c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch l10n_util::GetStringUTF16(IDS_EXTENSION_STORAGE_MONITOR_TITLE), 400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch l10n_util::GetStringFUTF16( 401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch IDS_EXTENSION_STORAGE_MONITOR_TEXT, 402c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::UTF8ToUTF16(extension->name()), 403c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::IntToString16(current_usage / kMBytes)), 404c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notification_image, 405c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::string16() /* display source */, 406c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_center::NotifierId( 407c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_center::NotifierId::SYSTEM_COMPONENT, kSystemNotifierId), 408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notification_data, 409c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch new message_center::HandleNotificationButtonClickDelegate(base::Bind( 410c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &ExtensionStorageMonitor::OnNotificationButtonClick, 411c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch weak_ptr_factory_.GetWeakPtr(), 412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch extension_id)))); 413c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notification->SetSystemPriority(); 414c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_center::MessageCenter::Get()->AddNotification(notification.Pass()); 415c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 416c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notified_extension_ids_.insert(extension_id); 417c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 418c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 419c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::OnNotificationButtonClick( 420c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string& extension_id, int button_index) { 421c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch switch (button_index) { 422c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch case BUTTON_DISABLE_NOTIFICATION: { 423c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DisableStorageMonitoring(extension_id); 424c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch break; 425c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) case BUTTON_UNINSTALL: { 42746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ShowUninstallPrompt(extension_id); 42846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) break; 42946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 430c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch default: 431c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch NOTREACHED(); 432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 433c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 434c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 435c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::DisableStorageMonitoring( 436c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string& extension_id) { 437c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StopMonitoringStorage(extension_id); 438c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 43946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SetStorageNotificationEnabled(extension_id, false); 440c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 441c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_center::MessageCenter::Get()->RemoveNotification( 442c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetNotificationId(extension_id), false); 443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 444c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 445c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::StartMonitoringStorage( 446c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const Extension* extension) { 44746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!ShouldMonitorStorageFor(extension)) 448c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 449c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 450c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // First apply this feature only to experimental ephemeral apps. If it works 451c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // well, roll it out to all extensions and apps. 45246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!enable_for_all_extensions_ && 45346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !extension_prefs_->IsEphemeralApp(extension->id())) { 454c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 45546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 456c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 45746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!IsStorageNotificationEnabled(extension->id())) 458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 459c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Lazily create the storage monitor proxy on the IO thread. 461c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!storage_observer_.get()) { 462c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch storage_observer_ = 463c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch new StorageEventObserver(weak_ptr_factory_.GetWeakPtr()); 464c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 465c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 466c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GURL site_url = 467c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch extensions::util::GetSiteForExtensionId(extension->id(), context_); 468c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch content::StoragePartition* storage_partition = 469c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch content::BrowserContext::GetStoragePartitionForSite(context_, site_url); 470c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(storage_partition); 47103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<storage::QuotaManager> quota_manager( 472c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch storage_partition->GetQuotaManager()); 473c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 474c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GURL storage_origin(site_url.GetOrigin()); 475c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (extension->is_hosted_app()) 476c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch storage_origin = AppLaunchInfo::GetLaunchWebURL(extension).GetOrigin(); 477c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 478c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BrowserThread::PostTask( 479c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BrowserThread::IO, 480c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FROM_HERE, 481c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&StorageEventObserver::StartObservingForExtension, 482c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch storage_observer_, 483c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch quota_manager, 484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch extension->id(), 485c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch storage_origin, 48646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) GetNextStorageThreshold(extension->id()), 487c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch observer_rate_)); 488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::StopMonitoringStorage( 491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string& extension_id) { 492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!storage_observer_.get()) 493c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 494c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 495c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BrowserThread::PostTask( 496c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BrowserThread::IO, 497c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FROM_HERE, 498c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&StorageEventObserver::StopObservingForExtension, 499c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch storage_observer_, 500c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch extension_id)); 501c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 502c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 503c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::StopMonitoringAll() { 50446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_registry_observer_.RemoveAll(); 505c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 506c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch RemoveAllNotifications(); 507c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 508c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!storage_observer_.get()) 509c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 510c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 511c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BrowserThread::PostTask( 512c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BrowserThread::IO, 513c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FROM_HERE, 514c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&StorageEventObserver::StopObserving, storage_observer_)); 515c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch storage_observer_ = NULL; 516c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 517c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 518c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::RemoveNotificationForExtension( 519c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string& extension_id) { 520c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch std::set<std::string>::iterator ext_id = 521c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notified_extension_ids_.find(extension_id); 522c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (ext_id == notified_extension_ids_.end()) 523c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 524c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 525c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notified_extension_ids_.erase(ext_id); 526c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_center::MessageCenter::Get()->RemoveNotification( 527c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetNotificationId(extension_id), false); 528c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 529c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 530c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ExtensionStorageMonitor::RemoveAllNotifications() { 531c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (notified_extension_ids_.empty()) 532c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 533c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 534c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_center::MessageCenter* center = message_center::MessageCenter::Get(); 535c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(center); 536c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch for (std::set<std::string>::iterator it = notified_extension_ids_.begin(); 537c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch it != notified_extension_ids_.end(); ++it) { 538c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch center->RemoveNotification(GetNotificationId(*it), false); 539c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 540c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notified_extension_ids_.clear(); 541c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 542c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 54346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ExtensionStorageMonitor::ShowUninstallPrompt( 54446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& extension_id) { 54546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Extension* extension = GetExtensionById(context_, extension_id); 54646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!extension) 54746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 54846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 54946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!uninstall_dialog_.get()) { 55046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uninstall_dialog_.reset(ExtensionUninstallDialog::Create( 55146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Profile::FromBrowserContext(context_), NULL, this)); 55246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 55346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 55446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uninstall_extension_id_ = extension->id(); 55546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uninstall_dialog_->ConfirmUninstall(extension); 55646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 55746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 55846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int64 ExtensionStorageMonitor::GetNextStorageThreshold( 55946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& extension_id) const { 56046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int next_threshold = GetNextStorageThresholdFromPrefs(extension_id); 56146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (next_threshold == 0) { 56246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The next threshold is written to the prefs after the initial threshold is 56346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // exceeded. 56446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) next_threshold = extension_prefs_->IsEphemeralApp(extension_id) 56546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ? initial_ephemeral_threshold_ 56646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : initial_extension_threshold_; 56746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 56846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return next_threshold; 56946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 57046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 57146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ExtensionStorageMonitor::SetNextStorageThreshold( 57246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& extension_id, 57346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int64 next_threshold) { 57446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_prefs_->UpdateExtensionPref( 57546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_id, 57646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) kPrefNextStorageThreshold, 57746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) next_threshold > 0 57846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ? new base::StringValue(base::Int64ToString(next_threshold)) 57946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : NULL); 58046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 58146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 58246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int64 ExtensionStorageMonitor::GetNextStorageThresholdFromPrefs( 58346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& extension_id) const { 58446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string next_threshold_str; 58546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (extension_prefs_->ReadPrefAsString( 58646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_id, kPrefNextStorageThreshold, &next_threshold_str)) { 58746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int64 next_threshold; 58846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (base::StringToInt64(next_threshold_str, &next_threshold)) 58946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return next_threshold; 59046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 59146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 59246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // A return value of zero indicates that the initial threshold has not yet 59346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // been reached. 59446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return 0; 59546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 59646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 59746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ExtensionStorageMonitor::IsStorageNotificationEnabled( 59846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& extension_id) const { 59946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool disable_notifications; 60046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (extension_prefs_->ReadPrefAsBoolean(extension_id, 60146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) kPrefDisableStorageNotifications, 60246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &disable_notifications)) { 60346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return !disable_notifications; 60446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 60546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 60646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 60746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 60846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 60946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ExtensionStorageMonitor::SetStorageNotificationEnabled( 61046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& extension_id, 61146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool enable_notifications) { 61246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_prefs_->UpdateExtensionPref( 61346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_id, 61446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) kPrefDisableStorageNotifications, 61546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) enable_notifications ? NULL : new base::FundamentalValue(true)); 61646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 61746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 618c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} // namespace extensions 619