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

Side by Side Diff: chrome/browser/permissions/permission_queue_controller.cc

Issue 2446063002: Implement a modal permission dialog on Android gated by a feature. (Closed)
Patch Set: Rebase Created 4 years, 1 month 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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698