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) 78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <string> 88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_manager.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_prefs.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/extension_toolbar_model_factory.h" 188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/feature_switch.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::ExtensionIdList; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::ExtensionList; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ExtensionToolbarModel::Observer::BrowserActionShowPopup( 358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const extensions::Extension* extension) { 368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ExtensionToolbarModel::ExtensionToolbarModel( 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Profile* profile, 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::ExtensionPrefs* extension_prefs) 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : profile_(profile), 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_(extension_prefs), 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) prefs_(profile_->GetPrefs()), 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extensions_initialized_(false), 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::Source<Profile>(profile_)); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::Source<Profile>(profile_)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::Source<Profile>(profile_)); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::Source<Profile>(profile_)); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::Source<extensions::ExtensionPrefs>(extension_prefs_)); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_icon_count_ = prefs_->GetInteger(prefs::kExtensionToolbarSize); 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Init(prefs_); 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_callback_ = 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ExtensionToolbarModel::OnExtensionToolbarPrefChange, 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)); 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Add(prefs::kExtensionToolbar, pref_change_callback_); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionToolbarModel::~ExtensionToolbarModel() { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ExtensionToolbarModel* ExtensionToolbarModel::Get(Profile* profile) { 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return ExtensionToolbarModelFactory::GetForProfile(profile); 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 75f2477e01787aa58f445919b809d89e252beef54fTorne (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, 1328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) GURL* popup_url_out, 1338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool should_grant) { 1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) content::WebContents* web_contents = NULL; 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int tab_id = 0; 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!extensions::ExtensionTabUtil::GetDefaultTab( 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser, &web_contents, &tab_id)) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionAction* browser_action = 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::ExtensionActionManager::Get(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) 1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (should_grant) { 1508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) extensions::TabHelper::FromWebContents(web_contents)-> 1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) active_tab_permission_granter()->GrantIfRequested(extension); 1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action->HasPopup(tab_id)) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_url_out) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *popup_url_out = browser_action->GetPopupUrl(tab_id); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_SHOW_POPUP; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) extensions::ExtensionActionAPI::BrowserActionExecuted( 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser->profile(), *browser_action, web_contents); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ACTION_NONE; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::SetVisibleIconCount(int count) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_icon_count_ = 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count == static_cast<int>(toolbar_items_.size()) ? -1 : count; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs_->SetInteger(prefs::kExtensionToolbarSize, visible_icon_count_); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::Observe( 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ExtensionService* extension_service = 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->extension_service(); 177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!extension_service || !extension_service->is_ready()) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSIONS_READY) { 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) InitializeExtensionList(extension_service); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = NULL; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension = content::Details<extensions::UnloadedExtensionInfo>( 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details)->extension; 189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else if (type == 190b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED) { 191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension = extension_service->GetExtensionById( 192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *content::Details<const std::string>(details).ptr(), true); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension = content::Details<const Extension>(details).ptr(); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to add the same extension twice. It may have already been 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // added by EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED below, if the user 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hides the browser action and then disables and enables the extension. 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < toolbar_items_.size(); i++) { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (toolbar_items_[i].get() == extension) 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; // Already exists. 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (extensions::ExtensionActionAPI::GetBrowserActionVisibility( 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_, extension->id())) { 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddExtension(extension); 207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RemoveExtension(extension); 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (type == chrome::NOTIFICATION_EXTENSION_UNINSTALLED) { 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UninstalledExtension(extension); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED) { 214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (extensions::ExtensionActionAPI::GetBrowserActionVisibility( 215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_, extension->id())) { 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddExtension(extension); 217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else { 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RemoveExtension(extension); 219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Received unexpected notification"; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t ExtensionToolbarModel::FindNewPositionFromLastKnownGood( 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension) { 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if we have last known good position for this extension. 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t new_index = 0; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Loop through the ID list of known positions, to count the number of visible 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // browser action icons preceding |extension|. 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ExtensionIdList::const_iterator iter_id = last_known_positions_.begin(); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter_id < last_known_positions_.end(); ++iter_id) { 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*iter_id) == extension->id()) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_index; // We've found the right position. 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Found an id, need to see if it is visible. 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ExtensionList::const_iterator iter_ext = toolbar_items_.begin(); 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter_ext < toolbar_items_.end(); ++iter_ext) { 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*iter_ext)->id().compare(*iter_id) == 0) { 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This extension is visible, update the index value. 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++new_index; 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::AddExtension(const Extension* extension) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only care about extensions with browser actions. 251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!extensions::ExtensionActionManager::Get(profile_)-> 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBrowserAction(*extension)) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t new_index = -1; 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if we have a last known good position for this extension. 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator last_pos = std::find(last_known_positions_.begin(), 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->id()); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (last_pos != last_known_positions_.end()) { 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_index = FindNewPositionFromLastKnownGood(extension); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_index != toolbar_items_.size()) { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.insert(toolbar_items_.begin() + new_index, 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) make_scoped_refptr(extension)); 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is a never before seen extension, that was added to the end. Make 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sure to reflect that. 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.push_back(extension->id()); 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_index = toolbar_items_.size() - 1; 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdatePrefs(); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserActionAdded(extension, new_index)); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::RemoveExtension(const Extension* extension) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList::iterator pos = 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::find(toolbar_items_.begin(), toolbar_items_.end(), extension); 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos == toolbar_items_.end()) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.erase(pos); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserActionRemoved(extension)); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePrefs(); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::UninstalledExtension(const Extension* extension) { 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove the extension id from the ordered list, if it exists (the extension 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // might not be represented in the list because it might not have an icon). 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator pos = 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::find(last_known_positions_.begin(), 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), extension->id()); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos != last_known_positions_.end()) { 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.erase(pos); 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdatePrefs(); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Combine the currently enabled extensions that have browser actions (which 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we get from the ExtensionService) with the ordering we get from the 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pref service. For robustness we use a somewhat inefficient process: 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. Create a vector of extensions sorted by their pref values. This vector may 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have holes. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Create a vector of extensions that did not have a pref value. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. Remove holes from the sorted vector and append the unsorted vector. 316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ExtensionToolbarModel::InitializeExtensionList(ExtensionService* service) { 317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(service->is_ready()); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) last_known_positions_ = extension_prefs_->GetToolbarOrder(); 320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Populate(last_known_positions_, service); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions_initialized_ = true; 323d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, VisibleCountChanged()); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExtensionToolbarModel::Populate( 327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const extensions::ExtensionIdList& positions, 328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ExtensionService* service) { 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Items that have explicit positions. 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList sorted; 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sorted.resize(positions.size(), NULL); 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The items that don't have explicit positions. 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList unsorted; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionActionManager* extension_action_manager = 336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::ExtensionActionManager::Get(profile_); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the lists. 339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (ExtensionSet::const_iterator it = service->extensions()->begin(); 340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it != service->extensions()->end(); ++it) { 3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const Extension* extension = it->get(); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_action_manager->GetBrowserAction(*extension)) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 344b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!extensions::ExtensionActionAPI::GetBrowserActionVisibility( 345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_, extension->id())) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionIdList::const_iterator pos = 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::find(positions.begin(), positions.end(), extension->id()); 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (pos != positions.end()) 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sorted[pos - positions.begin()] = extension; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsorted.push_back(make_scoped_refptr(extension)); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Erase current icons. 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < toolbar_items_.size(); i++) { 359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FOR_EACH_OBSERVER( 360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Observer, observers_, BrowserActionRemoved(toolbar_items_[i].get())); 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.clear(); 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Merge the lists. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.reserve(sorted.size() + unsorted.size()); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::const_iterator iter = sorted.begin(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != sorted.end(); ++iter) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's possible for the extension order to contain items that aren't 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually loaded on this machine. For example, when extension sync is on, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we sync the extension order as-is but double-check with the user before 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // syncing NPAPI-containing extensions, so if one of those is not actually 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // synced, we'll get a NULL in the list. This sort of case can also happen 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if some error prevents an extension from loading. 374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (iter->get() != NULL) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.push_back(*iter); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.insert(toolbar_items_.end(), unsorted.begin(), 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsorted.end()); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inform observers. 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < toolbar_items_.size(); i++) { 382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FOR_EACH_OBSERVER( 383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Observer, observers_, BrowserActionAdded(toolbar_items_[i].get(), i)); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::UpdatePrefs() { 388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!extension_prefs_) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Don't observe change caused by self. 392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Remove(prefs::kExtensionToolbar); 393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_->SetToolbarOrder(last_known_positions_); 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Add(prefs::kExtensionToolbar, pref_change_callback_); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int original_index = 0, i = 0; 399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ExtensionService* extension_service = 400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->extension_service(); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++original_index) { 404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (extension_util::IsIncognitoEnabled((*iter)->id(), extension_service)) { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (incognito_index == i) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_index; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionToolbarModel::OriginalIndexToIncognito(int original_index) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int incognito_index = 0, i = 0; 415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ExtensionService* extension_service = 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->extension_service(); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++i) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original_index == i) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (extension_util::IsIncognitoEnabled((*iter)->id(), extension_service)) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++incognito_index; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return incognito_index; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExtensionToolbarModel::OnExtensionToolbarPrefChange() { 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If extensions are not ready, defer to later Populate() call. 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!extensions_initialized_) 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Recalculate |last_known_positions_| to be |pref_positions| followed by 434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ones that are only in |last_known_positions_|. 435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extensions::ExtensionIdList pref_positions = 436f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_->GetToolbarOrder(); 437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t pref_position_size = pref_positions.size(); 438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < last_known_positions_.size(); ++i) { 439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (std::find(pref_positions.begin(), pref_positions.end(), 440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_[i]) == pref_positions.end()) { 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_positions.push_back(last_known_positions_[i]); 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_.swap(pref_positions); 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Re-populate. 447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Populate(last_known_positions_, 448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->extension_service()); 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (last_known_positions_.size() > pref_position_size) { 451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Need to update pref because we have extra icons. But can't call 452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // UpdatePrefs() directly within observation closure. 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostTask( 454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ExtensionToolbarModel::UpdatePrefs, 456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 4598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 4608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ExtensionToolbarModel::ShowBrowserActionPopup( 4618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const extensions::Extension* extension) { 4628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ObserverListBase<Observer>::Iterator it(observers_); 4638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Observer* obs = NULL; 4648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) while ((obs = it.GetNext()) != NULL) { 4658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Stop after first popup since it should only show in the active window. 4668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (obs->BrowserActionShowPopup(extension)) 4678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 4688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 4698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 4708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 471d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) 472d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)void ExtensionToolbarModel::EnsureVisibility( 473d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) const extensions::ExtensionIdList& extension_ids) { 474d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) if (visible_icon_count_ == -1) 475d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) return; // Already showing all. 476d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) 477d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) // Otherwise, make sure we have enough room to show all the extensions 478d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) // requested. 479d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) if (visible_icon_count_ < static_cast<int>(extension_ids.size())) { 480d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) SetVisibleIconCount(extension_ids.size()); 481d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) 482d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) // Inform observers. 483d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, VisibleCountChanged()); 484d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) } 485d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) 486d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) if (visible_icon_count_ == -1) 487d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) return; // May have been set to max by SetVisibleIconCount. 488d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) 489d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) // Guillotine's Delight: Move an orange noble to the front of the line. 490d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) for (ExtensionIdList::const_iterator it = extension_ids.begin(); 491d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) it != extension_ids.end(); ++it) { 492d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) for (ExtensionList::const_iterator extension = toolbar_items_.begin(); 493d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) extension != toolbar_items_.end(); ++extension) { 494d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) if ((*extension)->id() == (*it)) { 495d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) if (extension - toolbar_items_.begin() >= visible_icon_count_) 496d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) MoveBrowserAction(*extension, 0); 497d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) break; 498d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) } 499d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) } 500d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) } 501d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)} 502