Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: chrome/browser/ui/toolbar/toolbar_actions_model.cc

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

Powered by Google App Engine
This is Rietveld 408576698