extension_toolbar_model.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_toolbar_model.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/browser_event_router.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_manager.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_prefs.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/feature_switch.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::ExtensionIdList; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::ExtensionList; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if an |extension| is in an |extension_list|. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsInExtensionList(const Extension* extension, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::ExtensionList& extension_list) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < extension_list.size(); i++) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension_list[i].get() == extension) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionToolbarModel::ExtensionToolbarModel(ExtensionService* service) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : service_(service), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs_(service->profile()->GetPrefs()), 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extensions_initialized_(false), 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(service_); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(service_->profile())); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(service_->profile())); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(service_->profile())); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<Profile>(service_->profile())); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<extensions::ExtensionPrefs>(service_->extension_prefs())); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_icon_count_ = prefs_->GetInteger(prefs::kExtensionToolbarSize); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Init(prefs_); 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_callback_ = 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ExtensionToolbarModel::OnExtensionToolbarPrefChange, 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Add(prefs::kExtensionToolbar, pref_change_callback_); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionToolbarModel::~ExtensionToolbarModel() { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::AddObserver(Observer* observer) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.AddObserver(observer); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::RemoveObserver(Observer* observer) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.RemoveObserver(observer); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::MoveBrowserAction(const Extension* extension, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList::iterator pos = std::find(toolbar_items_.begin(), 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.end(), extension); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pos == toolbar_items_.end()) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.erase(pos); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator pos_id; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pos_id = std::find(last_known_positions_.begin(), 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), extension->id()); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos_id != last_known_positions_.end()) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.erase(pos_id); 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool inserted = false; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++i) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == index) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pos_id = std::find(last_known_positions_.begin(), 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), (*iter)->id()); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.insert(pos_id, extension->id()); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.insert(iter, make_scoped_refptr(extension)); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inserted = true; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!inserted) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(index, static_cast<int>(toolbar_items_.size())); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = toolbar_items_.size(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.push_back(extension->id()); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, BrowserActionMoved(extension, index)); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePrefs(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionToolbarModel::Action ExtensionToolbarModel::ExecuteBrowserAction( 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL* popup_url_out) { 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* web_contents = 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser->tab_strip_model()->GetActiveWebContents(); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!web_contents) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(web_contents); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_id < 0) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionAction* browser_action = 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionActionManager::Get(service_->profile())-> 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBrowserAction(*extension); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For browser actions, visibility == enabledness. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!browser_action->GetIsVisible(tab_id)) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::TabHelper::FromWebContents(web_contents)-> 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_tab_permission_granter()->GrantIfRequested(extension); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action->HasPopup(tab_id)) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_url_out) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *popup_url_out = browser_action->GetPopupUrl(tab_id); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_SHOW_POPUP; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->browser_event_router()->BrowserActionExecuted( 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser_action, browser); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::SetVisibleIconCount(int count) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_icon_count_ = 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count == static_cast<int>(toolbar_items_.size()) ? -1 : count; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs_->SetInteger(prefs::kExtensionToolbarSize, visible_icon_count_); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::Observe( 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSIONS_READY) { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InitializeExtensionList(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!service_->is_ready()) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = NULL; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension = content::Details<extensions::UnloadedExtensionInfo>( 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details)->extension; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension = content::Details<const Extension>(details).ptr(); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to add the same extension twice. It may have already been 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // added by EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED below, if the user 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hides the browser action and then disables and enables the extension. 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < toolbar_items_.size(); i++) { 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (toolbar_items_[i].get() == extension) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; // Already exists. 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (service_->extension_prefs()->GetBrowserActionVisibility(extension)) 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddExtension(extension); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RemoveExtension(extension); 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (type == chrome::NOTIFICATION_EXTENSION_UNINSTALLED) { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UninstalledExtension(extension); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED) { 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (service_->extension_prefs()->GetBrowserActionVisibility(extension)) 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddExtension(extension); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RemoveExtension(extension); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Received unexpected notification"; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t ExtensionToolbarModel::FindNewPositionFromLastKnownGood( 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension) { 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if we have last known good position for this extension. 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t new_index = 0; 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Loop through the ID list of known positions, to count the number of visible 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // browser action icons preceding |extension|. 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ExtensionIdList::const_iterator iter_id = last_known_positions_.begin(); 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter_id < last_known_positions_.end(); ++iter_id) { 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*iter_id) == extension->id()) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_index; // We've found the right position. 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Found an id, need to see if it is visible. 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ExtensionList::const_iterator iter_ext = toolbar_items_.begin(); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter_ext < toolbar_items_.end(); ++iter_ext) { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*iter_ext)->id().compare(*iter_id) == 0) { 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This extension is visible, update the index value. 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++new_index; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::AddExtension(const Extension* extension) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only care about extensions with browser actions. 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extensions::ExtensionActionManager::Get(service_->profile())-> 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBrowserAction(*extension)) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t new_index = -1; 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if we have a last known good position for this extension. 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator last_pos = std::find(last_known_positions_.begin(), 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->id()); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (last_pos != last_known_positions_.end()) { 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_index = FindNewPositionFromLastKnownGood(extension); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_index != toolbar_items_.size()) { 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.insert(toolbar_items_.begin() + new_index, 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) make_scoped_refptr(extension)); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is a never before seen extension, that was added to the end. Make 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sure to reflect that. 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.push_back(extension->id()); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_index = toolbar_items_.size() - 1; 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdatePrefs(); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserActionAdded(extension, new_index)); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::RemoveExtension(const Extension* extension) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList::iterator pos = 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::find(toolbar_items_.begin(), toolbar_items_.end(), extension); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos == toolbar_items_.end()) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.erase(pos); 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserActionRemoved(extension)); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePrefs(); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::UninstalledExtension(const Extension* extension) { 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove the extension id from the ordered list, if it exists (the extension 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // might not be represented in the list because it might not have an icon). 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator pos = 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::find(last_known_positions_.begin(), 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), extension->id()); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos != last_known_positions_.end()) { 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.erase(pos); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdatePrefs(); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Combine the currently enabled extensions that have browser actions (which 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we get from the ExtensionService) with the ordering we get from the 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pref service. For robustness we use a somewhat inefficient process: 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. Create a vector of extensions sorted by their pref values. This vector may 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have holes. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Create a vector of extensions that did not have a pref value. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. Remove holes from the sorted vector and append the unsorted vector. 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::InitializeExtensionList() { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(service_->is_ready()); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_ = service_->extension_prefs()->GetToolbarOrder(); 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Populate(last_known_positions_); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions_initialized_ = true; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ModelLoaded()); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExtensionToolbarModel::Populate( 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const extensions::ExtensionIdList& positions) { 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Items that have explicit positions. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList sorted; 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sorted.resize(positions.size(), NULL); 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The items that don't have explicit positions. 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList unsorted; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionActionManager* extension_action_manager = 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionActionManager::Get(service_->profile()); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the lists. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionSet::const_iterator it = service_->extensions()->begin(); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != service_->extensions()->end(); ++it) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = *it; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_action_manager->GetBrowserAction(*extension)) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!service_->extension_prefs()->GetBrowserActionVisibility(extension)) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionIdList::const_iterator pos = 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::find(positions.begin(), positions.end(), extension->id()); 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (pos != positions.end()) 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sorted[pos - positions.begin()] = extension; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsorted.push_back(make_scoped_refptr(extension)); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Erase current icons. 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < toolbar_items_.size(); i++) { 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BrowserActionRemoved(toolbar_items_[i])); 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.clear(); 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Merge the lists. 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.reserve(sorted.size() + unsorted.size()); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::const_iterator iter = sorted.begin(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != sorted.end(); ++iter) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's possible for the extension order to contain items that aren't 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually loaded on this machine. For example, when extension sync is on, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we sync the extension order as-is but double-check with the user before 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // syncing NPAPI-containing extensions, so if one of those is not actually 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // synced, we'll get a NULL in the list. This sort of case can also happen 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if some error prevents an extension from loading. 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*iter != NULL) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.push_back(*iter); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.insert(toolbar_items_.end(), unsorted.begin(), 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsorted.end()); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inform observers. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < toolbar_items_.size(); i++) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionAdded(toolbar_items_[i], i)); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::FillExtensionList( 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const extensions::ExtensionIdList& order) { 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.clear(); 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.reserve(order.size()); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < order.size(); ++i) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::Extension* extension = 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->GetExtensionById(order[i], false); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension) 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddExtension(extension); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::UpdatePrefs() { 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!service_->extension_prefs()) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Don't observe change caused by self. 389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Remove(prefs::kExtensionToolbar); 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_->extension_prefs()->SetToolbarOrder(last_known_positions_); 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Add(prefs::kExtensionToolbar, pref_change_callback_); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int original_index = 0, i = 0; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++original_index) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (service_->IsIncognitoEnabled((*iter)->id())) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (incognito_index == i) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_index; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionToolbarModel::OriginalIndexToIncognito(int original_index) { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int incognito_index = 0, i = 0; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++i) { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original_index == i) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (service_->IsIncognitoEnabled((*iter)->id())) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++incognito_index; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return incognito_index; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExtensionToolbarModel::OnExtensionToolbarPrefChange() { 422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If extensions are not ready, defer to later Populate() call. 423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!extensions_initialized_) 424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Recalculate |last_known_positions_| to be |pref_positions| followed by 427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ones that are only in |last_known_positions_|. 428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extensions::ExtensionIdList pref_positions = 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) service_->extension_prefs()->GetToolbarOrder(); 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t pref_position_size = pref_positions.size(); 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < last_known_positions_.size(); ++i) { 432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (std::find(pref_positions.begin(), pref_positions.end(), 433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_[i]) == pref_positions.end()) { 434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_positions.push_back(last_known_positions_[i]); 435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_.swap(pref_positions); 438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Re-populate. 440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Populate(last_known_positions_); 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (last_known_positions_.size() > pref_position_size) { 443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Need to update pref because we have extra icons. But can't call 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // UpdatePrefs() directly within observation closure. 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostTask( 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ExtensionToolbarModel::UpdatePrefs, 448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 451