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

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

Powered by Google App Engine
This is Rietveld 408576698