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