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" 87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/browser_event_router.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_manager.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_prefs.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/feature_switch.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::ExtensionIdList; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::ExtensionList; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if an |extension| is in an |extension_list|. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsInExtensionList(const Extension* extension, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::ExtensionList& extension_list) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < extension_list.size(); i++) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension_list[i].get() == extension) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionToolbarModel::ExtensionToolbarModel(ExtensionService* service) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : service_(service), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs_(service->profile()->GetPrefs()), 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extensions_initialized_(false), 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(service_); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(service_->profile())); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(service_->profile())); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(service_->profile())); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<Profile>(service_->profile())); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<extensions::ExtensionPrefs>(service_->extension_prefs())); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_icon_count_ = prefs_->GetInteger(prefs::kExtensionToolbarSize); 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Init(prefs_); 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_callback_ = 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ExtensionToolbarModel::OnExtensionToolbarPrefChange, 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)); 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Add(prefs::kExtensionToolbar, pref_change_callback_); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionToolbarModel::~ExtensionToolbarModel() { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::AddObserver(Observer* observer) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.AddObserver(observer); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::RemoveObserver(Observer* observer) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.RemoveObserver(observer); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::MoveBrowserAction(const Extension* extension, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList::iterator pos = std::find(toolbar_items_.begin(), 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.end(), extension); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pos == toolbar_items_.end()) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.erase(pos); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator pos_id; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pos_id = std::find(last_known_positions_.begin(), 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), extension->id()); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos_id != last_known_positions_.end()) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.erase(pos_id); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool inserted = false; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++i) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == index) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pos_id = std::find(last_known_positions_.begin(), 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), (*iter)->id()); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.insert(pos_id, extension->id()); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.insert(iter, make_scoped_refptr(extension)); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inserted = true; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!inserted) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(index, static_cast<int>(toolbar_items_.size())); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = toolbar_items_.size(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.push_back(extension->id()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, BrowserActionMoved(extension, index)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePrefs(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionToolbarModel::Action ExtensionToolbarModel::ExecuteBrowserAction( 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL* popup_url_out) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* web_contents = 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser->tab_strip_model()->GetActiveWebContents(); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!web_contents) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(web_contents); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_id < 0) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionAction* browser_action = 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionActionManager::Get(service_->profile())-> 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBrowserAction(*extension); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For browser actions, visibility == enabledness. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!browser_action->GetIsVisible(tab_id)) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::TabHelper::FromWebContents(web_contents)-> 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_tab_permission_granter()->GrantIfRequested(extension); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action->HasPopup(tab_id)) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_url_out) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *popup_url_out = browser_action->GetPopupUrl(tab_id); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_SHOW_POPUP; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->browser_event_router()->BrowserActionExecuted( 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser_action, browser); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::SetVisibleIconCount(int count) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_icon_count_ = 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count == static_cast<int>(toolbar_items_.size()) ? -1 : count; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs_->SetInteger(prefs::kExtensionToolbarSize, visible_icon_count_); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::Observe( 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSIONS_READY) { 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InitializeExtensionList(); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!service_->is_ready()) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = NULL; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension = content::Details<extensions::UnloadedExtensionInfo>( 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details)->extension; 186b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else if (type == 187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED) { 188b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extension = service_->GetExtensionById( 189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *content::Details<const std::string>(details).ptr(), true); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension = content::Details<const Extension>(details).ptr(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to add the same extension twice. It may have already been 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // added by EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED below, if the user 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hides the browser action and then disables and enables the extension. 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < toolbar_items_.size(); i++) { 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (toolbar_items_[i].get() == extension) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; // Already exists. 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (extensions::ExtensionActionAPI::GetBrowserActionVisibility( 202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) service_->extension_prefs(), extension->id())) { 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddExtension(extension); 204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RemoveExtension(extension); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (type == chrome::NOTIFICATION_EXTENSION_UNINSTALLED) { 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UninstalledExtension(extension); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED) { 211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (extensions::ExtensionActionAPI::GetBrowserActionVisibility( 212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) service_->extension_prefs(), extension->id())) { 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddExtension(extension); 214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else { 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RemoveExtension(extension); 216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Received unexpected notification"; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t ExtensionToolbarModel::FindNewPositionFromLastKnownGood( 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension) { 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if we have last known good position for this extension. 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t new_index = 0; 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Loop through the ID list of known positions, to count the number of visible 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // browser action icons preceding |extension|. 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ExtensionIdList::const_iterator iter_id = last_known_positions_.begin(); 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter_id < last_known_positions_.end(); ++iter_id) { 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*iter_id) == extension->id()) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_index; // We've found the right position. 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Found an id, need to see if it is visible. 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ExtensionList::const_iterator iter_ext = toolbar_items_.begin(); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter_ext < toolbar_items_.end(); ++iter_ext) { 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*iter_ext)->id().compare(*iter_id) == 0) { 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This extension is visible, update the index value. 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++new_index; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::AddExtension(const Extension* extension) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only care about extensions with browser actions. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extensions::ExtensionActionManager::Get(service_->profile())-> 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBrowserAction(*extension)) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t new_index = -1; 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if we have a last known good position for this extension. 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator last_pos = std::find(last_known_positions_.begin(), 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->id()); 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (last_pos != last_known_positions_.end()) { 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_index = FindNewPositionFromLastKnownGood(extension); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_index != toolbar_items_.size()) { 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.insert(toolbar_items_.begin() + new_index, 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) make_scoped_refptr(extension)); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is a never before seen extension, that was added to the end. Make 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sure to reflect that. 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.push_back(extension->id()); 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_index = toolbar_items_.size() - 1; 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdatePrefs(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserActionAdded(extension, new_index)); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::RemoveExtension(const Extension* extension) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList::iterator pos = 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::find(toolbar_items_.begin(), toolbar_items_.end(), extension); 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos == toolbar_items_.end()) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.erase(pos); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserActionRemoved(extension)); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePrefs(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::UninstalledExtension(const Extension* extension) { 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove the extension id from the ordered list, if it exists (the extension 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // might not be represented in the list because it might not have an icon). 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator pos = 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::find(last_known_positions_.begin(), 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), extension->id()); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos != last_known_positions_.end()) { 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.erase(pos); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdatePrefs(); 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Combine the currently enabled extensions that have browser actions (which 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we get from the ExtensionService) with the ordering we get from the 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pref service. For robustness we use a somewhat inefficient process: 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. Create a vector of extensions sorted by their pref values. This vector may 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have holes. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Create a vector of extensions that did not have a pref value. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. Remove holes from the sorted vector and append the unsorted vector. 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::InitializeExtensionList() { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(service_->is_ready()); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_ = service_->extension_prefs()->GetToolbarOrder(); 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Populate(last_known_positions_); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions_initialized_ = true; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ModelLoaded()); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExtensionToolbarModel::Populate( 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const extensions::ExtensionIdList& positions) { 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Items that have explicit positions. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList sorted; 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sorted.resize(positions.size(), NULL); 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The items that don't have explicit positions. 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList unsorted; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionActionManager* extension_action_manager = 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionActionManager::Get(service_->profile()); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the lists. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionSet::const_iterator it = service_->extensions()->begin(); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != service_->extensions()->end(); ++it) { 3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const Extension* extension = it->get(); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_action_manager->GetBrowserAction(*extension)) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!extensions::ExtensionActionAPI::GetBrowserActionVisibility( 341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) service_->extension_prefs(), extension->id())) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 343b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionIdList::const_iterator pos = 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::find(positions.begin(), positions.end(), extension->id()); 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (pos != positions.end()) 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sorted[pos - positions.begin()] = extension; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsorted.push_back(make_scoped_refptr(extension)); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Erase current icons. 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < toolbar_items_.size(); i++) { 355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FOR_EACH_OBSERVER( 356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Observer, observers_, BrowserActionRemoved(toolbar_items_[i].get())); 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.clear(); 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Merge the lists. 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.reserve(sorted.size() + unsorted.size()); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::const_iterator iter = sorted.begin(); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != sorted.end(); ++iter) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's possible for the extension order to contain items that aren't 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually loaded on this machine. For example, when extension sync is on, 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we sync the extension order as-is but double-check with the user before 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // syncing NPAPI-containing extensions, so if one of those is not actually 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // synced, we'll get a NULL in the list. This sort of case can also happen 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if some error prevents an extension from loading. 370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (iter->get() != NULL) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.push_back(*iter); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.insert(toolbar_items_.end(), unsorted.begin(), 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsorted.end()); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inform observers. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < toolbar_items_.size(); i++) { 378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FOR_EACH_OBSERVER( 379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Observer, observers_, BrowserActionAdded(toolbar_items_[i].get(), i)); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::FillExtensionList( 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const extensions::ExtensionIdList& order) { 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.clear(); 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.reserve(order.size()); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < order.size(); ++i) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::Extension* extension = 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->GetExtensionById(order[i], false); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension) 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddExtension(extension); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::UpdatePrefs() { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!service_->extension_prefs()) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Don't observe change caused by self. 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Remove(prefs::kExtensionToolbar); 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_->extension_prefs()->SetToolbarOrder(last_known_positions_); 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Add(prefs::kExtensionToolbar, pref_change_callback_); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int original_index = 0, i = 0; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++original_index) { 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (service_->IsIncognitoEnabled((*iter)->id())) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (incognito_index == i) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_index; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionToolbarModel::OriginalIndexToIncognito(int original_index) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int incognito_index = 0, i = 0; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++i) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original_index == i) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (service_->IsIncognitoEnabled((*iter)->id())) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++incognito_index; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return incognito_index; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExtensionToolbarModel::OnExtensionToolbarPrefChange() { 433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If extensions are not ready, defer to later Populate() call. 434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!extensions_initialized_) 435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Recalculate |last_known_positions_| to be |pref_positions| followed by 438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ones that are only in |last_known_positions_|. 439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extensions::ExtensionIdList pref_positions = 440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) service_->extension_prefs()->GetToolbarOrder(); 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t pref_position_size = pref_positions.size(); 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < last_known_positions_.size(); ++i) { 443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (std::find(pref_positions.begin(), pref_positions.end(), 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_[i]) == pref_positions.end()) { 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_positions.push_back(last_known_positions_[i]); 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_.swap(pref_positions); 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Re-populate. 451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Populate(last_known_positions_); 452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (last_known_positions_.size() > pref_position_size) { 454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Need to update pref because we have extra icons. But can't call 455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // UpdatePrefs() directly within observation closure. 456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostTask( 457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ExtensionToolbarModel::UpdatePrefs, 459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 462