permission_queue_controller.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "chrome/browser/content_settings/permission_queue_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h"
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/content_settings/permission_context_uma_util.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/geolocation/geolocation_infobar_delegate.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/infobars/infobar_service.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/media/midi_permission_infobar_delegate.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/services/gcm/push_messaging_infobar_delegate.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/tab_contents/tab_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/content_settings.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/infobars/core/infobar.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/common/url_constants.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_ANDROID)
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/media/protected_media_identifier_infobar_delegate.h"
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33a3f7b4e666c476898878fa745f637129375cd889Ben MurdochInfoBarService* GetInfoBarService(const PermissionRequestID& id) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WebContents* web_contents =
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_util::GetWebContentsByID(id.render_process_id(), id.render_view_id());
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_contents ? InfoBarService::FromWebContents(web_contents) : NULL;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PermissionQueueController::PendingInfobarRequest {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequest(ContentSettingsType type,
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        const PermissionRequestID& id,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const GURL& requesting_frame,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const GURL& embedder,
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        const std::string& accept_button_label,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        PermissionDecidedCallback callback);
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ~PendingInfobarRequest();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsForPair(const GURL& requesting_frame,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const GURL& embedder) const;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  const PermissionRequestID& id() const { return id_; }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& requesting_frame() const { return requesting_frame_; }
57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bool has_infobar() const { return !!infobar_; }
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  infobars::InfoBar* infobar() { return infobar_; }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunCallback(bool allowed);
61a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  void CreateInfoBar(PermissionQueueController* controller,
62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                     const std::string& display_languages);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ContentSettingsType type_;
66a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  PermissionRequestID id_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL requesting_frame_;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL embedder_;
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string accept_button_label_;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionDecidedCallback callback_;
710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  infobars::InfoBar* infobar_;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Purposefully do not disable copying, as this is stored in STL containers.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PermissionQueueController::PendingInfobarRequest::PendingInfobarRequest(
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ContentSettingsType type,
78a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& accept_button_label,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PermissionDecidedCallback callback)
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : type_(type),
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      id_(id),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requesting_frame_(requesting_frame),
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      embedder_(embedder),
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      accept_button_label_(accept_button_label),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(callback),
89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      infobar_(NULL) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PermissionQueueController::PendingInfobarRequest::~PendingInfobarRequest() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PermissionQueueController::PendingInfobarRequest::IsForPair(
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder) const {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (requesting_frame_ == requesting_frame) && (embedder_ == embedder);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionQueueController::PendingInfobarRequest::RunCallback(
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allowed) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(allowed);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionQueueController::PendingInfobarRequest::CreateInfoBar(
107a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    PermissionQueueController* controller,
108a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const std::string& display_languages) {
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  switch (type_) {
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case CONTENT_SETTINGS_TYPE_GEOLOCATION:
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      infobar_ = GeolocationInfoBarDelegate::Create(
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          GetInfoBarService(id_), controller, id_, requesting_frame_,
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          display_languages, accept_button_label_);
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      infobar_ = MidiPermissionInfoBarDelegate::Create(
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          GetInfoBarService(id_), controller, id_, requesting_frame_,
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          display_languages, type_);
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING:
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      infobar_ = gcm::PushMessagingInfoBarDelegate::Create(
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          GetInfoBarService(id_), controller, id_, requesting_frame_,
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          display_languages, type_);
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_ANDROID)
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      infobar_ = ProtectedMediaIdentifierInfoBarDelegate::Create(
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          GetInfoBarService(id_), controller, id_, requesting_frame_,
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          display_languages);
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    default:
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      NOTREACHED();
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
139558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPermissionQueueController::PermissionQueueController(Profile* profile,
140558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                                     ContentSettingsType type)
141a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    : profile_(profile),
142558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      type_(type),
143558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      in_shutdown_(false) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
146a3f7b4e666c476898878fa745f637129375cd889Ben MurdochPermissionQueueController::~PermissionQueueController() {
147558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Cancel all outstanding requests.
148558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  in_shutdown_ = true;
149558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  while (!pending_infobar_requests_.empty())
150558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    CancelInfoBarRequest(pending_infobar_requests_.front().id());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
153a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::CreateInfoBarRequest(
154a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& accept_button_label,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PermissionDecidedCallback callback) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (requesting_frame.SchemeIs(content::kChromeUIScheme) ||
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      embedder.SchemeIs(content::kChromeUIScheme))
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pending_infobar_requests_.push_back(PendingInfobarRequest(
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      type_, id, requesting_frame, embedder,
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      accept_button_label, callback));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AlreadyShowingInfoBarForTab(id))
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowQueuedInfoBarForTab(id);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::CancelInfoBarRequest(
173a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i(pending_infobar_requests_.begin());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->id().Equals(id)) {
179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (i->has_infobar())
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        GetInfoBarService(id)->RemoveInfoBar(i->infobar());
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_infobar_requests_.erase(i);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
188a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::OnPermissionSet(
189a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool update_content_setting,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allowed) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(miguelg): move the permission persistence to
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // PermissionContextBase once all the types are moved there.
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (update_content_setting) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateContentSetting(requesting_frame, embedder, allowed);
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (allowed)
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PermissionContextUmaUtil::PermissionGranted(type_);
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    else
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PermissionContextUmaUtil::PermissionDenied(type_);
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    PermissionContextUmaUtil::PermissionDismissed(type_);
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel this request first, then notify listeners.  TODO(pkasting): Why
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is this order important?
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequests requests_to_notify;
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequests infobars_to_remove;
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::vector<PendingInfobarRequests::iterator> pending_requests_to_remove;
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!i->IsForPair(requesting_frame, embedder))
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      continue;
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    requests_to_notify.push_back(*i);
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!i->has_infobar()) {
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // We haven't created an infobar yet, just record the pending request
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // index and remove it later.
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pending_requests_to_remove.push_back(i);
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      continue;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (i->id().Equals(id)) {
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // The infobar that called us is i->infobar(), and its delegate is
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // currently in either Accept() or Cancel(). This means that
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // RemoveInfoBar() will be called later on, and that will trigger a
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // notification we're observing.
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      continue;
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // This infobar is for the same frame/embedder pair, but in a different
233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // tab. We should remove it now that we've got an answer for it.
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    infobars_to_remove.push_back(*i);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Remove all infobars for the same |requesting_frame| and |embedder|.
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = infobars_to_remove.begin();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != infobars_to_remove.end(); ++i)
240a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    GetInfoBarService(i->id())->RemoveInfoBar(i->infobar());
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send out the permission notifications.
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = requests_to_notify.begin();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != requests_to_notify.end(); ++i)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->RunCallback(allowed);
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Remove the pending requests in reverse order.
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (int i = pending_requests_to_remove.size() - 1; i >= 0; --i)
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    pending_infobar_requests_.erase(pending_requests_to_remove[i]);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::Observe(
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We will receive this notification for all infobar closures, so we need to
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // check whether this is the geolocation infobar we're tracking. Note that the
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // InfoBarContainer (if any) may have received this notification before us and
260ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // caused the infobar to be deleted, so it's not safe to dereference the
261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // contents of the infobar. The address of the infobar, however, is OK to
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // use to find the PendingInfobarRequest to remove because
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending_infobar_requests_ will not have received any new entries between
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the NotificationService's call to InfoBarContainer::Observe and this
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // method.
2660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  infobars::InfoBar* infobar =
2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      content::Details<infobars::InfoBar::RemovedDetails>(details)->first;
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
270ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->infobar() == infobar) {
271a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      PermissionRequestID id(i->id());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_infobar_requests_.erase(i);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ShowQueuedInfoBarForTab(id);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
279a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool PermissionQueueController::AlreadyShowingInfoBarForTab(
280a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) const {
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::const_iterator i(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pending_infobar_requests_.begin());
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->id().IsForSameTabAs(id) && i->has_infobar())
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
290a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::ShowQueuedInfoBarForTab(
291a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!AlreadyShowingInfoBarForTab(id));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
294558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // We can get here for example during tab shutdown, when the InfoBarService is
2952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // removing all existing infobars, thus calling back to Observe(). In this
296558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // case the service still exists, and is supplied as the source of the
297558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // notification we observed, but is no longer accessible from its WebContents.
298558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // In this case we should just go ahead and cancel further infobars for this
299558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // tab instead of trying to access the service.
300558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  //
301558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Similarly, if we're being destroyed, we should also avoid showing further
302558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // infobars.
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InfoBarService* infobar_service = GetInfoBarService(id);
304558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!infobar_service || in_shutdown_) {
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ClearPendingInfobarRequestsForTab(id);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->id().IsForSameTabAs(id) && !i->has_infobar()) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RegisterForInfoBarNotifications(infobar_service);
313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      i->CreateInfoBar(
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this, profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UnregisterForInfoBarNotifications(infobar_service);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionQueueController::ClearPendingInfobarRequestsForTab(
323a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ) {
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (i->id().IsForSameTabAs(id)) {
327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      DCHECK(!i->has_infobar());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = pending_infobar_requests_.erase(i);
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::RegisterForInfoBarNotifications(
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!registrar_.IsRegistered(
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<InfoBarService>(infobar_service))) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   content::Source<InfoBarService>(infobar_service));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
346a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::UnregisterForInfoBarNotifications(
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (registrar_.IsRegistered(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<InfoBarService>(infobar_service))) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Remove(this,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      content::Source<InfoBarService>(infobar_service));
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
357a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::UpdateContentSetting(
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& requesting_frame,
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& embedder,
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool allowed) {
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (requesting_frame.GetOrigin().SchemeIsFile()) {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Chrome can be launched with --disable-web-security which allows
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // geolocation requests from file:// URLs. We don't want to store these
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // in the host content settings map.
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentSetting content_setting =
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(requesting_frame.GetOrigin()),
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(embedder.GetOrigin()),
373a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      type_,
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string(),
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content_setting);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
377