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