OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2015 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/extensions/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/chrome_notification_types.h" | |
12 #include "chrome/browser/extensions/extension_service.h" | |
13 #include "chrome/browser/extensions/sidebar_container.h" | |
14 #include "chrome/browser/extensions/sidebar_manager_observer.h" | |
15 #include "content/public/browser/notification_service.h" | |
16 #include "content/public/browser/web_contents.h" | |
17 #include "extensions/browser/extension_system.h" | |
18 #include "extensions/common/switches.h" | |
19 #include "url/gurl.h" | |
20 | |
21 using content::BrowserContext; | |
22 using content::WebContents; | |
23 | |
24 namespace extensions { | |
25 struct SidebarManager::SidebarStateForTab { | |
26 // Sidebars linked to this tab. | |
27 ContentIdToSidebarContainerMap content_id_to_sidebar_container; | |
Devlin
2015/06/04 18:00:14
I don't think we should support multiple sidebars
| |
28 // Content id of the currently active (expanded and visible) sidebar. | |
29 std::string active_content_id; | |
30 }; | |
31 | |
32 // static | |
33 SidebarManager* SidebarManager::GetFromContext(BrowserContext* context) { | |
34 return ExtensionSystem::Get(context)->sidebar_manager(); | |
35 } | |
36 | |
37 SidebarManager::SidebarManager() { | |
38 } | |
39 | |
40 SidebarContainer* SidebarManager::GetActiveSidebarContainerFor( | |
41 content::WebContents* tab) { | |
42 TabToSidebarContainerMap::iterator it = tab_to_sidebar_container_.find(tab); | |
43 if (it == tab_to_sidebar_container_.end()) | |
44 return NULL; | |
45 if (it->second.active_content_id.empty()) | |
46 return NULL; | |
47 ContentIdToSidebarContainerMap::iterator container_it = | |
48 it->second.content_id_to_sidebar_container.find( | |
49 it->second.active_content_id); | |
50 DCHECK(container_it != it->second.content_id_to_sidebar_container.end()); | |
51 return container_it->second; | |
52 } | |
53 | |
54 SidebarContainer* SidebarManager::MigrateSidebarTo(WebContents* tab) { | |
55 if (tab_to_sidebar_container_.empty()) | |
56 return NULL; | |
57 SidebarContainer* container = | |
58 GetActiveSidebarContainerFor(tab_to_sidebar_container_.begin()->first); | |
59 if (container) | |
60 return NULL; | |
61 | |
62 return container; | |
63 } | |
64 | |
65 SidebarContainer* SidebarManager::GetSidebarContainerFor( | |
66 WebContents* tab, | |
67 const std::string& content_id) { | |
68 DCHECK(!content_id.empty()); | |
69 TabToSidebarContainerMap::iterator it = tab_to_sidebar_container_.find(tab); | |
70 if (it == tab_to_sidebar_container_.end()) | |
71 return NULL; | |
72 ContentIdToSidebarContainerMap::iterator container_it = | |
73 it->second.content_id_to_sidebar_container.find(content_id); | |
74 if (container_it == it->second.content_id_to_sidebar_container.end()) | |
75 return NULL; | |
76 return container_it->second; | |
77 } | |
78 | |
79 content::WebContents* SidebarManager::GetSidebarTabContents( | |
80 content::WebContents* tab, | |
81 const std::string& content_id) { | |
82 DCHECK(!content_id.empty()); | |
83 SidebarContainer* container = GetSidebarContainerFor(tab, content_id); | |
84 if (!container) | |
85 return NULL; | |
86 return container->host_contents(); | |
87 } | |
88 | |
89 void SidebarManager::NotifyStateChanges( | |
90 content::WebContents* was_active_sidebar_contents, | |
91 content::WebContents* active_sidebar_contents) { | |
92 if (was_active_sidebar_contents == active_sidebar_contents) | |
93 return; | |
94 | |
95 SidebarContainer* was_active_container = | |
96 was_active_sidebar_contents == NULL | |
Devlin
2015/06/04 18:00:14
nit (cl-wide): Prefer nullptr over NULL now.
| |
97 ? NULL | |
98 : FindSidebarContainerFor(was_active_sidebar_contents); | |
99 SidebarContainer* active_container = | |
100 active_sidebar_contents == NULL | |
101 ? NULL | |
102 : FindSidebarContainerFor(active_sidebar_contents); | |
103 | |
104 content::WebContents* old_tab = was_active_container == NULL | |
105 ? NULL | |
106 : was_active_container->web_contents(); | |
107 content::WebContents* new_tab = | |
108 active_container == NULL ? NULL : active_container->web_contents(); | |
109 const std::string& old_content_id = | |
110 was_active_container == NULL ? "" : was_active_container->extension_id(); | |
111 const std::string& new_content_id = | |
112 active_container == NULL ? "" : active_container->extension_id(); | |
113 | |
114 FOR_EACH_OBSERVER( | |
115 SidebarManagerObserver, observer_list_, | |
116 OnSidebarSwitched(old_tab, old_content_id, new_tab, new_content_id)); | |
117 } | |
118 | |
119 void SidebarManager::ShowSidebar(content::WebContents* tab, | |
120 const std::string& content_id, | |
121 const GURL& url, | |
122 Browser* browser) { | |
123 DCHECK(!content_id.empty()); | |
124 SidebarContainer* container = GetSidebarContainerFor(tab, content_id); | |
125 if (!container) { | |
126 container = new SidebarContainer(browser, tab, url); | |
127 RegisterSidebarContainerFor(tab, container); | |
128 } | |
129 | |
130 container->Show(); | |
131 ExpandSidebar(tab, content_id); | |
132 | |
133 FOR_EACH_OBSERVER(SidebarManagerObserver, observer_list_, | |
134 OnSidebarShown(tab, content_id)); | |
135 } | |
136 | |
137 void SidebarManager::ExpandSidebar(content::WebContents* tab, | |
138 const std::string& content_id) { | |
139 DCHECK(!content_id.empty()); | |
140 TabToSidebarContainerMap::iterator it = tab_to_sidebar_container_.find(tab); | |
141 if (it == tab_to_sidebar_container_.end()) | |
142 return; | |
143 // If it's already active, bail out. | |
144 if (it->second.active_content_id == content_id) | |
145 return; | |
146 | |
147 SidebarContainer* container = GetSidebarContainerFor(tab, content_id); | |
148 DCHECK(container); | |
149 if (!container) | |
150 return; | |
151 it->second.active_content_id = content_id; | |
152 | |
153 container->Expand(); | |
154 } | |
155 | |
156 void SidebarManager::CollapseSidebar(content::WebContents* tab, | |
157 const std::string& content_id) { | |
158 DCHECK(!content_id.empty()); | |
159 TabToSidebarContainerMap::iterator it = tab_to_sidebar_container_.find(tab); | |
160 if (it == tab_to_sidebar_container_.end()) | |
161 return; | |
162 // If it's not the one active now, bail out. | |
163 if (it->second.active_content_id != content_id) | |
164 return; | |
165 | |
166 SidebarContainer* container = GetSidebarContainerFor(tab, content_id); | |
167 DCHECK(container); | |
168 if (!container) | |
169 return; | |
170 it->second.active_content_id.clear(); | |
171 } | |
172 | |
173 void SidebarManager::HideSidebar(WebContents* tab, | |
174 const std::string& content_id) { | |
175 DCHECK(!content_id.empty()); | |
176 TabToSidebarContainerMap::iterator it = tab_to_sidebar_container_.find(tab); | |
177 if (it == tab_to_sidebar_container_.end()) | |
178 return; | |
179 if (it->second.active_content_id == content_id) | |
180 it->second.active_content_id.clear(); | |
181 | |
182 SidebarContainer* container = GetSidebarContainerFor(tab, content_id); | |
183 DCHECK(container); | |
184 CollapseSidebar(tab, content_id); | |
185 UnregisterSidebarContainerFor(tab, content_id); | |
186 | |
187 FOR_EACH_OBSERVER(SidebarManagerObserver, observer_list_, | |
188 OnSidebarHidden(tab, content_id)); | |
189 } | |
190 | |
191 void SidebarManager::NavigateSidebar(content::WebContents* tab, | |
Devlin
2015/06/04 18:00:14
Certain methods here (like this one) seem to belon
| |
192 const std::string& content_id, | |
193 const GURL& url) { | |
194 DCHECK(!content_id.empty()); | |
195 SidebarContainer* container = GetSidebarContainerFor(tab, content_id); | |
196 if (!container) | |
197 return; | |
198 | |
199 container->Navigate(url); | |
200 } | |
201 | |
202 SidebarManager::~SidebarManager() { | |
203 DCHECK(tab_to_sidebar_container_.empty()); | |
204 DCHECK(sidebar_container_to_tab_.empty()); | |
205 } | |
206 | |
207 void SidebarManager::Observe(int type, | |
208 const content::NotificationSource& source, | |
209 const content::NotificationDetails& details) { | |
210 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { | |
211 HideAllSidebars(content::Source<WebContents>(source).ptr()); | |
212 } else { | |
213 NOTREACHED() << "Got a notification we didn't register for!"; | |
214 } | |
215 } | |
216 | |
217 void SidebarManager::HideAllSidebars(WebContents* tab) { | |
218 TabToSidebarContainerMap::iterator tab_it = | |
219 tab_to_sidebar_container_.find(tab); | |
220 if (tab_it == tab_to_sidebar_container_.end()) | |
221 return; | |
222 const ContentIdToSidebarContainerMap& containers = | |
223 tab_it->second.content_id_to_sidebar_container; | |
224 | |
225 std::vector<std::string> content_ids; | |
226 for (ContentIdToSidebarContainerMap::const_iterator it = containers.begin(); | |
227 it != containers.end(); ++it) { | |
228 content_ids.push_back(it->first); | |
229 } | |
230 | |
231 for (std::vector<std::string>::iterator it = content_ids.begin(); | |
232 it != content_ids.end(); ++it) { | |
233 HideSidebar(tab, *it); | |
234 } | |
235 } | |
236 | |
237 SidebarContainer* SidebarManager::FindSidebarContainerFor( | |
238 content::WebContents* sidebar_contents) { | |
239 for (SidebarContainerToTabMap::iterator it = | |
240 sidebar_container_to_tab_.begin(); | |
241 it != sidebar_container_to_tab_.end(); ++it) { | |
242 if (sidebar_contents == it->first->host_contents()) | |
243 return it->first; | |
244 } | |
245 return NULL; | |
246 } | |
247 | |
248 void SidebarManager::RegisterSidebarContainerFor(WebContents* tab, | |
249 SidebarContainer* container) { | |
250 DCHECK(!GetSidebarContainerFor(tab, container->extension_id())); | |
251 | |
252 // If it's a first sidebar for this tab, register destroy notification. | |
253 if (tab_to_sidebar_container_.find(tab) == tab_to_sidebar_container_.end()) { | |
254 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
255 content::Source<WebContents>(tab)); | |
256 } | |
257 | |
258 BindSidebarContainer(tab, container); | |
259 } | |
260 | |
261 void SidebarManager::UnregisterSidebarContainerFor( | |
262 WebContents* tab, | |
263 const std::string& content_id) { | |
264 SidebarContainer* container = GetSidebarContainerFor(tab, content_id); | |
265 DCHECK(container); | |
266 if (!container) | |
267 return; | |
268 | |
269 UnbindSidebarContainer(tab, container); | |
270 | |
271 // If there's no more sidebars linked to this tab, unsubscribe. | |
272 if (tab_to_sidebar_container_.find(tab) == tab_to_sidebar_container_.end()) { | |
273 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
274 content::Source<WebContents>(tab)); | |
275 } | |
276 | |
277 // Destroy sidebar container. | |
278 delete container; | |
279 } | |
280 | |
281 void SidebarManager::BindSidebarContainer(WebContents* tab, | |
282 SidebarContainer* container) { | |
283 const std::string& content_id = container->extension_id(); | |
284 | |
285 DCHECK(GetSidebarContainerFor(tab, content_id) == NULL); | |
286 DCHECK(sidebar_container_to_tab_.find(container) == | |
287 sidebar_container_to_tab_.end()); | |
288 | |
289 tab_to_sidebar_container_[tab].content_id_to_sidebar_container[content_id] = | |
290 container; | |
291 sidebar_container_to_tab_[container] = tab; | |
292 } | |
293 | |
294 void SidebarManager::UnbindSidebarContainer(WebContents* tab, | |
295 SidebarContainer* container) { | |
296 const std::string& content_id = container->extension_id(); | |
297 | |
298 DCHECK(GetSidebarContainerFor(tab, content_id) == container); | |
299 DCHECK(sidebar_container_to_tab_.find(container)->second == tab); | |
300 DCHECK(tab_to_sidebar_container_[tab].active_content_id != content_id); | |
301 | |
302 tab_to_sidebar_container_[tab].content_id_to_sidebar_container.erase( | |
303 content_id); | |
304 if (tab_to_sidebar_container_[tab].content_id_to_sidebar_container.empty()) | |
305 tab_to_sidebar_container_.erase(tab); | |
306 sidebar_container_to_tab_.erase(container); | |
307 } | |
308 | |
309 void SidebarManager::AddObserver(SidebarManagerObserver* observer) { | |
310 observer_list_.AddObserver(observer); | |
311 } | |
312 | |
313 void SidebarManager::RemoveObserver(SidebarManagerObserver* observer) { | |
314 observer_list_.RemoveObserver(observer); | |
315 } | |
316 | |
317 } // namespace extensions | |
OLD | NEW |