summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-12 23:11:00 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-12 23:11:00 +0000
commit90e800cc11053770e70884e94e6e96802b559ff8 (patch)
treeeba9770456db610c6a5c75d227b878fc85829e20
parenta934ece52fddea9e430d724c26ccbe76b4806809 (diff)
downloadchromium_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.cc21
-rw-r--r--base/value_conversions.h8
-rw-r--r--chrome/browser/extensions/api/alarms/alarm_manager.cc106
-rw-r--r--chrome/browser/extensions/api/alarms/alarm_manager.h21
-rw-r--r--chrome/browser/extensions/extension_prefs.cc43
-rw-r--r--chrome/browser/extensions/extension_prefs.h8
-rw-r--r--chrome/browser/extensions/extension_service.cc1
-rw-r--r--chrome/browser/extensions/extension_service.h4
-rw-r--r--chrome/browser/extensions/extension_system.cc13
-rw-r--r--chrome/browser/extensions/extension_system.h10
-rw-r--r--chrome/browser/extensions/state_store.cc75
-rw-r--r--chrome/browser/extensions/state_store.h64
-rw-r--r--chrome/browser/extensions/test_extension_system.cc4
-rw-r--r--chrome/browser/extensions/test_extension_system.h1
-rw-r--r--chrome/chrome_browser_extensions.gypi2
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',