OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/geolocation/geolocation_infobar_queue_controller.h" | 5 #include "chrome/browser/geolocation/geolocation_infobar_queue_controller.h" |
6 | 6 |
7 #include "chrome/browser/content_settings/host_content_settings_map.h" | 7 #include "chrome/browser/content_settings/host_content_settings_map.h" |
8 #include "chrome/browser/geolocation/geolocation_confirm_infobar_delegate.h" | 8 #include "chrome/browser/geolocation/geolocation_confirm_infobar_delegate.h" |
9 #include "chrome/browser/geolocation/geolocation_confirm_infobar_delegate_factor
y.h" | 9 #include "chrome/browser/geolocation/geolocation_confirm_infobar_delegate_factor
y.h" |
10 #include "chrome/browser/infobars/infobar.h" | 10 #include "chrome/browser/infobars/infobar.h" |
11 #include "chrome/browser/infobars/infobar_tab_helper.h" | 11 #include "chrome/browser/infobars/infobar_tab_helper.h" |
12 #include "chrome/browser/prefs/pref_service.h" | 12 #include "chrome/browser/prefs/pref_service.h" |
13 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
14 #include "chrome/browser/tab_contents/tab_util.h" | 14 #include "chrome/browser/tab_contents/tab_util.h" |
15 #include "chrome/common/chrome_notification_types.h" | 15 #include "chrome/common/chrome_notification_types.h" |
16 #include "chrome/common/content_settings.h" | 16 #include "chrome/common/content_settings.h" |
17 #include "chrome/common/pref_names.h" | 17 #include "chrome/common/pref_names.h" |
18 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
19 #include "content/public/browser/notification_details.h" | 19 #include "content/public/browser/notification_details.h" |
20 #include "content/public/browser/notification_source.h" | 20 #include "content/public/browser/notification_source.h" |
21 #include "content/public/browser/notification_types.h" | 21 #include "content/public/browser/notification_types.h" |
22 #include "content/public/browser/web_contents.h" | 22 #include "content/public/browser/web_contents.h" |
23 | 23 |
24 using content::BrowserThread; | 24 |
25 using content::WebContents; | 25 // Utilities ------------------------------------------------------------------ |
| 26 |
| 27 namespace { |
| 28 |
| 29 InfoBarTabHelper* GetInfoBarHelper(const GeolocationPermissionRequestID& id) { |
| 30 content::WebContents* web_contents = |
| 31 tab_util::GetWebContentsByID(id.render_process_id(), id.render_view_id()); |
| 32 return web_contents ? InfoBarTabHelper::FromWebContents(web_contents) : NULL; |
| 33 } |
| 34 |
| 35 } |
| 36 |
26 | 37 |
27 // GeolocationInfoBarQueueController::PendingInfoBarRequest ------------------- | 38 // GeolocationInfoBarQueueController::PendingInfoBarRequest ------------------- |
28 | 39 |
29 struct GeolocationInfoBarQueueController::PendingInfoBarRequest { | 40 class GeolocationInfoBarQueueController::PendingInfoBarRequest { |
30 public: | 41 public: |
31 PendingInfoBarRequest(int render_process_id, | 42 PendingInfoBarRequest(const GeolocationPermissionRequestID& id, |
32 int render_view_id, | |
33 int bridge_id, | |
34 const GURL& requesting_frame, | 43 const GURL& requesting_frame, |
35 const GURL& embedder, | 44 const GURL& embedder, |
36 PermissionDecidedCallback callback); | 45 PermissionDecidedCallback callback); |
| 46 ~PendingInfoBarRequest(); |
37 | 47 |
38 bool IsForTab(int p_render_process_id, int p_render_view_id) const; | 48 bool IsForPair(const GURL& requesting_frame, |
39 bool IsForPair(const GURL& p_requesting_frame, | 49 const GURL& embedder) const; |
40 const GURL& p_embedder) const; | |
41 bool Equals(int p_render_process_id, | |
42 int p_render_view_id, | |
43 int p_bridge_id) const; | |
44 | 50 |
45 int render_process_id; | 51 const GeolocationPermissionRequestID& id() const { return id_; } |
46 int render_view_id; | 52 const GURL& requesting_frame() const { return requesting_frame_; } |
47 int bridge_id; | 53 bool has_infobar_delegate() const { return !!infobar_delegate_; } |
48 GURL requesting_frame; | 54 GeolocationConfirmInfoBarDelegate* infobar_delegate() { |
49 GURL embedder; | 55 return infobar_delegate_; |
50 PermissionDecidedCallback callback; | 56 } |
51 GeolocationConfirmInfoBarDelegate* infobar_delegate; | 57 |
| 58 void RunCallback(bool allowed); |
| 59 void CreateInfoBarDelegate(GeolocationInfoBarQueueController* controller, |
| 60 const std::string& display_languages); |
| 61 |
| 62 private: |
| 63 GeolocationPermissionRequestID id_; |
| 64 GURL requesting_frame_; |
| 65 GURL embedder_; |
| 66 PermissionDecidedCallback callback_; |
| 67 GeolocationConfirmInfoBarDelegate* infobar_delegate_; |
| 68 |
| 69 // Purposefully do not disable copying, as this is stored in STL containers. |
52 }; | 70 }; |
53 | 71 |
54 GeolocationInfoBarQueueController::PendingInfoBarRequest::PendingInfoBarRequest( | 72 GeolocationInfoBarQueueController::PendingInfoBarRequest::PendingInfoBarRequest( |
55 int render_process_id, | 73 const GeolocationPermissionRequestID& id, |
56 int render_view_id, | |
57 int bridge_id, | |
58 const GURL& requesting_frame, | 74 const GURL& requesting_frame, |
59 const GURL& embedder, | 75 const GURL& embedder, |
60 PermissionDecidedCallback callback) | 76 PermissionDecidedCallback callback) |
61 : render_process_id(render_process_id), | 77 : id_(id), |
62 render_view_id(render_view_id), | 78 requesting_frame_(requesting_frame), |
63 bridge_id(bridge_id), | 79 embedder_(embedder), |
64 requesting_frame(requesting_frame), | 80 callback_(callback), |
65 embedder(embedder), | 81 infobar_delegate_(NULL) { |
66 callback(callback), | |
67 infobar_delegate(NULL) { | |
68 } | 82 } |
69 | 83 |
70 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForTab( | 84 GeolocationInfoBarQueueController::PendingInfoBarRequest:: |
71 int p_render_process_id, | 85 ~PendingInfoBarRequest() { |
72 int p_render_view_id) const { | |
73 return (render_process_id == p_render_process_id) && | |
74 (render_view_id == p_render_view_id); | |
75 } | 86 } |
76 | 87 |
77 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForPair( | 88 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForPair( |
78 const GURL& p_requesting_frame, | 89 const GURL& requesting_frame, |
79 const GURL& p_embedder) const { | 90 const GURL& embedder) const { |
80 return (requesting_frame == p_requesting_frame) && (embedder == p_embedder); | 91 return (requesting_frame_ == requesting_frame) && (embedder_ == embedder); |
81 } | 92 } |
82 | 93 |
83 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::Equals( | 94 void GeolocationInfoBarQueueController::PendingInfoBarRequest::RunCallback( |
84 int p_render_process_id, | 95 bool allowed) { |
85 int p_render_view_id, | 96 callback_.Run(allowed); |
86 int p_bridge_id) const { | 97 } |
87 return IsForTab(p_render_process_id, p_render_view_id) && | 98 |
88 (bridge_id == p_bridge_id); | 99 void GeolocationInfoBarQueueController::PendingInfoBarRequest:: |
| 100 CreateInfoBarDelegate(GeolocationInfoBarQueueController* controller, |
| 101 const std::string& display_languages) { |
| 102 infobar_delegate_ = GeolocationConfirmInfoBarDelegateFactory::Create( |
| 103 GetInfoBarHelper(id_), controller, id_, requesting_frame_, |
| 104 display_languages); |
| 105 |
89 } | 106 } |
90 | 107 |
91 | 108 |
92 // GeolocationInfoBarQueueController::RequestEquals --------------------------- | |
93 | |
94 // Useful predicate for checking PendingInfoBarRequest equality. | |
95 class GeolocationInfoBarQueueController::RequestEquals | |
96 : public std::unary_function<PendingInfoBarRequest, bool> { | |
97 public: | |
98 RequestEquals(int render_process_id, int render_view_id, int bridge_id); | |
99 | |
100 bool operator()(const PendingInfoBarRequest& request) const; | |
101 | |
102 private: | |
103 int render_process_id_; | |
104 int render_view_id_; | |
105 int bridge_id_; | |
106 }; | |
107 | |
108 GeolocationInfoBarQueueController::RequestEquals::RequestEquals( | |
109 int render_process_id, | |
110 int render_view_id, | |
111 int bridge_id) | |
112 : render_process_id_(render_process_id), | |
113 render_view_id_(render_view_id), | |
114 bridge_id_(bridge_id) { | |
115 } | |
116 | |
117 bool GeolocationInfoBarQueueController::RequestEquals::operator()( | |
118 const PendingInfoBarRequest& request) const { | |
119 return request.Equals(render_process_id_, render_view_id_, bridge_id_); | |
120 } | |
121 | |
122 // GeolocationInfoBarQueueController ------------------------------------------ | 109 // GeolocationInfoBarQueueController ------------------------------------------ |
123 | 110 |
124 GeolocationInfoBarQueueController::GeolocationInfoBarQueueController( | 111 GeolocationInfoBarQueueController::GeolocationInfoBarQueueController( |
125 Profile* profile) | 112 Profile* profile) |
126 : profile_(profile) { | 113 : profile_(profile) { |
127 } | 114 } |
128 | 115 |
129 GeolocationInfoBarQueueController::~GeolocationInfoBarQueueController() { | 116 GeolocationInfoBarQueueController::~GeolocationInfoBarQueueController() { |
130 } | 117 } |
131 | 118 |
132 void GeolocationInfoBarQueueController::CreateInfoBarRequest( | 119 void GeolocationInfoBarQueueController::CreateInfoBarRequest( |
133 int render_process_id, | 120 const GeolocationPermissionRequestID& id, |
134 int render_view_id, | |
135 int bridge_id, | |
136 const GURL& requesting_frame, | 121 const GURL& requesting_frame, |
137 const GURL& embedder, | 122 const GURL& embedder, |
138 PermissionDecidedCallback callback) { | 123 PermissionDecidedCallback callback) { |
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 124 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
140 | 125 |
141 // We shouldn't get duplicate requests. | 126 // We shouldn't get duplicate requests. |
142 DCHECK(std::find_if(pending_infobar_requests_.begin(), | 127 for (PendingInfoBarRequests::const_iterator i( |
143 pending_infobar_requests_.end(), | 128 pending_infobar_requests_.begin()); |
144 RequestEquals(render_process_id, render_view_id, bridge_id)) == | 129 i != pending_infobar_requests_.end(); ++i) |
145 pending_infobar_requests_.end()); | 130 DCHECK(!i->id().Equals(id)); |
146 | 131 |
147 InfoBarTabHelper* helper = GetInfoBarHelper(render_process_id, | 132 pending_infobar_requests_.push_back(PendingInfoBarRequest( |
148 render_view_id); | 133 id, requesting_frame, embedder, callback)); |
149 if (!helper) { | 134 if (!AlreadyShowingInfoBarForTab(id)) |
150 // We won't be able to create any infobars, shortcut and remove any pending | 135 ShowQueuedInfoBarForTab(id); |
151 // requests. | |
152 ClearPendingInfoBarRequestsForTab(render_process_id, render_view_id); | |
153 return; | |
154 } | |
155 pending_infobar_requests_.push_back(PendingInfoBarRequest(render_process_id, | |
156 render_view_id, bridge_id, requesting_frame, embedder, callback)); | |
157 if (!AlreadyShowingInfoBar(render_process_id, render_view_id)) | |
158 ShowQueuedInfoBar(render_process_id, render_view_id, helper); | |
159 } | 136 } |
160 | 137 |
161 void GeolocationInfoBarQueueController::CancelInfoBarRequest( | 138 void GeolocationInfoBarQueueController::CancelInfoBarRequest( |
162 int render_process_id, | 139 const GeolocationPermissionRequestID& id) { |
163 int render_view_id, | 140 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
164 int bridge_id) { | |
165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
166 | 141 |
167 PendingInfoBarRequests::iterator i = std::find_if( | 142 for (PendingInfoBarRequests::iterator i(pending_infobar_requests_.begin()); |
168 pending_infobar_requests_.begin(), pending_infobar_requests_.end(), | 143 i != pending_infobar_requests_.end(); ++i) { |
169 RequestEquals(render_process_id, render_view_id, bridge_id)); | 144 if (i->id().Equals(id)) { |
170 // TODO(pkasting): Can this conditional become a DCHECK()? | 145 if (i->has_infobar_delegate()) |
171 if (i == pending_infobar_requests_.end()) | 146 GetInfoBarHelper(id)->RemoveInfoBar(i->infobar_delegate()); |
172 return; | 147 else |
173 InfoBarDelegate* delegate = i->infobar_delegate; | 148 pending_infobar_requests_.erase(i); |
174 if (!delegate) { | 149 return; |
175 pending_infobar_requests_.erase(i); | 150 } |
176 return; | |
177 } | 151 } |
178 InfoBarTabHelper* helper = GetInfoBarHelper(render_process_id, | |
179 render_view_id); | |
180 helper->RemoveInfoBar(delegate); | |
181 } | 152 } |
182 | 153 |
183 void GeolocationInfoBarQueueController::OnPermissionSet( | 154 void GeolocationInfoBarQueueController::OnPermissionSet( |
184 int render_process_id, | 155 const GeolocationPermissionRequestID& id, |
185 int render_view_id, | |
186 int bridge_id, | |
187 const GURL& requesting_frame, | 156 const GURL& requesting_frame, |
188 const GURL& embedder, | 157 const GURL& embedder, |
189 bool update_content_setting, | 158 bool update_content_setting, |
190 bool allowed) { | 159 bool allowed) { |
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 160 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 161 |
192 if (update_content_setting) { | 162 if (update_content_setting) { |
193 ContentSetting content_setting = | 163 ContentSetting content_setting = |
194 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; | 164 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; |
195 profile_->GetHostContentSettingsMap()->SetContentSetting( | 165 profile_->GetHostContentSettingsMap()->SetContentSetting( |
196 ContentSettingsPattern::FromURLNoWildcard(requesting_frame.GetOrigin()), | 166 ContentSettingsPattern::FromURLNoWildcard(requesting_frame.GetOrigin()), |
197 ContentSettingsPattern::FromURLNoWildcard(embedder.GetOrigin()), | 167 ContentSettingsPattern::FromURLNoWildcard(embedder.GetOrigin()), |
198 CONTENT_SETTINGS_TYPE_GEOLOCATION, | 168 CONTENT_SETTINGS_TYPE_GEOLOCATION, |
199 std::string(), | 169 std::string(), |
200 content_setting); | 170 content_setting); |
201 } | 171 } |
| 172 |
202 // Cancel this request first, then notify listeners. TODO(pkasting): Why | 173 // Cancel this request first, then notify listeners. TODO(pkasting): Why |
203 // is this order important? | 174 // is this order important? |
204 PendingInfoBarRequests requests_to_notify; | 175 PendingInfoBarRequests requests_to_notify; |
205 PendingInfoBarRequests infobars_to_remove; | 176 PendingInfoBarRequests infobars_to_remove; |
206 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); | 177 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); |
207 i != pending_infobar_requests_.end(); ) { | 178 i != pending_infobar_requests_.end(); ) { |
208 if (i->IsForPair(requesting_frame, embedder)) { | 179 if (i->IsForPair(requesting_frame, embedder)) { |
209 requests_to_notify.push_back(*i); | 180 requests_to_notify.push_back(*i); |
210 if (i->Equals(render_process_id, render_view_id, bridge_id)) { | 181 if (i->id().Equals(id)) { |
211 // The delegate that called us is i, and it's currently in either | 182 // The delegate that called us is i, and it's currently in either |
212 // Accept() or Cancel(). This means that the owning InfoBar will call | 183 // Accept() or Cancel(). This means that the owning InfoBar will call |
213 // RemoveInfoBar() later on, and that will trigger a notification we're | 184 // RemoveInfoBar() later on, and that will trigger a notification we're |
214 // observing. | 185 // observing. |
215 ++i; | 186 ++i; |
216 } else if (i->infobar_delegate) { | 187 } else if (i->has_infobar_delegate()) { |
217 // This InfoBar is for the same frame/embedder pair, but in a different | 188 // This InfoBar is for the same frame/embedder pair, but in a different |
218 // tab. We should remove it now that we've got an answer for it. | 189 // tab. We should remove it now that we've got an answer for it. |
219 infobars_to_remove.push_back(*i); | 190 infobars_to_remove.push_back(*i); |
220 ++i; | 191 ++i; |
221 } else { | 192 } else { |
222 // We haven't created an InfoBar yet, just remove the pending request. | 193 // We haven't created an InfoBar yet, just remove the pending request. |
223 i = pending_infobar_requests_.erase(i); | 194 i = pending_infobar_requests_.erase(i); |
224 } | 195 } |
225 } else { | 196 } else { |
226 ++i; | 197 ++i; |
227 } | 198 } |
228 } | 199 } |
229 | 200 |
230 // Remove all InfoBars for the same |requesting_frame| and |embedder|. | 201 // Remove all InfoBars for the same |requesting_frame| and |embedder|. |
231 for (PendingInfoBarRequests::iterator i = infobars_to_remove.begin(); | 202 for (PendingInfoBarRequests::iterator i = infobars_to_remove.begin(); |
232 i != infobars_to_remove.end(); ++i ) { | 203 i != infobars_to_remove.end(); ++i) |
233 InfoBarTabHelper* helper = GetInfoBarHelper(i->render_process_id, | 204 GetInfoBarHelper(i->id())->RemoveInfoBar(i->infobar_delegate()); |
234 i->render_view_id); | |
235 helper->RemoveInfoBar(i->infobar_delegate); | |
236 } | |
237 | 205 |
238 // Send out the permission notifications. | 206 // Send out the permission notifications. |
239 for (PendingInfoBarRequests::iterator i = requests_to_notify.begin(); | 207 for (PendingInfoBarRequests::iterator i = requests_to_notify.begin(); |
240 i != requests_to_notify.end(); ++i ) { | 208 i != requests_to_notify.end(); ++i) |
241 i->callback.Run(allowed); | 209 i->RunCallback(allowed); |
242 } | |
243 } | 210 } |
244 | 211 |
245 void GeolocationInfoBarQueueController::Observe( | 212 void GeolocationInfoBarQueueController::Observe( |
246 int type, | 213 int type, |
247 const content::NotificationSource& source, | 214 const content::NotificationSource& source, |
248 const content::NotificationDetails& details) { | 215 const content::NotificationDetails& details) { |
249 DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type); | 216 DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type); |
250 // We will receive this notification for all infobar closures, so we need to | 217 // We will receive this notification for all infobar closures, so we need to |
251 // check whether this is the geolocation infobar we're tracking. Note that the | 218 // check whether this is the geolocation infobar we're tracking. Note that the |
252 // InfoBarContainer (if any) may have received this notification before us and | 219 // InfoBarContainer (if any) may have received this notification before us and |
253 // caused the delegate to be deleted, so it's not safe to dereference the | 220 // caused the delegate to be deleted, so it's not safe to dereference the |
254 // contents of the delegate. The address of the delegate, however, is OK to | 221 // contents of the delegate. The address of the delegate, however, is OK to |
255 // use to find the PendingInfoBarRequest to remove because | 222 // use to find the PendingInfoBarRequest to remove because |
256 // pending_infobar_requests_ will not have received any new entries between | 223 // pending_infobar_requests_ will not have received any new entries between |
257 // the NotificationService's call to InfoBarContainer::Observe and this | 224 // the NotificationService's call to InfoBarContainer::Observe and this |
258 // method. | 225 // method. |
259 InfoBarDelegate* delegate = | 226 InfoBarDelegate* delegate = |
260 content::Details<InfoBarRemovedDetails>(details)->first; | 227 content::Details<InfoBarRemovedDetails>(details)->first; |
261 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); | 228 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); |
262 i != pending_infobar_requests_.end(); ++i) { | 229 i != pending_infobar_requests_.end(); ++i) { |
263 GeolocationConfirmInfoBarDelegate* confirm_delegate = i->infobar_delegate; | 230 GeolocationConfirmInfoBarDelegate* confirm_delegate = i->infobar_delegate(); |
264 if (confirm_delegate == delegate) { | 231 if (confirm_delegate == delegate) { |
265 InfoBarTabHelper* helper = | 232 GeolocationPermissionRequestID id(i->id()); |
266 content::Source<InfoBarTabHelper>(source).ptr(); | |
267 int render_process_id = i->render_process_id; | |
268 int render_view_id = i->render_view_id; | |
269 pending_infobar_requests_.erase(i); | 233 pending_infobar_requests_.erase(i); |
270 ShowQueuedInfoBar(render_process_id, render_view_id, helper); | 234 ShowQueuedInfoBarForTab(id); |
271 return; | 235 return; |
272 } | 236 } |
273 } | 237 } |
274 } | 238 } |
275 | 239 |
276 GeolocationConfirmInfoBarDelegate* | 240 bool GeolocationInfoBarQueueController::AlreadyShowingInfoBarForTab( |
277 GeolocationInfoBarQueueController::CreateInfoBarDelegate( | 241 const GeolocationPermissionRequestID& id) const { |
278 InfoBarTabHelper* infobar_helper, | 242 for (PendingInfoBarRequests::const_iterator i( |
279 GeolocationInfoBarQueueController* controller, | 243 pending_infobar_requests_.begin()); |
280 int render_process_id, | 244 i != pending_infobar_requests_.end(); ++i) { |
281 int render_view_id, | 245 if (i->id().IsForSameTabAs(id) && i->has_infobar_delegate()) |
282 int bridge_id, | 246 return true; |
283 const GURL& requesting_frame_url, | 247 } |
284 const std::string& display_languages) { | 248 return false; |
285 return GeolocationConfirmInfoBarDelegateFactory::Create( | |
286 infobar_helper, controller, render_process_id, render_view_id, bridge_id, | |
287 requesting_frame_url, display_languages); | |
288 } | 249 } |
289 | 250 |
290 void GeolocationInfoBarQueueController::ShowQueuedInfoBar( | 251 void GeolocationInfoBarQueueController::ShowQueuedInfoBarForTab( |
291 int render_process_id, | 252 const GeolocationPermissionRequestID& id) { |
292 int render_view_id, | 253 DCHECK(!AlreadyShowingInfoBarForTab(id)); |
293 InfoBarTabHelper* helper) { | 254 |
294 DCHECK(helper); | 255 InfoBarTabHelper* helper = GetInfoBarHelper(id); |
295 DCHECK(!AlreadyShowingInfoBar(render_process_id, render_view_id)); | 256 if (!helper) { |
| 257 // We can get here for example during tab shutdown, when the |
| 258 // InfoBarTabHelper is removing all existing infobars, thus calling back to |
| 259 // Observe(). In this case the helper still exists, and is supplied as the |
| 260 // source of the notification we observed, but is no longer accessible from |
| 261 // its WebContents. In this case we should just go ahead and cancel further |
| 262 // infobars for this tab instead of trying to access the helper. |
| 263 ClearPendingInfoBarRequestsForTab(id); |
| 264 return; |
| 265 } |
| 266 |
296 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); | 267 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); |
297 i != pending_infobar_requests_.end(); ++i) { | 268 i != pending_infobar_requests_.end(); ++i) { |
298 if (i->IsForTab(render_process_id, render_view_id) && | 269 if (i->id().IsForSameTabAs(id) && !i->has_infobar_delegate()) { |
299 !i->infobar_delegate) { | |
300 RegisterForInfoBarNotifications(helper); | 270 RegisterForInfoBarNotifications(helper); |
301 i->infobar_delegate = CreateInfoBarDelegate( | 271 i->CreateInfoBarDelegate( |
302 helper, this, render_process_id, | 272 this, profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); |
303 render_view_id, i->bridge_id, i->requesting_frame, | 273 helper->AddInfoBar(i->infobar_delegate()); |
304 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); | |
305 helper->AddInfoBar(i->infobar_delegate); | |
306 return; | 274 return; |
307 } | 275 } |
308 } | 276 } |
| 277 |
309 UnregisterForInfoBarNotifications(helper); | 278 UnregisterForInfoBarNotifications(helper); |
310 } | 279 } |
311 | 280 |
312 void GeolocationInfoBarQueueController::ClearPendingInfoBarRequestsForTab( | 281 void GeolocationInfoBarQueueController::ClearPendingInfoBarRequestsForTab( |
313 int render_process_id, | 282 const GeolocationPermissionRequestID& id) { |
314 int render_view_id) { | |
315 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); | 283 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); |
316 i != pending_infobar_requests_.end(); ) { | 284 i != pending_infobar_requests_.end(); ) { |
317 if (i->IsForTab(render_process_id, render_view_id)) | 285 if (i->id().IsForSameTabAs(id)) |
318 i = pending_infobar_requests_.erase(i); | 286 i = pending_infobar_requests_.erase(i); |
319 else | 287 else |
320 ++i; | 288 ++i; |
321 } | 289 } |
322 } | 290 } |
323 | 291 |
324 InfoBarTabHelper* GeolocationInfoBarQueueController::GetInfoBarHelper( | |
325 int render_process_id, | |
326 int render_view_id) { | |
327 WebContents* web_contents = | |
328 tab_util::GetWebContentsByID(render_process_id, render_view_id); | |
329 return web_contents ? InfoBarTabHelper::FromWebContents(web_contents) : NULL; | |
330 } | |
331 | |
332 bool GeolocationInfoBarQueueController::AlreadyShowingInfoBar( | |
333 int render_process_id, | |
334 int render_view_id) { | |
335 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); | |
336 i != pending_infobar_requests_.end(); ++i) { | |
337 if (i->IsForTab(render_process_id, render_view_id) && i->infobar_delegate) | |
338 return true; | |
339 } | |
340 return false; | |
341 } | |
342 | |
343 void GeolocationInfoBarQueueController::RegisterForInfoBarNotifications( | 292 void GeolocationInfoBarQueueController::RegisterForInfoBarNotifications( |
344 InfoBarTabHelper* helper) { | 293 InfoBarTabHelper* helper) { |
345 if (!registrar_.IsRegistered( | 294 if (!registrar_.IsRegistered( |
346 this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, | 295 this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, |
347 content::Source<InfoBarTabHelper>(helper))) { | 296 content::Source<InfoBarTabHelper>(helper))) { |
348 registrar_.Add(this, | 297 registrar_.Add(this, |
349 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, | 298 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, |
350 content::Source<InfoBarTabHelper>(helper)); | 299 content::Source<InfoBarTabHelper>(helper)); |
351 } | 300 } |
352 } | 301 } |
353 | 302 |
354 void GeolocationInfoBarQueueController::UnregisterForInfoBarNotifications( | 303 void GeolocationInfoBarQueueController::UnregisterForInfoBarNotifications( |
355 InfoBarTabHelper* helper) { | 304 InfoBarTabHelper* helper) { |
356 if (registrar_.IsRegistered( | 305 if (registrar_.IsRegistered( |
357 this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, | 306 this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, |
358 content::Source<InfoBarTabHelper>(helper))) { | 307 content::Source<InfoBarTabHelper>(helper))) { |
359 registrar_.Remove(this, | 308 registrar_.Remove(this, |
360 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, | 309 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, |
361 content::Source<InfoBarTabHelper>(helper)); | 310 content::Source<InfoBarTabHelper>(helper)); |
362 } | 311 } |
363 } | 312 } |
OLD | NEW |