Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_toolbar_model.h" | 5 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 12 #include "base/metrics/histogram_base.h" | 12 #include "base/metrics/histogram_base.h" |
| 13 #include "base/prefs/pref_service.h" | 13 #include "base/prefs/pref_service.h" |
| 14 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
| 15 #include "base/thread_task_runner_handle.h" | 15 #include "base/thread_task_runner_handle.h" |
| 16 #include "chrome/browser/chrome_notification_types.h" | 16 #include "chrome/browser/chrome_notification_types.h" |
| 17 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" | |
| 18 #include "chrome/browser/extensions/extension_action_manager.h" | 17 #include "chrome/browser/extensions/extension_action_manager.h" |
| 19 #include "chrome/browser/extensions/extension_tab_util.h" | 18 #include "chrome/browser/extensions/extension_tab_util.h" |
| 20 #include "chrome/browser/extensions/extension_toolbar_model_factory.h" | |
| 21 #include "chrome/browser/extensions/extension_util.h" | 19 #include "chrome/browser/extensions/extension_util.h" |
| 22 #include "chrome/browser/extensions/tab_helper.h" | 20 #include "chrome/browser/extensions/tab_helper.h" |
| 23 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
| 24 #include "chrome/browser/ui/browser.h" | 22 #include "chrome/browser/ui/browser.h" |
| 23 #include "chrome/browser/ui/extensions/extension_action_view_controller.h" | |
| 25 #include "chrome/browser/ui/extensions/extension_toolbar_icon_surfacing_bubble_d elegate.h" | 24 #include "chrome/browser/ui/extensions/extension_toolbar_icon_surfacing_bubble_d elegate.h" |
| 26 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 25 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 26 #include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h" | |
| 27 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" | |
| 28 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" | |
| 29 #include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h" | |
| 27 #include "content/public/browser/notification_details.h" | 30 #include "content/public/browser/notification_details.h" |
| 28 #include "content/public/browser/notification_source.h" | 31 #include "content/public/browser/notification_source.h" |
| 29 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
| 30 #include "extensions/browser/extension_prefs.h" | |
| 31 #include "extensions/browser/extension_registry.h" | 33 #include "extensions/browser/extension_registry.h" |
| 32 #include "extensions/browser/extension_system.h" | 34 #include "extensions/browser/extension_system.h" |
| 33 #include "extensions/browser/pref_names.h" | 35 #include "extensions/browser/pref_names.h" |
| 34 #include "extensions/common/extension.h" | |
| 35 #include "extensions/common/extension_set.h" | 36 #include "extensions/common/extension_set.h" |
| 36 #include "extensions/common/feature_switch.h" | 37 #include "extensions/common/feature_switch.h" |
| 37 #include "extensions/common/manifest_constants.h" | 38 #include "extensions/common/manifest_constants.h" |
| 38 #include "extensions/common/one_shot_event.h" | 39 #include "extensions/common/one_shot_event.h" |
| 39 | 40 |
| 40 namespace extensions { | 41 ToolbarActionsModel::ToolbarActionsModel(Profile* profile, |
| 41 | 42 extensions::ExtensionPrefs* extension_prefs) |
| 42 ExtensionToolbarModel::ExtensionToolbarModel(Profile* profile, | |
| 43 ExtensionPrefs* extension_prefs) | |
| 44 : profile_(profile), | 43 : profile_(profile), |
| 45 extension_prefs_(extension_prefs), | 44 extension_prefs_(extension_prefs), |
| 46 prefs_(profile_->GetPrefs()), | 45 prefs_(profile_->GetPrefs()), |
| 47 extension_action_api_(ExtensionActionAPI::Get(profile_)), | 46 extension_action_api_(extensions::ExtensionActionAPI::Get(profile_)), |
| 48 extensions_initialized_(false), | 47 extension_registry_(extensions::ExtensionRegistry::Get(profile_)), |
| 49 include_all_extensions_(FeatureSwitch::extension_action_redesign() | 48 actions_initialized_(false), |
| 50 ->IsEnabled()), | 49 use_redesign_( |
| 50 extensions::FeatureSwitch::extension_action_redesign()->IsEnabled()), | |
| 51 highlight_type_(HIGHLIGHT_NONE), | 51 highlight_type_(HIGHLIGHT_NONE), |
| 52 extension_action_observer_(this), | 52 extension_action_observer_(this), |
| 53 extension_registry_observer_(this), | 53 extension_registry_observer_(this), |
| 54 weak_ptr_factory_(this) { | 54 weak_ptr_factory_(this) { |
| 55 ExtensionSystem::Get(profile_)->ready().Post( | 55 extensions::ExtensionSystem::Get(profile_)->ready().Post( |
| 56 FROM_HERE, | 56 FROM_HERE, |
| 57 base::Bind(&ExtensionToolbarModel::OnReady, | 57 base::Bind(&ToolbarActionsModel::OnReady, |
| 58 weak_ptr_factory_.GetWeakPtr())); | 58 weak_ptr_factory_.GetWeakPtr())); |
| 59 visible_icon_count_ = prefs_->GetInteger(pref_names::kToolbarSize); | 59 visible_icon_count_ = prefs_->GetInteger( |
| 60 extensions::pref_names::kToolbarSize); | |
| 60 | 61 |
| 61 // We only care about watching the prefs if not in incognito mode. | 62 // We only care about watching the prefs if not in incognito mode. |
| 62 if (!profile_->IsOffTheRecord()) { | 63 if (!profile_->IsOffTheRecord()) { |
| 63 pref_change_registrar_.Init(prefs_); | 64 pref_change_registrar_.Init(prefs_); |
| 64 pref_change_callback_ = | 65 pref_change_callback_ = |
| 65 base::Bind(&ExtensionToolbarModel::OnExtensionToolbarPrefChange, | 66 base::Bind(&ToolbarActionsModel::OnActionToolbarPrefChange, |
| 66 base::Unretained(this)); | 67 base::Unretained(this)); |
| 67 pref_change_registrar_.Add(pref_names::kToolbar, pref_change_callback_); | 68 pref_change_registrar_.Add(extensions::pref_names::kToolbar, |
| 69 pref_change_callback_); | |
| 68 } | 70 } |
| 69 } | 71 } |
| 70 | 72 |
| 71 ExtensionToolbarModel::~ExtensionToolbarModel() { | 73 ToolbarActionsModel::~ToolbarActionsModel() { |
| 72 } | 74 } |
| 73 | 75 |
| 74 // static | 76 // static |
| 75 ExtensionToolbarModel* ExtensionToolbarModel::Get(Profile* profile) { | 77 ToolbarActionsModel* ToolbarActionsModel::Get(Profile* profile) { |
| 76 return ExtensionToolbarModelFactory::GetForProfile(profile); | 78 return ToolbarActionsModelFactory::GetForProfile(profile); |
| 77 } | 79 } |
| 78 | 80 |
| 79 void ExtensionToolbarModel::AddObserver(Observer* observer) { | 81 void ToolbarActionsModel::AddObserver(Observer* observer) { |
| 80 observers_.AddObserver(observer); | 82 observers_.AddObserver(observer); |
| 81 } | 83 } |
| 82 | 84 |
| 83 void ExtensionToolbarModel::RemoveObserver(Observer* observer) { | 85 void ToolbarActionsModel::RemoveObserver(Observer* observer) { |
| 84 observers_.RemoveObserver(observer); | 86 observers_.RemoveObserver(observer); |
| 85 } | 87 } |
| 86 | 88 |
| 87 void ExtensionToolbarModel::MoveExtensionIcon(const std::string& id, | 89 void ToolbarActionsModel::MoveActionIcon(const std::string& id, size_t index) { |
| 88 size_t index) { | 90 std::vector<ToolbarItem>::iterator pos = toolbar_items_.begin(); |
| 89 ExtensionList::iterator pos = toolbar_items_.begin(); | 91 while (pos != toolbar_items_.end() && (*pos).id != id) |
| 90 while (pos != toolbar_items_.end() && (*pos)->id() != id) | |
| 91 ++pos; | 92 ++pos; |
| 92 if (pos == toolbar_items_.end()) { | 93 if (pos == toolbar_items_.end()) { |
| 93 NOTREACHED(); | 94 NOTREACHED(); |
| 94 return; | 95 return; |
| 95 } | 96 } |
| 96 scoped_refptr<const Extension> extension = *pos; | 97 |
| 98 ToolbarItem action = *pos; | |
| 97 toolbar_items_.erase(pos); | 99 toolbar_items_.erase(pos); |
| 98 | 100 |
| 99 ExtensionIdList::iterator pos_id = std::find(last_known_positions_.begin(), | 101 std::vector<std::string>::iterator pos_id = |
| 100 last_known_positions_.end(), | 102 std::find(last_known_positions_.begin(), |
| 101 id); | 103 last_known_positions_.end(), |
| 104 id); | |
| 102 if (pos_id != last_known_positions_.end()) | 105 if (pos_id != last_known_positions_.end()) |
| 103 last_known_positions_.erase(pos_id); | 106 last_known_positions_.erase(pos_id); |
| 104 | 107 |
| 105 if (index < toolbar_items_.size()) { | 108 if (index < toolbar_items_.size()) { |
| 106 // If the index is not at the end, find the item currently at |index|, and | 109 // If the index is not at the end, find the item currently at |index|, and |
| 107 // insert |extension| before it in both |toolbar_items_| and | 110 // insert |action| before it in |toolbar_items_| and |action|'s id in |
| 108 // |last_known_positions_|. | 111 // |last_known_positions_|. |
| 109 ExtensionList::iterator iter = toolbar_items_.begin() + index; | 112 std::vector<ToolbarItem>::iterator iter = toolbar_items_.begin() + index; |
| 110 last_known_positions_.insert(std::find(last_known_positions_.begin(), | 113 last_known_positions_.insert(std::find(last_known_positions_.begin(), |
| 111 last_known_positions_.end(), | 114 last_known_positions_.end(), |
| 112 (*iter)->id()), | 115 (*iter).id), |
| 113 id); | 116 id); |
| 114 toolbar_items_.insert(iter, extension); | 117 toolbar_items_.insert(iter, action); |
| 115 } else { | 118 } else { |
| 116 // Otherwise, put |extension| at the end. | 119 // Otherwise, put |action| and |id| at the end. |
| 117 DCHECK_EQ(toolbar_items_.size(), index); | 120 DCHECK_EQ(toolbar_items_.size(), index); |
| 118 index = toolbar_items_.size(); | 121 toolbar_items_.push_back(action); |
| 119 toolbar_items_.push_back(extension); | |
| 120 last_known_positions_.push_back(id); | 122 last_known_positions_.push_back(id); |
| 121 } | 123 } |
| 122 | 124 |
| 123 FOR_EACH_OBSERVER(Observer, observers_, | 125 FOR_EACH_OBSERVER(Observer, observers_, OnToolbarActionMoved(id, index)); |
| 124 OnToolbarExtensionMoved(extension.get(), index)); | 126 MaybeUpdateVisibilityPref(action, index); |
| 125 MaybeUpdateVisibilityPref(extension.get(), index); | |
| 126 UpdatePrefs(); | 127 UpdatePrefs(); |
| 127 } | 128 } |
| 128 | 129 |
| 129 void ExtensionToolbarModel::SetVisibleIconCount(size_t count) { | 130 void ToolbarActionsModel::SetVisibleIconCount(size_t count) { |
| 130 visible_icon_count_ = (count >= toolbar_items_.size()) ? -1 : count; | 131 visible_icon_count_ = (count >= toolbar_items_.size()) ? -1 : count; |
| 131 | 132 |
| 132 // Only set the prefs if we're not in highlight mode and the profile is not | 133 // Only set the prefs if we're not in highlight mode and the profile is not |
| 133 // incognito. Highlight mode is designed to be a transitory state, and should | 134 // incognito. Highlight mode is designed to be a transitory state, and should |
| 134 // not persist across browser restarts (though it may be re-entered), and we | 135 // not persist across browser restarts (though it may be re-entered), and we |
| 135 // don't store anything in incognito. | 136 // don't store anything in incognito. |
| 136 if (!is_highlighting() && !profile_->IsOffTheRecord()) { | 137 if (!is_highlighting() && !profile_->IsOffTheRecord()) { |
| 137 // Additionally, if we are using the new toolbar, any icons which are in the | 138 // Additionally, if we are using the new toolbar, any icons which are in the |
| 138 // overflow menu are considered "hidden". But it so happens that the times | 139 // overflow menu are considered "hidden". But it so happens that the times |
| 139 // we are likely to call SetVisibleIconCount() are also those when we are | 140 // we are likely to call SetVisibleIconCount() are also those when we are |
| 140 // in flux. So wait for things to cool down before setting the prefs. | 141 // in flux. So wait for things to cool down before setting the prefs. |
| 141 base::ThreadTaskRunnerHandle::Get()->PostTask( | 142 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 142 FROM_HERE, | 143 FROM_HERE, |
| 143 base::Bind(&ExtensionToolbarModel::MaybeUpdateVisibilityPrefs, | 144 base::Bind(&ToolbarActionsModel::MaybeUpdateVisibilityPrefs, |
| 144 weak_ptr_factory_.GetWeakPtr())); | 145 weak_ptr_factory_.GetWeakPtr())); |
| 145 prefs_->SetInteger(pref_names::kToolbarSize, visible_icon_count_); | 146 prefs_->SetInteger(extensions::pref_names::kToolbarSize, |
| 147 visible_icon_count_); | |
| 146 } | 148 } |
| 147 | 149 |
| 148 FOR_EACH_OBSERVER(Observer, observers_, OnToolbarVisibleCountChanged()); | 150 FOR_EACH_OBSERVER(Observer, observers_, OnToolbarVisibleCountChanged()); |
| 149 } | 151 } |
| 150 | 152 |
| 151 void ExtensionToolbarModel::OnExtensionActionUpdated( | 153 void ToolbarActionsModel::OnExtensionActionUpdated( |
| 152 ExtensionAction* extension_action, | 154 ExtensionAction* extension_action, |
| 153 content::WebContents* web_contents, | 155 content::WebContents* web_contents, |
| 154 content::BrowserContext* browser_context) { | 156 content::BrowserContext* browser_context) { |
| 155 const Extension* extension = | |
| 156 ExtensionRegistry::Get(profile_)->enabled_extensions().GetByID( | |
| 157 extension_action->extension_id()); | |
| 158 // Notify observers if the extension exists and is in the model. | 157 // Notify observers if the extension exists and is in the model. |
| 159 if (std::find(toolbar_items_.begin(), toolbar_items_.end(), extension) != | 158 if (std::find(toolbar_items_.begin(), toolbar_items_.end(), |
| 159 ToolbarItem(extension_action->extension_id(), EXTENSION_ACTION)) != | |
| 160 toolbar_items_.end()) { | 160 toolbar_items_.end()) { |
| 161 FOR_EACH_OBSERVER(Observer, observers_, | 161 FOR_EACH_OBSERVER(Observer, observers_, |
| 162 OnToolbarExtensionUpdated(extension)); | 162 OnToolbarActionUpdated( |
| 163 extension_action->extension_id())); | |
| 163 } | 164 } |
| 164 } | 165 } |
| 165 | 166 |
| 166 void ExtensionToolbarModel::OnExtensionActionVisibilityChanged( | 167 ScopedVector<ToolbarActionViewController> ToolbarActionsModel::CreateActions( |
| 168 Browser* browser, ToolbarActionsBar* bar) { | |
| 169 DCHECK(browser); | |
| 170 DCHECK(bar); | |
| 171 ScopedVector<ToolbarActionViewController> action_list; | |
| 172 | |
| 173 // Get the component action list. | |
| 174 ScopedVector<ToolbarActionViewController> component_actions = | |
| 175 ComponentToolbarActionsFactory::GetInstance()-> | |
| 176 GetComponentToolbarActions(browser); | |
| 177 | |
| 178 extensions::ExtensionActionManager* action_manager = | |
| 179 extensions::ExtensionActionManager::Get(profile_); | |
| 180 | |
| 181 // toolbar_items() might not equate to toolbar_items_ in the case where a | |
| 182 // subset are highlighted. | |
| 183 std::vector<ToolbarItem> items = toolbar_items(); | |
| 184 for (const ToolbarItem& action : items) { | |
| 185 if (action.type == EXTENSION_ACTION) { | |
| 186 // Get the extension. | |
| 187 const extensions::Extension* extension = GetExtensionById(action.id); | |
| 188 DCHECK(extension); | |
| 189 | |
| 190 // Create and add an ExtensionActionViewController for the extension. | |
| 191 action_list.push_back(new ExtensionActionViewController( | |
| 192 extension, | |
| 193 browser, | |
| 194 action_manager->GetExtensionAction(*extension), | |
| 195 bar)); | |
| 196 } else if (action.type == COMPONENT_ACTION) { | |
| 197 DCHECK(use_redesign_); | |
| 198 // Find the corresponding action to |action|. | |
| 199 for (auto component_action : component_actions) { | |
| 200 if (component_action->GetId() == action.id) { | |
| 201 action_list.push_back(component_action); | |
| 202 break; | |
| 203 } | |
| 204 } | |
| 205 } | |
| 206 } | |
| 207 | |
| 208 // We've moved ownership of the subset of the component actions that we | |
| 209 // kept track of via toolbar_items() from |component_actions| to | |
| 210 // |action_list|, so we don't need to keep track of these. | |
| 211 component_actions.weak_clear(); | |
| 212 | |
| 213 return action_list.Pass(); | |
| 214 } | |
| 215 | |
| 216 void ToolbarActionsModel::OnExtensionActionVisibilityChanged( | |
| 167 const std::string& extension_id, | 217 const std::string& extension_id, |
| 168 bool is_now_visible) { | 218 bool is_now_visible) { |
| 169 const Extension* extension = | |
| 170 ExtensionRegistry::Get(profile_)->GetExtensionById( | |
| 171 extension_id, ExtensionRegistry::EVERYTHING); | |
| 172 | |
| 173 // Hiding works differently with the new and old toolbars. | 219 // Hiding works differently with the new and old toolbars. |
| 174 if (include_all_extensions_) { | 220 if (use_redesign_) { |
| 175 // It's possible that we haven't added this extension yet, if its | 221 // It's possible that we haven't added this action yet, if its |
| 176 // visibility was adjusted in the course of its initialization. | 222 // visibility was adjusted in the course of its initialization. |
| 177 if (std::find(toolbar_items_.begin(), toolbar_items_.end(), extension) == | 223 if (std::find(toolbar_items_.begin(), toolbar_items_.end(), |
| 224 ToolbarItem(extension_id, EXTENSION_ACTION)) == | |
| 178 toolbar_items_.end()) | 225 toolbar_items_.end()) |
| 179 return; | 226 return; |
| 180 | 227 |
| 181 int new_size = 0; | 228 int new_size = 0; |
| 182 int new_index = 0; | 229 int new_index = 0; |
| 183 if (is_now_visible) { | 230 if (is_now_visible) { |
| 184 // If this action used to be hidden, we can't possibly be showing all. | 231 // If this action used to be hidden, we can't possibly be showing all. |
| 185 DCHECK_LT(visible_icon_count(), toolbar_items_.size()); | 232 DCHECK_LT(visible_icon_count(), toolbar_items_.size()); |
| 186 // Grow the bar by one and move the extension to the end of the visibles. | 233 // Grow the bar by one and move the action to the end of the visibles. |
| 187 new_size = visible_icon_count() + 1; | 234 new_size = visible_icon_count() + 1; |
| 188 new_index = new_size - 1; | 235 new_index = new_size - 1; |
| 189 } else { | 236 } else { |
| 190 // If we're hiding one, we must be showing at least one. | 237 // If we're hiding one, we must be showing at least one. |
| 191 DCHECK_GE(visible_icon_count(), 0u); | 238 DCHECK_GE(visible_icon_count(), 0u); |
| 192 // Shrink the bar by one and move the extension to the beginning of the | 239 // Shrink the bar by one and move the action to the beginning of the |
| 193 // overflow menu. | 240 // overflow menu. |
| 194 new_size = visible_icon_count() - 1; | 241 new_size = visible_icon_count() - 1; |
| 195 new_index = new_size; | 242 new_index = new_size; |
| 196 } | 243 } |
| 197 SetVisibleIconCount(new_size); | 244 SetVisibleIconCount(new_size); |
| 198 MoveExtensionIcon(extension->id(), new_index); | 245 MoveActionIcon(extension_id, new_index); |
| 199 } else { // Don't include all extensions. | 246 } else { // Don't include all extensions. |
| 247 const extensions::Extension* extension = GetExtensionById(extension_id); | |
| 200 if (is_now_visible) | 248 if (is_now_visible) |
| 201 AddExtension(extension); | 249 AddExtension(extension); |
| 202 else | 250 else |
| 203 RemoveExtension(extension); | 251 RemoveExtension(extension); |
| 204 } | 252 } |
| 205 } | 253 } |
| 206 | 254 |
| 207 void ExtensionToolbarModel::OnExtensionLoaded( | 255 void ToolbarActionsModel::OnExtensionLoaded( |
| 208 content::BrowserContext* browser_context, | 256 content::BrowserContext* browser_context, |
| 209 const Extension* extension) { | 257 const extensions::Extension* extension) { |
| 210 // We don't want to add the same extension twice. It may have already been | 258 // We don't want to add the same extension twice. It may have already been |
| 211 // added by EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED below, if the user | 259 // added by EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED below, if the user |
| 212 // hides the browser action and then disables and enables the extension. | 260 // hides the browser action and then disables and enables the extension. |
| 213 for (size_t i = 0; i < toolbar_items_.size(); i++) { | 261 if (std::find(toolbar_items_.begin(), toolbar_items_.end(), |
| 214 if (toolbar_items_[i].get() == extension) | 262 ToolbarItem(extension->id(), EXTENSION_ACTION)) != |
| 215 return; | 263 toolbar_items_.end()) |
| 216 } | 264 return; |
| 217 | 265 |
| 218 AddExtension(extension); | 266 AddExtension(extension); |
| 219 } | 267 } |
| 220 | 268 |
| 221 void ExtensionToolbarModel::OnExtensionUnloaded( | 269 void ToolbarActionsModel::OnExtensionUnloaded( |
| 222 content::BrowserContext* browser_context, | 270 content::BrowserContext* browser_context, |
| 223 const Extension* extension, | 271 const extensions::Extension* extension, |
| 224 UnloadedExtensionInfo::Reason reason) { | 272 extensions::UnloadedExtensionInfo::Reason reason) { |
| 225 RemoveExtension(extension); | 273 RemoveExtension(extension); |
| 226 } | 274 } |
| 227 | 275 |
| 228 void ExtensionToolbarModel::OnExtensionUninstalled( | 276 void ToolbarActionsModel::OnExtensionUninstalled( |
| 229 content::BrowserContext* browser_context, | 277 content::BrowserContext* browser_context, |
| 230 const Extension* extension, | 278 const extensions::Extension* extension, |
| 231 extensions::UninstallReason reason) { | 279 extensions::UninstallReason reason) { |
| 232 // Remove the extension id from the ordered list, if it exists (the extension | 280 // Remove the extension id from the ordered list, if it exists (the extension |
| 233 // might not be represented in the list because it might not have an icon). | 281 // might not be represented in the list because it might not have an icon). |
| 234 ExtensionIdList::iterator pos = | 282 std::vector<std::string>::iterator pos = |
| 235 std::find(last_known_positions_.begin(), | 283 std::find(last_known_positions_.begin(), |
| 236 last_known_positions_.end(), extension->id()); | 284 last_known_positions_.end(), |
| 285 extension->id()); | |
| 237 | 286 |
| 238 if (pos != last_known_positions_.end()) { | 287 if (pos != last_known_positions_.end()) { |
| 239 last_known_positions_.erase(pos); | 288 last_known_positions_.erase(pos); |
| 240 UpdatePrefs(); | 289 UpdatePrefs(); |
| 241 } | 290 } |
| 242 } | 291 } |
| 243 | 292 |
| 244 void ExtensionToolbarModel::OnReady() { | 293 void ToolbarActionsModel::OnReady() { |
| 245 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); | 294 InitializeActionList(); |
| 246 InitializeExtensionList(); | |
| 247 // Wait until the extension system is ready before observing any further | 295 // Wait until the extension system is ready before observing any further |
| 248 // changes so that the toolbar buttons can be shown in their stable ordering | 296 // changes so that the toolbar buttons can be shown in their stable ordering |
| 249 // taken from prefs. | 297 // taken from prefs. |
| 250 extension_registry_observer_.Add(registry); | 298 extension_registry_observer_.Add(extension_registry_); |
| 251 extension_action_observer_.Add(extension_action_api_); | 299 extension_action_observer_.Add(extension_action_api_); |
| 252 | 300 |
| 253 if (ExtensionToolbarIconSurfacingBubbleDelegate::ShouldShowForProfile( | 301 if (ExtensionToolbarIconSurfacingBubbleDelegate::ShouldShowForProfile( |
| 254 profile_)) { | 302 profile_)) { |
| 255 ExtensionIdList ids; | 303 std::vector<std::string> ids; |
| 256 for (const auto& extension : toolbar_items_) | 304 for (const ToolbarItem& action : toolbar_items_) |
| 257 ids.push_back(extension->id()); | 305 ids.push_back(action.id); |
| 258 HighlightExtensions(ids, HIGHLIGHT_INFO); | 306 HighlightActions(ids, HIGHLIGHT_INFO); |
| 259 } | 307 } |
| 260 | 308 |
| 261 extensions_initialized_ = true; | 309 actions_initialized_ = true; |
| 262 FOR_EACH_OBSERVER(Observer, observers_, OnToolbarModelInitialized()); | 310 FOR_EACH_OBSERVER(Observer, observers_, OnToolbarModelInitialized()); |
| 263 } | 311 } |
| 264 | 312 |
| 265 size_t ExtensionToolbarModel::FindNewPositionFromLastKnownGood( | 313 size_t ToolbarActionsModel::FindNewPositionFromLastKnownGood( |
| 266 const Extension* extension) { | 314 const ToolbarItem& action) { |
| 267 // See if we have last known good position for this extension. | 315 // See if we have last known good position for this action. |
| 268 size_t new_index = 0; | 316 size_t new_index = 0; |
| 269 // Loop through the ID list of known positions, to count the number of visible | 317 // Loop through the ID list of known positions, to count the number of |
| 270 // extension icons preceding |extension|. | 318 // visible action icons preceding |action|'s id. |
| 271 for (ExtensionIdList::const_iterator iter_id = last_known_positions_.begin(); | 319 for (const std::string& last_pos_id : last_known_positions_) { |
| 272 iter_id < last_known_positions_.end(); ++iter_id) { | 320 if (last_pos_id == action.id) |
| 273 if ((*iter_id) == extension->id()) | |
| 274 return new_index; // We've found the right position. | 321 return new_index; // We've found the right position. |
| 275 // Found an id, need to see if it is visible. | 322 // Found an action, need to see if it is visible. |
| 276 for (ExtensionList::const_iterator iter_ext = toolbar_items_.begin(); | 323 for (const ToolbarItem& item : toolbar_items_) { |
| 277 iter_ext < toolbar_items_.end(); ++iter_ext) { | 324 if (item.id == last_pos_id) { |
| 278 if ((*iter_ext)->id() == (*iter_id)) { | |
| 279 // This extension is visible, update the index value. | 325 // This extension is visible, update the index value. |
| 280 ++new_index; | 326 ++new_index; |
| 281 break; | 327 break; |
| 282 } | 328 } |
| 283 } | 329 } |
| 284 } | 330 } |
| 285 | 331 |
| 286 // Position not found. | 332 // Position not found. |
| 287 return toolbar_items_.size(); | 333 return toolbar_items_.size(); |
| 288 } | 334 } |
| 289 | 335 |
| 290 bool ExtensionToolbarModel::ShouldAddExtension(const Extension* extension) { | 336 bool ToolbarActionsModel::ShouldAddExtension( |
| 337 const extensions::Extension* extension) { | |
| 291 // In incognito mode, don't add any extensions that aren't incognito-enabled. | 338 // In incognito mode, don't add any extensions that aren't incognito-enabled. |
| 292 if (profile_->IsOffTheRecord() && | 339 if (profile_->IsOffTheRecord() && |
| 293 !util::IsIncognitoEnabled(extension->id(), profile_)) | 340 !extensions::util::IsIncognitoEnabled(extension->id(), profile_)) |
| 294 return false; | 341 return false; |
| 295 | 342 |
| 296 ExtensionActionManager* action_manager = | 343 extensions::ExtensionActionManager* action_manager = |
| 297 ExtensionActionManager::Get(profile_); | 344 extensions::ExtensionActionManager::Get(profile_); |
| 298 if (include_all_extensions_) { | 345 if (use_redesign_) { |
| 299 // In this case, we don't care about the browser action visibility, because | 346 // In this case, we don't care about the browser action visibility, because |
| 300 // we want to show each extension regardless. | 347 // we want to show each extension regardless. |
| 301 // TODO(devlin): Extension actions which are not visible should be moved to | |
| 302 // the overflow menu by default. | |
| 303 return action_manager->GetExtensionAction(*extension) != NULL; | 348 return action_manager->GetExtensionAction(*extension) != NULL; |
| 304 } | 349 } |
| 305 | 350 |
| 306 return action_manager->GetBrowserAction(*extension) && | 351 return action_manager->GetBrowserAction(*extension) && |
| 307 extension_action_api_->GetBrowserActionVisibility(extension->id()); | 352 extension_action_api_->GetBrowserActionVisibility(extension->id()); |
| 308 } | 353 } |
| 309 | 354 |
| 310 void ExtensionToolbarModel::AddExtension(const Extension* extension) { | 355 void ToolbarActionsModel::AddExtension(const extensions::Extension* extension) { |
| 311 // We only use AddExtension() once the system is initialized. | 356 // We only use AddExtension() once the system is initialized. |
| 312 DCHECK(extensions_initialized_); | 357 DCHECK(actions_initialized_); |
| 313 if (!ShouldAddExtension(extension)) | 358 if (!ShouldAddExtension(extension)) |
| 314 return; | 359 return; |
| 315 | 360 |
| 316 // See if we have a last known good position for this extension. | 361 // See if we have a last known good position for this extension. |
| 317 bool is_new_extension = | 362 bool is_new_extension = |
| 318 std::find(last_known_positions_.begin(), | 363 std::find(last_known_positions_.begin(), |
| 319 last_known_positions_.end(), | 364 last_known_positions_.end(), |
| 320 extension->id()) == last_known_positions_.end(); | 365 extension->id()) == last_known_positions_.end(); |
| 321 | 366 |
| 322 // New extensions go at the right (end) of the visible extensions. Other | 367 // New extensions go at the right (end) of the visible extensions. Other |
| 323 // extensions go at their previous position. | 368 // extensions go at their previous position. |
| 324 size_t new_index = 0; | 369 size_t new_index = 0; |
| 325 if (is_new_extension) { | 370 if (is_new_extension) { |
| 326 new_index = Manifest::IsComponentLocation(extension->location()) ? | 371 new_index = extensions::Manifest::IsComponentLocation( |
| 327 0 : visible_icon_count(); | 372 extension->location()) ? 0 : visible_icon_count(); |
| 328 // For the last-known position, we use the index of the extension that is | 373 // For the last-known position, we use the index of the extension that is |
| 329 // just before this extension, plus one. (Note that this isn't the same | 374 // just before this extension, plus one. (Note that this isn't the same |
| 330 // as new_index + 1, because last_known_positions_ can include disabled | 375 // as new_index + 1, because last_known_positions_ can include disabled |
| 331 // extensions.) | 376 // extensions.) |
| 332 int new_last_known_index = | 377 int new_last_known_index = |
| 333 new_index == 0 ? 0 : | 378 new_index == 0 ? 0 : |
| 334 std::find(last_known_positions_.begin(), | 379 std::find(last_known_positions_.begin(), |
| 335 last_known_positions_.end(), | 380 last_known_positions_.end(), |
| 336 toolbar_items_[new_index - 1]->id()) - | 381 toolbar_items_[new_index - 1].id) - |
| 337 last_known_positions_.begin() + 1; | 382 last_known_positions_.begin() + 1; |
| 338 // In theory, the extension before this one should always | 383 // In theory, the extension before this one should always |
| 339 // be in last known positions, but if something funny happened with prefs, | 384 // be in last known positions, but if something funny happened with prefs, |
| 340 // make sure we handle it. | 385 // make sure we handle it. |
| 341 // TODO(devlin): Track down these cases so we can CHECK this. | 386 // TODO(devlin): Track down these cases so we can CHECK this. |
| 342 new_last_known_index = | 387 new_last_known_index = |
| 343 std::min<int>(new_last_known_index, last_known_positions_.size()); | 388 std::min<int>(new_last_known_index, last_known_positions_.size()); |
| 344 last_known_positions_.insert( | 389 last_known_positions_.insert( |
| 345 last_known_positions_.begin() + new_last_known_index, extension->id()); | 390 last_known_positions_.begin() + new_last_known_index, extension->id()); |
| 346 UpdatePrefs(); | 391 UpdatePrefs(); |
| 347 } else { | 392 } else { |
| 348 new_index = FindNewPositionFromLastKnownGood(extension); | 393 new_index = FindNewPositionFromLastKnownGood( |
| 394 ToolbarItem(extension->id(), EXTENSION_ACTION)); | |
| 349 } | 395 } |
| 350 | 396 |
| 351 toolbar_items_.insert(toolbar_items_.begin() + new_index, extension); | 397 toolbar_items_.insert(toolbar_items_.begin() + new_index, |
| 398 ToolbarItem(extension->id(), EXTENSION_ACTION)); | |
| 352 | 399 |
| 353 // If we're currently highlighting, then even though we add a browser action | 400 // If we're currently highlighting, then even though we add a browser action |
| 354 // to the full list (|toolbar_items_|, there won't be another *visible* | 401 // to the full list (|toolbar_items_|, there won't be another *visible* |
| 355 // browser action, which was what the observers care about. | 402 // browser action, which was what the observers care about. |
| 356 if (!is_highlighting()) { | 403 if (!is_highlighting()) { |
| 357 FOR_EACH_OBSERVER(Observer, observers_, | 404 FOR_EACH_OBSERVER(Observer, observers_, |
| 358 OnToolbarExtensionAdded(extension, new_index)); | 405 OnToolbarActionAdded(extension->id(), new_index)); |
| 359 | 406 |
| 360 int visible_count_delta = 0; | 407 int visible_count_delta = 0; |
| 361 if (is_new_extension && !all_icons_visible()) { | 408 if (is_new_extension && !all_icons_visible()) { |
| 362 // If this is a new extension (and not all extensions are visible), we | 409 // If this is a new extension (and not all extensions are visible), we |
| 363 // expand the toolbar out so that the new one can be seen. | 410 // expand the toolbar out so that the new one can be seen. |
| 364 visible_count_delta = 1; | 411 visible_count_delta = 1; |
| 365 } else if (profile_->IsOffTheRecord()) { | 412 } else if (profile_->IsOffTheRecord()) { |
| 366 // If this is an incognito profile, we also have to check to make sure the | 413 // If this is an incognito profile, we also have to check to make sure the |
| 367 // overflow matches the main bar's status. | 414 // overflow matches the main bar's status. |
| 368 ExtensionToolbarModel* main_model = | 415 ToolbarActionsModel* main_model = |
| 369 ExtensionToolbarModel::Get(profile_->GetOriginalProfile()); | 416 ToolbarActionsModel::Get(profile_->GetOriginalProfile()); |
| 370 // Find what the index will be in the main bar. Because Observer calls are | 417 // Find what the index will be in the main bar. Because Observer calls are |
| 371 // nondeterministic, we can't just assume the main bar will have the | 418 // nondeterministic, we can't just assume the main bar will have the |
| 372 // extension and look it up. | 419 // extension and look it up. |
| 373 size_t main_index = | 420 size_t main_index = main_model->FindNewPositionFromLastKnownGood( |
| 374 main_model->FindNewPositionFromLastKnownGood(extension); | 421 ToolbarItem(extension->id(), EXTENSION_ACTION)); |
| 375 bool visible = main_index < main_model->visible_icon_count(); | 422 bool visible = main_index < main_model->visible_icon_count(); |
| 376 // We may need to adjust the visible count if the incognito bar isn't | 423 // We may need to adjust the visible count if the incognito bar isn't |
| 377 // showing all icons and this one is visible, or if it is showing all | 424 // showing all icons and this one is visible, or if it is showing all |
| 378 // icons and this is hidden. | 425 // icons and this is hidden. |
| 379 if (visible && !all_icons_visible()) | 426 if (visible && !all_icons_visible()) |
| 380 visible_count_delta = 1; | 427 visible_count_delta = 1; |
| 381 else if (!visible && all_icons_visible()) | 428 else if (!visible && all_icons_visible()) |
| 382 visible_count_delta = -1; | 429 visible_count_delta = -1; |
| 383 } | 430 } |
| 384 | 431 |
| 385 if (visible_count_delta) | 432 if (visible_count_delta) |
| 386 SetVisibleIconCount(visible_icon_count() + visible_count_delta); | 433 SetVisibleIconCount(visible_icon_count() + visible_count_delta); |
| 387 } | 434 } |
| 388 | 435 |
| 389 MaybeUpdateVisibilityPref(extension, new_index); | 436 MaybeUpdateVisibilityPref(ToolbarItem(extension->id(), EXTENSION_ACTION), |
| 437 new_index); | |
| 390 } | 438 } |
| 391 | 439 |
| 392 void ExtensionToolbarModel::RemoveExtension(const Extension* extension) { | 440 void ToolbarActionsModel::RemoveExtension( |
| 393 ExtensionList::iterator pos = | 441 const extensions::Extension* extension) { |
| 394 std::find(toolbar_items_.begin(), toolbar_items_.end(), extension); | 442 std::vector<ToolbarItem>::iterator pos = |
| 443 std::find(toolbar_items_.begin(), toolbar_items_.end(), | |
| 444 ToolbarItem(extension->id(), EXTENSION_ACTION)); | |
| 445 | |
| 395 if (pos == toolbar_items_.end()) | 446 if (pos == toolbar_items_.end()) |
| 396 return; | 447 return; |
| 397 | 448 |
| 398 size_t index = pos - toolbar_items_.begin(); | 449 size_t index = pos - toolbar_items_.begin(); |
| 399 // If the removed extension was on the toolbar, a new one will take its place | 450 // If the removed extension was on the toolbar, a new one will take its place |
| 400 // if there are any in overflow. | 451 // if there are any in overflow. |
| 401 bool new_extension_shown = | 452 bool new_extension_shown = |
| 402 !all_icons_visible() && index < visible_icon_count(); | 453 !all_icons_visible() && index < visible_icon_count(); |
| 403 | 454 |
| 404 // If our visible count is set to the current size, we need to decrement it. | 455 // If our visible count is set to the current size, we need to decrement it. |
| 405 if (visible_icon_count_ == static_cast<int>(toolbar_items_.size())) | 456 if (visible_icon_count_ == static_cast<int>(toolbar_items_.size())) |
| 406 SetVisibleIconCount(toolbar_items_.size() - 1); | 457 SetVisibleIconCount(toolbar_items_.size() - 1); |
| 407 | 458 |
| 408 toolbar_items_.erase(pos); | 459 toolbar_items_.erase(pos); |
| 409 | 460 |
| 410 // If we're in highlight mode, we also have to remove the extension from | 461 // If we're in highlight mode, we also have to remove the extension from |
| 411 // the highlighted list. | 462 // the highlighted list. |
| 412 if (is_highlighting()) { | 463 if (is_highlighting()) { |
| 413 pos = std::find(highlighted_items_.begin(), | 464 pos = std::find(highlighted_items_.begin(), |
| 414 highlighted_items_.end(), | 465 highlighted_items_.end(), |
| 415 extension); | 466 ToolbarItem(extension->id(), EXTENSION_ACTION)); |
| 416 if (pos != highlighted_items_.end()) { | 467 if (pos != highlighted_items_.end()) { |
| 417 highlighted_items_.erase(pos); | 468 highlighted_items_.erase(pos); |
| 418 FOR_EACH_OBSERVER(Observer, observers_, | 469 FOR_EACH_OBSERVER(Observer, observers_, |
| 419 OnToolbarExtensionRemoved(extension)); | 470 OnToolbarActionRemoved(extension->id())); |
| 420 // If the highlighted list is now empty, we stop highlighting. | 471 // If the highlighted list is now empty, we stop highlighting. |
| 421 if (highlighted_items_.empty()) | 472 if (highlighted_items_.empty()) |
| 422 StopHighlighting(); | 473 StopHighlighting(); |
| 423 } | 474 } |
| 424 } else { | 475 } else { |
| 425 FOR_EACH_OBSERVER(Observer, observers_, | 476 FOR_EACH_OBSERVER(Observer, observers_, |
| 426 OnToolbarExtensionRemoved(extension)); | 477 OnToolbarActionRemoved(extension->id())); |
| 427 } | 478 } |
| 428 | 479 |
| 429 UpdatePrefs(); | 480 UpdatePrefs(); |
| 430 if (new_extension_shown) { | 481 if (new_extension_shown) { |
| 431 size_t newly_visible_index = visible_icon_count() - 1; | 482 size_t newly_visible_index = visible_icon_count() - 1; |
| 432 MaybeUpdateVisibilityPref(toolbar_items_[newly_visible_index].get(), | 483 MaybeUpdateVisibilityPref(toolbar_items_[newly_visible_index], |
| 433 newly_visible_index); | 484 newly_visible_index); |
| 434 } | 485 } |
| 435 } | 486 } |
| 436 | 487 |
| 437 // Combine the currently enabled extensions that have browser actions (which | 488 // Combine the currently enabled extensions that have browser actions (which |
| 438 // we get from the ExtensionRegistry) with the ordering we get from the | 489 // we get from the ExtensionRegistry) and component actions (which we get from |
| 439 // pref service. For robustness we use a somewhat inefficient process: | 490 // ComponentToolbarActionsFactory) with the ordering we get from the pref |
| 440 // 1. Create a vector of extensions sorted by their pref values. This vector may | 491 // service. For robustness we use a somewhat inefficient process: |
| 492 // 1. Create a vector of actions sorted by their pref values. This vector may | |
| 441 // have holes. | 493 // have holes. |
| 442 // 2. Create a vector of extensions that did not have a pref value. | 494 // 2. Create a vector of actions that did not have a pref value. |
| 443 // 3. Remove holes from the sorted vector and append the unsorted vector. | 495 // 3. Remove holes from the sorted vector and append the unsorted vector. |
| 444 void ExtensionToolbarModel::InitializeExtensionList() { | 496 void ToolbarActionsModel::InitializeActionList() { |
| 445 DCHECK(toolbar_items_.empty()); // We shouldn't have any items yet. | 497 DCHECK(toolbar_items_.empty()); // We shouldn't have any items yet. |
| 446 | 498 |
| 447 last_known_positions_ = extension_prefs_->GetToolbarOrder(); | 499 last_known_positions_ = extension_prefs_->GetToolbarOrder(); |
| 448 if (profile_->IsOffTheRecord()) | 500 if (profile_->IsOffTheRecord()) |
| 449 IncognitoPopulate(); | 501 IncognitoPopulate(); |
| 450 else | 502 else |
| 451 Populate(&last_known_positions_); | 503 Populate(&last_known_positions_); |
| 452 | 504 |
| 453 MaybeUpdateVisibilityPrefs(); | 505 MaybeUpdateVisibilityPrefs(); |
| 454 } | 506 } |
| 455 | 507 |
| 456 void ExtensionToolbarModel::Populate(ExtensionIdList* positions) { | 508 void ToolbarActionsModel::Populate(std::vector<std::string>* positions) { |
| 457 DCHECK(!profile_->IsOffTheRecord()); | 509 DCHECK(!profile_->IsOffTheRecord()); |
| 458 const ExtensionSet& extensions = | |
| 459 ExtensionRegistry::Get(profile_)->enabled_extensions(); | |
| 460 // Items that have explicit positions. | |
| 461 ExtensionList sorted(positions->size(), NULL); | |
| 462 // The items that don't have explicit positions. | |
| 463 ExtensionList unsorted; | |
| 464 | 510 |
| 465 // Create the lists. | 511 std::vector<ToolbarItem> all_actions; |
| 512 // Ids of actions that have explicit positions. | |
| 513 std::vector<ToolbarItem> sorted(positions->size(), ToolbarItem()); | |
| 514 // Ids of actions that don't have explicit positions. | |
| 515 std::vector<ToolbarItem> unsorted; | |
| 516 | |
| 517 // Populate the lists. | |
| 466 int hidden = 0; | 518 int hidden = 0; |
| 467 for (const scoped_refptr<const Extension>& extension : extensions) { | 519 int browser_actions_count = 0; |
| 520 int component_actions_count = 0; | |
| 521 | |
| 522 // First, add the extension action ids to all_actions. | |
| 523 const extensions::ExtensionSet& extensions = | |
| 524 extension_registry_->enabled_extensions(); | |
| 525 for (const scoped_refptr<const extensions::Extension>& extension : | |
| 526 extensions) { | |
| 468 if (!ShouldAddExtension(extension.get())) { | 527 if (!ShouldAddExtension(extension.get())) { |
| 469 if (!extension_action_api_->GetBrowserActionVisibility(extension->id())) | 528 if (!extension_action_api_->GetBrowserActionVisibility(extension->id())) |
| 470 ++hidden; | 529 ++hidden; |
| 471 continue; | 530 continue; |
| 472 } | 531 } |
| 473 | 532 |
| 474 ExtensionIdList::const_iterator pos = | 533 all_actions.push_back(ToolbarItem(extension->id(), EXTENSION_ACTION)); |
| 475 std::find(positions->begin(), positions->end(), extension->id()); | 534 } |
| 535 | |
| 536 // Next, add the component action ids. | |
| 537 scoped_ptr<std::vector<std::string>> component_ids = | |
| 538 ComponentToolbarActionsFactory::GetComponentIds(); | |
| 539 for (const std::string& id : *component_ids) | |
| 540 all_actions.push_back(ToolbarItem(id, COMPONENT_ACTION)); | |
| 541 | |
| 542 // Add each action id to the appropriate list. | |
| 543 for (const ToolbarItem& action : all_actions) { | |
| 544 std::vector<std::string>::const_iterator pos = | |
| 545 std::find(positions->begin(), | |
| 546 positions->end(), | |
| 547 action.id); | |
| 476 if (pos != positions->end()) { | 548 if (pos != positions->end()) { |
| 477 sorted[pos - positions->begin()] = extension; | 549 sorted[pos - positions->begin()] = action; |
| 478 } else { | 550 } else { |
| 479 // Unknown extension - push it to the back of unsorted, and add it to the | 551 // Unknown action - push it to the back of unsorted, and add it to the |
| 480 // list of ids at the end. | 552 // list of ids at the end. |
| 481 unsorted.push_back(extension); | 553 unsorted.push_back(action); |
| 482 positions->push_back(extension->id()); | 554 positions->push_back(action.id); |
| 483 } | 555 } |
| 484 } | 556 } |
| 485 | 557 |
| 486 // Merge the lists. | 558 // Merge the lists. |
| 487 sorted.insert(sorted.end(), unsorted.begin(), unsorted.end()); | 559 sorted.insert(sorted.end(), unsorted.begin(), unsorted.end()); |
| 488 toolbar_items_.reserve(sorted.size()); | 560 toolbar_items_.reserve(sorted.size()); |
| 489 | 561 |
| 490 for (const scoped_refptr<const Extension>& extension : sorted) { | 562 // We don't notify observers of the added extension yet. Rather, observers |
| 491 // It's possible for the extension order to contain items that aren't | 563 // should wait for the "OnToolbarModelInitialized" notification, and then |
| 492 // actually loaded on this machine. For example, when extension sync is on, | 564 // bulk-update. (This saves a lot of bouncing-back-and-forth here, and allows |
| 493 // we sync the extension order as-is but double-check with the user before | 565 // observers to ensure that the extension system is always initialized before |
| 494 // syncing NPAPI-containing extensions, so if one of those is not actually | 566 // using the extensions). |
| 495 // synced, we'll get a NULL in the list. This sort of case can also happen | 567 for (const ToolbarItem& action : sorted) { |
| 496 // if some error prevents an extension from loading. | 568 if (action.type == EXTENSION_ACTION) { |
| 497 if (extension.get()) { | 569 // It's possible for the extension order to contain items that aren't |
| 498 // We don't notify observers of the added extension yet. Rather, observers | 570 // actually loaded on this machine. For example, when extension sync is |
| 499 // should wait for the "OnToolbarModelInitialized" notification, and then | 571 // on, we sync the extension order as-is but double-check with the user |
| 500 // bulk-update. (This saves a lot of bouncing-back-and-forth here, and | 572 // before syncing NPAPI-containing extensions, so if one of those is not |
| 501 // allows observers to ensure that the extension system is always | 573 // actually synced, we'll get a NULL in the list. This sort of case can |
| 502 // initialized before using the extensions). | 574 // also happen if some error prevents an extension from loading. |
| 503 toolbar_items_.push_back(extension); | 575 if (GetExtensionById(action.id)) { |
| 576 toolbar_items_.push_back(ToolbarItem(action.id, EXTENSION_ACTION)); | |
| 577 ++browser_actions_count; | |
| 578 } | |
| 579 } else if (action.type == COMPONENT_ACTION) { | |
| 580 toolbar_items_.push_back(ToolbarItem(action.id, COMPONENT_ACTION)); | |
| 581 ++component_actions_count; | |
| 504 } | 582 } |
| 505 } | 583 } |
| 506 | 584 |
| 585 // Histogram names are prefixed with "ExtensionToolbarModel" rather than | |
| 586 // "ToolbarActionsModel" for historical reasons. | |
| 507 UMA_HISTOGRAM_COUNTS_100( | 587 UMA_HISTOGRAM_COUNTS_100( |
| 508 "ExtensionToolbarModel.BrowserActionsPermanentlyHidden", hidden); | 588 "ExtensionToolbarModel.BrowserActionsPermanentlyHidden", hidden); |
| 509 UMA_HISTOGRAM_COUNTS_100("ExtensionToolbarModel.BrowserActionsCount", | 589 UMA_HISTOGRAM_COUNTS_100("ExtensionToolbarModel.BrowserActionsCount", |
| 590 browser_actions_count); | |
| 591 UMA_HISTOGRAM_COUNTS_100("Toolbar.ActionsModel.ComponentActionsCount", | |
| 592 component_actions_count); | |
| 593 UMA_HISTOGRAM_COUNTS_100("Toolbar.ActionsModel.OverallActionsCount", | |
| 510 toolbar_items_.size()); | 594 toolbar_items_.size()); |
| 511 | 595 |
| 512 if (!toolbar_items_.empty()) { | 596 if (!toolbar_items_.empty()) { |
| 513 // Visible count can be -1, meaning: 'show all'. Since UMA converts negative | 597 // Visible count can be -1, meaning: 'show all'. Since UMA converts negative |
| 514 // values to 0, this would be counted as 'show none' unless we convert it to | 598 // values to 0, this would be counted as 'show none' unless we convert it to |
| 515 // max. | 599 // max. |
| 600 int visible_browser_icon_size = visible_icon_count_ - | |
| 601 component_actions_count; | |
|
Devlin
2015/08/17 16:32:21
visible_browser_icon_size sounds wrong for what th
apacible
2015/08/17 18:23:32
Done.
| |
| 516 UMA_HISTOGRAM_COUNTS_100("ExtensionToolbarModel.BrowserActionsVisible", | 602 UMA_HISTOGRAM_COUNTS_100("ExtensionToolbarModel.BrowserActionsVisible", |
| 517 visible_icon_count_ == -1 ? | 603 visible_icon_count_ == -1 ? |
| 518 base::HistogramBase::kSampleType_MAX : | 604 base::HistogramBase::kSampleType_MAX : |
| 605 visible_browser_icon_size); | |
| 606 UMA_HISTOGRAM_COUNTS_100("Toolbar.ActionsModel.ToolbarActionsVisible", | |
|
Devlin
2015/08/17 16:32:21
This is only going to be interested (i.e., vary fr
apacible
2015/08/17 18:23:32
Done.
| |
| 607 visible_icon_count_ == -1 ? | |
| 608 base::HistogramBase::kSampleType_MAX : | |
| 519 visible_icon_count_); | 609 visible_icon_count_); |
| 520 } | 610 } |
| 521 } | 611 } |
| 522 | 612 |
| 523 void ExtensionToolbarModel::IncognitoPopulate() { | 613 void ToolbarActionsModel::IncognitoPopulate() { |
| 524 DCHECK(profile_->IsOffTheRecord()); | 614 DCHECK(profile_->IsOffTheRecord()); |
| 525 const ExtensionToolbarModel* original_model = | 615 const ToolbarActionsModel* original_model = |
| 526 ExtensionToolbarModel::Get(profile_->GetOriginalProfile()); | 616 ToolbarActionsModel::Get(profile_->GetOriginalProfile()); |
| 527 | 617 |
| 528 // Find the absolute value of the original model's count. | 618 // Find the absolute value of the original model's count. |
| 529 int original_visible = original_model->visible_icon_count(); | 619 int original_visible = original_model->visible_icon_count(); |
| 530 | 620 |
| 531 // In incognito mode, we show only those extensions that are | 621 // In incognito mode, we show only those actions that are incognito-enabled |
| 532 // incognito-enabled. Further, any actions that were overflowed in regular | 622 // Further, any actions that were overflowed in regular mode are still |
| 533 // mode are still overflowed. Order is the same as in regular mode. | 623 // overflowed. Order is the same as in regular mode. |
| 534 visible_icon_count_ = 0; | 624 visible_icon_count_ = 0; |
| 535 for (ExtensionList::const_iterator iter = | 625 |
| 536 original_model->toolbar_items_.begin(); | 626 for (std::vector<ToolbarItem>::const_iterator iter = |
| 627 original_model->toolbar_items_.begin(); | |
| 537 iter != original_model->toolbar_items_.end(); ++iter) { | 628 iter != original_model->toolbar_items_.end(); ++iter) { |
| 538 if (ShouldAddExtension(iter->get())) { | 629 if ((*iter).type == EXTENSION_ACTION) { |
|
Devlin
2015/08/17 16:32:21
The body of this for-loop seems like it would be s
apacible
2015/08/17 18:23:32
Done.
| |
| 630 if (ShouldAddExtension(GetExtensionById((*iter).id))) { | |
|
Devlin
2015/08/17 16:32:21
nit: prefer iter->id, rather than (*iter).id (this
apacible
2015/08/17 18:23:32
Done and changed elsewhere.
| |
| 631 toolbar_items_.push_back(*iter); | |
| 632 if (iter - original_model->toolbar_items_.begin() < original_visible) | |
| 633 ++visible_icon_count_; | |
| 634 } | |
| 635 } else if ((*iter).type == COMPONENT_ACTION) { | |
| 636 // At the moment, we assume component actions will always be present | |
| 637 // in incognito. This may change in the future if there are component | |
| 638 // actions that should not be enabled in incognito. | |
| 539 toolbar_items_.push_back(*iter); | 639 toolbar_items_.push_back(*iter); |
| 540 if (iter - original_model->toolbar_items_.begin() < original_visible) | 640 if (iter - original_model->toolbar_items_.begin() < original_visible) |
| 541 ++visible_icon_count_; | 641 ++visible_icon_count_; |
| 542 } | 642 } |
| 543 } | 643 } |
| 544 } | 644 } |
| 545 | 645 |
| 546 void ExtensionToolbarModel::UpdatePrefs() { | 646 void ToolbarActionsModel::UpdatePrefs() { |
| 547 if (!extension_prefs_ || profile_->IsOffTheRecord()) | 647 if (!extension_prefs_ || profile_->IsOffTheRecord()) |
| 548 return; | 648 return; |
| 549 | 649 |
| 550 // Don't observe change caused by self. | 650 // Don't observe change caused by self. |
| 551 pref_change_registrar_.Remove(pref_names::kToolbar); | 651 pref_change_registrar_.Remove(extensions::pref_names::kToolbar); |
| 552 extension_prefs_->SetToolbarOrder(last_known_positions_); | 652 extension_prefs_->SetToolbarOrder(last_known_positions_); |
| 553 pref_change_registrar_.Add(pref_names::kToolbar, pref_change_callback_); | 653 pref_change_registrar_.Add(extensions::pref_names::kToolbar, |
| 654 pref_change_callback_); | |
| 554 } | 655 } |
| 555 | 656 |
| 556 void ExtensionToolbarModel::MaybeUpdateVisibilityPref( | 657 void ToolbarActionsModel::MaybeUpdateVisibilityPref(const ToolbarItem& action, |
| 557 const Extension* extension, size_t index) { | 658 size_t index) { |
| 659 // Component actions don't have prefs to update. | |
| 660 if (action.type == COMPONENT_ACTION) | |
| 661 return; | |
| 662 | |
| 558 // We only update the visibility pref for hidden/not hidden based on the | 663 // We only update the visibility pref for hidden/not hidden based on the |
| 559 // overflow menu with the new toolbar design. | 664 // overflow menu with the new toolbar design. |
| 560 if (include_all_extensions_ && !profile_->IsOffTheRecord()) { | 665 if (use_redesign_ && !profile_->IsOffTheRecord()) { |
| 561 bool visible = index < visible_icon_count(); | 666 bool visible = index < visible_icon_count(); |
| 562 if (visible != extension_action_api_->GetBrowserActionVisibility( | 667 if (visible != |
| 563 extension->id())) { | 668 extension_action_api_->GetBrowserActionVisibility(action.id)) { |
| 564 // Don't observe changes caused by ourselves. | 669 // Don't observe changes caused by ourselves. |
| 565 bool was_registered = false; | 670 bool was_registered = false; |
| 566 if (extension_action_observer_.IsObserving(extension_action_api_)) { | 671 if (extension_action_observer_.IsObserving(extension_action_api_)) { |
| 567 was_registered = true; | 672 was_registered = true; |
| 568 extension_action_observer_.RemoveAll(); | 673 extension_action_observer_.RemoveAll(); |
| 569 } | 674 } |
| 570 extension_action_api_->SetBrowserActionVisibility(extension->id(), | 675 extension_action_api_->SetBrowserActionVisibility(action.id, visible); |
| 571 visible); | |
| 572 if (was_registered) | 676 if (was_registered) |
| 573 extension_action_observer_.Add(extension_action_api_); | 677 extension_action_observer_.Add(extension_action_api_); |
| 574 } | 678 } |
| 575 } | 679 } |
| 576 } | 680 } |
| 577 | 681 |
| 578 void ExtensionToolbarModel::MaybeUpdateVisibilityPrefs() { | 682 void ToolbarActionsModel::MaybeUpdateVisibilityPrefs() { |
| 579 for (size_t i = 0u; i < toolbar_items_.size(); ++i) | 683 for (size_t i = 0u; i < toolbar_items_.size(); ++i) |
| 580 MaybeUpdateVisibilityPref(toolbar_items_[i].get(), i); | 684 MaybeUpdateVisibilityPref(toolbar_items_[i], i); |
| 581 } | 685 } |
| 582 | 686 |
| 583 void ExtensionToolbarModel::OnExtensionToolbarPrefChange() { | 687 void ToolbarActionsModel::OnActionToolbarPrefChange() { |
| 584 // If extensions are not ready, defer to later Populate() call. | 688 // If extensions are not ready, defer to later Populate() call. |
| 585 if (!extensions_initialized_) | 689 if (!actions_initialized_) |
| 586 return; | 690 return; |
| 587 | 691 |
| 588 // Recalculate |last_known_positions_| to be |pref_positions| followed by | 692 // Recalculate |last_known_positions_| to be |pref_positions| followed by |
| 589 // ones that are only in |last_known_positions_|. | 693 // ones that are only in |last_known_positions_|. |
| 590 ExtensionIdList pref_positions = extension_prefs_->GetToolbarOrder(); | 694 std::vector<std::string> pref_positions = extension_prefs_->GetToolbarOrder(); |
| 591 size_t pref_position_size = pref_positions.size(); | 695 size_t pref_position_size = pref_positions.size(); |
| 592 for (size_t i = 0; i < last_known_positions_.size(); ++i) { | 696 for (size_t i = 0; i < last_known_positions_.size(); ++i) { |
| 593 if (std::find(pref_positions.begin(), pref_positions.end(), | 697 if (std::find(pref_positions.begin(), pref_positions.end(), |
| 594 last_known_positions_[i]) == pref_positions.end()) { | 698 last_known_positions_[i]) == pref_positions.end()) { |
| 595 pref_positions.push_back(last_known_positions_[i]); | 699 pref_positions.push_back(last_known_positions_[i]); |
| 596 } | 700 } |
| 597 } | 701 } |
| 598 last_known_positions_.swap(pref_positions); | 702 last_known_positions_.swap(pref_positions); |
| 599 | 703 |
| 600 int desired_index = 0; | 704 int desired_index = 0; |
| 601 // Loop over the updated list of last known positions, moving any extensions | 705 // Loop over the updated list of last known positions, moving any extensions |
| 602 // that are in the wrong place. | 706 // that are in the wrong place. |
| 603 for (const std::string& id : last_known_positions_) { | 707 for (const std::string& id : last_known_positions_) { |
| 604 int current_index = GetIndexForId(id); | 708 int current_index = GetIndexForId(id); |
| 605 if (current_index == -1) | 709 if (current_index == -1) |
| 606 continue; | 710 continue; |
| 607 if (current_index != desired_index) { | 711 if (current_index != desired_index) { |
| 608 scoped_refptr<const Extension> extension = toolbar_items_[current_index]; | 712 ToolbarItem action = toolbar_items_[current_index]; |
| 609 toolbar_items_.erase(toolbar_items_.begin() + current_index); | 713 toolbar_items_.erase(toolbar_items_.begin() + current_index); |
| 610 toolbar_items_.insert(toolbar_items_.begin() + desired_index, extension); | 714 toolbar_items_.insert(toolbar_items_.begin() + desired_index, action); |
| 611 // Notify the observers to keep them up-to-date. | 715 // Notify the observers to keep them up-to-date. |
| 612 FOR_EACH_OBSERVER( | 716 FOR_EACH_OBSERVER(Observer, observers_, |
| 613 Observer, observers_, | 717 OnToolbarActionMoved(action.id, desired_index)); |
| 614 OnToolbarExtensionMoved(extension.get(), desired_index)); | |
| 615 } | 718 } |
| 616 ++desired_index; | 719 ++desired_index; |
| 617 } | 720 } |
| 618 | 721 |
| 619 if (last_known_positions_.size() > pref_position_size) { | 722 if (last_known_positions_.size() > pref_position_size) { |
| 620 // Need to update pref because we have extra icons. But can't call | 723 // Need to update pref because we have extra icons. But can't call |
| 621 // UpdatePrefs() directly within observation closure. | 724 // UpdatePrefs() directly within observation closure. |
| 622 base::ThreadTaskRunnerHandle::Get()->PostTask( | 725 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 623 FROM_HERE, base::Bind(&ExtensionToolbarModel::UpdatePrefs, | 726 FROM_HERE, base::Bind(&ToolbarActionsModel::UpdatePrefs, |
| 624 weak_ptr_factory_.GetWeakPtr())); | 727 weak_ptr_factory_.GetWeakPtr())); |
| 625 } | 728 } |
| 626 } | 729 } |
| 627 | 730 |
| 628 int ExtensionToolbarModel::GetIndexForId(const std::string& id) const { | 731 int ToolbarActionsModel::GetIndexForId(const std::string& id) const { |
| 629 for (size_t i = 0; i < toolbar_items().size(); ++i) { | 732 for (size_t i = 0; i < toolbar_items().size(); ++i) { |
| 630 if (toolbar_items()[i]->id() == id) | 733 if (toolbar_items()[i].id == id) |
| 631 return i; | 734 return i; |
| 632 } | 735 } |
| 633 return -1; | 736 return -1; |
| 634 } | 737 } |
| 635 | 738 |
| 636 bool ExtensionToolbarModel::ShowExtensionActionPopup( | 739 bool ToolbarActionsModel::ShowToolbarActionPopup(const std::string& id, |
| 637 const Extension* extension, | 740 Browser* browser, |
| 638 Browser* browser, | 741 bool grant_active_tab) { |
| 639 bool grant_active_tab) { | |
| 640 base::ObserverListBase<Observer>::Iterator it(&observers_); | 742 base::ObserverListBase<Observer>::Iterator it(&observers_); |
| 641 Observer* obs = NULL; | 743 Observer* obs = NULL; |
| 642 // Look for the Observer associated with the browser. | 744 // Look for the Observer associated with the browser. |
| 643 // This would be cleaner if we had an abstract class for the Toolbar UI | 745 // This would be cleaner if we had an abstract class for the Toolbar UI |
| 644 // (like we do for LocationBar), but sadly, we don't. | 746 // (like we do for LocationBar), but sadly, we don't. |
| 645 while ((obs = it.GetNext()) != NULL) { | 747 while ((obs = it.GetNext()) != NULL) { |
| 646 if (obs->GetBrowser() == browser) | 748 if (obs->GetBrowser() == browser) |
| 647 return obs->ShowExtensionActionPopup(extension, grant_active_tab); | 749 return obs->ShowToolbarActionPopup(id, grant_active_tab); |
| 648 } | 750 } |
| 649 return false; | 751 return false; |
| 650 } | 752 } |
| 651 | 753 |
| 652 void ExtensionToolbarModel::EnsureVisibility( | 754 void ToolbarActionsModel::EnsureVisibility( |
| 653 const ExtensionIdList& extension_ids) { | 755 const std::vector<std::string>& ids) { |
| 654 if (all_icons_visible()) | 756 if (all_icons_visible()) |
| 655 return; // Already showing all. | 757 return; // Already showing all. |
| 656 | 758 |
| 657 // Otherwise, make sure we have enough room to show all the extensions | 759 // Otherwise, make sure we have enough room to show all the extensions |
| 658 // requested. | 760 // requested. |
| 659 if (visible_icon_count() < extension_ids.size()) | 761 if (visible_icon_count() < ids.size()) |
| 660 SetVisibleIconCount(extension_ids.size()); | 762 SetVisibleIconCount(ids.size()); |
| 661 | 763 |
| 662 if (all_icons_visible()) | 764 if (all_icons_visible()) |
| 663 return; // May have been set to max by SetVisibleIconCount. | 765 return; // May have been set to max by SetVisibleIconCount. |
| 664 | 766 |
| 665 // Guillotine's Delight: Move an orange noble to the front of the line. | 767 // Guillotine's Delight: Move an orange noble to the front of the line. |
| 666 for (ExtensionIdList::const_iterator it = extension_ids.begin(); | 768 for (std::vector<std::string>::const_iterator it = ids.begin(); |
| 667 it != extension_ids.end(); ++it) { | 769 it != ids.end(); ++it) { |
| 668 for (ExtensionList::const_iterator extension = toolbar_items_.begin(); | 770 for (std::vector<ToolbarItem>::const_iterator item = toolbar_items_.begin(); |
| 669 extension != toolbar_items_.end(); ++extension) { | 771 item != toolbar_items_.end(); ++item) { |
| 670 if ((*extension)->id() == (*it)) { | 772 if ((*item).id == *it) { |
| 671 if (extension - toolbar_items_.begin() >= | 773 if (item - toolbar_items_.begin() >= |
| 672 static_cast<int>(visible_icon_count())) | 774 static_cast<int>(visible_icon_count())) |
| 673 MoveExtensionIcon((*extension)->id(), 0); | 775 MoveActionIcon(*it, 0); |
| 674 break; | 776 break; |
| 675 } | 777 } |
| 676 } | 778 } |
| 677 } | 779 } |
| 678 } | 780 } |
| 679 | 781 |
| 680 bool ExtensionToolbarModel::HighlightExtensions( | 782 bool ToolbarActionsModel::HighlightActions(const std::vector<std::string>& ids, |
| 681 const ExtensionIdList& extension_ids, | 783 HighlightType highlight_type) { |
| 682 HighlightType highlight_type) { | |
| 683 highlighted_items_.clear(); | 784 highlighted_items_.clear(); |
| 684 | 785 |
| 685 for (ExtensionIdList::const_iterator id = extension_ids.begin(); | 786 for (const std::string& action_id : ids) { |
| 686 id != extension_ids.end(); | 787 for (const ToolbarItem& item : toolbar_items_) { |
| 687 ++id) { | 788 if (action_id == item.id) |
| 688 for (ExtensionList::const_iterator extension = toolbar_items_.begin(); | 789 highlighted_items_.push_back(item); |
| 689 extension != toolbar_items_.end(); | |
| 690 ++extension) { | |
| 691 if (*id == (*extension)->id()) | |
| 692 highlighted_items_.push_back(*extension); | |
| 693 } | 790 } |
| 694 } | 791 } |
| 695 | 792 |
| 696 // If we have any items in |highlighted_items_|, then we entered highlighting | 793 // If we have any items in |highlighted_items_|, then we entered highlighting |
| 697 // mode. | 794 // mode. |
| 698 if (highlighted_items_.size()) { | 795 if (highlighted_items_.size()) { |
| 699 // It's important that is_highlighting_ is changed immediately before the | 796 // It's important that is_highlighting_ is changed immediately before the |
| 700 // observers are notified since it changes the result of toolbar_items(). | 797 // observers are notified since it changes the result of toolbar_items(). |
| 701 highlight_type_ = highlight_type; | 798 highlight_type_ = highlight_type; |
| 702 FOR_EACH_OBSERVER(Observer, observers_, | 799 FOR_EACH_OBSERVER(Observer, observers_, |
| 703 OnToolbarHighlightModeChanged(true)); | 800 OnToolbarHighlightModeChanged(true)); |
| 704 | 801 |
| 705 // We set the visible icon count after the highlight mode change because | 802 // We set the visible icon count after the highlight mode change because |
| 706 // the UI actions are created/destroyed during highlight, and doing that | 803 // the UI actions are created/destroyed during highlight, and doing that |
| 707 // prior to changing the size allows us to still have smooth animations. | 804 // prior to changing the size allows us to still have smooth animations. |
| 708 if (visible_icon_count() < extension_ids.size()) | 805 if (visible_icon_count() < ids.size()) |
| 709 SetVisibleIconCount(extension_ids.size()); | 806 SetVisibleIconCount(ids.size()); |
| 710 | 807 |
| 711 return true; | 808 return true; |
| 712 } | 809 } |
| 713 | 810 |
| 714 // Otherwise, we didn't enter highlighting mode (and, in fact, exited it if | 811 // Otherwise, we didn't enter highlighting mode (and, in fact, exited it if |
| 715 // we were otherwise in it). | 812 // we were otherwise in it). |
| 716 if (is_highlighting()) | 813 if (is_highlighting()) |
| 717 StopHighlighting(); | 814 StopHighlighting(); |
| 718 return false; | 815 return false; |
| 719 } | 816 } |
| 720 | 817 |
| 721 void ExtensionToolbarModel::StopHighlighting() { | 818 void ToolbarActionsModel::StopHighlighting() { |
| 722 if (is_highlighting()) { | 819 if (is_highlighting()) { |
| 723 // It's important that is_highlighting_ is changed immediately before the | 820 // It's important that is_highlighting_ is changed immediately before the |
| 724 // observers are notified since it changes the result of toolbar_items(). | 821 // observers are notified since it changes the result of toolbar_items(). |
| 725 highlight_type_ = HIGHLIGHT_NONE; | 822 highlight_type_ = HIGHLIGHT_NONE; |
| 726 FOR_EACH_OBSERVER(Observer, observers_, | 823 FOR_EACH_OBSERVER(Observer, observers_, |
| 727 OnToolbarHighlightModeChanged(false)); | 824 OnToolbarHighlightModeChanged(false)); |
| 728 | 825 |
| 729 // For the same reason, we don't clear highlighted_items_ until after the | 826 // For the same reason, we don't clear highlighted_items_ until after the |
| 730 // mode changed. | 827 // mode changed. |
| 731 highlighted_items_.clear(); | 828 highlighted_items_.clear(); |
| 732 | 829 |
| 733 // We set the visible icon count after the highlight mode change because | 830 // We set the visible icon count after the highlight mode change because |
| 734 // the UI actions are created/destroyed during highlight, and doing that | 831 // the UI actions are created/destroyed during highlight, and doing that |
| 735 // prior to changing the size allows us to still have smooth animations. | 832 // prior to changing the size allows us to still have smooth animations. |
| 736 int saved_icon_count = prefs_->GetInteger(pref_names::kToolbarSize); | 833 int saved_icon_count = prefs_->GetInteger( |
| 834 extensions::pref_names::kToolbarSize); | |
| 737 if (saved_icon_count != visible_icon_count_) | 835 if (saved_icon_count != visible_icon_count_) |
| 738 SetVisibleIconCount(saved_icon_count); | 836 SetVisibleIconCount(saved_icon_count); |
| 739 } | 837 } |
| 740 } | 838 } |
| 741 | 839 |
| 742 bool ExtensionToolbarModel::RedesignIsShowingNewIcons() const { | 840 bool ToolbarActionsModel::RedesignIsShowingNewIcons() const { |
| 743 for (const scoped_refptr<const Extension>& extension : toolbar_items_) { | 841 for (const ToolbarItem& action : toolbar_items_) { |
| 744 // Without the redesign, we only show extensions with browser actions. | 842 if (action.type == EXTENSION_ACTION) { |
| 745 // Any extension without a browser action is an indication that we're | 843 // Without the redesign, we only show extensions with browser actions. |
| 746 // showing something new. | 844 // Any extension without a browser action is an indication that we're |
| 747 if (!extension->manifest()->HasKey(manifest_keys::kBrowserAction)) | 845 // showing something new. |
| 748 return true; | 846 if (!GetExtensionById(action.id)->manifest()->HasKey( |
| 847 extensions::manifest_keys::kBrowserAction)) | |
| 848 return true; | |
| 849 } | |
| 749 } | 850 } |
| 750 return false; | 851 return false; |
| 751 } | 852 } |
| 752 | 853 |
| 753 } // namespace extensions | 854 const extensions::Extension* ToolbarActionsModel::GetExtensionById( |
| 855 const std::string& id) const { | |
| 856 return extension_registry_->enabled_extensions().GetByID(id); | |
| 857 } | |
| OLD | NEW |