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/geolocation/geolocation_infobar_delegate_android.h" | 9 #include "chrome/browser/geolocation/geolocation_infobar_delegate_android.h" |
10 #include "chrome/browser/infobars/infobar_service.h" | 10 #include "chrome/browser/infobars/infobar_service.h" |
11 #include "chrome/browser/media/midi_permission_infobar_delegate_android.h" | 11 #include "chrome/browser/media/midi_permission_infobar_delegate_android.h" |
12 #include "chrome/browser/media/protected_media_identifier_infobar_delegate_andro
id.h" | 12 #include "chrome/browser/media/protected_media_identifier_infobar_delegate_andro
id.h" |
13 #include "chrome/browser/notifications/notification_permission_infobar_delegate.
h" | 13 #include "chrome/browser/notifications/notification_permission_infobar_delegate.
h" |
| 14 #include "chrome/browser/permissions/permission_request.h" |
14 #include "chrome/browser/permissions/permission_request_id.h" | 15 #include "chrome/browser/permissions/permission_request_id.h" |
15 #include "chrome/browser/permissions/permission_uma_util.h" | 16 #include "chrome/browser/permissions/permission_uma_util.h" |
16 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/browser/tab_contents/tab_util.h" | 18 #include "chrome/browser/tab_contents/tab_util.h" |
18 #include "components/content_settings/core/browser/host_content_settings_map.h" | 19 #include "components/content_settings/core/browser/host_content_settings_map.h" |
19 #include "components/content_settings/core/common/content_settings.h" | 20 #include "components/content_settings/core/common/content_settings.h" |
20 #include "components/infobars/core/infobar.h" | 21 #include "components/infobars/core/infobar.h" |
21 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
22 #include "content/public/browser/notification_details.h" | 23 #include "content/public/browser/notification_details.h" |
23 #include "content/public/browser/notification_source.h" | 24 #include "content/public/browser/notification_source.h" |
(...skipping 21 matching lines...) Expand all Loading... |
45 } | 46 } |
46 | 47 |
47 } // anonymous namespace | 48 } // anonymous namespace |
48 | 49 |
49 class PermissionQueueController::PendingInfobarRequest { | 50 class PermissionQueueController::PendingInfobarRequest { |
50 public: | 51 public: |
51 PendingInfobarRequest(content::PermissionType type, | 52 PendingInfobarRequest(content::PermissionType type, |
52 const PermissionRequestID& id, | 53 const PermissionRequestID& id, |
53 const GURL& requesting_frame, | 54 const GURL& requesting_frame, |
54 const GURL& embedder, | 55 const GURL& embedder, |
| 56 bool user_gesture, |
55 Profile* profile, | 57 Profile* profile, |
56 const PermissionDecidedCallback& callback); | 58 const PermissionDecidedCallback& callback); |
57 ~PendingInfobarRequest(); | 59 ~PendingInfobarRequest(); |
58 | 60 |
59 bool IsForPair(const GURL& requesting_frame, | 61 bool IsForPair(const GURL& requesting_frame, |
60 const GURL& embedder) const; | 62 const GURL& embedder) const; |
61 | 63 |
62 const PermissionRequestID& id() const { return id_; } | 64 const PermissionRequestID& id() const { return id_; } |
63 const GURL& requesting_frame() const { return requesting_frame_; } | 65 const GURL& requesting_frame() const { return requesting_frame_; } |
64 bool has_infobar() const { return !!infobar_; } | 66 bool has_infobar() const { return !!infobar_; } |
65 infobars::InfoBar* infobar() { return infobar_; } | 67 infobars::InfoBar* infobar() { return infobar_; } |
66 | 68 |
67 void RunCallback(ContentSetting content_setting); | 69 void RunCallback(ContentSetting content_setting); |
68 void CreateInfoBar(PermissionQueueController* controller); | 70 void CreateInfoBar(PermissionQueueController* controller); |
69 | 71 |
70 private: | 72 private: |
71 content::PermissionType type_; | 73 content::PermissionType type_; |
72 PermissionRequestID id_; | 74 PermissionRequestID id_; |
73 GURL requesting_frame_; | 75 GURL requesting_frame_; |
74 GURL embedder_; | 76 GURL embedder_; |
| 77 bool user_gesture_; |
75 Profile* profile_; | 78 Profile* profile_; |
76 PermissionDecidedCallback callback_; | 79 PermissionDecidedCallback callback_; |
77 infobars::InfoBar* infobar_; | 80 infobars::InfoBar* infobar_; |
78 | 81 |
79 // Purposefully do not disable copying, as this is stored in STL containers. | 82 // Purposefully do not disable copying, as this is stored in STL containers. |
80 }; | 83 }; |
81 | 84 |
82 PermissionQueueController::PendingInfobarRequest::PendingInfobarRequest( | 85 PermissionQueueController::PendingInfobarRequest::PendingInfobarRequest( |
83 content::PermissionType type, | 86 content::PermissionType type, |
84 const PermissionRequestID& id, | 87 const PermissionRequestID& id, |
85 const GURL& requesting_frame, | 88 const GURL& requesting_frame, |
86 const GURL& embedder, | 89 const GURL& embedder, |
| 90 bool user_gesture, |
87 Profile* profile, | 91 Profile* profile, |
88 const PermissionDecidedCallback& callback) | 92 const PermissionDecidedCallback& callback) |
89 : type_(type), | 93 : type_(type), |
90 id_(id), | 94 id_(id), |
91 requesting_frame_(requesting_frame), | 95 requesting_frame_(requesting_frame), |
92 embedder_(embedder), | 96 embedder_(embedder), |
| 97 user_gesture_(user_gesture), |
93 profile_(profile), | 98 profile_(profile), |
94 callback_(callback), | 99 callback_(callback), |
95 infobar_(NULL) {} | 100 infobar_(NULL) {} |
96 | 101 |
97 PermissionQueueController::PendingInfobarRequest::~PendingInfobarRequest() { | 102 PermissionQueueController::PendingInfobarRequest::~PendingInfobarRequest() { |
98 } | 103 } |
99 | 104 |
100 bool PermissionQueueController::PendingInfobarRequest::IsForPair( | 105 bool PermissionQueueController::PendingInfobarRequest::IsForPair( |
101 const GURL& requesting_frame, | 106 const GURL& requesting_frame, |
102 const GURL& embedder) const { | 107 const GURL& embedder) const { |
103 return (requesting_frame_ == requesting_frame) && (embedder_ == embedder); | 108 return (requesting_frame_ == requesting_frame) && (embedder_ == embedder); |
104 } | 109 } |
105 | 110 |
106 void PermissionQueueController::PendingInfobarRequest::RunCallback( | 111 void PermissionQueueController::PendingInfobarRequest::RunCallback( |
107 ContentSetting content_setting) { | 112 ContentSetting content_setting) { |
108 callback_.Run(content_setting); | 113 callback_.Run(content_setting); |
109 } | 114 } |
110 | 115 |
111 void PermissionQueueController::PendingInfobarRequest::CreateInfoBar( | 116 void PermissionQueueController::PendingInfobarRequest::CreateInfoBar( |
112 PermissionQueueController* controller) { | 117 PermissionQueueController* controller) { |
113 // Controller can be Unretained because the lifetime of the infobar | 118 // Controller can be Unretained because the lifetime of the infobar |
114 // is tied to that of the queue controller. Before QueueController | 119 // is tied to that of the queue controller. Before QueueController |
115 // is destroyed, all requests will be cancelled and so all delegates | 120 // is destroyed, all requests will be cancelled and so all delegates |
116 // will be destroyed. | 121 // will be destroyed. |
117 PermissionInfobarDelegate::PermissionSetCallback callback = | 122 PermissionInfobarDelegate::PermissionSetCallback callback = base::Bind( |
118 base::Bind(&PermissionQueueController::OnPermissionSet, | 123 &PermissionQueueController::OnPermissionSet, base::Unretained(controller), |
119 base::Unretained(controller), | 124 id_, requesting_frame_, embedder_, user_gesture_); |
120 id_, | |
121 requesting_frame_, | |
122 embedder_); | |
123 switch (type_) { | 125 switch (type_) { |
124 case content::PermissionType::GEOLOCATION: | 126 case content::PermissionType::GEOLOCATION: |
125 infobar_ = GeolocationInfoBarDelegateAndroid::Create( | 127 infobar_ = GeolocationInfoBarDelegateAndroid::Create( |
126 GetInfoBarService(id_), requesting_frame_, profile_, callback); | 128 GetInfoBarService(id_), requesting_frame_, user_gesture_, profile_, |
| 129 callback); |
127 break; | 130 break; |
128 #if defined(ENABLE_NOTIFICATIONS) | 131 #if defined(ENABLE_NOTIFICATIONS) |
129 case content::PermissionType::NOTIFICATIONS: | 132 case content::PermissionType::NOTIFICATIONS: |
130 infobar_ = NotificationPermissionInfobarDelegate::Create( | 133 infobar_ = NotificationPermissionInfobarDelegate::Create( |
131 GetInfoBarService(id_), requesting_frame_, profile_, callback); | 134 GetInfoBarService(id_), requesting_frame_, user_gesture_, profile_, |
| 135 callback); |
132 break; | 136 break; |
133 #endif // ENABLE_NOTIFICATIONS | 137 #endif // ENABLE_NOTIFICATIONS |
134 case content::PermissionType::MIDI_SYSEX: | 138 case content::PermissionType::MIDI_SYSEX: |
135 infobar_ = MidiPermissionInfoBarDelegateAndroid::Create( | 139 infobar_ = MidiPermissionInfoBarDelegateAndroid::Create( |
136 GetInfoBarService(id_), requesting_frame_, profile_, callback); | 140 GetInfoBarService(id_), requesting_frame_, user_gesture_, profile_, |
| 141 callback); |
137 break; | 142 break; |
138 case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER: | 143 case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER: |
139 infobar_ = ProtectedMediaIdentifierInfoBarDelegateAndroid::Create( | 144 infobar_ = ProtectedMediaIdentifierInfoBarDelegateAndroid::Create( |
140 GetInfoBarService(id_), requesting_frame_, profile_, callback); | 145 GetInfoBarService(id_), requesting_frame_, user_gesture_, profile_, |
| 146 callback); |
141 break; | 147 break; |
142 default: | 148 default: |
143 NOTREACHED(); | 149 NOTREACHED(); |
144 break; | 150 break; |
145 } | 151 } |
146 } | 152 } |
147 | 153 |
148 PermissionQueueController::PermissionQueueController( | 154 PermissionQueueController::PermissionQueueController( |
149 Profile* profile, | 155 Profile* profile, |
150 content::PermissionType permission_type, | 156 content::PermissionType permission_type, |
151 ContentSettingsType content_settings_type) | 157 ContentSettingsType content_settings_type) |
152 : profile_(profile), | 158 : profile_(profile), |
153 permission_type_(permission_type), | 159 permission_type_(permission_type), |
154 content_settings_type_(content_settings_type), | 160 content_settings_type_(content_settings_type), |
155 in_shutdown_(false) {} | 161 in_shutdown_(false) {} |
156 | 162 |
157 PermissionQueueController::~PermissionQueueController() { | 163 PermissionQueueController::~PermissionQueueController() { |
158 // Cancel all outstanding requests. | 164 // Cancel all outstanding requests. |
159 in_shutdown_ = true; | 165 in_shutdown_ = true; |
160 while (!pending_infobar_requests_.empty()) | 166 while (!pending_infobar_requests_.empty()) |
161 CancelInfoBarRequest(pending_infobar_requests_.front().id()); | 167 CancelInfoBarRequest(pending_infobar_requests_.front().id()); |
162 } | 168 } |
163 | 169 |
164 void PermissionQueueController::CreateInfoBarRequest( | 170 void PermissionQueueController::CreateInfoBarRequest( |
165 const PermissionRequestID& id, | 171 const PermissionRequestID& id, |
166 const GURL& requesting_frame, | 172 const GURL& requesting_frame, |
167 const GURL& embedder, | 173 const GURL& embedder, |
| 174 bool user_gesture, |
168 const PermissionDecidedCallback& callback) { | 175 const PermissionDecidedCallback& callback) { |
169 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 176 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
170 | 177 |
171 if (requesting_frame.SchemeIs(content::kChromeUIScheme) || | 178 if (requesting_frame.SchemeIs(content::kChromeUIScheme) || |
172 embedder.SchemeIs(content::kChromeUIScheme)) | 179 embedder.SchemeIs(content::kChromeUIScheme)) |
173 return; | 180 return; |
174 | 181 |
175 pending_infobar_requests_.push_back(PendingInfobarRequest( | 182 pending_infobar_requests_.push_back( |
176 permission_type_, id, requesting_frame, embedder, profile_, callback)); | 183 PendingInfobarRequest(permission_type_, id, requesting_frame, embedder, |
| 184 user_gesture, profile_, callback)); |
177 if (!AlreadyShowingInfoBarForTab(id)) | 185 if (!AlreadyShowingInfoBarForTab(id)) |
178 ShowQueuedInfoBarForTab(id); | 186 ShowQueuedInfoBarForTab(id); |
179 } | 187 } |
180 | 188 |
181 void PermissionQueueController::CancelInfoBarRequest( | 189 void PermissionQueueController::CancelInfoBarRequest( |
182 const PermissionRequestID& id) { | 190 const PermissionRequestID& id) { |
183 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 191 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
184 | 192 |
185 for (PendingInfobarRequests::iterator i(pending_infobar_requests_.begin()); | 193 for (PendingInfobarRequests::iterator i(pending_infobar_requests_.begin()); |
186 i != pending_infobar_requests_.end(); ++i) { | 194 i != pending_infobar_requests_.end(); ++i) { |
187 if (id != i->id()) | 195 if (id != i->id()) |
188 continue; | 196 continue; |
189 | 197 |
190 InfoBarService* infobar_service = GetInfoBarService(id); | 198 InfoBarService* infobar_service = GetInfoBarService(id); |
191 if (infobar_service && i->has_infobar()) | 199 if (infobar_service && i->has_infobar()) |
192 infobar_service->RemoveInfoBar(i->infobar()); | 200 infobar_service->RemoveInfoBar(i->infobar()); |
193 else | 201 else |
194 pending_infobar_requests_.erase(i); | 202 pending_infobar_requests_.erase(i); |
195 return; | 203 return; |
196 } | 204 } |
197 } | 205 } |
198 | 206 |
199 void PermissionQueueController::OnPermissionSet( | 207 void PermissionQueueController::OnPermissionSet(const PermissionRequestID& id, |
200 const PermissionRequestID& id, | 208 const GURL& requesting_frame, |
201 const GURL& requesting_frame, | 209 const GURL& embedder, |
202 const GURL& embedder, | 210 bool user_gesture, |
203 bool update_content_setting, | 211 bool update_content_setting, |
204 bool allowed) { | 212 bool allowed) { |
205 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 213 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
206 | 214 |
207 // TODO(miguelg): move the permission persistence to | 215 // TODO(miguelg): move the permission persistence to |
208 // PermissionContextBase once all the types are moved there. | 216 // PermissionContextBase once all the types are moved there. |
209 // TODO(stefanocs): Pass the actual |gesture_type| value to PermissionUmaUtil. | 217 PermissionRequestGestureType gesture_type = |
| 218 user_gesture ? PermissionRequestGestureType::GESTURE |
| 219 : PermissionRequestGestureType::NO_GESTURE; |
210 if (update_content_setting) { | 220 if (update_content_setting) { |
211 UpdateContentSetting(requesting_frame, embedder, allowed); | 221 UpdateContentSetting(requesting_frame, embedder, allowed); |
212 if (allowed) { | 222 if (allowed) { |
213 PermissionUmaUtil::PermissionGranted( | 223 PermissionUmaUtil::PermissionGranted(permission_type_, gesture_type, |
214 permission_type_, PermissionRequestGestureType::UNKNOWN, | 224 requesting_frame, profile_); |
215 requesting_frame, profile_); | |
216 } else { | 225 } else { |
217 PermissionUmaUtil::PermissionDenied(permission_type_, | 226 PermissionUmaUtil::PermissionDenied(permission_type_, gesture_type, |
218 PermissionRequestGestureType::UNKNOWN, | |
219 requesting_frame, profile_); | 227 requesting_frame, profile_); |
220 } | 228 } |
221 } else { | 229 } else { |
222 PermissionUmaUtil::PermissionDismissed( | 230 PermissionUmaUtil::PermissionDismissed(permission_type_, gesture_type, |
223 permission_type_, PermissionRequestGestureType::UNKNOWN, | 231 requesting_frame, profile_); |
224 requesting_frame, profile_); | |
225 } | 232 } |
226 | 233 |
227 // Cancel this request first, then notify listeners. TODO(pkasting): Why | 234 // Cancel this request first, then notify listeners. TODO(pkasting): Why |
228 // is this order important? | 235 // is this order important? |
229 PendingInfobarRequests requests_to_notify; | 236 PendingInfobarRequests requests_to_notify; |
230 PendingInfobarRequests infobars_to_remove; | 237 PendingInfobarRequests infobars_to_remove; |
231 std::vector<PendingInfobarRequests::iterator> pending_requests_to_remove; | 238 std::vector<PendingInfobarRequests::iterator> pending_requests_to_remove; |
232 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); | 239 for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); |
233 i != pending_infobar_requests_.end(); ++i) { | 240 i != pending_infobar_requests_.end(); ++i) { |
234 if (!i->IsForPair(requesting_frame, embedder)) | 241 if (!i->IsForPair(requesting_frame, embedder)) |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 } | 401 } |
395 | 402 |
396 ContentSetting content_setting = | 403 ContentSetting content_setting = |
397 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; | 404 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; |
398 | 405 |
399 HostContentSettingsMapFactory::GetForProfile(profile_) | 406 HostContentSettingsMapFactory::GetForProfile(profile_) |
400 ->SetContentSettingDefaultScope( | 407 ->SetContentSettingDefaultScope( |
401 requesting_frame.GetOrigin(), embedder.GetOrigin(), | 408 requesting_frame.GetOrigin(), embedder.GetOrigin(), |
402 content_settings_type_, std::string(), content_setting); | 409 content_settings_type_, std::string(), content_setting); |
403 } | 410 } |
OLD | NEW |