OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_toolbar_model.h" | 5 #include "chrome/browser/extensions/extension_toolbar_model.h" |
6 | 6 |
7 #include "chrome/browser/extensions/extension_browser_event_router.h" | 7 #include "chrome/browser/extensions/extension_browser_event_router.h" |
8 #include "chrome/browser/extensions/extension_prefs.h" | 8 #include "chrome/browser/extensions/extension_prefs.h" |
9 #include "chrome/browser/extensions/extension_service.h" | 9 #include "chrome/browser/extensions/extension_service.h" |
10 #include "chrome/browser/extensions/extension_tab_helper.h" | 10 #include "chrome/browser/extensions/extension_tab_helper.h" |
11 #include "chrome/browser/extensions/extension_tab_util.h" | 11 #include "chrome/browser/extensions/extension_tab_util.h" |
12 #include "chrome/browser/prefs/pref_service.h" | 12 #include "chrome/browser/prefs/pref_service.h" |
13 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
14 #include "chrome/browser/ui/browser.h" | 14 #include "chrome/browser/ui/browser.h" |
15 #include "chrome/browser/ui/browser_tabstrip.h" | 15 #include "chrome/browser/ui/browser_tabstrip.h" |
16 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 16 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
17 #include "chrome/common/chrome_notification_types.h" | 17 #include "chrome/common/chrome_notification_types.h" |
18 #include "chrome/common/extensions/extension.h" | 18 #include "chrome/common/extensions/extension.h" |
| 19 #include "chrome/common/extensions/extension_switch_utils.h" |
19 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
20 #include "content/public/browser/notification_details.h" | 21 #include "content/public/browser/notification_details.h" |
21 #include "content/public/browser/notification_source.h" | 22 #include "content/public/browser/notification_source.h" |
22 #include "content/public/browser/web_contents.h" | 23 #include "content/public/browser/web_contents.h" |
23 | 24 |
24 using extensions::Extension; | 25 using extensions::Extension; |
25 using extensions::ExtensionList; | 26 using extensions::ExtensionList; |
26 | 27 |
27 ExtensionToolbarModel::ExtensionToolbarModel(ExtensionService* service) | 28 ExtensionToolbarModel::ExtensionToolbarModel(ExtensionService* service) |
28 : service_(service), | 29 : service_(service), |
(...skipping 25 matching lines...) Expand all Loading... |
54 observers_.RemoveObserver(observer); | 55 observers_.RemoveObserver(observer); |
55 } | 56 } |
56 | 57 |
57 void ExtensionToolbarModel::MoveBrowserAction(const Extension* extension, | 58 void ExtensionToolbarModel::MoveBrowserAction(const Extension* extension, |
58 int index) { | 59 int index) { |
59 ExtensionList::iterator pos = std::find(begin(), end(), extension); | 60 ExtensionList::iterator pos = std::find(begin(), end(), extension); |
60 if (pos == end()) { | 61 if (pos == end()) { |
61 NOTREACHED(); | 62 NOTREACHED(); |
62 return; | 63 return; |
63 } | 64 } |
64 toolitems_.erase(pos); | 65 toolbar_items_.erase(pos); |
65 | 66 |
66 int i = 0; | 67 int i = 0; |
67 bool inserted = false; | 68 bool inserted = false; |
68 for (ExtensionList::iterator iter = begin(); iter != end(); ++iter, ++i) { | 69 for (ExtensionList::iterator iter = begin(); iter != end(); ++iter, ++i) { |
69 if (i == index) { | 70 if (i == index) { |
70 toolitems_.insert(iter, make_scoped_refptr(extension)); | 71 toolbar_items_.insert(iter, make_scoped_refptr(extension)); |
71 inserted = true; | 72 inserted = true; |
72 break; | 73 break; |
73 } | 74 } |
74 } | 75 } |
75 | 76 |
76 if (!inserted) { | 77 if (!inserted) { |
77 DCHECK_EQ(index, static_cast<int>(toolitems_.size())); | 78 DCHECK_EQ(index, static_cast<int>(toolbar_items_.size())); |
78 index = toolitems_.size(); | 79 index = toolbar_items_.size(); |
79 | 80 |
80 toolitems_.push_back(make_scoped_refptr(extension)); | 81 toolbar_items_.push_back(make_scoped_refptr(extension)); |
81 } | 82 } |
82 | 83 |
83 FOR_EACH_OBSERVER(Observer, observers_, BrowserActionMoved(extension, index)); | 84 FOR_EACH_OBSERVER(Observer, observers_, BrowserActionMoved(extension, index)); |
84 | 85 |
85 UpdatePrefs(); | 86 UpdatePrefs(); |
86 } | 87 } |
87 | 88 |
88 ExtensionToolbarModel::Action ExtensionToolbarModel::ExecuteBrowserAction( | 89 ExtensionToolbarModel::Action ExtensionToolbarModel::ExecuteBrowserAction( |
89 const Extension* extension, | 90 const Extension* extension, |
90 Browser* browser, | 91 Browser* browser, |
(...skipping 24 matching lines...) Expand all Loading... |
115 void ExtensionToolbarModel::SetVisibleIconCount(int count) { | 116 void ExtensionToolbarModel::SetVisibleIconCount(int count) { |
116 visible_icon_count_ = count == static_cast<int>(size()) ? -1 : count; | 117 visible_icon_count_ = count == static_cast<int>(size()) ? -1 : count; |
117 prefs_->SetInteger(prefs::kExtensionToolbarSize, visible_icon_count_); | 118 prefs_->SetInteger(prefs::kExtensionToolbarSize, visible_icon_count_); |
118 } | 119 } |
119 | 120 |
120 void ExtensionToolbarModel::Observe( | 121 void ExtensionToolbarModel::Observe( |
121 int type, | 122 int type, |
122 const content::NotificationSource& source, | 123 const content::NotificationSource& source, |
123 const content::NotificationDetails& details) { | 124 const content::NotificationDetails& details) { |
124 if (type == chrome::NOTIFICATION_EXTENSIONS_READY) { | 125 if (type == chrome::NOTIFICATION_EXTENSIONS_READY) { |
125 InitializeExtensionList(); | 126 InitializeExtensionLists(); |
126 return; | 127 return; |
127 } | 128 } |
128 | 129 |
129 if (!service_->is_ready()) | 130 if (!service_->is_ready()) |
130 return; | 131 return; |
131 | 132 |
132 const Extension* extension = NULL; | 133 const Extension* extension = NULL; |
133 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { | 134 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { |
134 extension = content::Details<extensions::UnloadedExtensionInfo>( | 135 extension = content::Details<extensions::UnloadedExtensionInfo>( |
135 details)->extension; | 136 details)->extension; |
136 } else { | 137 } else { |
137 extension = content::Details<const Extension>(details).ptr(); | 138 extension = content::Details<const Extension>(details).ptr(); |
138 } | 139 } |
139 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { | 140 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { |
140 // We don't want to add the same extension twice. It may have already been | 141 // We don't want to add the same extension twice. It may have already been |
141 // added by EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED below, if the user | 142 // added by EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED below, if the user |
142 // hides the browser action and then disables and enables the extension. | 143 // hides the browser action and then disables and enables the extension. |
143 for (size_t i = 0; i < toolitems_.size(); i++) { | 144 for (size_t i = 0; i < toolbar_items_.size(); i++) { |
144 if (toolitems_[i].get() == extension) | 145 if (toolbar_items_[i].get() == extension) |
145 return; // Already exists. | 146 return; // Already exists. |
146 } | 147 } |
147 if (service_->extension_prefs()->GetBrowserActionVisibility(extension)) | 148 if (service_->extension_prefs()->GetBrowserActionVisibility(extension)) |
148 AddExtension(extension); | 149 AddExtension(extension); |
149 } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { | 150 } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { |
150 RemoveExtension(extension); | 151 RemoveExtension(extension); |
151 } else if ( | 152 } else if ( |
152 type == | 153 type == |
153 chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED) { | 154 chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED) { |
154 if (service_->extension_prefs()->GetBrowserActionVisibility(extension)) | 155 if (service_->extension_prefs()->GetBrowserActionVisibility(extension)) |
155 AddExtension(extension); | 156 AddExtension(extension); |
156 else | 157 else |
157 RemoveExtension(extension); | 158 RemoveExtension(extension); |
158 } else { | 159 } else { |
159 NOTREACHED() << "Received unexpected notification"; | 160 NOTREACHED() << "Received unexpected notification"; |
160 } | 161 } |
161 } | 162 } |
162 | 163 |
163 void ExtensionToolbarModel::AddExtension(const Extension* extension) { | 164 void ExtensionToolbarModel::AddExtension(const Extension* extension) { |
164 // We only care about extensions with browser actions. | 165 // We only care about extensions with browser actions. |
165 if (!extension->browser_action()) | 166 if (!extension->browser_action()) |
166 return; | 167 return; |
167 | 168 |
168 if (extension->id() == last_extension_removed_ && | 169 if (extension->id() == last_extension_removed_ && |
169 last_extension_removed_index_ < toolitems_.size()) { | 170 last_extension_removed_index_ < toolbar_items_.size()) { |
170 toolitems_.insert(begin() + last_extension_removed_index_, | 171 toolbar_items_.insert(begin() + last_extension_removed_index_, |
171 make_scoped_refptr(extension)); | 172 make_scoped_refptr(extension)); |
172 FOR_EACH_OBSERVER(Observer, observers_, | 173 FOR_EACH_OBSERVER(Observer, observers_, |
173 BrowserActionAdded(extension, last_extension_removed_index_)); | 174 BrowserActionAdded(extension, last_extension_removed_index_)); |
174 } else { | 175 } else { |
175 toolitems_.push_back(make_scoped_refptr(extension)); | 176 toolbar_items_.push_back(make_scoped_refptr(extension)); |
176 FOR_EACH_OBSERVER(Observer, observers_, | 177 FOR_EACH_OBSERVER(Observer, observers_, |
177 BrowserActionAdded(extension, toolitems_.size() - 1)); | 178 BrowserActionAdded(extension, toolbar_items_.size() - 1)); |
178 } | 179 } |
179 | 180 |
180 last_extension_removed_ = ""; | 181 last_extension_removed_ = ""; |
181 last_extension_removed_index_ = -1; | 182 last_extension_removed_index_ = -1; |
182 | 183 |
183 UpdatePrefs(); | 184 UpdatePrefs(); |
184 } | 185 } |
185 | 186 |
186 void ExtensionToolbarModel::RemoveExtension(const Extension* extension) { | 187 void ExtensionToolbarModel::RemoveExtension(const Extension* extension) { |
187 ExtensionList::iterator pos = std::find(begin(), end(), extension); | 188 ExtensionList::iterator pos = std::find(begin(), end(), extension); |
188 if (pos == end()) { | 189 if (pos == end()) { |
189 return; | 190 return; |
190 } | 191 } |
191 | 192 |
192 last_extension_removed_ = extension->id(); | 193 last_extension_removed_ = extension->id(); |
193 last_extension_removed_index_ = pos - begin(); | 194 last_extension_removed_index_ = pos - begin(); |
194 | 195 |
195 toolitems_.erase(pos); | 196 toolbar_items_.erase(pos); |
196 FOR_EACH_OBSERVER(Observer, observers_, | 197 FOR_EACH_OBSERVER(Observer, observers_, |
197 BrowserActionRemoved(extension)); | 198 BrowserActionRemoved(extension)); |
198 | 199 |
199 UpdatePrefs(); | 200 UpdatePrefs(); |
200 } | 201 } |
201 | 202 |
202 // Combine the currently enabled extensions that have browser actions (which | 203 // Combine the currently enabled extensions that have browser actions (which |
203 // we get from the ExtensionService) with the ordering we get from the | 204 // we get from the ExtensionService) with the ordering we get from the |
204 // pref service. For robustness we use a somewhat inefficient process: | 205 // pref service. For robustness we use a somewhat inefficient process: |
205 // 1. Create a vector of extensions sorted by their pref values. This vector may | 206 // 1. Create a vector of extensions sorted by their pref values. This vector may |
206 // have holes. | 207 // have holes. |
207 // 2. Create a vector of extensions that did not have a pref value. | 208 // 2. Create a vector of extensions that did not have a pref value. |
208 // 3. Remove holes from the sorted vector and append the unsorted vector. | 209 // 3. Remove holes from the sorted vector and append the unsorted vector. |
209 void ExtensionToolbarModel::InitializeExtensionList() { | 210 void ExtensionToolbarModel::InitializeExtensionLists() { |
210 DCHECK(service_->is_ready()); | 211 DCHECK(service_->is_ready()); |
211 | 212 |
212 std::vector<std::string> pref_order = service_->extension_prefs()-> | 213 if (extensions::switch_utils::IsActionBoxEnabled()) |
213 GetToolbarOrder(); | 214 PopulateForActionBoxMode(); |
| 215 else |
| 216 PopulateForNonActionBoxMode(); |
| 217 |
| 218 UpdatePrefs(); |
| 219 |
| 220 extensions_initialized_ = true; |
| 221 FOR_EACH_OBSERVER(Observer, observers_, ModelLoaded()); |
| 222 } |
| 223 |
| 224 void ExtensionToolbarModel::PopulateForActionBoxMode() { |
| 225 const std::vector<std::string> toolbar_order = |
| 226 service_->extension_prefs()->GetToolbarOrder(); |
| 227 std::vector<std::string> action_box_order = |
| 228 service_->extension_prefs()->GetActionBoxOrder(); |
| 229 |
| 230 // Create the lists. |
| 231 for (ExtensionSet::const_iterator it = service_->extensions()->begin(); |
| 232 it != service_->extensions()->end(); ++it) { |
| 233 const Extension* extension = *it; |
| 234 if (!extension->browser_action()) |
| 235 continue; |
| 236 |
| 237 std::vector<std::string>::const_iterator toolbar_pos = |
| 238 std::find(toolbar_order.begin(), toolbar_order.end(), extension->id()); |
| 239 std::vector<std::string>::const_iterator action_box_pos = |
| 240 std::find(action_box_order.begin(), action_box_order.end(), |
| 241 extension->id()); |
| 242 if ((toolbar_pos == toolbar_order.end()) && |
| 243 (action_box_pos == action_box_order.end())) { |
| 244 action_box_order.push_back(extension->id()); |
| 245 } |
| 246 } |
| 247 |
| 248 FillExtensionList(action_box_order, &action_box_menu_items_); |
| 249 FillExtensionList(toolbar_order, &toolbar_items_); |
| 250 |
| 251 // Inform observers. |
| 252 for (size_t i = 0; i < toolbar_items_.size(); i++) { |
| 253 FOR_EACH_OBSERVER(Observer, observers_, |
| 254 BrowserActionAdded(action_box_menu_items_[i], i)); |
| 255 FOR_EACH_OBSERVER(Observer, observers_, |
| 256 BrowserActionAdded(toolbar_items_[i], i)); |
| 257 } |
| 258 } |
| 259 |
| 260 void ExtensionToolbarModel::AddToProperList(const Extension* extension, |
| 261 const std::vector<std::string>& order, |
| 262 ExtensionList* sorted, |
| 263 ExtensionList* unsorted) { |
| 264 std::vector<std::string>::const_iterator pos = |
| 265 std::find(order.begin(), order.end(), extension->id()); |
| 266 if (pos != order.end()) { |
| 267 int index = std::distance(order.begin(), pos); |
| 268 (*sorted)[index] = extension; |
| 269 } else { |
| 270 unsorted->push_back(make_scoped_refptr(extension)); |
| 271 } |
| 272 } |
| 273 |
| 274 void ExtensionToolbarModel::MergeLists(const ExtensionList& sorted, |
| 275 const ExtensionList& unsorted, |
| 276 ExtensionList* result_list) { |
| 277 result_list->reserve(sorted.size() + unsorted.size()); |
| 278 for (ExtensionList::const_iterator iter = sorted.begin(); |
| 279 iter != sorted.end(); |
| 280 ++iter) { |
| 281 if (*iter != NULL) |
| 282 result_list->push_back(*iter); |
| 283 } |
| 284 result_list->insert(result_list->end(), unsorted.begin(), unsorted.end()); |
| 285 } |
| 286 |
| 287 void ExtensionToolbarModel::FillExtensionList( |
| 288 const std::vector<std::string>& order, ExtensionList* result_list) { |
| 289 result_list->clear(); |
| 290 result_list->reserve(order.size()); |
| 291 for (size_t i = 0; i < order.size(); ++i) { |
| 292 const extensions::Extension* extension = |
| 293 service_->GetExtensionById(order[i], false); |
| 294 if (!extension) |
| 295 return; |
| 296 result_list->push_back(extension); |
| 297 } |
| 298 } |
| 299 |
| 300 void ExtensionToolbarModel::PopulateForNonActionBoxMode() { |
| 301 const std::vector<std::string> pref_order = |
| 302 service_->extension_prefs()->GetToolbarOrder(); |
214 // Items that have a pref for their position. | 303 // Items that have a pref for their position. |
215 ExtensionList sorted; | 304 ExtensionList sorted; |
216 sorted.resize(pref_order.size(), NULL); | 305 sorted.resize(pref_order.size(), NULL); |
217 // The items that don't have a pref for their position. | 306 // The items that don't have a pref for their position. |
218 ExtensionList unsorted; | 307 ExtensionList unsorted; |
219 | 308 |
220 // Create the lists. | 309 // Create the lists. |
221 for (ExtensionSet::const_iterator it = service_->extensions()->begin(); | 310 for (ExtensionSet::const_iterator it = service_->extensions()->begin(); |
222 it != service_->extensions()->end(); ++it) { | 311 it != service_->extensions()->end(); ++it) { |
223 const Extension* extension = *it; | 312 const Extension* extension = *it; |
224 if (!extension->browser_action()) | 313 if (!extension->browser_action()) |
225 continue; | 314 continue; |
226 if (!service_->extension_prefs()->GetBrowserActionVisibility(extension)) | 315 if (!service_->extension_prefs()->GetBrowserActionVisibility(extension)) |
227 continue; | 316 continue; |
228 | 317 |
229 std::vector<std::string>::iterator pos = | 318 AddToProperList(extension, pref_order, &sorted, &unsorted); |
230 std::find(pref_order.begin(), pref_order.end(), extension->id()); | |
231 if (pos != pref_order.end()) { | |
232 int index = std::distance(pref_order.begin(), pos); | |
233 sorted[index] = extension; | |
234 } else { | |
235 unsorted.push_back(make_scoped_refptr(extension)); | |
236 } | |
237 } | 319 } |
238 | 320 |
239 // Merge the lists. | 321 MergeLists(sorted, unsorted, &toolbar_items_); |
240 toolitems_.reserve(sorted.size() + unsorted.size()); | |
241 for (ExtensionList::iterator iter = sorted.begin(); | |
242 iter != sorted.end(); ++iter) { | |
243 if (*iter != NULL) | |
244 toolitems_.push_back(*iter); | |
245 } | |
246 toolitems_.insert(toolitems_.end(), unsorted.begin(), unsorted.end()); | |
247 | 322 |
248 // Inform observers. | 323 // Inform observers. |
249 for (size_t i = 0; i < toolitems_.size(); i++) { | 324 for (size_t i = 0; i < toolbar_items_.size(); i++) { |
250 FOR_EACH_OBSERVER(Observer, observers_, | 325 FOR_EACH_OBSERVER(Observer, observers_, |
251 BrowserActionAdded(toolitems_[i], i)); | 326 BrowserActionAdded(toolbar_items_[i], i)); |
252 } | 327 } |
253 | |
254 UpdatePrefs(); | |
255 | |
256 extensions_initialized_ = true; | |
257 FOR_EACH_OBSERVER(Observer, observers_, ModelLoaded()); | |
258 } | 328 } |
259 | 329 |
260 void ExtensionToolbarModel::UpdatePrefs() { | 330 void ExtensionToolbarModel::UpdatePrefs() { |
261 if (!service_->extension_prefs()) | 331 if (!service_->extension_prefs()) |
262 return; | 332 return; |
263 | 333 |
264 std::vector<std::string> ids; | 334 std::vector<std::string> ids; |
265 ids.reserve(toolitems_.size()); | 335 ids.reserve(toolbar_items_.size()); |
266 for (ExtensionList::iterator iter = begin(); iter != end(); ++iter) | 336 for (ExtensionList::iterator iter = begin(); iter != end(); ++iter) |
267 ids.push_back((*iter)->id()); | 337 ids.push_back((*iter)->id()); |
268 service_->extension_prefs()->SetToolbarOrder(ids); | 338 service_->extension_prefs()->SetToolbarOrder(ids); |
| 339 |
| 340 ids.clear(); |
| 341 ids.reserve(action_box_menu_items_.size()); |
| 342 for (size_t i = 0; i < action_box_menu_items_.size(); ++i) |
| 343 ids.push_back(action_box_menu_items_[i]->id()); |
| 344 service_->extension_prefs()->SetActionBoxOrder(ids); |
269 } | 345 } |
270 | 346 |
271 const Extension* ExtensionToolbarModel::GetExtensionByIndex(int index) const { | 347 const Extension* ExtensionToolbarModel::GetExtensionByIndex(int index) const { |
272 return toolitems_[index]; | 348 return toolbar_items_[index]; |
273 } | 349 } |
274 | 350 |
275 int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) { | 351 int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) { |
276 int original_index = 0, i = 0; | 352 int original_index = 0, i = 0; |
277 for (ExtensionList::iterator iter = begin(); iter != end(); | 353 for (ExtensionList::iterator iter = begin(); iter != end(); |
278 ++iter, ++original_index) { | 354 ++iter, ++original_index) { |
279 if (service_->IsIncognitoEnabled((*iter)->id())) { | 355 if (service_->IsIncognitoEnabled((*iter)->id())) { |
280 if (incognito_index == i) | 356 if (incognito_index == i) |
281 break; | 357 break; |
282 ++i; | 358 ++i; |
283 } | 359 } |
284 } | 360 } |
285 return original_index; | 361 return original_index; |
286 } | 362 } |
287 | 363 |
288 int ExtensionToolbarModel::OriginalIndexToIncognito(int original_index) { | 364 int ExtensionToolbarModel::OriginalIndexToIncognito(int original_index) { |
289 int incognito_index = 0, i = 0; | 365 int incognito_index = 0, i = 0; |
290 for (ExtensionList::iterator iter = begin(); iter != end(); | 366 for (ExtensionList::iterator iter = begin(); iter != end(); |
291 ++iter, ++i) { | 367 ++iter, ++i) { |
292 if (original_index == i) | 368 if (original_index == i) |
293 break; | 369 break; |
294 if (service_->IsIncognitoEnabled((*iter)->id())) | 370 if (service_->IsIncognitoEnabled((*iter)->id())) |
295 ++incognito_index; | 371 ++incognito_index; |
296 } | 372 } |
297 return incognito_index; | 373 return incognito_index; |
298 } | 374 } |
| 375 |
| 376 const Extension* ExtensionToolbarModel::GetActionBoxExtensionByIndex( |
| 377 int index) const { |
| 378 return action_box_menu_items_[index]; |
| 379 } |
OLD | NEW |