permission_queue_controller.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/geolocation/geolocation_infobar_delegate.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/infobars/infobar.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"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/tab_contents/tab_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/content_settings.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_ANDROID)
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/media/protected_media_identifier_infobar_delegate.h"
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30a3f7b4e666c476898878fa745f637129375cd889Ben MurdochInfoBarService* GetInfoBarService(const PermissionRequestID& id) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WebContents* web_contents =
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_util::GetWebContentsByID(id.render_process_id(), id.render_view_id());
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_contents ? InfoBarService::FromWebContents(web_contents) : NULL;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PermissionQueueController::PendingInfobarRequest {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequest(ContentSettingsType type,
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        const PermissionRequestID& id,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const GURL& requesting_frame,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const GURL& embedder,
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        const std::string& accept_button_label,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        PermissionDecidedCallback callback);
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ~PendingInfobarRequest();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsForPair(const GURL& requesting_frame,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const GURL& embedder) const;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  const PermissionRequestID& id() const { return id_; }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& requesting_frame() const { return requesting_frame_; }
54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bool has_infobar() const { return !!infobar_; }
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  InfoBar* infobar() { return infobar_; }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunCallback(bool allowed);
58a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  void CreateInfoBar(PermissionQueueController* controller,
59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                     const std::string& display_languages);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ContentSettingsType type_;
63a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  PermissionRequestID id_;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL requesting_frame_;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL embedder_;
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string accept_button_label_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionDecidedCallback callback_;
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  InfoBar* infobar_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Purposefully do not disable copying, as this is stored in STL containers.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PermissionQueueController::PendingInfobarRequest::PendingInfobarRequest(
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ContentSettingsType type,
75a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& accept_button_label,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PermissionDecidedCallback callback)
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : type_(type),
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      id_(id),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requesting_frame_(requesting_frame),
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      embedder_(embedder),
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      accept_button_label_(accept_button_label),
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)  // TODO(toyoshim): Remove following ContentType dependent code.
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Also these InfoBarDelegate can share much more code each other.
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // http://crbug.com/266743
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_,
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          display_languages);
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_ANDROID)
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      infobar_ = ProtectedMediaIdentifierInfoBarDelegate::Create(
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          GetInfoBarService(id_), controller, id_, requesting_frame_,
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          display_languages);
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    default:
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      NOTREACHED();
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
134558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPermissionQueueController::PermissionQueueController(Profile* profile,
135558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                                     ContentSettingsType type)
136a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    : profile_(profile),
137558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      type_(type),
138558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      in_shutdown_(false) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
141a3f7b4e666c476898878fa745f637129375cd889Ben MurdochPermissionQueueController::~PermissionQueueController() {
142558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Cancel all outstanding requests.
143558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  in_shutdown_ = true;
144558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  while (!pending_infobar_requests_.empty())
145558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    CancelInfoBarRequest(pending_infobar_requests_.front().id());
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
148a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::CreateInfoBarRequest(
149a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& accept_button_label,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PermissionDecidedCallback callback) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We shouldn't get duplicate requests.
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::const_iterator i(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pending_infobar_requests_.begin());
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!i->id().Equals(id));
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pending_infobar_requests_.push_back(PendingInfobarRequest(
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      type_, id, requesting_frame, embedder,
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      accept_button_label, callback));
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AlreadyShowingInfoBarForTab(id))
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowQueuedInfoBarForTab(id);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
169a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::CancelInfoBarRequest(
170a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i(pending_infobar_requests_.begin());
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->id().Equals(id)) {
176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (i->has_infobar())
177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        GetInfoBarService(id)->RemoveInfoBar(i->infobar());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_infobar_requests_.erase(i);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionQueueController::CancelInfoBarRequests(int group_id) {
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If we remove an infobar in the following loop, the next pending infobar
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // will be shown. Therefore, we erase all the pending infobars first and
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // remove an infobar later.
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequests infobar_requests_to_cancel;
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       i != pending_infobar_requests_.end();) {
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (i->id().group_id() == group_id) {
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (i->has_infobar()) {
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // |i| will be erased from |pending_infobar_requests_|
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // in |PermissionQueueController::Observe| when the infobar is removed.
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        infobar_requests_to_cancel.push_back(*i);
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ++i;
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        i = pending_infobar_requests_.erase(i);
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++i;
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = infobar_requests_to_cancel.begin();
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       i != infobar_requests_to_cancel.end();
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ++i) {
211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    GetInfoBarService(i->id())->RemoveInfoBar(i->infobar());
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::OnPermissionSet(
216a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool update_content_setting,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allowed) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (update_content_setting)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateContentSetting(requesting_frame, embedder, allowed);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel this request first, then notify listeners.  TODO(pkasting): Why
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is this order important?
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequests requests_to_notify;
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PendingInfobarRequests infobars_to_remove;
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->IsForPair(requesting_frame, embedder)) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requests_to_notify.push_back(*i);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i->id().Equals(id)) {
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // The infobar that called us is i->infobar(), and its delegate is
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // currently in either Accept() or Cancel(). This means that
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // RemoveInfoBar() will be called later on, and that will trigger a
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // notification we're observing.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++i;
240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      } else if (i->has_infobar()) {
241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // This infobar is for the same frame/embedder pair, but in a different
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // tab. We should remove it now that we've got an answer for it.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        infobars_to_remove.push_back(*i);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++i;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // We haven't created an infobar yet, just remove the pending request.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i = pending_infobar_requests_.erase(i);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Remove all infobars for the same |requesting_frame| and |embedder|.
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = infobars_to_remove.begin();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != infobars_to_remove.end(); ++i)
257a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    GetInfoBarService(i->id())->RemoveInfoBar(i->infobar());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send out the permission notifications.
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = requests_to_notify.begin();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != requests_to_notify.end(); ++i)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->RunCallback(allowed);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::Observe(
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We will receive this notification for all infobar closures, so we need to
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // check whether this is the geolocation infobar we're tracking. Note that the
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // InfoBarContainer (if any) may have received this notification before us and
273ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // caused the infobar to be deleted, so it's not safe to dereference the
274ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // contents of the infobar. The address of the infobar, however, is OK to
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // use to find the PendingInfobarRequest to remove because
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending_infobar_requests_ will not have received any new entries between
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the NotificationService's call to InfoBarContainer::Observe and this
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // method.
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  InfoBar* infobar = content::Details<InfoBar::RemovedDetails>(details)->first;
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->infobar() == infobar) {
283a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      PermissionRequestID id(i->id());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_infobar_requests_.erase(i);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ShowQueuedInfoBarForTab(id);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
291a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool PermissionQueueController::AlreadyShowingInfoBarForTab(
292a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) const {
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::const_iterator i(
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pending_infobar_requests_.begin());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->id().IsForSameTabAs(id) && i->has_infobar())
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
302a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::ShowQueuedInfoBarForTab(
303a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!AlreadyShowingInfoBarForTab(id));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
306558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // We can get here for example during tab shutdown, when the InfoBarService is
3072385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // removing all existing infobars, thus calling back to Observe(). In this
308558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // case the service still exists, and is supplied as the source of the
309558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // notification we observed, but is no longer accessible from its WebContents.
310558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // In this case we should just go ahead and cancel further infobars for this
311558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // tab instead of trying to access the service.
312558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  //
313558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Similarly, if we're being destroyed, we should also avoid showing further
314558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // infobars.
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InfoBarService* infobar_service = GetInfoBarService(id);
316558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!infobar_service || in_shutdown_) {
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ClearPendingInfobarRequestsForTab(id);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->id().IsForSameTabAs(id) && !i->has_infobar()) {
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RegisterForInfoBarNotifications(infobar_service);
325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      i->CreateInfoBar(
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this, profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UnregisterForInfoBarNotifications(infobar_service);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PermissionQueueController::ClearPendingInfobarRequestsForTab(
335a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ) {
3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (i->id().IsForSameTabAs(id)) {
339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      DCHECK(!i->has_infobar());
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = pending_infobar_requests_.erase(i);
3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
347a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::RegisterForInfoBarNotifications(
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!registrar_.IsRegistered(
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<InfoBarService>(infobar_service))) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   content::Source<InfoBarService>(infobar_service));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
358a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::UnregisterForInfoBarNotifications(
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (registrar_.IsRegistered(
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<InfoBarService>(infobar_service))) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Remove(this,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      content::Source<InfoBarService>(infobar_service));
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
369a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::UpdateContentSetting(
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& requesting_frame,
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& embedder,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool allowed) {
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (requesting_frame.GetOrigin().SchemeIsFile()) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Chrome can be launched with --disable-web-security which allows
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // geolocation requests from file:// URLs. We don't want to store these
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // in the host content settings map.
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentSetting content_setting =
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(requesting_frame.GetOrigin()),
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(embedder.GetOrigin()),
385a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      type_,
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string(),
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content_setting);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
389