OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/permissions/permission_queue_controller.h" | 5 #include "chrome/browser/permissions/permission_queue_controller.h" |
6 | 6 |
7 #include "chrome/browser/chrome_notification_types.h" | 7 #include "chrome/browser/chrome_notification_types.h" |
8 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 8 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
9 #include "chrome/browser/infobars/infobar_service.h" | 9 #include "chrome/browser/infobars/infobar_service.h" |
10 #include "chrome/browser/permissions/permission_dialog_delegate.h" | |
10 #include "chrome/browser/permissions/permission_infobar_delegate.h" | 11 #include "chrome/browser/permissions/permission_infobar_delegate.h" |
11 #include "chrome/browser/permissions/permission_request.h" | 12 #include "chrome/browser/permissions/permission_request.h" |
12 #include "chrome/browser/permissions/permission_request_id.h" | 13 #include "chrome/browser/permissions/permission_request_id.h" |
13 #include "chrome/browser/permissions/permission_uma_util.h" | 14 #include "chrome/browser/permissions/permission_uma_util.h" |
14 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
15 #include "chrome/browser/tab_contents/tab_util.h" | 16 #include "chrome/browser/tab_contents/tab_util.h" |
16 #include "components/content_settings/core/browser/host_content_settings_map.h" | 17 #include "components/content_settings/core/browser/host_content_settings_map.h" |
17 #include "components/content_settings/core/common/content_settings.h" | 18 #include "components/content_settings/core/common/content_settings.h" |
18 #include "components/infobars/core/infobar.h" | 19 #include "components/infobars/core/infobar.h" |
19 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
20 #include "content/public/browser/notification_details.h" | 21 #include "content/public/browser/notification_details.h" |
21 #include "content/public/browser/notification_source.h" | 22 #include "content/public/browser/notification_source.h" |
22 #include "content/public/browser/notification_types.h" | 23 #include "content/public/browser/notification_types.h" |
23 #include "content/public/browser/web_contents.h" | 24 #include "content/public/browser/web_contents.h" |
24 #include "content/public/common/url_constants.h" | 25 #include "content/public/common/url_constants.h" |
25 | 26 |
26 namespace { | 27 namespace { |
27 | 28 |
29 content::WebContents* GetWebContents(const PermissionRequestID& id) { | |
30 return tab_util::GetWebContentsByFrameID( | |
31 id.render_process_id(), id.render_frame_id()); | |
32 } | |
33 | |
34 | |
28 InfoBarService* GetInfoBarService(const PermissionRequestID& id) { | 35 InfoBarService* GetInfoBarService(const PermissionRequestID& id) { |
29 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( | 36 content::WebContents* web_contents = GetWebContents(id); |
30 id.render_process_id(), id.render_frame_id()); | 37 return web_contents ? InfoBarService::FromWebContents(web_contents) : nullptr; |
31 return web_contents ? InfoBarService::FromWebContents(web_contents) : NULL; | |
32 } | 38 } |
33 | 39 |
34 bool ArePermissionRequestsForSameTab( | 40 bool ArePermissionRequestsForSameTab( |
35 const PermissionRequestID& request, | 41 const PermissionRequestID& request, |
36 const PermissionRequestID& other_request) { | 42 const PermissionRequestID& other_request) { |
37 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( | 43 content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( |
38 request.render_process_id(), request.render_frame_id()); | 44 request.render_process_id(), request.render_frame_id()); |
39 content::WebContents* other_web_contents = tab_util::GetWebContentsByFrameID( | 45 content::WebContents* other_web_contents = tab_util::GetWebContentsByFrameID( |
40 other_request.render_process_id(), other_request.render_frame_id()); | 46 other_request.render_process_id(), other_request.render_frame_id()); |
41 | 47 |
(...skipping 11 matching lines...) Expand all Loading... | |
53 bool user_gesture, | 59 bool user_gesture, |
54 Profile* profile, | 60 Profile* profile, |
55 const PermissionDecidedCallback& callback); | 61 const PermissionDecidedCallback& callback); |
56 ~PendingInfobarRequest(); | 62 ~PendingInfobarRequest(); |
57 | 63 |
58 bool IsForPair(const GURL& requesting_frame, | 64 bool IsForPair(const GURL& requesting_frame, |
59 const GURL& embedder) const; | 65 const GURL& embedder) const; |
60 | 66 |
61 const PermissionRequestID& id() const { return id_; } | 67 const PermissionRequestID& id() const { return id_; } |
62 const GURL& requesting_frame() const { return requesting_frame_; } | 68 const GURL& requesting_frame() const { return requesting_frame_; } |
69 bool has_gesture() const { return user_gesture_; } | |
63 bool has_infobar() const { return !!infobar_; } | 70 bool has_infobar() const { return !!infobar_; } |
64 infobars::InfoBar* infobar() { return infobar_; } | 71 infobars::InfoBar* infobar() { return infobar_; } |
65 | 72 |
66 void RunCallback(ContentSetting content_setting); | 73 void RunCallback(ContentSetting content_setting); |
67 void CreateInfoBar(PermissionQueueController* controller); | 74 void CreateInfoBar(PermissionQueueController* controller); |
68 | 75 |
69 private: | 76 private: |
70 content::PermissionType type_; | 77 content::PermissionType type_; |
71 PermissionRequestID id_; | 78 PermissionRequestID id_; |
72 GURL requesting_frame_; | 79 GURL requesting_frame_; |
(...skipping 14 matching lines...) Expand all Loading... | |
87 bool user_gesture, | 94 bool user_gesture, |
88 Profile* profile, | 95 Profile* profile, |
89 const PermissionDecidedCallback& callback) | 96 const PermissionDecidedCallback& callback) |
90 : type_(type), | 97 : type_(type), |
91 id_(id), | 98 id_(id), |
92 requesting_frame_(requesting_frame), | 99 requesting_frame_(requesting_frame), |
93 embedder_(embedder), | 100 embedder_(embedder), |
94 user_gesture_(user_gesture), | 101 user_gesture_(user_gesture), |
95 profile_(profile), | 102 profile_(profile), |
96 callback_(callback), | 103 callback_(callback), |
97 infobar_(NULL) {} | 104 infobar_(nullptr) {} |
98 | 105 |
99 PermissionQueueController::PendingInfobarRequest::~PendingInfobarRequest() { | 106 PermissionQueueController::PendingInfobarRequest::~PendingInfobarRequest() { |
100 } | 107 } |
101 | 108 |
102 bool PermissionQueueController::PendingInfobarRequest::IsForPair( | 109 bool PermissionQueueController::PendingInfobarRequest::IsForPair( |
103 const GURL& requesting_frame, | 110 const GURL& requesting_frame, |
104 const GURL& embedder) const { | 111 const GURL& embedder) const { |
105 return (requesting_frame_ == requesting_frame) && (embedder_ == embedder); | 112 return (requesting_frame_ == requesting_frame) && (embedder_ == embedder); |
106 } | 113 } |
107 | 114 |
108 void PermissionQueueController::PendingInfobarRequest::RunCallback( | 115 void PermissionQueueController::PendingInfobarRequest::RunCallback( |
109 ContentSetting content_setting) { | 116 ContentSetting content_setting) { |
110 callback_.Run(content_setting); | 117 callback_.Run(content_setting); |
111 } | 118 } |
112 | 119 |
113 void PermissionQueueController::PendingInfobarRequest::CreateInfoBar( | 120 void PermissionQueueController::PendingInfobarRequest::CreateInfoBar( |
114 PermissionQueueController* controller) { | 121 PermissionQueueController* controller) { |
115 // Controller can be Unretained because the lifetime of the infobar | 122 // Controller can be Unretained because the lifetime of the infobar |
116 // is tied to that of the queue controller. Before QueueController | 123 // is tied to that of the queue controller. Before QueueController |
117 // is destroyed, all requests will be cancelled and so all delegates | 124 // is destroyed, all requests will be cancelled and so all delegates |
118 // will be destroyed. | 125 // will be destroyed. |
119 PermissionInfoBarDelegate::PermissionSetCallback callback = base::Bind( | 126 PermissionInfoBarDelegate::PermissionSetCallback callback = base::Bind( |
120 &PermissionQueueController::OnPermissionSet, base::Unretained(controller), | 127 &PermissionQueueController::OnPermissionSet, base::Unretained(controller), |
121 id_, requesting_frame_, embedder_, user_gesture_); | 128 id_, requesting_frame_, embedder_, user_gesture_); |
122 | 129 |
123 infobar_ = PermissionInfoBarDelegate::Create(type_, GetInfoBarService(id_), | 130 if (PermissionDialogDelegate::PromptUser(user_gesture_)) { |
lshang
2016/11/01 03:47:44
I'd rename this method as ShouldPromptUser(), sinc
dominickn
2016/11/01 04:44:00
Done.
| |
124 requesting_frame_, user_gesture_, | 131 // We should show a dialog prompt instead of an infobar. Since only one |
125 profile_, callback); | 132 // dialog can be shown at a time, the Java-side owns and manages the queue |
133 // of prompts; the bookkeeping in this class will work as expected: | |
134 // i. no pending request will ever have an infobar created for it. | |
135 // ii. OnPermissionSet is still called when the user makes a decision. | |
136 PermissionDialogDelegate::Create(type_, GetWebContents(id_), | |
137 requesting_frame_, user_gesture_, profile_, | |
138 callback); | |
139 } else { | |
140 infobar_ = PermissionInfoBarDelegate::Create( | |
141 type_, GetInfoBarService(id_), requesting_frame_, user_gesture_, | |
142 profile_, callback); | |
143 } | |
126 } | 144 } |
127 | 145 |
128 PermissionQueueController::PermissionQueueController( | 146 PermissionQueueController::PermissionQueueController( |
129 Profile* profile, | 147 Profile* profile, |
130 content::PermissionType permission_type, | 148 content::PermissionType permission_type, |
131 ContentSettingsType content_settings_type) | 149 ContentSettingsType content_settings_type) |
132 : profile_(profile), | 150 : profile_(profile), |
133 permission_type_(permission_type), | 151 permission_type_(permission_type), |
134 content_settings_type_(content_settings_type), | 152 content_settings_type_(content_settings_type), |
135 in_shutdown_(false) {} | 153 in_shutdown_(false) {} |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 // Cancel this request first, then notify listeners. TODO(pkasting): Why | 232 // Cancel this request first, then notify listeners. TODO(pkasting): Why |
215 // is this order important? | 233 // is this order important? |
216 PendingInfobarRequests requests_to_notify; | 234 PendingInfobarRequests requests_to_notify; |
217 PendingInfobarRequests infobars_to_remove; | 235 PendingInfobarRequests infobars_to_remove; |
218 std::vector<PendingInfobarRequests::iterator> pending_requests_to_remove; | 236 std::vector<PendingInfobarRequests::iterator> pending_requests_to_remove; |
219 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); | 237 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); |
220 i != pending_infobar_requests_.end(); ++i) { | 238 i != pending_infobar_requests_.end(); ++i) { |
221 if (!i->IsForPair(requesting_frame, embedder)) | 239 if (!i->IsForPair(requesting_frame, embedder)) |
222 continue; | 240 continue; |
223 requests_to_notify.push_back(*i); | 241 requests_to_notify.push_back(*i); |
224 if (!i->has_infobar()) { | 242 if (!i->has_infobar() || |
225 // We haven't created an infobar yet, just record the pending request | 243 PermissionDialogDelegate::PromptUser(i->has_gesture())) { |
raymes
2016/11/01 02:56:46
Is this check strictly necessary? Won't has_infoba
dominickn
2016/11/01 03:30:59
Good point. Removed.
| |
226 // index and remove it later. | 244 // We haven't created an infobar yet, or no infobars are being created. |
245 // Record the pending request index and remove it later. | |
227 pending_requests_to_remove.push_back(i); | 246 pending_requests_to_remove.push_back(i); |
228 continue; | 247 continue; |
229 } | 248 } |
230 if (id == i->id()) { | 249 if (id == i->id()) { |
231 // The infobar that called us is i->infobar(), and its delegate is | 250 // The infobar that called us is i->infobar(), and its delegate is |
232 // currently in either Accept() or Cancel(). This means that | 251 // currently in either Accept() or Cancel(). This means that |
233 // RemoveInfoBar() will be called later on, and that will trigger a | 252 // RemoveInfoBar() will be called later on, and that will trigger a |
234 // notification we're observing. | 253 // notification we're observing. |
235 continue; | 254 continue; |
236 } | 255 } |
(...skipping 16 matching lines...) Expand all Loading... | |
253 ContentSetting content_setting = CONTENT_SETTING_DEFAULT; | 272 ContentSetting content_setting = CONTENT_SETTING_DEFAULT; |
254 if (decision == GRANTED) | 273 if (decision == GRANTED) |
255 content_setting = CONTENT_SETTING_ALLOW; | 274 content_setting = CONTENT_SETTING_ALLOW; |
256 else if (decision == DENIED) | 275 else if (decision == DENIED) |
257 content_setting = CONTENT_SETTING_BLOCK; | 276 content_setting = CONTENT_SETTING_BLOCK; |
258 else | 277 else |
259 DCHECK_EQ(DISMISSED, decision); | 278 DCHECK_EQ(DISMISSED, decision); |
260 | 279 |
261 // Send out the permission notifications. | 280 // Send out the permission notifications. |
262 for (PendingInfobarRequests::iterator i = requests_to_notify.begin(); | 281 for (PendingInfobarRequests::iterator i = requests_to_notify.begin(); |
263 i != requests_to_notify.end(); ++i) | 282 i != requests_to_notify.end(); ++i) { |
264 i->RunCallback(content_setting); | 283 i->RunCallback(content_setting); |
284 } | |
265 | 285 |
266 // Remove the pending requests in reverse order. | 286 // Remove the pending requests in reverse order. |
267 for (int i = pending_requests_to_remove.size() - 1; i >= 0; --i) | 287 for (int i = pending_requests_to_remove.size() - 1; i >= 0; --i) |
268 pending_infobar_requests_.erase(pending_requests_to_remove[i]); | 288 pending_infobar_requests_.erase(pending_requests_to_remove[i]); |
269 } | 289 } |
270 | 290 |
271 void PermissionQueueController::Observe( | 291 void PermissionQueueController::Observe( |
272 int type, | 292 int type, |
273 const content::NotificationSource& source, | 293 const content::NotificationSource& source, |
274 const content::NotificationDetails& details) { | 294 const content::NotificationDetails& details) { |
(...skipping 18 matching lines...) Expand all Loading... | |
293 return; | 313 return; |
294 } | 314 } |
295 } | 315 } |
296 } | 316 } |
297 | 317 |
298 bool PermissionQueueController::AlreadyShowingInfoBarForTab( | 318 bool PermissionQueueController::AlreadyShowingInfoBarForTab( |
299 const PermissionRequestID& id) const { | 319 const PermissionRequestID& id) const { |
300 for (PendingInfobarRequests::const_iterator i( | 320 for (PendingInfobarRequests::const_iterator i( |
301 pending_infobar_requests_.begin()); | 321 pending_infobar_requests_.begin()); |
302 i != pending_infobar_requests_.end(); ++i) { | 322 i != pending_infobar_requests_.end(); ++i) { |
303 if (ArePermissionRequestsForSameTab(i->id(), id) && i->has_infobar()) | 323 if (ArePermissionRequestsForSameTab(i->id(), id) && i->has_infobar()) |
lshang
2016/11/01 03:47:44
Should also check if already showing modal prompt
dominickn
2016/11/01 04:44:00
Hmm, that logic doesn't work, because the request
| |
304 return true; | 324 return true; |
305 } | 325 } |
306 return false; | 326 return false; |
307 } | 327 } |
308 | 328 |
309 void PermissionQueueController::ShowQueuedInfoBarForTab( | 329 void PermissionQueueController::ShowQueuedInfoBarForTab( |
310 const PermissionRequestID& id) { | 330 const PermissionRequestID& id) { |
311 DCHECK(!AlreadyShowingInfoBarForTab(id)); | 331 DCHECK(!AlreadyShowingInfoBarForTab(id)); |
312 | 332 |
313 // We can get here for example during tab shutdown, when the InfoBarService is | 333 // We can get here for example during tab shutdown, when the InfoBarService is |
314 // removing all existing infobars, thus calling back to Observe(). In this | 334 // removing all existing infobars, thus calling back to Observe(). In this |
315 // case the service still exists, and is supplied as the source of the | 335 // case the service still exists, and is supplied as the source of the |
316 // notification we observed, but is no longer accessible from its WebContents. | 336 // notification we observed, but is no longer accessible from its WebContents. |
317 // In this case we should just go ahead and cancel further infobars for this | 337 // In this case we should just go ahead and cancel further infobars for this |
318 // tab instead of trying to access the service. | 338 // tab instead of trying to access the service. |
319 // | 339 // |
320 // Similarly, if we're being destroyed, we should also avoid showing further | 340 // Similarly, if we're being destroyed, we should also avoid showing further |
321 // infobars. | 341 // infobars. |
322 InfoBarService* infobar_service = GetInfoBarService(id); | 342 InfoBarService* infobar_service = GetInfoBarService(id); |
323 if (!infobar_service || in_shutdown_) { | 343 if (!infobar_service || in_shutdown_) { |
324 ClearPendingInfobarRequestsForTab(id); | 344 ClearPendingInfobarRequestsForTab(id); |
325 return; | 345 return; |
326 } | 346 } |
327 | 347 |
328 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); | 348 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); |
329 i != pending_infobar_requests_.end(); ++i) { | 349 i != pending_infobar_requests_.end(); ++i) { |
330 if (ArePermissionRequestsForSameTab(i->id(), id) && !i->has_infobar()) { | 350 if (ArePermissionRequestsForSameTab(i->id(), id) && !i->has_infobar()) { |
331 RegisterForInfoBarNotifications(infobar_service); | 351 // When using modal permission prompts, Java controls the display queue, |
352 // so infobar notifications are not relevant. | |
353 if (!PermissionDialogDelegate::PromptUser(i->has_gesture())) | |
354 RegisterForInfoBarNotifications(infobar_service); | |
355 | |
332 i->CreateInfoBar(this); | 356 i->CreateInfoBar(this); |
333 return; | 357 return; |
334 } | 358 } |
335 } | 359 } |
336 | 360 |
337 UnregisterForInfoBarNotifications(infobar_service); | 361 UnregisterForInfoBarNotifications(infobar_service); |
338 } | 362 } |
339 | 363 |
340 void PermissionQueueController::ClearPendingInfobarRequestsForTab( | 364 void PermissionQueueController::ClearPendingInfobarRequestsForTab( |
341 const PermissionRequestID& id) { | 365 const PermissionRequestID& id) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
385 } | 409 } |
386 | 410 |
387 ContentSetting content_setting = | 411 ContentSetting content_setting = |
388 (decision == GRANTED) ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; | 412 (decision == GRANTED) ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; |
389 | 413 |
390 HostContentSettingsMapFactory::GetForProfile(profile_) | 414 HostContentSettingsMapFactory::GetForProfile(profile_) |
391 ->SetContentSettingDefaultScope( | 415 ->SetContentSettingDefaultScope( |
392 requesting_frame.GetOrigin(), embedder.GetOrigin(), | 416 requesting_frame.GetOrigin(), embedder.GetOrigin(), |
393 content_settings_type_, std::string(), content_setting); | 417 content_settings_type_, std::string(), content_setting); |
394 } | 418 } |
OLD | NEW |