[Extensions] Fix IsBeingUpgraded runtime data bug and make RuntimeData take ids
Fix a bug where IsBeingUpgraded would be reset during the reload process (even
though it's also *set* during the reload process...), and make RuntimeData take
extension ids instead of extensions.
BUG=435336
[email protected] (micro change in ui/toolbar/)
Review URL: https://codereview.chromium.org/743373002
Cr-Commit-Position: refs/heads/master@{#305134}
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 283f42a1..c96dc5a 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -608,7 +608,7 @@
path = transient_current_extension->path();
// BeingUpgraded is set back to false when the extension is added.
- system_->runtime_data()->SetBeingUpgraded(transient_current_extension,
+ system_->runtime_data()->SetBeingUpgraded(transient_current_extension->id(),
true);
DisableExtension(extension_id, Extension::DISABLE_RELOAD);
reloading_extensions_.insert(extension_id);
@@ -1342,7 +1342,12 @@
if (!Manifest::IsUnpackedLocation(extension->location()))
CHECK_GE(version_compare_result, 0);
}
- system_->runtime_data()->SetBeingUpgraded(extension, is_extension_upgrade);
+ // If the extension was disabled for a reload, then enable it.
+ bool reloading = reloading_extensions_.erase(extension->id()) > 0;
+
+ // Set the upgraded bit; we consider reloads upgrades.
+ system_->runtime_data()->SetBeingUpgraded(extension->id(),
+ is_extension_upgrade || reloading);
// The extension is now loaded, remove its data from unloaded extension map.
unloaded_extension_paths_.erase(extension->id());
@@ -1350,9 +1355,6 @@
// If a terminated extension is loaded, remove it from the terminated list.
UntrackTerminatedExtension(extension->id());
- // If the extension was disabled for a reload, then enable it.
- bool reloading = reloading_extensions_.erase(extension->id()) > 0;
-
// Check if the extension's privileges have changed and mark the
// extension disabled if necessary.
CheckPermissionsIncrease(extension, is_extension_installed);
@@ -1414,7 +1416,7 @@
extension_sync_service_->SyncExtensionChangeIfNeeded(*extension);
NotifyExtensionLoaded(extension);
}
- system_->runtime_data()->SetBeingUpgraded(extension, false);
+ system_->runtime_data()->SetBeingUpgraded(extension->id(), false);
}
void ExtensionService::AddComponentExtension(const Extension* extension) {
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
index 7dec674..5f57805 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -314,7 +314,7 @@
// If this is just an upgrade, then don't worry about resizing.
if (extensions::ExtensionSystem::Get(browser_->profile())->runtime_data()->
- IsBeingUpgraded(extension)) {
+ IsBeingUpgraded(extension->id())) {
delegate_->Redraw(false);
} else {
// We may need to resize (e.g. to show the new icon, or the chevron).
@@ -340,7 +340,7 @@
// If the extension is being upgraded we don't want the bar to shrink
// because the icon is just going to get re-added to the same location.
if (!extensions::ExtensionSystem::Get(browser_->profile())->runtime_data()->
- IsBeingUpgraded(extension)) {
+ IsBeingUpgraded(extension->id())) {
if (toolbar_actions_.size() > model_->visible_icon_count()) {
// If we have more icons than we can show, then we must not be changing
// the container size (since we either removed an icon from the main
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc b/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc
index e95deef..21f7a0a0 100644
--- a/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc
+++ b/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc
@@ -233,7 +233,7 @@
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&extension_web_request_api_helpers::NotifyWebRequestAPIUsed,
- browser_context_, make_scoped_refptr(extension)));
+ browser_context_, extension->id()));
}
return std::string();
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index c1e8f9d3..509dd98 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -2256,7 +2256,7 @@
FROM_HERE,
base::Bind(&helpers::NotifyWebRequestAPIUsed,
profile_id(),
- make_scoped_refptr(extension)));
+ extension->id()));
return true;
}
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.cc b/extensions/browser/api/web_request/web_request_api_helpers.cc
index 825b0bd..7dd2739f 100644
--- a/extensions/browser/api/web_request/web_request_api_helpers.cc
+++ b/extensions/browser/api/web_request/web_request_api_helpers.cc
@@ -1194,9 +1194,8 @@
}
}
-void NotifyWebRequestAPIUsed(
- void* browser_context_id,
- scoped_refptr<const extensions::Extension> extension) {
+void NotifyWebRequestAPIUsed(void* browser_context_id,
+ const std::string& extension_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::BrowserContext* browser_context =
reinterpret_cast<content::BrowserContext*>(browser_context_id);
@@ -1206,11 +1205,9 @@
extensions::RuntimeData* runtime_data =
extensions::ExtensionSystem::Get(browser_context)->runtime_data();
- if (extension.get()) {
- if (runtime_data->HasUsedWebRequest(extension.get()))
- return;
- runtime_data->SetHasUsedWebRequest(extension.get(), true);
- }
+ if (runtime_data->HasUsedWebRequest(extension_id))
+ return;
+ runtime_data->SetHasUsedWebRequest(extension_id, true);
for (content::RenderProcessHost::iterator it =
content::RenderProcessHost::AllHostsIterator();
@@ -1234,7 +1231,7 @@
for (extensions::ExtensionSet::const_iterator it = extensions.begin();
!webrequest_used && it != extensions.end();
++it) {
- webrequest_used |= runtime_data->HasUsedWebRequest(it->get());
+ webrequest_used |= runtime_data->HasUsedWebRequest((*it)->id());
}
host->Send(new ExtensionMsg_UsingWebRequestAPI(webrequest_used));
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.h b/extensions/browser/api/web_request/web_request_api_helpers.h
index a7ae5dd6..d5ea20a 100644
--- a/extensions/browser/api/web_request/web_request_api_helpers.h
+++ b/extensions/browser/api/web_request/web_request_api_helpers.h
@@ -310,12 +310,11 @@
void ClearCacheOnNavigation();
// Tells renderer processes that the web request or declarative web request
-// API has been used by |extension| in browser_context |browser_context_id| to
-// collect UMA statistics on Page Load Times. Needs to be called on the UI
-// thread.
-void NotifyWebRequestAPIUsed(
- void* browser_context_id,
- scoped_refptr<const extensions::Extension> extension);
+// API has been used by the extension with the given |extension_id| in the
+// given |browser_context_id| to collect UMA statistics on Page Load Times.
+// Needs to be called on the UI thread.
+void NotifyWebRequestAPIUsed(void* browser_context_id,
+ const std::string& extension_id);
// Send updates to |host| with information about what webRequest-related
// extensions are installed.
diff --git a/extensions/browser/extension_host.cc b/extensions/browser/extension_host.cc
index 4f2941b..9aa14c3 100644
--- a/extensions/browser/extension_host.cc
+++ b/extensions/browser/extension_host.cc
@@ -313,7 +313,7 @@
DCHECK(extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
ExtensionSystem::Get(browser_context_)
->runtime_data()
- ->SetBackgroundPageReady(extension_, true);
+ ->SetBackgroundPageReady(extension_->id(), true);
content::NotificationService::current()->Notify(
extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
content::Source<const Extension>(extension_),
diff --git a/extensions/browser/runtime_data.cc b/extensions/browser/runtime_data.cc
index 8f359bc..3cee846 100644
--- a/extensions/browser/runtime_data.cc
+++ b/extensions/browser/runtime_data.cc
@@ -21,32 +21,35 @@
bool RuntimeData::IsBackgroundPageReady(const Extension* extension) const {
if (!BackgroundInfo::HasPersistentBackgroundPage(extension))
return true;
- return HasFlag(extension, BACKGROUND_PAGE_READY);
+ return HasFlag(extension->id(), BACKGROUND_PAGE_READY);
}
-void RuntimeData::SetBackgroundPageReady(const Extension* extension,
+void RuntimeData::SetBackgroundPageReady(const std::string& extension_id,
bool value) {
- SetFlag(extension, BACKGROUND_PAGE_READY, value);
+ SetFlag(extension_id, BACKGROUND_PAGE_READY, value);
}
-bool RuntimeData::IsBeingUpgraded(const Extension* extension) const {
- return HasFlag(extension, BEING_UPGRADED);
+bool RuntimeData::IsBeingUpgraded(const std::string& extension_id) const {
+ return HasFlag(extension_id, BEING_UPGRADED);
}
-void RuntimeData::SetBeingUpgraded(const Extension* extension, bool value) {
- SetFlag(extension, BEING_UPGRADED, value);
+void RuntimeData::SetBeingUpgraded(const std::string& extension_id,
+ bool value) {
+ SetFlag(extension_id, BEING_UPGRADED, value);
}
-bool RuntimeData::HasUsedWebRequest(const Extension* extension) const {
- return HasFlag(extension, HAS_USED_WEBREQUEST);
+bool RuntimeData::HasUsedWebRequest(const std::string& extension_id) const {
+ return HasFlag(extension_id, HAS_USED_WEBREQUEST);
}
-void RuntimeData::SetHasUsedWebRequest(const Extension* extension, bool value) {
- SetFlag(extension, HAS_USED_WEBREQUEST, value);
+void RuntimeData::SetHasUsedWebRequest(const std::string& extension_id,
+ bool value) {
+ SetFlag(extension_id, HAS_USED_WEBREQUEST, value);
}
-bool RuntimeData::HasExtensionForTesting(const Extension* extension) const {
- return extension_flags_.find(extension->id()) != extension_flags_.end();
+bool RuntimeData::HasExtensionForTesting(
+ const std::string& extension_id) const {
+ return extension_flags_.find(extension_id) != extension_flags_.end();
}
void RuntimeData::ClearAll() {
@@ -56,23 +59,26 @@
void RuntimeData::OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionInfo::Reason reason) {
- extension_flags_.erase(extension->id());
+ ExtensionFlagsMap::iterator iter = extension_flags_.find(extension->id());
+ if (iter != extension_flags_.end())
+ iter->second = iter->second & kPersistAcrossUnloadMask;
}
-bool RuntimeData::HasFlag(const Extension* extension, RuntimeFlag flag) const {
- ExtensionFlagsMap::const_iterator it = extension_flags_.find(extension->id());
+bool RuntimeData::HasFlag(const std::string& extension_id,
+ RuntimeFlag flag) const {
+ ExtensionFlagsMap::const_iterator it = extension_flags_.find(extension_id);
if (it == extension_flags_.end())
return false;
return !!(it->second & flag);
}
-void RuntimeData::SetFlag(const Extension* extension,
+void RuntimeData::SetFlag(const std::string& extension_id,
RuntimeFlag flag,
bool value) {
if (value)
- extension_flags_[extension->id()] |= flag;
+ extension_flags_[extension_id] |= flag;
else
- extension_flags_[extension->id()] &= ~flag;
+ extension_flags_[extension_id] &= ~flag;
}
} // namespace extensions
diff --git a/extensions/browser/runtime_data.h b/extensions/browser/runtime_data.h
index 9d74041..c937a99f7 100644
--- a/extensions/browser/runtime_data.h
+++ b/extensions/browser/runtime_data.h
@@ -13,13 +13,15 @@
namespace extensions {
-class Extension;
class ExtensionRegistry;
// Contains per-extension data that can change during the life of the process,
// but does not persist across restarts. Shared between incognito and regular
// browser contexts. Lives on the UI thread. Must be destroyed before
// ExtensionRegistry.
+// If we start putting to much into this, we should expose the generic
+// "[G|S]etRuntimeProperty(const std::string& extension_id, RuntimeFlag flag)"
+// instead of all these.
class RuntimeData : public ExtensionRegistryObserver {
public:
// Observes |registry| to clean itself up when extensions change state.
@@ -31,20 +33,21 @@
// other components until then. If there is no background page, or if it is
// non-persistent (lazy), we consider it to be ready.
bool IsBackgroundPageReady(const Extension* extension) const;
- void SetBackgroundPageReady(const Extension* extension, bool value);
+ void SetBackgroundPageReady(const std::string& extension_id, bool value);
// Getter and setter for the flag that specifies whether the extension is
// being upgraded.
- bool IsBeingUpgraded(const Extension* extension) const;
- void SetBeingUpgraded(const Extension* extension, bool value);
+ // For these purposes, a reload counts as an upgrade.
+ bool IsBeingUpgraded(const std::string& extension_id) const;
+ void SetBeingUpgraded(const std::string& extension_id, bool value);
// Getter and setter for the flag that specifies if the extension has used
// the webrequest API.
- bool HasUsedWebRequest(const Extension* extension) const;
- void SetHasUsedWebRequest(const Extension* extension, bool value);
+ bool HasUsedWebRequest(const std::string& extension_id) const;
+ void SetHasUsedWebRequest(const std::string& extension_id, bool value);
// Returns true if the extension is being tracked. Used only for testing.
- bool HasExtensionForTesting(const Extension* extension) const;
+ bool HasExtensionForTesting(const std::string& extension_id) const;
// Erase runtime data for all extensions. Used only for testing. Cannot be
// named ClearAllForTesting due to false-positive presubmit errors.
@@ -66,12 +69,16 @@
HAS_USED_WEBREQUEST = 1 << 2,
};
+ // The mask of any data that should persist across the extension being
+ // unloaded.
+ static const int kPersistAcrossUnloadMask = BEING_UPGRADED;
+
// Returns the setting for the flag or false if the extension isn't found.
- bool HasFlag(const Extension* extension, RuntimeFlag flag) const;
+ bool HasFlag(const std::string& extension_id, RuntimeFlag flag) const;
// Sets |flag| for |extension| to |value|. Adds |extension| to the list of
// extensions if it isn't present.
- void SetFlag(const Extension* extension, RuntimeFlag flag, bool value);
+ void SetFlag(const std::string& extension_id, RuntimeFlag flag, bool value);
// Map from extension ID to the RuntimeFlags bits.
typedef std::map<std::string, int> ExtensionFlagsMap;
diff --git a/extensions/browser/runtime_data_unittest.cc b/extensions/browser/runtime_data_unittest.cc
index 451308c..bec1e130 100644
--- a/extensions/browser/runtime_data_unittest.cc
+++ b/extensions/browser/runtime_data_unittest.cc
@@ -53,9 +53,9 @@
EXPECT_FALSE(runtime_data_.IsBackgroundPageReady(with_background.get()));
// The flag can be toggled.
- runtime_data_.SetBackgroundPageReady(with_background.get(), true);
+ runtime_data_.SetBackgroundPageReady(with_background->id(), true);
EXPECT_TRUE(runtime_data_.IsBackgroundPageReady(with_background.get()));
- runtime_data_.SetBackgroundPageReady(with_background.get(), false);
+ runtime_data_.SetBackgroundPageReady(with_background->id(), false);
EXPECT_FALSE(runtime_data_.IsBackgroundPageReady(with_background.get()));
}
@@ -63,37 +63,41 @@
scoped_refptr<Extension> extension = test_util::CreateEmptyExtension();
// An extension is not being upgraded until the flag is set.
- EXPECT_FALSE(runtime_data_.IsBeingUpgraded(extension.get()));
+ EXPECT_FALSE(runtime_data_.IsBeingUpgraded(extension->id()));
// The flag can be toggled.
- runtime_data_.SetBeingUpgraded(extension.get(), true);
- EXPECT_TRUE(runtime_data_.IsBeingUpgraded(extension.get()));
- runtime_data_.SetBeingUpgraded(extension.get(), false);
- EXPECT_FALSE(runtime_data_.IsBeingUpgraded(extension.get()));
+ runtime_data_.SetBeingUpgraded(extension->id(), true);
+ EXPECT_TRUE(runtime_data_.IsBeingUpgraded(extension->id()));
+ runtime_data_.SetBeingUpgraded(extension->id(), false);
+ EXPECT_FALSE(runtime_data_.IsBeingUpgraded(extension->id()));
}
TEST_F(RuntimeDataTest, HasUsedWebRequest) {
scoped_refptr<Extension> extension = test_util::CreateEmptyExtension();
// An extension has not used web request until the flag is set.
- EXPECT_FALSE(runtime_data_.HasUsedWebRequest(extension.get()));
+ EXPECT_FALSE(runtime_data_.HasUsedWebRequest(extension->id()));
// The flag can be toggled.
- runtime_data_.SetHasUsedWebRequest(extension.get(), true);
- EXPECT_TRUE(runtime_data_.HasUsedWebRequest(extension.get()));
- runtime_data_.SetHasUsedWebRequest(extension.get(), false);
- EXPECT_FALSE(runtime_data_.HasUsedWebRequest(extension.get()));
+ runtime_data_.SetHasUsedWebRequest(extension->id(), true);
+ EXPECT_TRUE(runtime_data_.HasUsedWebRequest(extension->id()));
+ runtime_data_.SetHasUsedWebRequest(extension->id(), false);
+ EXPECT_FALSE(runtime_data_.HasUsedWebRequest(extension->id()));
}
-// Unloading an extension stops tracking it.
+// Unloading an extension erases any data that shouldn't explicitly be kept
+// across loads.
TEST_F(RuntimeDataTest, OnExtensionUnloaded) {
scoped_refptr<Extension> extension = CreateExtensionWithBackgroundPage();
- runtime_data_.SetBackgroundPageReady(extension.get(), true);
- ASSERT_TRUE(runtime_data_.HasExtensionForTesting(extension.get()));
+ runtime_data_.SetBackgroundPageReady(extension->id(), true);
+ ASSERT_TRUE(runtime_data_.HasExtensionForTesting(extension->id()));
+ runtime_data_.SetBeingUpgraded(extension->id(), true);
runtime_data_.OnExtensionUnloaded(
NULL, extension.get(), UnloadedExtensionInfo::REASON_DISABLE);
- EXPECT_FALSE(runtime_data_.HasExtensionForTesting(extension.get()));
+ EXPECT_TRUE(runtime_data_.HasExtensionForTesting(extension->id()));
+ EXPECT_FALSE(runtime_data_.IsBackgroundPageReady(extension.get()));
+ EXPECT_TRUE(runtime_data_.IsBeingUpgraded(extension->id()));
}
} // namespace