Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(615)

Side by Side Diff: chrome/browser/extensions/sidebar_manager.cc

Issue 1152613003: Implement sidebar support for extension action popups (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move SidebarManager to ExtensionSystem and remove notifications Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698