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

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

Powered by Google App Engine
This is Rietveld 408576698