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 |