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"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/notifications/desktop_notification_infobar_delegate.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/services/gcm/push_messaging_infobar_delegate.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/tab_contents/tab_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/content_settings/core/common/content_settings.h"
200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/infobars/core/infobar.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/common/url_constants.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_ANDROID)
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/media/protected_media_identifier_infobar_delegate.h"
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34a3f7b4e666c476898878fa745f637129375cd889Ben MurdochInfoBarService* GetInfoBarService(const PermissionRequestID& id) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WebContents* web_contents =
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_util::GetWebContentsByID(id.render_process_id(), id.render_view_id());
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_contents ? InfoBarService::FromWebContents(web_contents) : NULL;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PermissionQueueController::PendingInfobarRequest {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequest(ContentSettingsType type,
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        const PermissionRequestID& id,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const GURL& requesting_frame,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const GURL& embedder,
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_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionDecidedCallback callback_;
700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  infobars::InfoBar* infobar_;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Purposefully do not disable copying, as this is stored in STL containers.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PermissionQueueController::PendingInfobarRequest::PendingInfobarRequest(
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ContentSettingsType type,
77a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PermissionDecidedCallback callback)
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : type_(type),
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      id_(id),
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requesting_frame_(requesting_frame),
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      embedder_(embedder),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(callback),
86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      infobar_(NULL) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PermissionQueueController::PendingInfobarRequest::~PendingInfobarRequest() {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PermissionQueueController::PendingInfobarRequest::IsForPair(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder) const {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (requesting_frame_ == requesting_frame) && (embedder_ == embedder);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionQueueController::PendingInfobarRequest::RunCallback(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allowed) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(allowed);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionQueueController::PendingInfobarRequest::CreateInfoBar(
104a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    PermissionQueueController* controller,
105a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const std::string& display_languages) {
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  switch (type_) {
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case CONTENT_SETTINGS_TYPE_GEOLOCATION:
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      infobar_ = GeolocationInfoBarDelegate::Create(
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          GetInfoBarService(id_), controller, id_, requesting_frame_,
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          display_languages);
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(ENABLE_NOTIFICATIONS)
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      infobar_ = DesktopNotificationInfoBarDelegate::Create(
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          GetInfoBarService(id_), controller, id_, requesting_frame_,
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          display_languages);
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif  // ENABLE_NOTIFICATIONS
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      infobar_ = MidiPermissionInfoBarDelegate::Create(
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          GetInfoBarService(id_), controller, id_, requesting_frame_,
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          display_languages, type_);
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING:
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      infobar_ = gcm::PushMessagingInfoBarDelegate::Create(
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          GetInfoBarService(id_), controller, id_, requesting_frame_,
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          display_languages, type_);
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_ANDROID)
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      infobar_ = ProtectedMediaIdentifierInfoBarDelegate::Create(
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          GetInfoBarService(id_), controller, id_, requesting_frame_,
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          display_languages);
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    default:
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      NOTREACHED();
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
143558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPermissionQueueController::PermissionQueueController(Profile* profile,
144558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                                     ContentSettingsType type)
145a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    : profile_(profile),
146558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      type_(type),
147558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      in_shutdown_(false) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
150a3f7b4e666c476898878fa745f637129375cd889Ben MurdochPermissionQueueController::~PermissionQueueController() {
151558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Cancel all outstanding requests.
152558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  in_shutdown_ = true;
153558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  while (!pending_infobar_requests_.empty())
154558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    CancelInfoBarRequest(pending_infobar_requests_.front().id());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::CreateInfoBarRequest(
158a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PermissionDecidedCallback callback) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (requesting_frame.SchemeIs(content::kChromeUIScheme) ||
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      embedder.SchemeIs(content::kChromeUIScheme))
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pending_infobar_requests_.push_back(PendingInfobarRequest(
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      type_, id, requesting_frame, embedder, callback));
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AlreadyShowingInfoBarForTab(id))
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowQueuedInfoBarForTab(id);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
174a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::CancelInfoBarRequest(
175a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i(pending_infobar_requests_.begin());
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->id().Equals(id)) {
181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (i->has_infobar())
182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        GetInfoBarService(id)->RemoveInfoBar(i->infobar());
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_infobar_requests_.erase(i);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
190a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::OnPermissionSet(
191a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool update_content_setting,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allowed) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(miguelg): move the permission persistence to
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // PermissionContextBase once all the types are moved there.
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (update_content_setting) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateContentSetting(requesting_frame, embedder, allowed);
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (allowed)
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PermissionContextUmaUtil::PermissionGranted(type_);
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    else
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PermissionContextUmaUtil::PermissionDenied(type_);
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    PermissionContextUmaUtil::PermissionDismissed(type_);
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel this request first, then notify listeners.  TODO(pkasting): Why
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is this order important?
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequests requests_to_notify;
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequests infobars_to_remove;
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::vector<PendingInfobarRequests::iterator> pending_requests_to_remove;
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!i->IsForPair(requesting_frame, embedder))
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      continue;
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    requests_to_notify.push_back(*i);
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!i->has_infobar()) {
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // We haven't created an infobar yet, just record the pending request
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // index and remove it later.
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pending_requests_to_remove.push_back(i);
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      continue;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (i->id().Equals(id)) {
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // The infobar that called us is i->infobar(), and its delegate is
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // currently in either Accept() or Cancel(). This means that
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // RemoveInfoBar() will be called later on, and that will trigger a
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // notification we're observing.
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      continue;
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // This infobar is for the same frame/embedder pair, but in a different
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // tab. We should remove it now that we've got an answer for it.
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    infobars_to_remove.push_back(*i);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Remove all infobars for the same |requesting_frame| and |embedder|.
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = infobars_to_remove.begin();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != infobars_to_remove.end(); ++i)
242a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    GetInfoBarService(i->id())->RemoveInfoBar(i->infobar());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send out the permission notifications.
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = requests_to_notify.begin();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != requests_to_notify.end(); ++i)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->RunCallback(allowed);
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Remove the pending requests in reverse order.
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (int i = pending_requests_to_remove.size() - 1; i >= 0; --i)
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    pending_infobar_requests_.erase(pending_requests_to_remove[i]);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
254a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::Observe(
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We will receive this notification for all infobar closures, so we need to
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // check whether this is the geolocation infobar we're tracking. Note that the
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // InfoBarContainer (if any) may have received this notification before us and
262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // caused the infobar to be deleted, so it's not safe to dereference the
263ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // contents of the infobar. The address of the infobar, however, is OK to
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // use to find the PendingInfobarRequest to remove because
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending_infobar_requests_ will not have received any new entries between
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the NotificationService's call to InfoBarContainer::Observe and this
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // method.
2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  infobars::InfoBar* infobar =
2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      content::Details<infobars::InfoBar::RemovedDetails>(details)->first;
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->infobar() == infobar) {
273a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      PermissionRequestID id(i->id());
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_infobar_requests_.erase(i);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ShowQueuedInfoBarForTab(id);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
281a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool PermissionQueueController::AlreadyShowingInfoBarForTab(
282a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) const {
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::const_iterator i(
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pending_infobar_requests_.begin());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->id().IsForSameTabAs(id) && i->has_infobar())
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
292a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::ShowQueuedInfoBarForTab(
293a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!AlreadyShowingInfoBarForTab(id));
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
296558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // We can get here for example during tab shutdown, when the InfoBarService is
2972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // removing all existing infobars, thus calling back to Observe(). In this
298558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // case the service still exists, and is supplied as the source of the
299558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // notification we observed, but is no longer accessible from its WebContents.
300558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // In this case we should just go ahead and cancel further infobars for this
301558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // tab instead of trying to access the service.
302558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  //
303558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Similarly, if we're being destroyed, we should also avoid showing further
304558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // infobars.
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InfoBarService* infobar_service = GetInfoBarService(id);
306558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!infobar_service || in_shutdown_) {
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ClearPendingInfobarRequestsForTab(id);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->id().IsForSameTabAs(id) && !i->has_infobar()) {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RegisterForInfoBarNotifications(infobar_service);
315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      i->CreateInfoBar(
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this, profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UnregisterForInfoBarNotifications(infobar_service);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionQueueController::ClearPendingInfobarRequestsForTab(
325a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ) {
3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (i->id().IsForSameTabAs(id)) {
329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      DCHECK(!i->has_infobar());
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = pending_infobar_requests_.erase(i);
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
337a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::RegisterForInfoBarNotifications(
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!registrar_.IsRegistered(
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<InfoBarService>(infobar_service))) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   content::Source<InfoBarService>(infobar_service));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
348a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::UnregisterForInfoBarNotifications(
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (registrar_.IsRegistered(
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<InfoBarService>(infobar_service))) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Remove(this,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      content::Source<InfoBarService>(infobar_service));
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
359a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::UpdateContentSetting(
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& requesting_frame,
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& embedder,
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool allowed) {
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (requesting_frame.GetOrigin().SchemeIsFile()) {
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Chrome can be launched with --disable-web-security which allows
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // geolocation requests from file:// URLs. We don't want to store these
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // in the host content settings map.
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentSetting content_setting =
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ContentSettingsPattern embedder_pattern =
3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      (type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) ?
3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ContentSettingsPattern::Wildcard() :
3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ContentSettingsPattern::FromURLNoWildcard(embedder.GetOrigin());
3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(requesting_frame.GetOrigin()),
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      embedder_pattern,
381a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      type_,
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string(),
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content_setting);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385