diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-12 23:11:00 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-12 23:11:00 +0000 |
commit | 90e800cc11053770e70884e94e6e96802b559ff8 (patch) | |
tree | eba9770456db610c6a5c75d227b878fc85829e20 | |
parent | a934ece52fddea9e430d724c26ccbe76b4806809 (diff) | |
download | chromium_src-90e800cc11053770e70884e94e6e96802b559ff8.zip chromium_src-90e800cc11053770e70884e94e6e96802b559ff8.tar.gz chromium_src-90e800cc11053770e70884e94e6e96802b559ff8.tar.bz2 |
Unrevert r141537: Add extensions::StateStore and use that instead of
ExtensionPrefs for persisting alarm state to disk.
More to come:
- context menus
- omnibox
- declarative webRequest
TBR=brettw
BUG=123366
TEST=extension alarms are still remembered after chrome restart
Change since last time: Fall back to a FailingValueStore if ValueStoreFrontend
can't open the database.
Review URL: https://chromiumcodereview.appspot.com/10545128
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141780 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/value_conversions.cc | 21 | ||||
-rw-r--r-- | base/value_conversions.h | 8 | ||||
-rw-r--r-- | chrome/browser/extensions/api/alarms/alarm_manager.cc | 106 | ||||
-rw-r--r-- | chrome/browser/extensions/api/alarms/alarm_manager.h | 21 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_prefs.cc | 43 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_prefs.h | 8 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_service.cc | 1 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_service.h | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_system.cc | 13 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_system.h | 10 | ||||
-rw-r--r-- | chrome/browser/extensions/state_store.cc | 75 | ||||
-rw-r--r-- | chrome/browser/extensions/state_store.h | 64 | ||||
-rw-r--r-- | chrome/browser/extensions/test_extension_system.cc | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/test_extension_system.h | 1 | ||||
-rw-r--r-- | chrome/chrome_browser_extensions.gypi | 2 |
15 files changed, 282 insertions, 99 deletions
diff --git a/base/value_conversions.cc b/base/value_conversions.cc index f4957a4..caf9d72 100644 --- a/base/value_conversions.cc +++ b/base/value_conversions.cc @@ -1,10 +1,12 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/value_conversions.h" #include "base/file_path.h" +#include "base/string_number_conversions.h" +#include "base/time.h" #include "base/values.h" namespace base { @@ -24,4 +26,21 @@ bool GetValueAsFilePath(const Value& value, FilePath* file_path) { return true; } +// |Value| does not support 64-bit integers, and doubles do not have enough +// precision, so we store the 64-bit time value as a string instead. +StringValue* CreateTimeValue(const Time& time) { + std::string string_value = base::Int64ToString(time.ToInternalValue()); + return new StringValue(string_value); +} + +bool GetValueAsTime(const Value& value, Time* time) { + std::string str; + int64 int_value; + if (!value.GetAsString(&str) || !base::StringToInt64(str, &int_value)) + return false; + if (time) + *time = base::Time::FromInternalValue(int_value); + return true; +} + } // namespace base diff --git a/base/value_conversions.h b/base/value_conversions.h index c65e627..7825bb1 100644 --- a/base/value_conversions.h +++ b/base/value_conversions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,7 @@ #define BASE_VALUE_CONVERSIONS_H_ #pragma once -// This file contains methods to convert a |FilePath| to a |Value| and back. +// This file contains methods to convert things to a |Value| and back. #include "base/base_export.h" @@ -14,6 +14,7 @@ class FilePath; namespace base { +class Time; class StringValue; class Value; @@ -21,6 +22,9 @@ class Value; BASE_EXPORT StringValue* CreateFilePathValue(const FilePath& in_value); BASE_EXPORT bool GetValueAsFilePath(const Value& value, FilePath* file_path); +BASE_EXPORT StringValue* CreateTimeValue(const Time& time); +BASE_EXPORT bool GetValueAsTime(const Value& value, Time* time); + } // namespace #endif // BASE_VALUE_CONVERSIONS_H_ diff --git a/chrome/browser/extensions/api/alarms/alarm_manager.cc b/chrome/browser/extensions/api/alarms/alarm_manager.cc index 2861a03..1dc8ba5 100644 --- a/chrome/browser/extensions/api/alarms/alarm_manager.cc +++ b/chrome/browser/extensions/api/alarms/alarm_manager.cc @@ -8,11 +8,12 @@ #include "base/json/json_writer.h" #include "base/message_loop.h" #include "base/time.h" +#include "base/value_conversions.h" #include "base/values.h" #include "chrome/browser/extensions/extension_event_router.h" -#include "chrome/browser/extensions/extension_prefs.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/extensions/state_store.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_notification_types.h" #include "content/public/browser/notification_service.h" @@ -23,6 +24,10 @@ namespace { const char kOnAlarmEvent[] = "alarms.onAlarm"; +// A list of alarms that this extension has set. +const char kRegisteredAlarms[] = "alarms"; +const char kAlarmScheduledRunTime[] = "scheduled_run_time"; + // The minimum period between polling for alarms to run. const base::TimeDelta kDefaultMinPollPeriod = base::TimeDelta::FromMinutes(5); @@ -45,12 +50,52 @@ class DefaultAlarmDelegate : public AlarmManager::Delegate { Profile* profile_; }; +// Contains the state we persist for each alarm. +struct AlarmState { + linked_ptr<AlarmManager::Alarm> alarm; + base::Time scheduled_run_time; + + AlarmState() {} + ~AlarmState() {} +}; + // Creates a TimeDelta from a delay as specified in the API. base::TimeDelta TimeDeltaFromDelay(double delay_in_minutes) { return base::TimeDelta::FromMicroseconds( delay_in_minutes * base::Time::kMicrosecondsPerMinute); } +std::vector<AlarmState> AlarmsFromValue(const base::ListValue* list) { + typedef AlarmManager::Alarm Alarm; + std::vector<AlarmState> alarms; + for (size_t i = 0; i < list->GetSize(); ++i) { + base::DictionaryValue* alarm_dict = NULL; + AlarmState alarm; + alarm.alarm.reset(new Alarm()); + if (list->GetDictionary(i, &alarm_dict) && + Alarm::Populate(*alarm_dict, alarm.alarm.get())) { + base::Value* time_value = NULL; + if (alarm_dict->Get(kAlarmScheduledRunTime, &time_value)) + base::GetValueAsTime(*time_value, &alarm.scheduled_run_time); + alarms.push_back(alarm); + } + } + return alarms; +} + +scoped_ptr<base::ListValue> AlarmsToValue( + const std::vector<AlarmState>& alarms) { + scoped_ptr<base::ListValue> list(new ListValue()); + for (size_t i = 0; i < alarms.size(); ++i) { + scoped_ptr<base::DictionaryValue> alarm = alarms[i].alarm->ToValue().Pass(); + alarm->Set(kAlarmScheduledRunTime, + base::CreateTimeValue(alarms[i].scheduled_run_time)); + list->Append(alarm.release()); + } + return list.Pass(); +} + + } // namespace // AlarmManager @@ -61,6 +106,10 @@ AlarmManager::AlarmManager(Profile* profile) last_poll_time_(base::Time()) { registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, content::Source<Profile>(profile_)); + + StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); + if (storage) + storage->RegisterKey(kRegisteredAlarms); } AlarmManager::~AlarmManager() { @@ -70,7 +119,7 @@ void AlarmManager::AddAlarm(const std::string& extension_id, const linked_ptr<Alarm>& alarm) { base::TimeDelta alarm_time = TimeDeltaFromDelay(alarm->delay_in_minutes); AddAlarmImpl(extension_id, alarm, alarm_time); - WriteToPrefs(extension_id); + WriteToStorage(extension_id); } const AlarmManager::Alarm* AlarmManager::GetAlarm( @@ -111,7 +160,7 @@ bool AlarmManager::RemoveAlarm(const std::string& extension_id, return false; RemoveAlarmIterator(it); - WriteToPrefs(extension_id); + WriteToStorage(extension_id); return true; } @@ -126,7 +175,7 @@ void AlarmManager::RemoveAllAlarms(const std::string& extension_id) { RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); CHECK(alarms_.find(extension_id) == alarms_.end()); - WriteToPrefs(extension_id); + WriteToStorage(extension_id); } void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { @@ -159,7 +208,7 @@ void AlarmManager::OnAlarm(const std::string& extension_id, scheduled_times_[alarm].time = last_poll_time_ + TimeDeltaFromDelay(alarm->delay_in_minutes); } - WriteToPrefs(extension_id_copy); + WriteToStorage(extension_id_copy); } void AlarmManager::AddAlarmImpl(const std::string& extension_id, @@ -180,43 +229,41 @@ void AlarmManager::AddAlarmImpl(const std::string& extension_id, ScheduleNextPoll(base::TimeDelta::FromMinutes(0)); } -void AlarmManager::WriteToPrefs(const std::string& extension_id) { - ExtensionService* service = - ExtensionSystem::Get(profile_)->extension_service(); - if (!service || !service->extension_prefs()) +void AlarmManager::WriteToStorage(const std::string& extension_id) { + StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); + if (!storage) return; - std::vector<AlarmPref> alarm_prefs; - + std::vector<AlarmState> alarm_states; AlarmMap::iterator list = alarms_.find(extension_id); if (list != alarms_.end()) { for (AlarmList::iterator it = list->second.begin(); it != list->second.end(); ++it) { - AlarmPref pref; + AlarmState pref; pref.alarm = *it; pref.scheduled_run_time = scheduled_times_[it->get()].time; - alarm_prefs.push_back(pref); + alarm_states.push_back(pref); } } - service->extension_prefs()->SetRegisteredAlarms(extension_id, alarm_prefs); + scoped_ptr<Value> alarms(AlarmsToValue(alarm_states).release()); + storage->SetExtensionValue(extension_id, kRegisteredAlarms, alarms.Pass()); } -void AlarmManager::ReadFromPrefs(const std::string& extension_id) { - ExtensionService* service = - ExtensionSystem::Get(profile_)->extension_service(); - if (!service || !service->extension_prefs()) +void AlarmManager::ReadFromStorage(const std::string& extension_id, + scoped_ptr<base::Value> value) { + base::ListValue* list = NULL; + if (!value.get() || !value->GetAsList(&list)) return; - std::vector<AlarmPref> alarm_prefs = - service->extension_prefs()->GetRegisteredAlarms(extension_id); - for (size_t i = 0; i < alarm_prefs.size(); ++i) { + std::vector<AlarmState> alarm_states = AlarmsFromValue(list); + for (size_t i = 0; i < alarm_states.size(); ++i) { base::TimeDelta delay = - alarm_prefs[i].scheduled_run_time - base::Time::Now(); + alarm_states[i].scheduled_run_time - base::Time::Now(); if (delay < base::TimeDelta::FromSeconds(0)) delay = base::TimeDelta::FromSeconds(0); - AddAlarmImpl(extension_id, alarm_prefs[i].alarm, delay); + AddAlarmImpl(extension_id, alarm_states[i].alarm, delay); } } @@ -291,7 +338,12 @@ void AlarmManager::Observe( case chrome::NOTIFICATION_EXTENSION_LOADED: { const Extension* extension = content::Details<const Extension>(details).ptr(); - ReadFromPrefs(extension->id()); + StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); + if (storage) { + storage->GetExtensionValue(extension->id(), kRegisteredAlarms, + base::Bind(&AlarmManager::ReadFromStorage, + AsWeakPtr(), extension->id())); + } break; } default: @@ -300,10 +352,4 @@ void AlarmManager::Observe( } } -AlarmPref::AlarmPref() { -} - -AlarmPref::~AlarmPref() { -} - } // namespace extensions diff --git a/chrome/browser/extensions/api/alarms/alarm_manager.h b/chrome/browser/extensions/api/alarms/alarm_manager.h index 47884f9..6930998 100644 --- a/chrome/browser/extensions/api/alarms/alarm_manager.h +++ b/chrome/browser/extensions/api/alarms/alarm_manager.h @@ -10,6 +10,7 @@ #include <map> #include <vector> +#include "base/memory/weak_ptr.h" #include "base/timer.h" #include "chrome/browser/extensions/extension_function.h" #include "chrome/common/extensions/api/alarms.h" @@ -24,7 +25,9 @@ class ExtensionAlarmsSchedulingTest; // Manages the currently pending alarms for every extension in a profile. // There is one manager per virtual Profile. -class AlarmManager : public content::NotificationObserver { +class AlarmManager + : public content::NotificationObserver, + public base::SupportsWeakPtr<AlarmManager> { public: typedef extensions::api::alarms::Alarm Alarm; typedef std::vector<linked_ptr<Alarm> > AlarmList; @@ -100,9 +103,10 @@ class AlarmManager : public content::NotificationObserver { const linked_ptr<Alarm>& alarm, base::TimeDelta time_delay); - // Syncs our alarm data for the given extension to/from the prefs file. - void WriteToPrefs(const std::string& extension_id); - void ReadFromPrefs(const std::string& extension_id); + // Syncs our alarm data for the given extension to/from the state storage. + void WriteToStorage(const std::string& extension_id); + void ReadFromStorage(const std::string& extension_id, + scoped_ptr<base::Value> value); // Schedules the next poll of alarms for when the next soonest alarm runs, // but do not more often than min_period. @@ -135,15 +139,6 @@ class AlarmManager : public content::NotificationObserver { base::Time next_poll_time_; }; -// Contains the data we store in the extension prefs for each alarm. -struct AlarmPref { - linked_ptr<AlarmManager::Alarm> alarm; - base::Time scheduled_run_time; - - AlarmPref(); - ~AlarmPref(); -}; - } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARM_MANAGER_H__ diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc index 6f0f3fb..c0a33f2 100644 --- a/chrome/browser/extensions/extension_prefs.cc +++ b/chrome/browser/extensions/extension_prefs.cc @@ -8,7 +8,6 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/extensions/admin_policy.h" -#include "chrome/browser/extensions/api/alarms/alarm_manager.h" #include "chrome/browser/extensions/api/omnibox/omnibox_api.h" #include "chrome/browser/extensions/extension_menu_manager.h" #include "chrome/browser/extensions/extension_pref_store.h" @@ -171,10 +170,6 @@ const char kPrefIncognitoContentSettings[] = "incognito_content_settings"; // background page. const char kRegisteredEvents[] = "events"; -// A list of alarms that this extension has set. -const char kRegisteredAlarms[] = "alarms"; -const char kAlarmScheduledRunTime[] = "scheduled_run_time"; - // Persisted value for omnibox.setDefaultSuggestion. const char kOmniboxDefaultSuggestion[] = "omnibox_default_suggestion"; @@ -957,43 +952,6 @@ void ExtensionPrefs::SetRegisteredEvents( UpdateExtensionPref(extension_id, kRegisteredEvents, value); } -std::vector<extensions::AlarmPref> ExtensionPrefs::GetRegisteredAlarms( - const std::string& extension_id) { - std::vector<extensions::AlarmPref> alarms; - const base::DictionaryValue* extension = GetExtensionPref(extension_id); - if (!extension) - return alarms; - - base::ListValue* list = NULL; - if (!extension->GetList(kRegisteredAlarms, &list)) - return alarms; - - typedef extensions::AlarmManager::Alarm Alarm; - for (size_t i = 0; i < list->GetSize(); ++i) { - base::DictionaryValue* alarm_dict = NULL; - extensions::AlarmPref alarm; - alarm.alarm.reset(new Alarm()); - if (list->GetDictionary(i, &alarm_dict) && - Alarm::Populate(*alarm_dict, alarm.alarm.get())) { - alarm.scheduled_run_time = ReadTime(alarm_dict, kAlarmScheduledRunTime); - alarms.push_back(alarm); - } - } - return alarms; -} - -void ExtensionPrefs::SetRegisteredAlarms( - const std::string& extension_id, - const std::vector<extensions::AlarmPref>& alarms) { - base::ListValue* list = new ListValue(); - for (size_t i = 0; i < alarms.size(); ++i) { - scoped_ptr<base::DictionaryValue> alarm = alarms[i].alarm->ToValue().Pass(); - SaveTime(alarm.get(), kAlarmScheduledRunTime, alarms[i].scheduled_run_time); - list->Append(alarm.release()); - } - UpdateExtensionPref(extension_id, kRegisteredAlarms, list); -} - extensions::ExtensionOmniboxSuggestion ExtensionPrefs::GetOmniboxDefaultSuggestion(const std::string& extension_id) { extensions::ExtensionOmniboxSuggestion suggestion; @@ -1241,7 +1199,6 @@ void ExtensionPrefs::OnExtensionInstalled( // Clear state that may be registered from a previous install. extension_dict->Remove(kRegisteredEvents, NULL); - extension_dict->Remove(kRegisteredAlarms, NULL); extension_dict->Remove(kPrefContextMenus, NULL); if (extension->is_app()) { diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h index 37607bf..e6e3cee 100644 --- a/chrome/browser/extensions/extension_prefs.h +++ b/chrome/browser/extensions/extension_prefs.h @@ -28,7 +28,6 @@ class PrefService; class URLPatternSet; namespace extensions { -struct AlarmPref; struct ExtensionOmniboxSuggestion; } @@ -276,13 +275,6 @@ class ExtensionPrefs : public extensions::ContentSettingsStore::Observer, void SetRegisteredEvents(const std::string& extension_id, const std::set<std::string>& events); - // Controls a list of alarms for this extension, including the next time they - // should run. - std::vector<extensions::AlarmPref> GetRegisteredAlarms( - const std::string& extension_id); - void SetRegisteredAlarms(const std::string& extension_id, - const std::vector<extensions::AlarmPref>& alarms); - // Controls the omnibox default suggestion as set by the extension. extensions::ExtensionOmniboxSuggestion GetOmniboxDefaultSuggestion( const std::string& extension_id); diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 496556f9..62a32a0 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -189,6 +189,7 @@ const char* ExtensionService::kSyncAppSettingsDirectoryName = "Sync App Settings"; const char* ExtensionService::kSyncExtensionSettingsDirectoryName = "Sync Extension Settings"; +const char* ExtensionService::kStateStoreName = "Extension State"; void ExtensionService::CheckExternalUninstall(const std::string& id) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h index 911e52a..b79ed33 100644 --- a/chrome/browser/extensions/extension_service.h +++ b/chrome/browser/extensions/extension_service.h @@ -171,6 +171,10 @@ class ExtensionService // settings are stored. static const char* kSyncExtensionSettingsDirectoryName; + // The name of the database inside the profile where chrome-internal + // extension state resides. + static const char* kStateStoreName; + // Returns the Extension of hosted or packaged apps, NULL otherwise. const extensions::Extension* GetInstalledApp(const GURL& url); diff --git a/chrome/browser/extensions/extension_system.cc b/chrome/browser/extensions/extension_system.cc index e0e5165..a5793e4 100644 --- a/chrome/browser/extensions/extension_system.cc +++ b/chrome/browser/extensions/extension_system.cc @@ -27,6 +27,7 @@ #include "chrome/browser/extensions/extension_system_factory.h" #include "chrome/browser/extensions/lazy_background_task_queue.h" #include "chrome/browser/extensions/management_policy.h" +#include "chrome/browser/extensions/state_store.h" #include "chrome/browser/extensions/unpacked_installer.h" #include "chrome/browser/extensions/user_script_master.h" #include "chrome/browser/prefs/pref_service.h" @@ -83,6 +84,10 @@ void ExtensionSystemImpl::Shared::InitPrefs() { profile_->GetPath().AppendASCII(ExtensionService::kInstallDirectoryName), ExtensionPrefValueMapFactory::GetForProfile(profile_))); extension_prefs_->Init(extensions_disabled); + + state_store_.reset(new extensions::StateStore( + profile_, + profile_->GetPath().AppendASCII(ExtensionService::kStateStoreName))); } void ExtensionSystemImpl::Shared::RegisterManagementPolicyProviders() { @@ -196,6 +201,10 @@ void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) { rules_registry_service_->RegisterDefaultRulesRegistries(); } +extensions::StateStore* ExtensionSystemImpl::Shared::state_store() { + return state_store_.get(); +} + ExtensionService* ExtensionSystemImpl::Shared::extension_service() { return extension_service_.get(); } @@ -298,6 +307,10 @@ extensions::AlarmManager* ExtensionSystemImpl::alarm_manager() { return alarm_manager_.get(); } +extensions::StateStore* ExtensionSystemImpl::state_store() { + return shared_->state_store(); +} + ExtensionInfoMap* ExtensionSystemImpl::info_map() { return shared_->info_map(); } diff --git a/chrome/browser/extensions/extension_system.h b/chrome/browser/extensions/extension_system.h index 676bdb1..23d228f 100644 --- a/chrome/browser/extensions/extension_system.h +++ b/chrome/browser/extensions/extension_system.h @@ -30,6 +30,7 @@ class Extension; class LazyBackgroundTaskQueue; class ManagementPolicy; class RulesRegistryService; +class StateStore; } // The ExtensionSystem manages the creation and destruction of services @@ -74,6 +75,9 @@ class ExtensionSystem : public ProfileKeyedService { // The AlarmManager is created at startup. virtual extensions::AlarmManager* alarm_manager() = 0; + // The StateStore is created at startup. + virtual extensions::StateStore* state_store() = 0; + // Returns the IO-thread-accessible extension data. virtual ExtensionInfoMap* info_map() = 0; @@ -126,6 +130,7 @@ class ExtensionSystemImpl : public ExtensionSystem { virtual ExtensionDevToolsManager* devtools_manager() OVERRIDE; virtual ExtensionProcessManager* process_manager() OVERRIDE; virtual extensions::AlarmManager* alarm_manager() OVERRIDE; + virtual extensions::StateStore* state_store() OVERRIDE; virtual extensions::LazyBackgroundTaskQueue* lazy_background_task_queue() OVERRIDE; // shared virtual ExtensionInfoMap* info_map() OVERRIDE; // shared @@ -159,6 +164,7 @@ class ExtensionSystemImpl : public ExtensionSystem { void InitInfoMap(); void Init(bool extensions_enabled); + extensions::StateStore* state_store(); ExtensionService* extension_service(); extensions::ManagementPolicy* management_policy(); UserScriptMaster* user_script_master(); @@ -173,9 +179,9 @@ class ExtensionSystemImpl : public ExtensionSystem { // The services that are shared between normal and incognito profiles. - // Keep extension_prefs_ above extension_service_, because the latter - // maintains a pointer to the former and must be destructed first. + scoped_ptr<extensions::StateStore> state_store_; scoped_ptr<ExtensionPrefs> extension_prefs_; + // ExtensionService depends on the 2 above. scoped_ptr<ExtensionService> extension_service_; scoped_ptr<extensions::ManagementPolicy> management_policy_; scoped_refptr<UserScriptMaster> user_script_master_; diff --git a/chrome/browser/extensions/state_store.cc b/chrome/browser/extensions/state_store.cc new file mode 100644 index 0000000..69d432e --- /dev/null +++ b/chrome/browser/extensions/state_store.cc @@ -0,0 +1,75 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/state_store.h" + +#include "chrome/common/chrome_notification_types.h" +#include "chrome/common/extensions/extension.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_types.h" + +namespace { + +std::string GetFullKey(const std::string& extension_id, + const std::string& key) { + return extension_id + "." + key; +} + +} // namespace + +namespace extensions { + +StateStore::StateStore(Profile* profile, const FilePath& db_path) + : store_(db_path) { + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, + content::Source<Profile>(profile)); + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, + content::Source<Profile>(profile)); +} + +StateStore::~StateStore() { +} + +void StateStore::RegisterKey(const std::string& key) { + registered_keys_.insert(key); +} + +void StateStore::GetExtensionValue(const std::string& extension_id, + const std::string& key, + ReadCallback callback) { + store_.Get(GetFullKey(extension_id, key), callback); +} + +void StateStore::SetExtensionValue( + const std::string& extension_id, + const std::string& key, + scoped_ptr<base::Value> value) { + store_.Set(GetFullKey(extension_id, key), value.Pass()); +} + +void StateStore::Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + std::string extension_id; + + switch (type) { + case chrome::NOTIFICATION_EXTENSION_INSTALLED: + extension_id = content::Details<const Extension>(details).ptr()->id(); + break; + case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: + extension_id = + *content::Details<const std::string>(details).ptr(); + break; + default: + NOTREACHED(); + return; + } + + for (std::set<std::string>::iterator key = registered_keys_.begin(); + key != registered_keys_.end(); ++key) { + store_.Remove(GetFullKey(extension_id, *key)); + } +} + +} // namespace extensions diff --git a/chrome/browser/extensions/state_store.h b/chrome/browser/extensions/state_store.h new file mode 100644 index 0000000..ebaf86b --- /dev/null +++ b/chrome/browser/extensions/state_store.h @@ -0,0 +1,64 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_STATE_STORE_H_ +#define CHROME_BROWSER_EXTENSIONS_STATE_STORE_H_ +#pragma once + +#include <set> +#include <string> + +#include "base/memory/weak_ptr.h" +#include "chrome/browser/value_store/value_store_frontend.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +class Profile; + +namespace extensions { + +// A storage area for per-extension state that needs to be persisted to disk. +class StateStore + : public base::SupportsWeakPtr<StateStore>, + public content::NotificationObserver { + public: + typedef ValueStoreFrontend::ReadCallback ReadCallback; + + StateStore(Profile* profile, const FilePath& db_path); + virtual ~StateStore(); + + // Register a key for removal upon extension install/uninstall. We remove + // for install to reset state when an extension upgrades. + void RegisterKey(const std::string& key); + + // Get the value associated with the given extension and key, and pass + // it to |callback| asynchronously. + void GetExtensionValue(const std::string& extension_id, + const std::string& key, + ReadCallback callback); + + // Sets a value for a given extension and key. + void SetExtensionValue(const std::string& extension_id, + const std::string& key, + scoped_ptr<base::Value> value); + + private: + // content::NotificationObserver + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // The store that holds our key/values. + ValueStoreFrontend store_; + + // List of all known keys. They will be cleared for each extension when it is + // (un)installed. + std::set<std::string> registered_keys_; + + content::NotificationRegistrar registrar_; +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_STATE_STORE_H_ diff --git a/chrome/browser/extensions/test_extension_system.cc b/chrome/browser/extensions/test_extension_system.cc index 00d69c6..2773d47 100644 --- a/chrome/browser/extensions/test_extension_system.cc +++ b/chrome/browser/extensions/test_extension_system.cc @@ -100,6 +100,10 @@ extensions::AlarmManager* TestExtensionSystem::alarm_manager() { return alarm_manager_.get(); } +extensions::StateStore* TestExtensionSystem::state_store() { + return NULL; +} + ExtensionInfoMap* TestExtensionSystem::info_map() { return NULL; } diff --git a/chrome/browser/extensions/test_extension_system.h b/chrome/browser/extensions/test_extension_system.h index 0a29c0c..9461302 100644 --- a/chrome/browser/extensions/test_extension_system.h +++ b/chrome/browser/extensions/test_extension_system.h @@ -45,6 +45,7 @@ class TestExtensionSystem : public ExtensionSystem { virtual ExtensionDevToolsManager* devtools_manager() OVERRIDE; virtual ExtensionProcessManager* process_manager() OVERRIDE; virtual extensions::AlarmManager* alarm_manager() OVERRIDE; + virtual extensions::StateStore* state_store() OVERRIDE; virtual ExtensionInfoMap* info_map() OVERRIDE; virtual extensions::LazyBackgroundTaskQueue* lazy_background_task_queue() OVERRIDE; diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index 9c21acd..a8f0c0e 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi @@ -459,6 +459,8 @@ 'browser/extensions/settings/weak_unlimited_settings_storage.h', 'browser/extensions/shell_window_registry.cc', 'browser/extensions/shell_window_registry.h', + 'browser/extensions/state_store.cc', + 'browser/extensions/state_store.h', 'browser/extensions/theme_installed_infobar_delegate.cc', 'browser/extensions/theme_installed_infobar_delegate.h', 'browser/extensions/unpacked_installer.cc', |