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) 703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <algorithm> 88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <string> 98bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/message_loop/message_loop.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram_base.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 15b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_manager.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/extension_toolbar_model_factory.h" 198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/browser/extension_registry.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/pref_names.h" 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h" 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/feature_switch.h" 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/common/one_shot_event.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace extensions { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ExtensionToolbarModel::ExtensionToolbarModel(Profile* profile, 40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ExtensionPrefs* extension_prefs) 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : profile_(profile), 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_(extension_prefs), 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) prefs_(profile_->GetPrefs()), 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extensions_initialized_(false), 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) include_all_extensions_( 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FeatureSwitch::extension_action_redesign()->IsEnabled()), 47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch is_highlighting_(false), 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension_action_observer_(this), 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu extension_registry_observer_(this), 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ExtensionSystem::Get(profile_)->ready().Post( 52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) FROM_HERE, 53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::Bind(&ExtensionToolbarModel::OnReady, 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) visible_icon_count_ = prefs_->GetInteger(pref_names::kToolbarSize); 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_registrar_.Init(prefs_); 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_change_callback_ = 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ExtensionToolbarModel::OnExtensionToolbarPrefChange, 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this)); 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) pref_change_registrar_.Add(pref_names::kToolbar, pref_change_callback_); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionToolbarModel::~ExtensionToolbarModel() { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ExtensionToolbarModel* ExtensionToolbarModel::Get(Profile* profile) { 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return ExtensionToolbarModelFactory::GetForProfile(profile); 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::AddObserver(Observer* observer) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.AddObserver(observer); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::RemoveObserver(Observer* observer) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.RemoveObserver(observer); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ExtensionToolbarModel::MoveExtensionIcon(const Extension* extension, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList::iterator pos = std::find(toolbar_items_.begin(), 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.end(), extension); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pos == toolbar_items_.end()) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.erase(pos); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator pos_id; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pos_id = std::find(last_known_positions_.begin(), 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), extension->id()); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos_id != last_known_positions_.end()) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.erase(pos_id); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool inserted = false; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++i) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == index) { 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pos_id = std::find(last_known_positions_.begin(), 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), (*iter)->id()); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.insert(pos_id, extension->id()); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.insert(iter, make_scoped_refptr(extension)); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inserted = true; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!inserted) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(index, static_cast<int>(toolbar_items_.size())); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = toolbar_items_.size(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.push_back(extension->id()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER( 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Observer, observers_, ToolbarExtensionMoved(extension, index)); 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MaybeUpdateVisibilityPref(extension, index); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePrefs(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::SetVisibleIconCount(int count) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_icon_count_ = 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count == static_cast<int>(toolbar_items_.size()) ? -1 : count; 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Only set the prefs if we're not in highlight mode. Highlight mode is 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // designed to be a transitory state, and should not persist across browser 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // restarts (though it may be re-entered). 13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!is_highlighting_) { 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Additionally, if we are using the new toolbar, any icons which are in the 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // overflow menu are considered "hidden". But it so happens that the times 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // we are likely to call SetVisibleIconCount() are also those when we are 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // in flux. So wait for things to cool down before setting the prefs. 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::MessageLoop::current()->PostTask( 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FROM_HERE, 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&ExtensionToolbarModel::MaybeUpdateVisibilityPrefs, 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) prefs_->SetInteger(pref_names::kToolbarSize, visible_icon_count_); 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ExtensionToolbarModel::OnExtensionActionUpdated( 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionAction* extension_action, 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) content::WebContents* web_contents, 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) content::BrowserContext* browser_context) { 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension = 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionRegistry::Get(profile_)->enabled_extensions().GetByID( 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension_action->extension_id()); 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Notify observers if the extension exists and is in the model. 15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (extension && 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::find(toolbar_items_.begin(), 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) toolbar_items_.end(), 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension) != toolbar_items_.end()) { 15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarExtensionUpdated(extension)); 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid ExtensionToolbarModel::OnExtensionLoaded( 1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content::BrowserContext* browser_context, 1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Extension* extension) { 1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // We don't want to add the same extension twice. It may have already been 1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // added by EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED below, if the user 1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // hides the browser action and then disables and enables the extension. 1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (size_t i = 0; i < toolbar_items_.size(); i++) { 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (toolbar_items_[i].get() == extension) 1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AddExtension(extension); 1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid ExtensionToolbarModel::OnExtensionUnloaded( 1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content::BrowserContext* browser_context, 1775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Extension* extension, 1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu UnloadedExtensionInfo::Reason reason) { 1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RemoveExtension(extension); 1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtensionToolbarModel::OnExtensionUninstalled( 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const Extension* extension, 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UninstallReason reason) { 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Remove the extension id from the ordered list, if it exists (the extension 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // might not be represented in the list because it might not have an icon). 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionIdList::iterator pos = 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::find(last_known_positions_.begin(), 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) last_known_positions_.end(), extension->id()); 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (pos != last_known_positions_.end()) { 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) last_known_positions_.erase(pos); 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UpdatePrefs(); 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::Observe( 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 20203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_EQ(NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, type); 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension = 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionRegistry::Get(profile_)->GetExtensionById( 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *content::Details<const std::string>(details).ptr(), 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionRegistry::EVERYTHING); 20703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool visible = ExtensionActionAPI::GetBrowserActionVisibility( 20903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension_prefs_, extension->id()); 21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Hiding works differently with the new and old toolbars. 21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (include_all_extensions_) { 21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int new_size = 0; 21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int new_index = 0; 21403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (visible) { 21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If this action used to be hidden, we can't possible be showing all. 21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_NE(-1, visible_icon_count_); 21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Grow the bar by one and move the extension to the end of the visibles. 21803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_size = visible_icon_count_ + 1; 21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_index = new_size - 1; 22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If we're hiding one, we must be showing at least one. 22203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_NE(visible_icon_count_, 0); 22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Shrink the bar by one and move the extension to the beginning of the 22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // overflow menu. 22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_size = visible_icon_count_ == -1 ? 22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) toolbar_items_.size() - 1 : visible_icon_count_ - 1; 22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_index = new_size; 22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SetVisibleIconCount(new_size); 23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MoveExtensionIcon(extension, new_index); 23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); 23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { // Don't include all extensions. 23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (visible) 23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AddExtension(extension); 23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) else 23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) RemoveExtension(extension); 23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ExtensionToolbarModel::OnReady() { 241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); 242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) InitializeExtensionList(registry->enabled_extensions()); 243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Wait until the extension system is ready before observing any further 244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // changes so that the toolbar buttons can be shown in their stable ordering 245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // taken from prefs. 246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) extension_registry_observer_.Add(registry); 24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension_action_observer_.Add(ExtensionActionAPI::Get(profile_)); 248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) registrar_.Add( 249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) this, 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, 251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) content::Source<ExtensionPrefs>(extension_prefs_)); 252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t ExtensionToolbarModel::FindNewPositionFromLastKnownGood( 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension) { 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if we have last known good position for this extension. 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t new_index = 0; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Loop through the ID list of known positions, to count the number of visible 25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // extension icons preceding |extension|. 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ExtensionIdList::const_iterator iter_id = last_known_positions_.begin(); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter_id < last_known_positions_.end(); ++iter_id) { 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*iter_id) == extension->id()) 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_index; // We've found the right position. 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Found an id, need to see if it is visible. 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ExtensionList::const_iterator iter_ext = toolbar_items_.begin(); 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter_ext < toolbar_items_.end(); ++iter_ext) { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*iter_ext)->id().compare(*iter_id) == 0) { 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This extension is visible, update the index value. 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++new_index; 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Position not found. 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return toolbar_items_.size(); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ExtensionToolbarModel::ShouldAddExtension(const Extension* extension) { 28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionActionManager* action_manager = 28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionActionManager::Get(profile_); 28203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (include_all_extensions_) { 28303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // In this case, we don't care about the browser action visibility, because 28403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // we want to show each extension regardless. 28503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // TODO(devlin): Extension actions which are not visible should be moved to 28603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // the overflow menu by default. 28703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return action_manager->GetBrowserAction(*extension) || 28803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) action_manager->GetPageAction(*extension); 28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 29003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 29103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return action_manager->GetBrowserAction(*extension) && 29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionActionAPI::GetBrowserActionVisibility( 29303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension_prefs_, extension->id()); 29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 29503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::AddExtension(const Extension* extension) { 29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ShouldAddExtension(extension)) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t new_index = toolbar_items_.size(); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if we have a last known good position for this extension. 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIdList::iterator last_pos = std::find(last_known_positions_.begin(), 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.end(), 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->id()); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (last_pos != last_known_positions_.end()) { 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_index = FindNewPositionFromLastKnownGood(extension); 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_index != toolbar_items_.size()) { 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.insert(toolbar_items_.begin() + new_index, 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) make_scoped_refptr(extension)); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is a never before seen extension, that was added to the end. Make 316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // sure to reflect that. (|new_index| was set above.) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.push_back(make_scoped_refptr(extension)); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_known_positions_.push_back(extension->id()); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdatePrefs(); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MaybeUpdateVisibilityPref(extension, new_index); 32303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If we're currently highlighting, then even though we add a browser action 325effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // to the full list (|toolbar_items_|, there won't be another *visible* 326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // browser action, which was what the observers care about. 327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!is_highlighting_) { 32803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER( 32903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Observer, observers_, ToolbarExtensionAdded(extension, new_index)); 330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionToolbarModel::RemoveExtension(const Extension* extension) { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList::iterator pos = 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::find(toolbar_items_.begin(), toolbar_items_.end(), extension); 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos == toolbar_items_.end()) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) toolbar_items_.erase(pos); 340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If we're in highlight mode, we also have to remove the extension from 342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // the highlighted list. 343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (is_highlighting_) { 344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch pos = std::find(highlighted_items_.begin(), 345effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch highlighted_items_.end(), 346effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch extension); 347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (pos != highlighted_items_.end()) { 348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch highlighted_items_.erase(pos); 34903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER( 35003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Observer, observers_, ToolbarExtensionRemoved(extension)); 351effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If the highlighted list is now empty, we stop highlighting. 352effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (highlighted_items_.empty()) 353effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch StopHighlighting(); 354effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 355effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 35603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarExtensionRemoved(extension)); 357effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePrefs(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Combine the currently enabled extensions that have browser actions (which 363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// we get from the ExtensionRegistry) with the ordering we get from the 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pref service. For robustness we use a somewhat inefficient process: 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. Create a vector of extensions sorted by their pref values. This vector may 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have holes. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Create a vector of extensions that did not have a pref value. 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. Remove holes from the sorted vector and append the unsorted vector. 369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ExtensionToolbarModel::InitializeExtensionList( 370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const ExtensionSet& extensions) { 371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) last_known_positions_ = extension_prefs_->GetToolbarOrder(); 372010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Populate(last_known_positions_, extensions); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions_initialized_ = true; 37503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MaybeUpdateVisibilityPrefs(); 37603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 379010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ExtensionToolbarModel::Populate(const ExtensionIdList& positions, 380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const ExtensionSet& extensions) { 381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Items that have explicit positions. 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList sorted; 383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sorted.resize(positions.size(), NULL); 384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The items that don't have explicit positions. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionList unsorted; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 387effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExtensionActionManager* extension_action_manager = 388effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExtensionActionManager::Get(profile_); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the lists. 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int hidden = 0; 392010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (ExtensionSet::const_iterator it = extensions.begin(); 393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) it != extensions.end(); 394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ++it) { 3957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const Extension* extension = it->get(); 39603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ShouldAddExtension(extension)) { 39703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (extension_action_manager->GetBrowserAction(*extension)) 39803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ++hidden; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 400b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 402effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExtensionIdList::const_iterator pos = 403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::find(positions.begin(), positions.end(), extension->id()); 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (pos != positions.end()) 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sorted[pos - positions.begin()] = extension; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsorted.push_back(make_scoped_refptr(extension)); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t items_count = toolbar_items_.size(); 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < items_count; i++) { 4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension = toolbar_items_.back().get(); 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // By popping the extension here (before calling BrowserActionRemoved), 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // we will not shrink visible count by one after BrowserActionRemoved 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // calls SetVisibleCount. 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) toolbar_items_.pop_back(); 417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FOR_EACH_OBSERVER( 41803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Observer, observers_, ToolbarExtensionRemoved(extension)); 419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(toolbar_items_.empty()); 421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Merge the lists. 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.reserve(sorted.size() + unsorted.size()); 424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::const_iterator iter = sorted.begin(); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != sorted.end(); ++iter) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's possible for the extension order to contain items that aren't 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually loaded on this machine. For example, when extension sync is on, 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we sync the extension order as-is but double-check with the user before 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // syncing NPAPI-containing extensions, so if one of those is not actually 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // synced, we'll get a NULL in the list. This sort of case can also happen 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if some error prevents an extension from loading. 433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (iter->get() != NULL) { 434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) toolbar_items_.push_back(*iter); 435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FOR_EACH_OBSERVER( 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Observer, 4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci observers_, 4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ToolbarExtensionAdded(iter->get(), toolbar_items_.size() - 1)); 439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (ExtensionList::const_iterator iter = unsorted.begin(); 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter != unsorted.end(); ++iter) { 443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (iter->get() != NULL) { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_items_.push_back(*iter); 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FOR_EACH_OBSERVER( 4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Observer, 4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci observers_, 4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ToolbarExtensionAdded(iter->get(), toolbar_items_.size() - 1)); 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100( 453a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ExtensionToolbarModel.BrowserActionsPermanentlyHidden", hidden); 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("ExtensionToolbarModel.BrowserActionsCount", 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) toolbar_items_.size()); 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!toolbar_items_.empty()) { 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Visible count can be -1, meaning: 'show all'. Since UMA converts negative 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // values to 0, this would be counted as 'show none' unless we convert it to 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // max. 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("ExtensionToolbarModel.BrowserActionsVisible", 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visible_icon_count_ == -1 ? 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::HistogramBase::kSampleType_MAX : 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visible_icon_count_); 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionToolbarModel::UpdatePrefs() { 469f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!extension_prefs_) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Don't observe change caused by self. 473effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch pref_change_registrar_.Remove(pref_names::kToolbar); 474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_->SetToolbarOrder(last_known_positions_); 475effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch pref_change_registrar_.Add(pref_names::kToolbar, pref_change_callback_); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ExtensionToolbarModel::MaybeUpdateVisibilityPref( 47903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension, int index) { 48003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // We only update the visibility pref for hidden/not hidden based on the 48103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // overflow menu with the new toolbar design. 48203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (include_all_extensions_) { 48303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool visible = index < visible_icon_count_ || visible_icon_count_ == -1; 48403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (visible != ExtensionActionAPI::GetBrowserActionVisibility( 48503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension_prefs_, extension->id())) { 48603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Don't observe changes caused by ourselves. 48703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool was_registered = false; 48803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (registrar_.IsRegistered( 48903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) this, 49003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, 49103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) content::Source<ExtensionPrefs>(extension_prefs_))) { 49203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) was_registered = true; 49303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) registrar_.Remove( 49403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) this, 49503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, 49603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) content::Source<ExtensionPrefs>(extension_prefs_)); 49703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 49803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionActionAPI::SetBrowserActionVisibility( 49903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension_prefs_, extension->id(), visible); 50003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (was_registered) { 50103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) registrar_.Add(this, 50203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, 50303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) content::Source<ExtensionPrefs>(extension_prefs_)); 50403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 50503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 50603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 50703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 50803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 50903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ExtensionToolbarModel::MaybeUpdateVisibilityPrefs() { 51003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (size_t i = 0u; i < toolbar_items_.size(); ++i) 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MaybeUpdateVisibilityPref(toolbar_items_[i].get(), i); 51203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 51303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int original_index = 0, i = 0; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++original_index) { 519effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (util::IsIncognitoEnabled((*iter)->id(), profile_)) { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (incognito_index == i) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_index; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionToolbarModel::OriginalIndexToIncognito(int original_index) { 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int incognito_index = 0, i = 0; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionList::iterator iter = toolbar_items_.begin(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items_.end(); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter, ++i) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original_index == i) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 535effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (util::IsIncognitoEnabled((*iter)->id(), profile_)) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++incognito_index; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return incognito_index; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExtensionToolbarModel::OnExtensionToolbarPrefChange() { 542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If extensions are not ready, defer to later Populate() call. 543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!extensions_initialized_) 544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Recalculate |last_known_positions_| to be |pref_positions| followed by 547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ones that are only in |last_known_positions_|. 548effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExtensionIdList pref_positions = extension_prefs_->GetToolbarOrder(); 549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t pref_position_size = pref_positions.size(); 550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < last_known_positions_.size(); ++i) { 551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (std::find(pref_positions.begin(), pref_positions.end(), 552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_[i]) == pref_positions.end()) { 553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pref_positions.push_back(last_known_positions_[i]); 554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_known_positions_.swap(pref_positions); 557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Re-populate. 559f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Populate(last_known_positions_, 560010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ExtensionRegistry::Get(profile_)->enabled_extensions()); 561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (last_known_positions_.size() > pref_position_size) { 563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Need to update pref because we have extra icons. But can't call 564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // UpdatePrefs() directly within observation closure. 565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostTask( 566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&ExtensionToolbarModel::UpdatePrefs, 568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 5718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ExtensionToolbarModel::ShowExtensionActionPopup( 5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension, 5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Browser* browser, 5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool grant_active_tab) { 5768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ObserverListBase<Observer>::Iterator it(observers_); 5778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Observer* obs = NULL; 5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Look for the Observer associated with the browser. 5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This would be cleaner if we had an abstract class for the Toolbar UI 5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // (like we do for LocationBar), but sadly, we don't. 5818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) while ((obs = it.GetNext()) != NULL) { 5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (obs->GetBrowser() == browser) 5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return obs->ShowExtensionActionPopup(extension, grant_active_tab); 5848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 5868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionToolbarModel::EnsureVisibility( 589effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const ExtensionIdList& extension_ids) { 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (visible_icon_count_ == -1) 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; // Already showing all. 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Otherwise, make sure we have enough room to show all the extensions 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // requested. 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (visible_icon_count_ < static_cast<int>(extension_ids.size())) { 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetVisibleIconCount(extension_ids.size()); 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Inform observers. 59903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (visible_icon_count_ == -1) 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; // May have been set to max by SetVisibleIconCount. 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Guillotine's Delight: Move an orange noble to the front of the line. 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (ExtensionIdList::const_iterator it = extension_ids.begin(); 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != extension_ids.end(); ++it) { 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (ExtensionList::const_iterator extension = toolbar_items_.begin(); 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension != toolbar_items_.end(); ++extension) { 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((*extension)->id() == (*it)) { 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extension - toolbar_items_.begin() >= visible_icon_count_) 6121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MoveExtensionIcon(extension->get(), 0); 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 618effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 619effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool ExtensionToolbarModel::HighlightExtensions( 620effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const ExtensionIdList& extension_ids) { 621effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch highlighted_items_.clear(); 622effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 623effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (ExtensionIdList::const_iterator id = extension_ids.begin(); 624effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch id != extension_ids.end(); 625effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++id) { 626effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (ExtensionList::const_iterator extension = toolbar_items_.begin(); 627effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch extension != toolbar_items_.end(); 628effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++extension) { 629effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (*id == (*extension)->id()) 630effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch highlighted_items_.push_back(*extension); 631effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 632effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 633effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 634effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If we have any items in |highlighted_items_|, then we entered highlighting 635effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // mode. 636effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (highlighted_items_.size()) { 637effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch old_visible_icon_count_ = visible_icon_count_; 638effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch is_highlighting_ = true; 639effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (visible_icon_count_ != -1 && 640effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch visible_icon_count_ < static_cast<int>(extension_ids.size())) { 641effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SetVisibleIconCount(extension_ids.size()); 64203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); 643effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 644effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 64503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarHighlightModeChanged(true)); 646effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return true; 647effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 648effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 649effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Otherwise, we didn't enter highlighting mode (and, in fact, exited it if 650effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // we were otherwise in it). 651effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (is_highlighting_) 652effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch StopHighlighting(); 653effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 654effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 655effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 656effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ExtensionToolbarModel::StopHighlighting() { 657effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (is_highlighting_) { 658effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch highlighted_items_.clear(); 659effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch is_highlighting_ = false; 660effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (old_visible_icon_count_ != visible_icon_count_) { 661effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SetVisibleIconCount(old_visible_icon_count_); 66203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); 663effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 66403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarHighlightModeChanged(false)); 665effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 666cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 667effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 66803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ExtensionToolbarModel::SetVisibleIconCountForTest(size_t visible_icons) { 66903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SetVisibleIconCount(visible_icons); 67003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); 67103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 67203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 673effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} // namespace extensions 674