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