sidebar_manager.cc revision bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/sidebar/sidebar_manager.h" 6 7#include <vector> 8 9#include "base/command_line.h" 10#include "chrome/browser/browser_process.h" 11#include "chrome/browser/extensions/extension_sidebar_api.h" 12#include "chrome/browser/prefs/pref_service.h" 13#include "chrome/browser/profile.h" 14#include "chrome/browser/tab_contents/tab_contents.h" 15#include "chrome/browser/sidebar/sidebar_container.h" 16#include "chrome/common/chrome_switches.h" 17#include "chrome/common/notification_service.h" 18#include "chrome/common/pref_names.h" 19#include "googleurl/src/gurl.h" 20 21// static 22SidebarManager* SidebarManager::GetInstance() { 23 return g_browser_process->sidebar_manager(); 24} 25 26// static 27bool SidebarManager::IsSidebarAllowed() { 28 return CommandLine::ForCurrentProcess()->HasSwitch( 29 switches::kEnableExperimentalExtensionApis); 30} 31 32SidebarManager::SidebarManager() { 33} 34 35SidebarContainer* SidebarManager::GetActiveSidebarContainerFor( 36 TabContents* tab) { 37 TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab); 38 if (it == tab_to_sidebar_host_.end()) 39 return NULL; 40 if (it->second.active_content_id.empty()) 41 return NULL; 42 ContentIdToSidebarHostMap::iterator host_it = 43 it->second.content_id_to_sidebar_host.find(it->second.active_content_id); 44 DCHECK(host_it != it->second.content_id_to_sidebar_host.end()); 45 return host_it->second; 46} 47 48SidebarContainer* SidebarManager::GetSidebarContainerFor( 49 TabContents* tab, const std::string& content_id) { 50 DCHECK(!content_id.empty()); 51 TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab); 52 if (it == tab_to_sidebar_host_.end()) 53 return NULL; 54 ContentIdToSidebarHostMap::iterator host_it = 55 it->second.content_id_to_sidebar_host.find(content_id); 56 if (host_it == it->second.content_id_to_sidebar_host.end()) 57 return NULL; 58 return host_it->second; 59} 60 61TabContents* SidebarManager::GetSidebarTabContents( 62 TabContents* tab, const std::string& content_id) { 63 DCHECK(!content_id.empty()); 64 SidebarContainer* sidebar_host = GetSidebarContainerFor(tab, content_id); 65 if (!sidebar_host) 66 return NULL; 67 return sidebar_host->sidebar_contents(); 68} 69 70void SidebarManager::NotifyStateChanges( 71 TabContents* was_active_sidebar_contents, 72 TabContents* active_sidebar_contents) { 73 if (was_active_sidebar_contents == active_sidebar_contents) 74 return; 75 76 SidebarContainer* was_active_host = 77 was_active_sidebar_contents == NULL ? NULL : 78 FindSidebarContainerFor(was_active_sidebar_contents); 79 SidebarContainer* active_host = 80 active_sidebar_contents == NULL ? NULL : 81 FindSidebarContainerFor(active_sidebar_contents); 82 83 if (was_active_host != NULL) { 84 ExtensionSidebarEventRouter::OnStateChanged( 85 was_active_sidebar_contents->profile(), 86 was_active_host->tab_contents(), was_active_host->content_id(), 87 extension_sidebar_constants::kShownState); 88 } 89 90 if (active_host != NULL) { 91 ExtensionSidebarEventRouter::OnStateChanged( 92 active_sidebar_contents->profile(), 93 active_host->tab_contents(), active_host->content_id(), 94 extension_sidebar_constants::kActiveState); 95 } 96} 97 98void SidebarManager::ShowSidebar(TabContents* tab, 99 const std::string& content_id) { 100 DCHECK(!content_id.empty()); 101 SidebarContainer* host = GetSidebarContainerFor(tab, content_id); 102 if (!host) { 103 host = new SidebarContainer(tab, content_id, this); 104 RegisterSidebarContainerFor(tab, host); 105 } 106 107 host->Show(); 108 109 ExtensionSidebarEventRouter::OnStateChanged( 110 tab->profile(), tab, content_id, 111 extension_sidebar_constants::kShownState); 112} 113 114void SidebarManager::ExpandSidebar(TabContents* tab, 115 const std::string& content_id) { 116 DCHECK(!content_id.empty()); 117 TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab); 118 if (it == tab_to_sidebar_host_.end()) 119 return; 120 // If it's already active, bail out. 121 if (it->second.active_content_id == content_id) 122 return; 123 124 SidebarContainer* host = GetSidebarContainerFor(tab, content_id); 125 DCHECK(host); 126 if (!host) 127 return; 128 it->second.active_content_id = content_id; 129 130 host->Expand(); 131} 132 133void SidebarManager::CollapseSidebar(TabContents* tab, 134 const std::string& content_id) { 135 DCHECK(!content_id.empty()); 136 TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab); 137 if (it == tab_to_sidebar_host_.end()) 138 return; 139 // If it's not the one active now, bail out. 140 if (it->second.active_content_id != content_id) 141 return; 142 143 SidebarContainer* host = GetSidebarContainerFor(tab, content_id); 144 DCHECK(host); 145 if (!host) 146 return; 147 it->second.active_content_id.clear(); 148 149 host->Collapse(); 150} 151 152void SidebarManager::HideSidebar(TabContents* tab, 153 const std::string& content_id) { 154 DCHECK(!content_id.empty()); 155 TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab); 156 if (it == tab_to_sidebar_host_.end()) 157 return; 158 if (it->second.active_content_id == content_id) 159 it->second.active_content_id.clear(); 160 161 SidebarContainer* host = GetSidebarContainerFor(tab, content_id); 162 DCHECK(host); 163 164 UnregisterSidebarContainerFor(tab, content_id); 165 166 ExtensionSidebarEventRouter::OnStateChanged( 167 tab->profile(), tab, content_id, 168 extension_sidebar_constants::kHiddenState); 169} 170 171void SidebarManager::NavigateSidebar(TabContents* tab, 172 const std::string& content_id, 173 const GURL& url) { 174 DCHECK(!content_id.empty()); 175 SidebarContainer* host = GetSidebarContainerFor(tab, content_id); 176 if (!host) 177 return; 178 179 host->Navigate(url); 180} 181 182void SidebarManager::SetSidebarBadgeText( 183 TabContents* tab, const std::string& content_id, 184 const string16& badge_text) { 185 SidebarContainer* host = GetSidebarContainerFor(tab, content_id); 186 if (!host) 187 return; 188 host->SetBadgeText(badge_text); 189} 190 191void SidebarManager::SetSidebarIcon( 192 TabContents* tab, const std::string& content_id, 193 const SkBitmap& bitmap) { 194 SidebarContainer* host = GetSidebarContainerFor(tab, content_id); 195 if (!host) 196 return; 197 host->SetIcon(bitmap); 198} 199 200void SidebarManager::SetSidebarTitle( 201 TabContents* tab, const std::string& content_id, 202 const string16& title) { 203 SidebarContainer* host = GetSidebarContainerFor(tab, content_id); 204 if (!host) 205 return; 206 host->SetTitle(title); 207} 208 209SidebarManager::~SidebarManager() { 210 DCHECK(tab_to_sidebar_host_.empty()); 211 DCHECK(sidebar_host_to_tab_.empty()); 212} 213 214void SidebarManager::Observe(NotificationType type, 215 const NotificationSource& source, 216 const NotificationDetails& details) { 217 if (type == NotificationType::TAB_CONTENTS_DESTROYED) { 218 HideAllSidebars(Source<TabContents>(source).ptr()); 219 } else { 220 NOTREACHED() << "Got a notification we didn't register for!"; 221 } 222} 223 224void SidebarManager::UpdateSidebar(SidebarContainer* host) { 225 NotificationService::current()->Notify( 226 NotificationType::SIDEBAR_CHANGED, 227 Source<SidebarManager>(this), 228 Details<SidebarContainer>(host)); 229} 230 231void SidebarManager::HideAllSidebars(TabContents* tab) { 232 TabToSidebarHostMap::iterator tab_it = tab_to_sidebar_host_.find(tab); 233 if (tab_it == tab_to_sidebar_host_.end()) 234 return; 235 const ContentIdToSidebarHostMap& hosts = 236 tab_it->second.content_id_to_sidebar_host; 237 238 std::vector<std::string> content_ids; 239 for (ContentIdToSidebarHostMap::const_iterator it = hosts.begin(); 240 it != hosts.end(); ++it) { 241 content_ids.push_back(it->first); 242 } 243 244 for (std::vector<std::string>::iterator it = content_ids.begin(); 245 it != content_ids.end(); ++it) { 246 HideSidebar(tab, *it); 247 } 248} 249 250SidebarContainer* SidebarManager::FindSidebarContainerFor( 251 TabContents* sidebar_contents) { 252 for (SidebarHostToTabMap::iterator it = sidebar_host_to_tab_.begin(); 253 it != sidebar_host_to_tab_.end(); 254 ++it) { 255 if (sidebar_contents == it->first->sidebar_contents()) 256 return it->first; 257 } 258 return NULL; 259} 260 261void SidebarManager::RegisterSidebarContainerFor( 262 TabContents* tab, SidebarContainer* sidebar_host) { 263 DCHECK(!GetSidebarContainerFor(tab, sidebar_host->content_id())); 264 265 // If it's a first sidebar for this tab, register destroy notification. 266 if (tab_to_sidebar_host_.find(tab) == tab_to_sidebar_host_.end()) { 267 registrar_.Add(this, 268 NotificationType::TAB_CONTENTS_DESTROYED, 269 Source<TabContents>(tab)); 270 } 271 272 BindSidebarHost(tab, sidebar_host); 273} 274 275void SidebarManager::UnregisterSidebarContainerFor( 276 TabContents* tab, const std::string& content_id) { 277 SidebarContainer* host = GetSidebarContainerFor(tab, content_id); 278 DCHECK(host); 279 if (!host) 280 return; 281 282 UnbindSidebarHost(tab, host); 283 284 // If there's no more sidebars linked to this tab, unsubscribe. 285 if (tab_to_sidebar_host_.find(tab) == tab_to_sidebar_host_.end()) { 286 registrar_.Remove(this, 287 NotificationType::TAB_CONTENTS_DESTROYED, 288 Source<TabContents>(tab)); 289 } 290 291 // Issue tab closing event post unbound. 292 host->SidebarClosing(); 293 // Destroy sidebar container. 294 delete host; 295} 296 297void SidebarManager::BindSidebarHost(TabContents* tab, 298 SidebarContainer* sidebar_host) { 299 const std::string& content_id = sidebar_host->content_id(); 300 301 DCHECK(GetSidebarContainerFor(tab, content_id) == NULL); 302 DCHECK(sidebar_host_to_tab_.find(sidebar_host) == 303 sidebar_host_to_tab_.end()); 304 305 tab_to_sidebar_host_[tab].content_id_to_sidebar_host[content_id] = 306 sidebar_host; 307 sidebar_host_to_tab_[sidebar_host] = tab; 308} 309 310void SidebarManager::UnbindSidebarHost(TabContents* tab, 311 SidebarContainer* sidebar_host) { 312 const std::string& content_id = sidebar_host->content_id(); 313 314 DCHECK(GetSidebarContainerFor(tab, content_id) == sidebar_host); 315 DCHECK(sidebar_host_to_tab_.find(sidebar_host)->second == tab); 316 DCHECK(tab_to_sidebar_host_[tab].active_content_id != content_id); 317 318 tab_to_sidebar_host_[tab].content_id_to_sidebar_host.erase(content_id); 319 if (tab_to_sidebar_host_[tab].content_id_to_sidebar_host.empty()) 320 tab_to_sidebar_host_.erase(tab); 321 sidebar_host_to_tab_.erase(sidebar_host); 322} 323