Index: chrome/browser/extensions/extension_prefs.cc |
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc |
index 79b11e3229ade7b9d70967fb747fcb701d2f28a6..a6ae0e56f343343bae327d5168eadf11579ac2e4 100644 |
--- a/chrome/browser/extensions/extension_prefs.cc |
+++ b/chrome/browser/extensions/extension_prefs.cc |
@@ -119,6 +119,9 @@ const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate"; |
// Path for the idle install info dictionary preference. |
const char kIdleInstallInfo[] = "idle_install_info"; |
+// Path for the suggested page ordinal of a delayed extension install. |
+const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal"; |
+ |
// A preference that, if true, will allow this extension to run in incognito |
// mode. |
const char kPrefIncognitoEnabled[] = "incognito"; |
@@ -1448,57 +1451,14 @@ void ExtensionPrefs::OnExtensionInstalled( |
const Extension* extension, |
Extension::State initial_state, |
const syncer::StringOrdinal& page_ordinal) { |
- const std::string& id = extension->id(); |
- CHECK(Extension::IdIsValid(id)); |
- ScopedExtensionPrefUpdate update(prefs_, id); |
+ ScopedExtensionPrefUpdate update(prefs_, extension->id()); |
DictionaryValue* extension_dict = update.Get(); |
const base::Time install_time = time_provider_->GetCurrentTime(); |
- |
- // Leave the state blank for component extensions so that old chrome versions |
- // loading new profiles do not fail in GetInstalledExtensionInfo. Older |
- // Chrome versions would only check for an omitted state. |
- if (initial_state != Extension::ENABLED_COMPONENT) |
- extension_dict->Set(kPrefState, Value::CreateIntegerValue(initial_state)); |
- |
- extension_dict->Set(kPrefLocation, |
- Value::CreateIntegerValue(extension->location())); |
- extension_dict->Set(kPrefCreationFlags, |
- Value::CreateIntegerValue(extension->creation_flags())); |
- extension_dict->Set(kPrefFromWebStore, |
- Value::CreateBooleanValue(extension->from_webstore())); |
- extension_dict->Set(kPrefFromBookmark, |
- Value::CreateBooleanValue(extension->from_bookmark())); |
- extension_dict->Set(kPrefWasInstalledByDefault, |
- Value::CreateBooleanValue(extension->was_installed_by_default())); |
- extension_dict->Set(kPrefInstallTime, |
- Value::CreateStringValue( |
- base::Int64ToString(install_time.ToInternalValue()))); |
- extension_dict->Set(kPrefPreferences, new DictionaryValue()); |
- extension_dict->Set(kPrefIncognitoPreferences, new DictionaryValue()); |
- extension_dict->Set(kPrefRegularOnlyPreferences, new DictionaryValue()); |
- extension_dict->Set(kPrefContentSettings, new ListValue()); |
- extension_dict->Set(kPrefIncognitoContentSettings, new ListValue()); |
- |
- FilePath::StringType path = MakePathRelative(install_directory_, |
- extension->path()); |
- extension_dict->Set(kPrefPath, Value::CreateStringValue(path)); |
- // We store prefs about LOAD extensions, but don't cache their manifest |
- // since it may change on disk. |
- if (extension->location() != Extension::LOAD) { |
- extension_dict->Set(kPrefManifest, |
- extension->manifest()->value()->DeepCopy()); |
- } |
- |
- // Clear state that may be registered from a previous install. |
- extension_dict->Remove(kRegisteredEvents, NULL); |
- |
- if (extension->RequiresSortOrdinal()) |
- extension_sorting_->EnsureValidOrdinals(extension->id(), page_ordinal); |
- |
- extension_pref_value_map_->RegisterExtension( |
- id, install_time, initial_state == Extension::ENABLED); |
- content_settings_store_->RegisterExtension( |
- id, install_time, initial_state == Extension::ENABLED); |
+ PopulateExtensionInfoPrefs(extension, install_time, initial_state, |
+ extension_dict); |
+ FinishExtensionInfoPrefs(extension->id(), install_time, |
+ extension->RequiresSortOrdinal(), |
+ page_ordinal, extension_dict); |
} |
void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id, |
@@ -1717,31 +1677,24 @@ scoped_ptr<ExtensionPrefs::ExtensionsInfo> |
void ExtensionPrefs::SetIdleInstallInfo( |
const Extension* extension, |
- Extension::State initial_state) { |
- const base::Time install_time = time_provider_->GetCurrentTime(); |
+ Extension::State initial_state, |
+ const syncer::StringOrdinal& page_ordinal) { |
DictionaryValue* extension_dict = new DictionaryValue(); |
- extension_dict->Set(kPrefState, Value::CreateIntegerValue(initial_state)); |
- extension_dict->Set(kPrefLocation, |
- Value::CreateIntegerValue(extension->location())); |
- extension_dict->Set(kPrefCreationFlags, |
- Value::CreateIntegerValue(extension->creation_flags())); |
- extension_dict->Set(kPrefFromWebStore, |
- Value::CreateBooleanValue(extension->from_webstore())); |
- extension_dict->Set(kPrefFromBookmark, |
- Value::CreateBooleanValue(extension->from_bookmark())); |
- extension_dict->Set(kPrefWasInstalledByDefault, |
- Value::CreateBooleanValue(extension->was_installed_by_default())); |
- extension_dict->Set(kPrefInstallTime, |
- Value::CreateStringValue( |
- base::Int64ToString(install_time.ToInternalValue()))); |
+ PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(), |
+ initial_state, extension_dict); |
- FilePath::StringType path = MakePathRelative(install_directory_, |
- extension->path()); |
- extension_dict->Set(kPrefPath, Value::CreateStringValue(path)); |
- extension_dict->Set(kPrefManifest, |
- extension->manifest()->value()->DeepCopy()); |
+ // Add transient data that is needed by FinishIdleInstallInfo(), but |
+ // should not be in the final extension prefs. All entries here should have |
+ // a corresponding Remove() call in FinishIdleInstallInfo(). |
+ if (extension->RequiresSortOrdinal()) { |
+ extension_dict->SetString(kPrefSuggestedPageOrdinal, |
+ page_ordinal.ToInternalValue()); |
+ } |
- UpdateExtensionPref(extension->id(), kIdleInstallInfo, extension_dict); |
+ // RESOLVE BEFORE COMMIT: Why did this used to use UpdateExtensionPref |
Marijn Kruisselbrink
2012/12/07 17:29:49
Why not? Most code seems to use UpdateExtensionPre
awong
2012/12/07 22:02:25
Okay...I'll move back to UpdateExtensionPref(). I
Marijn Kruisselbrink
2012/12/07 22:15:09
Ah, yeah, RemoveIdleInstallInfo I didn't touch, an
|
+ // directly? |
+ ScopedExtensionPrefUpdate update(prefs_, extension->id()); |
+ update->Set(kIdleInstallInfo, extension_dict); |
} |
bool ExtensionPrefs::RemoveIdleInstallInfo(const std::string& extension_id) { |
@@ -1756,34 +1709,32 @@ bool ExtensionPrefs::FinishIdleInstallInfo(const std::string& extension_id) { |
CHECK(Extension::IdIsValid(extension_id)); |
ScopedExtensionPrefUpdate update(prefs_, extension_id); |
DictionaryValue* extension_dict = update.Get(); |
- DictionaryValue* update_dict; |
- if (!extension_dict->GetDictionary(kIdleInstallInfo, &update_dict)) |
+ DictionaryValue* pending_install_dict = NULL; |
+ if (!extension_dict->GetDictionary(kIdleInstallInfo, &pending_install_dict)) |
return false; |
- const base::Time install_time = time_provider_->GetCurrentTime(); |
- extension_dict->MergeDictionary(update_dict); |
- extension_dict->Set(kPrefInstallTime, |
- Value::CreateStringValue( |
- base::Int64ToString(install_time.ToInternalValue()))); |
- extension_dict->Set(kPrefPreferences, new DictionaryValue()); |
- extension_dict->Set(kPrefIncognitoPreferences, new DictionaryValue()); |
- extension_dict->Set(kPrefRegularOnlyPreferences, new DictionaryValue()); |
- extension_dict->Set(kPrefContentSettings, new ListValue()); |
- extension_dict->Set(kPrefIncognitoContentSettings, new ListValue()); |
- |
- // Clear state that may be registered from a previous install. |
- extension_dict->Remove(kRegisteredEvents, NULL); |
+ // Retrieve and clear transient values populated by SetIdleInstallInfo(). Also |
+ // do any other data cleanup that makes sense. |
+ std::string serialized_ordinal; |
+ syncer::StringOrdinal suggested_page_ordinal; |
+ bool needs_sort_ordinal = false; |
+ if (pending_install_dict->GetString(kPrefSuggestedPageOrdinal, |
+ &serialized_ordinal)) { |
+ suggested_page_ordinal = syncer::StringOrdinal(serialized_ordinal); |
+ needs_sort_ordinal = true; |
+ pending_install_dict->Remove(kPrefSuggestedPageOrdinal, NULL); |
+ } |
- // Remove pending update information |
- extension_dict->Remove(kIdleInstallInfo, NULL); |
+ const base::Time install_time = time_provider_->GetCurrentTime(); |
+ pending_install_dict->Set( |
+ kPrefInstallTime, |
+ Value::CreateStringValue( |
+ base::Int64ToString(install_time.ToInternalValue()))); |
- int initial_state; |
- if (extension_dict->GetInteger(kPrefState, &initial_state)) { |
- extension_pref_value_map_->RegisterExtension( |
- extension_id, install_time, initial_state == Extension::ENABLED); |
- content_settings_store_->RegisterExtension( |
- extension_id, install_time, initial_state == Extension::ENABLED); |
- } |
+ // Commit the delayed install data. |
+ extension_dict->MergeDictionary(pending_install_dict); |
+ FinishExtensionInfoPrefs(extension_id, install_time, needs_sort_ordinal, |
+ suggested_page_ordinal, extension_dict); |
return true; |
} |
@@ -2315,4 +2266,89 @@ void ExtensionPrefs::SetExtensionPrefFromVector( |
list_of_values->Append(new StringValue(*iter)); |
} |
+void ExtensionPrefs::PopulateExtensionInfoPrefs( |
+ const Extension* extension, |
+ const base::Time install_time, |
+ Extension::State initial_state, |
+ DictionaryValue* extension_dict) { |
+ // Leave the state blank for component extensions so that old chrome versions |
+ // loading new profiles do not fail in GetInstalledExtensionInfo. Older |
+ // Chrome versions would only check for an omitted state. |
+ if (initial_state != Extension::ENABLED_COMPONENT) |
+ extension_dict->Set(kPrefState, Value::CreateIntegerValue(initial_state)); |
+ |
+ extension_dict->Set(kPrefLocation, |
+ Value::CreateIntegerValue(extension->location())); |
+ extension_dict->Set(kPrefCreationFlags, |
+ Value::CreateIntegerValue(extension->creation_flags())); |
+ extension_dict->Set(kPrefFromWebStore, |
+ Value::CreateBooleanValue(extension->from_webstore())); |
+ extension_dict->Set(kPrefFromBookmark, |
+ Value::CreateBooleanValue(extension->from_bookmark())); |
+ extension_dict->Set(kPrefWasInstalledByDefault, |
+ Value::CreateBooleanValue(extension->was_installed_by_default())); |
+ extension_dict->Set(kPrefInstallTime, |
+ Value::CreateStringValue( |
+ base::Int64ToString(install_time.ToInternalValue()))); |
+ |
+ FilePath::StringType path = MakePathRelative(install_directory_, |
+ extension->path()); |
+ extension_dict->Set(kPrefPath, Value::CreateStringValue(path)); |
+ // We store prefs about LOAD extensions, but don't cache their manifest |
+ // since it may change on disk. |
+ if (extension->location() != Extension::LOAD) { |
+ // RESOLVE ME BEFORE COMMIT: We did not preivously avoid this for LOAD extensions in |
Marijn Kruisselbrink
2012/12/07 17:29:49
Yes, I agree. No reason to not avoid this even in
awong
2012/12/07 22:02:25
Done.
|
+ // SetIdleInstallInfo(). Having this condition still seems sensible even |
+ // if the extension was delayed. |
+ extension_dict->Set(kPrefManifest, |
+ extension->manifest()->value()->DeepCopy()); |
+ } |
+ |
+ // RESOLVE ME BEFORE COMMIT: This could be created post commit, but it feels |
Marijn Kruisselbrink
2012/12/07 17:29:49
I'm not sure if this actually works though. In Fin
awong
2012/12/07 22:02:25
Ah! Good catch. Moved into FinishExtensionInfoPref
|
+ // cleaner to just keep all this in one spot. Do we actually care enough to |
+ // save these 5 empty preferences from being committed to disk? |
+ extension_dict->Set(kPrefPreferences, new DictionaryValue()); |
+ extension_dict->Set(kPrefIncognitoPreferences, new DictionaryValue()); |
+ extension_dict->Set(kPrefRegularOnlyPreferences, new DictionaryValue()); |
+ extension_dict->Set(kPrefContentSettings, new ListValue()); |
+ extension_dict->Set(kPrefIncognitoContentSettings, new ListValue()); |
+} |
+ |
+void ExtensionPrefs::FinishExtensionInfoPrefs( |
+ const std::string& extension_id, |
+ const base::Time install_time, |
+ bool needs_sort_ordinal, |
+ const syncer::StringOrdinal& suggested_page_ordinal, |
+ DictionaryValue* extension_dict) { |
+ // If this point has been reached, any pending installs should be considered |
+ // out of date. |
+ extension_dict->Remove(kIdleInstallInfo, NULL); |
+ |
+ // Clear state that may be registered from a previous install. |
+ extension_dict->Remove(kRegisteredEvents, NULL); |
+ |
+ // FYI, all code below here races on sudden shutdown because |
+ // |extension_dict|, |extension_sorting_|, |extension_pref_value_map_|, |
+ // and |content_settings_store_| are updated non-transactionally. This is |
+ // probably not fixable without nested transactional updates to pref |
+ // dictionaries. |
+ if (needs_sort_ordinal) { |
+ extension_sorting_->EnsureValidOrdinals(extension_id, |
+ suggested_page_ordinal); |
+ } |
+ |
+ int initial_state; |
+ if (extension_dict->GetInteger(kPrefState, &initial_state)) { |
+ /* RESOLVE ME BEFORE COMMIT: This conditional seems impossible to fail since |
Marijn Kruisselbrink
2012/12/07 17:29:49
Isn't initial_state not set when its value would b
awong
2012/12/07 22:02:25
Oh interesting. Yeah, that came in via a last minu
Marijn Kruisselbrink
2012/12/07 22:15:09
It probably isn't right to skip these calls. OnExt
awong
2012/12/07 22:56:53
Added some logic that I *think* has the correct be
|
+ * SetIdleInstallInfo() sets it. Should we NOTREACHED() the failure of this |
+ * or are we supporting old prefs somehow? If we're supporting old prefs, |
+ * should we pick a default initial_state? |
+ */ |
+ extension_pref_value_map_->RegisterExtension( |
+ extension_id, install_time, initial_state == Extension::ENABLED); |
+ content_settings_store_->RegisterExtension( |
+ extension_id, install_time, initial_state == Extension::ENABLED); |
+ } |
+} |
+ |
} // namespace extensions |