Index: chrome/browser/extensions/extension_action.h |
diff --git a/chrome/browser/extensions/extension_action.h b/chrome/browser/extensions/extension_action.h |
index 18684039a00b6d8508714d3a15ba934a5c815e28..95fae5a69a44a6e2522738617be5d29367c42a7c 100644 |
--- a/chrome/browser/extensions/extension_action.h |
+++ b/chrome/browser/extensions/extension_action.h |
@@ -220,15 +220,22 @@ class ExtensionAction { |
// care of any appropriate transition animations. Returns true if |
// the appearance has changed. |
bool SetAppearance(int tab_id, Appearance value); |
+ // The declarative appearance overrides a default appearance but is overrided |
+ // by an appearance set directly on the tab. |
+ void SetDeclarativeAppearance(int tab_id, Appearance value); |
+ void ClearDeclarativeAppearance(int tab_id); |
+ |
// Get the badge visibility for a tab, or the default badge visibility |
// if none was set. |
bool GetIsVisible(int tab_id) const { |
- return GetValue(&appearance_, tab_id) != INVISIBLE; |
+ return GetDeclarativeValue(&appearance_, &declarative_appearance_, tab_id) |
+ != INVISIBLE; |
} |
// True if the tab's action wants the user's attention. |
bool WantsAttention(int tab_id) const { |
- return GetValue(&appearance_, tab_id) == WANTS_ATTENTION; |
+ return GetDeclarativeValue(&appearance_, &declarative_appearance_, tab_id) |
+ == WANTS_ATTENTION; |
} |
// Remove all tab-specific state. |
@@ -283,6 +290,30 @@ class ExtensionAction { |
} |
} |
+ // Returns the first of map[tab_id], declarative_map[tab_id], |
+ // map[kDefaultTabId], or ValueTraits<T>::CreateEmpty() that's defined. Don't |
+ // return this result to an extension's background page because the |
+ // declarative state can leak information about hosts the extension doesn't |
+ // have permission to access. |
+ template<class T> |
+ T GetDeclarativeValue(const std::map<int, T>* map, |
+ const std::map<int, T>* declarative_map, |
+ int tab_id) const { |
+ typename std::map<int, T>::const_iterator iter = map->find(tab_id); |
+ if (iter != map->end()) |
+ return iter->second; |
+ |
+ iter = declarative_map->find(tab_id); |
+ if (iter != declarative_map->end()) |
+ return iter->second; |
+ |
+ iter = map->find(kDefaultTabId); |
+ if (iter != map->end()) |
+ return iter->second; |
+ |
+ return ValueTraits<T>::CreateEmpty(); |
+ } |
+ |
// The id for the extension this action belongs to (as defined in the |
// extension manifest). |
const std::string extension_id_; |
@@ -298,6 +329,13 @@ class ExtensionAction { |
std::map<int, SkColor> badge_background_color_; |
std::map<int, SkColor> badge_text_color_; |
std::map<int, Appearance> appearance_; |
+ // Declarative state exists for two reasons: First, we need to hide it from |
+ // the extension's background/event page to avoid leaking data from hosts the |
+ // extension doesn't have permission to access. Second, the action's state |
+ // gets both reset and given its declarative values in response to a |
+ // WebContentsObserver::DidNavigateMainFrame event, and there's no way to set |
+ // those up to be called in the right order. |
+ std::map<int, Appearance> declarative_appearance_; |
// IconAnimations are destroyed by a delayed task on the UI message loop so |
// that even if the Extension and ExtensionAction are destroyed on a non-UI |