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_; } |
| 71 bool has_dialog() const { return has_dialog_; } |
64 infobars::InfoBar* infobar() { return infobar_; } | 72 infobars::InfoBar* infobar() { return infobar_; } |
65 | 73 |
66 void RunCallback(ContentSetting content_setting); | 74 void RunCallback(ContentSetting content_setting); |
67 void CreateInfoBar(PermissionQueueController* controller); | 75 void CreatePrompt(PermissionQueueController* controller, bool show_dialog); |
68 | 76 |
69 private: | 77 private: |
70 content::PermissionType type_; | 78 content::PermissionType type_; |
71 PermissionRequestID id_; | 79 PermissionRequestID id_; |
72 GURL requesting_frame_; | 80 GURL requesting_frame_; |
73 GURL embedder_; | 81 GURL embedder_; |
74 bool user_gesture_; | 82 bool user_gesture_; |
75 Profile* profile_; | 83 Profile* profile_; |
76 PermissionDecidedCallback callback_; | 84 PermissionDecidedCallback callback_; |
77 infobars::InfoBar* infobar_; | 85 infobars::InfoBar* infobar_; |
| 86 bool has_dialog_; |
78 | 87 |
79 // Purposefully do not disable copying, as this is stored in STL containers. | 88 // Purposefully do not disable copying, as this is stored in STL containers. |
80 }; | 89 }; |
81 | 90 |
82 PermissionQueueController::PendingInfobarRequest::PendingInfobarRequest( | 91 PermissionQueueController::PendingInfobarRequest::PendingInfobarRequest( |
83 content::PermissionType type, | 92 content::PermissionType type, |
84 const PermissionRequestID& id, | 93 const PermissionRequestID& id, |
85 const GURL& requesting_frame, | 94 const GURL& requesting_frame, |
86 const GURL& embedder, | 95 const GURL& embedder, |
87 bool user_gesture, | 96 bool user_gesture, |
88 Profile* profile, | 97 Profile* profile, |
89 const PermissionDecidedCallback& callback) | 98 const PermissionDecidedCallback& callback) |
90 : type_(type), | 99 : type_(type), |
91 id_(id), | 100 id_(id), |
92 requesting_frame_(requesting_frame), | 101 requesting_frame_(requesting_frame), |
93 embedder_(embedder), | 102 embedder_(embedder), |
94 user_gesture_(user_gesture), | 103 user_gesture_(user_gesture), |
95 profile_(profile), | 104 profile_(profile), |
96 callback_(callback), | 105 callback_(callback), |
97 infobar_(NULL) {} | 106 infobar_(nullptr), |
| 107 has_dialog_(false) {} |
98 | 108 |
99 PermissionQueueController::PendingInfobarRequest::~PendingInfobarRequest() { | 109 PermissionQueueController::PendingInfobarRequest::~PendingInfobarRequest() { |
100 } | 110 } |
101 | 111 |
102 bool PermissionQueueController::PendingInfobarRequest::IsForPair( | 112 bool PermissionQueueController::PendingInfobarRequest::IsForPair( |
103 const GURL& requesting_frame, | 113 const GURL& requesting_frame, |
104 const GURL& embedder) const { | 114 const GURL& embedder) const { |
105 return (requesting_frame_ == requesting_frame) && (embedder_ == embedder); | 115 return (requesting_frame_ == requesting_frame) && (embedder_ == embedder); |
106 } | 116 } |
107 | 117 |
108 void PermissionQueueController::PendingInfobarRequest::RunCallback( | 118 void PermissionQueueController::PendingInfobarRequest::RunCallback( |
109 ContentSetting content_setting) { | 119 ContentSetting content_setting) { |
110 callback_.Run(content_setting); | 120 callback_.Run(content_setting); |
111 } | 121 } |
112 | 122 |
113 void PermissionQueueController::PendingInfobarRequest::CreateInfoBar( | 123 void PermissionQueueController::PendingInfobarRequest::CreatePrompt( |
114 PermissionQueueController* controller) { | 124 PermissionQueueController* controller, |
| 125 bool show_dialog) { |
115 // Controller can be Unretained because the lifetime of the infobar | 126 // Controller can be Unretained because the lifetime of the infobar |
116 // is tied to that of the queue controller. Before QueueController | 127 // is tied to that of the queue controller. Before QueueController |
117 // is destroyed, all requests will be cancelled and so all delegates | 128 // is destroyed, all requests will be cancelled and so all delegates |
118 // will be destroyed. | 129 // will be destroyed. |
119 PermissionInfoBarDelegate::PermissionSetCallback callback = base::Bind( | 130 PermissionInfoBarDelegate::PermissionSetCallback callback = base::Bind( |
120 &PermissionQueueController::OnPermissionSet, base::Unretained(controller), | 131 &PermissionQueueController::OnPermissionSet, base::Unretained(controller), |
121 id_, requesting_frame_, embedder_, user_gesture_); | 132 id_, requesting_frame_, embedder_, user_gesture_); |
122 | 133 |
123 infobar_ = PermissionInfoBarDelegate::Create(type_, GetInfoBarService(id_), | 134 if (show_dialog) { |
124 requesting_frame_, user_gesture_, | 135 // We should show a dialog prompt instead of an infobar. Since only one |
125 profile_, callback); | 136 // dialog can be shown at a time, the Java-side owns and manages the queue |
| 137 // of prompts; the bookkeeping in this class will work as expected: |
| 138 // i. no pending request will ever have an infobar created for it. |
| 139 // ii. OnPermissionSet is still called when the user makes a decision. |
| 140 has_dialog_ = true; |
| 141 PermissionDialogDelegate::Create(GetWebContents(id_), type_, |
| 142 requesting_frame_, user_gesture_, profile_, |
| 143 callback); |
| 144 } else { |
| 145 infobar_ = PermissionInfoBarDelegate::Create( |
| 146 GetInfoBarService(id_), type_, requesting_frame_, user_gesture_, |
| 147 profile_, callback); |
| 148 } |
126 } | 149 } |
127 | 150 |
128 PermissionQueueController::PermissionQueueController( | 151 PermissionQueueController::PermissionQueueController( |
129 Profile* profile, | 152 Profile* profile, |
130 content::PermissionType permission_type, | 153 content::PermissionType permission_type, |
131 ContentSettingsType content_settings_type) | 154 ContentSettingsType content_settings_type) |
132 : profile_(profile), | 155 : profile_(profile), |
133 permission_type_(permission_type), | 156 permission_type_(permission_type), |
134 content_settings_type_(content_settings_type), | 157 content_settings_type_(content_settings_type), |
135 in_shutdown_(false) {} | 158 in_shutdown_(false) {} |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 ContentSetting content_setting = CONTENT_SETTING_DEFAULT; | 276 ContentSetting content_setting = CONTENT_SETTING_DEFAULT; |
254 if (decision == GRANTED) | 277 if (decision == GRANTED) |
255 content_setting = CONTENT_SETTING_ALLOW; | 278 content_setting = CONTENT_SETTING_ALLOW; |
256 else if (decision == DENIED) | 279 else if (decision == DENIED) |
257 content_setting = CONTENT_SETTING_BLOCK; | 280 content_setting = CONTENT_SETTING_BLOCK; |
258 else | 281 else |
259 DCHECK_EQ(DISMISSED, decision); | 282 DCHECK_EQ(DISMISSED, decision); |
260 | 283 |
261 // Send out the permission notifications. | 284 // Send out the permission notifications. |
262 for (PendingInfobarRequests::iterator i = requests_to_notify.begin(); | 285 for (PendingInfobarRequests::iterator i = requests_to_notify.begin(); |
263 i != requests_to_notify.end(); ++i) | 286 i != requests_to_notify.end(); ++i) { |
264 i->RunCallback(content_setting); | 287 i->RunCallback(content_setting); |
| 288 } |
265 | 289 |
266 // Remove the pending requests in reverse order. | 290 // Remove the pending requests in reverse order. |
267 for (int i = pending_requests_to_remove.size() - 1; i >= 0; --i) | 291 for (int i = pending_requests_to_remove.size() - 1; i >= 0; --i) |
268 pending_infobar_requests_.erase(pending_requests_to_remove[i]); | 292 pending_infobar_requests_.erase(pending_requests_to_remove[i]); |
269 } | 293 } |
270 | 294 |
271 void PermissionQueueController::Observe( | 295 void PermissionQueueController::Observe( |
272 int type, | 296 int type, |
273 const content::NotificationSource& source, | 297 const content::NotificationSource& source, |
274 const content::NotificationDetails& details) { | 298 const content::NotificationDetails& details) { |
(...skipping 18 matching lines...) Expand all Loading... |
293 return; | 317 return; |
294 } | 318 } |
295 } | 319 } |
296 } | 320 } |
297 | 321 |
298 bool PermissionQueueController::AlreadyShowingInfoBarForTab( | 322 bool PermissionQueueController::AlreadyShowingInfoBarForTab( |
299 const PermissionRequestID& id) const { | 323 const PermissionRequestID& id) const { |
300 for (PendingInfobarRequests::const_iterator i( | 324 for (PendingInfobarRequests::const_iterator i( |
301 pending_infobar_requests_.begin()); | 325 pending_infobar_requests_.begin()); |
302 i != pending_infobar_requests_.end(); ++i) { | 326 i != pending_infobar_requests_.end(); ++i) { |
303 if (ArePermissionRequestsForSameTab(i->id(), id) && i->has_infobar()) | 327 if (ArePermissionRequestsForSameTab(i->id(), id) && |
| 328 (i->has_infobar() || i->has_dialog())) { |
304 return true; | 329 return true; |
| 330 } |
305 } | 331 } |
306 return false; | 332 return false; |
307 } | 333 } |
308 | 334 |
309 void PermissionQueueController::ShowQueuedInfoBarForTab( | 335 void PermissionQueueController::ShowQueuedInfoBarForTab( |
310 const PermissionRequestID& id) { | 336 const PermissionRequestID& id) { |
311 DCHECK(!AlreadyShowingInfoBarForTab(id)); | 337 DCHECK(!AlreadyShowingInfoBarForTab(id)); |
312 | 338 |
313 // We can get here for example during tab shutdown, when the InfoBarService is | 339 // 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 | 340 // 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 | 341 // 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. | 342 // 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 | 343 // In this case we should just go ahead and cancel further infobars for this |
318 // tab instead of trying to access the service. | 344 // tab instead of trying to access the service. |
319 // | 345 // |
320 // Similarly, if we're being destroyed, we should also avoid showing further | 346 // Similarly, if we're being destroyed, we should also avoid showing further |
321 // infobars. | 347 // infobars. |
322 InfoBarService* infobar_service = GetInfoBarService(id); | 348 InfoBarService* infobar_service = GetInfoBarService(id); |
323 if (!infobar_service || in_shutdown_) { | 349 if (!infobar_service || in_shutdown_) { |
324 ClearPendingInfobarRequestsForTab(id); | 350 ClearPendingInfobarRequestsForTab(id); |
325 return; | 351 return; |
326 } | 352 } |
327 | 353 |
328 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); | 354 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); |
329 i != pending_infobar_requests_.end(); ++i) { | 355 i != pending_infobar_requests_.end(); ++i) { |
330 if (ArePermissionRequestsForSameTab(i->id(), id) && !i->has_infobar()) { | 356 if (ArePermissionRequestsForSameTab(i->id(), id) && !i->has_infobar()) { |
331 RegisterForInfoBarNotifications(infobar_service); | 357 // When using modal permission prompts, Java controls the display queue, |
332 i->CreateInfoBar(this); | 358 // so infobar notifications are not relevant. |
| 359 bool show_dialog = |
| 360 PermissionDialogDelegate::ShouldShowDialog(i->has_gesture()); |
| 361 if (!show_dialog) |
| 362 RegisterForInfoBarNotifications(infobar_service); |
| 363 |
| 364 i->CreatePrompt(this, show_dialog); |
333 return; | 365 return; |
334 } | 366 } |
335 } | 367 } |
336 | 368 |
337 UnregisterForInfoBarNotifications(infobar_service); | 369 UnregisterForInfoBarNotifications(infobar_service); |
338 } | 370 } |
339 | 371 |
340 void PermissionQueueController::ClearPendingInfobarRequestsForTab( | 372 void PermissionQueueController::ClearPendingInfobarRequestsForTab( |
341 const PermissionRequestID& id) { | 373 const PermissionRequestID& id) { |
342 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); | 374 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 } | 417 } |
386 | 418 |
387 ContentSetting content_setting = | 419 ContentSetting content_setting = |
388 (decision == GRANTED) ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; | 420 (decision == GRANTED) ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; |
389 | 421 |
390 HostContentSettingsMapFactory::GetForProfile(profile_) | 422 HostContentSettingsMapFactory::GetForProfile(profile_) |
391 ->SetContentSettingDefaultScope( | 423 ->SetContentSettingDefaultScope( |
392 requesting_frame.GetOrigin(), embedder.GetOrigin(), | 424 requesting_frame.GetOrigin(), embedder.GetOrigin(), |
393 content_settings_type_, std::string(), content_setting); | 425 content_settings_type_, std::string(), content_setting); |
394 } | 426 } |
OLD | NEW |