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

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

Powered by Google App Engine
This is Rietveld 408576698