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
parent a934ece5
// 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
// 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_
......@@ -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
......@@ -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__
......@@ -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()) {
......
......@@ -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);
......
......@@ -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));
......
......@@ -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);
......
......@@ -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();
}
......
......@@ -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_;
......
// 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
// 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_
......@@ -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;
}
......
......@@ -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;
......
......@@ -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',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment