summaryrefslogtreecommitdiffstats
path: root/extensions/browser/api/runtime/runtime_api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/browser/api/runtime/runtime_api.cc')
-rw-r--r--extensions/browser/api/runtime/runtime_api.cc82
1 files changed, 72 insertions, 10 deletions
diff --git a/extensions/browser/api/runtime/runtime_api.cc b/extensions/browser/api/runtime/runtime_api.cc
index a7e6ef4..1473a43 100644
--- a/extensions/browser/api/runtime/runtime_api.cc
+++ b/extensions/browser/api/runtime/runtime_api.cc
@@ -62,6 +62,15 @@ const char kUpdatesDisabledError[] = "Autoupdate is not enabled.";
// A preference key storing the url loaded when an extension is uninstalled.
const char kUninstallUrl[] = "uninstall_url";
+// A preference key storing the information about an extension that was
+// installed but not loaded. We keep the pending info here so that we can send
+// chrome.runtime.onInstalled event during the extension load.
+const char kPrefPendingOnInstalledEventDispatchInfo[] =
+ "pending_on_installed_event_dispatch_info";
+
+// Previously installed version number.
+const char kPrefPreviousVersion[] = "previous_version";
+
// The name of the directory to be returned by getPackageDirectoryEntry. This
// particular value does not matter to user code, but is chosen for consistency
// with the equivalent Pepper API.
@@ -182,6 +191,15 @@ void RuntimeAPI::Observe(int type,
void RuntimeAPI::OnExtensionLoaded(content::BrowserContext* browser_context,
const Extension* extension) {
+ base::Version previous_version;
+ if (ReadPendingOnInstallInfoFromPref(extension->id(), &previous_version)) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent,
+ browser_context_, extension->id(), previous_version, false));
+ RemovePendingOnInstallInfoFromPref(extension->id());
+ }
+
if (!dispatch_chrome_updated_event_)
return;
@@ -200,22 +218,19 @@ void RuntimeAPI::OnExtensionWillBeInstalled(
const Extension* extension,
bool is_update,
const std::string& old_name) {
- Version old_version = delegate_->GetPreviousExtensionVersion(extension);
-
- // Dispatch the onInstalled event.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent,
- browser_context_,
- extension->id(),
- old_version,
- false));
+ // This extension might be disabled before it has a chance to load, e.g. if
+ // the extension increased its permissions. So instead of trying to send the
+ // onInstalled event here, we remember the fact in prefs and fire the event
+ // when the extension is actually loaded.
+ StorePendingOnInstallInfoToPref(extension);
}
void RuntimeAPI::OnExtensionUninstalled(
content::BrowserContext* browser_context,
const Extension* extension,
UninstallReason reason) {
+ RemovePendingOnInstallInfoFromPref(extension->id());
+
RuntimeEventRouter::OnExtensionUninstalled(
browser_context_, extension->id(), reason);
}
@@ -237,6 +252,53 @@ void RuntimeAPI::OnBackgroundHostStartup(const Extension* extension) {
RuntimeEventRouter::DispatchOnStartupEvent(browser_context_, extension->id());
}
+bool RuntimeAPI::ReadPendingOnInstallInfoFromPref(
+ const ExtensionId& extension_id,
+ base::Version* previous_version) {
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_);
+ DCHECK(prefs);
+
+ const base::DictionaryValue* info = nullptr;
+ if (!prefs->ReadPrefAsDictionary(
+ extension_id, kPrefPendingOnInstalledEventDispatchInfo, &info)) {
+ return false;
+ }
+
+ std::string previous_version_string;
+ info->GetString(kPrefPreviousVersion, &previous_version_string);
+ // |previous_version_string| can be empty.
+ *previous_version = base::Version(previous_version_string);
+ return true;
+}
+
+void RuntimeAPI::RemovePendingOnInstallInfoFromPref(
+ const ExtensionId& extension_id) {
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_);
+ DCHECK(prefs);
+
+ prefs->UpdateExtensionPref(extension_id,
+ kPrefPendingOnInstalledEventDispatchInfo, nullptr);
+}
+
+void RuntimeAPI::StorePendingOnInstallInfoToPref(const Extension* extension) {
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_);
+ DCHECK(prefs);
+
+ // |pending_on_install_info| currently only contains a version string. Instead
+ // of making the pref hold a plain string, we store it as a dictionary value
+ // so that we can add more stuff to it in the future if necessary.
+ scoped_ptr<base::DictionaryValue> pending_on_install_info(
+ new base::DictionaryValue());
+ base::Version previous_version =
+ delegate_->GetPreviousExtensionVersion(extension);
+ pending_on_install_info->SetString(
+ kPrefPreviousVersion,
+ previous_version.IsValid() ? previous_version.GetString() : "");
+ prefs->UpdateExtensionPref(extension->id(),
+ kPrefPendingOnInstalledEventDispatchInfo,
+ pending_on_install_info.release());
+}
+
void RuntimeAPI::ReloadExtension(const std::string& extension_id) {
delegate_->ReloadExtension(extension_id);
}