permission_queue_controller.cc revision 558790d6acca3451cf3a6b497803a5f07d0bec58
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"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/tab_contents/tab_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/content_settings.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26a3f7b4e666c476898878fa745f637129375cd889Ben MurdochInfoBarService* GetInfoBarService(const PermissionRequestID& id) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WebContents* web_contents =
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_util::GetWebContentsByID(id.render_process_id(), id.render_view_id());
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_contents ? InfoBarService::FromWebContents(web_contents) : NULL;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35a3f7b4e666c476898878fa745f637129375cd889Ben Murdochclass PermissionQueueController::PendingInfoBarRequest {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
37a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  PendingInfoBarRequest(const PermissionRequestID& id,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const GURL& requesting_frame,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const GURL& embedder,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        PermissionDecidedCallback callback);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PendingInfoBarRequest();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsForPair(const GURL& requesting_frame,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const GURL& embedder) const;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  const PermissionRequestID& id() const { return id_; }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& requesting_frame() const { return requesting_frame_; }
48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bool has_infobar() const { return !!infobar_; }
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  InfoBarDelegate* infobar() { return infobar_; }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunCallback(bool allowed);
52a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  void CreateInfoBar(PermissionQueueController* controller,
53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                     const std::string& display_languages);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
56a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  PermissionRequestID id_;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL requesting_frame_;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL embedder_;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionDecidedCallback callback_;
60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  InfoBarDelegate* infobar_;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Purposefully do not disable copying, as this is stored in STL containers.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65a3f7b4e666c476898878fa745f637129375cd889Ben MurdochPermissionQueueController::PendingInfoBarRequest::PendingInfoBarRequest(
66a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PermissionDecidedCallback callback)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : id_(id),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requesting_frame_(requesting_frame),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      embedder_(embedder),
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(callback),
74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      infobar_(NULL) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77a3f7b4e666c476898878fa745f637129375cd889Ben MurdochPermissionQueueController::PendingInfoBarRequest::~PendingInfoBarRequest() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool PermissionQueueController::PendingInfoBarRequest::IsForPair(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder) const {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (requesting_frame_ == requesting_frame) && (embedder_ == embedder);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::PendingInfoBarRequest::RunCallback(
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allowed) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(allowed);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::PendingInfoBarRequest::CreateInfoBar(
92a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    PermissionQueueController* controller,
93a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const std::string& display_languages) {
94a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // TODO(toyoshim): Remove following dependency on geolocation.
95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  infobar_ = GeolocationInfoBarDelegate::Create(
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetInfoBarService(id_), controller, id_, requesting_frame_,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_languages);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPermissionQueueController::PermissionQueueController(Profile* profile,
102558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                                     ContentSettingsType type)
103a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    : profile_(profile),
104558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      type_(type),
105558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      in_shutdown_(false) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
108a3f7b4e666c476898878fa745f637129375cd889Ben MurdochPermissionQueueController::~PermissionQueueController() {
109558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Cancel all outstanding requests.
110558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  in_shutdown_ = true;
111558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  while (!pending_infobar_requests_.empty())
112558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    CancelInfoBarRequest(pending_infobar_requests_.front().id());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::CreateInfoBarRequest(
116a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PermissionDecidedCallback callback) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We shouldn't get duplicate requests.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingInfoBarRequests::const_iterator i(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pending_infobar_requests_.begin());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!i->id().Equals(id));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_infobar_requests_.push_back(PendingInfoBarRequest(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      id, requesting_frame, embedder, callback));
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AlreadyShowingInfoBarForTab(id))
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowQueuedInfoBarForTab(id);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
134a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::CancelInfoBarRequest(
135a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingInfoBarRequests::iterator i(pending_infobar_requests_.begin());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->id().Equals(id)) {
141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (i->has_infobar())
142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        GetInfoBarService(id)->RemoveInfoBar(i->infobar());
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_infobar_requests_.erase(i);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
150a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::OnPermissionSet(
151a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& requesting_frame,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& embedder,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool update_content_setting,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allowed) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (update_content_setting)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateContentSetting(requesting_frame, embedder, allowed);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel this request first, then notify listeners.  TODO(pkasting): Why
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is this order important?
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingInfoBarRequests requests_to_notify;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingInfoBarRequests infobars_to_remove;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->IsForPair(requesting_frame, embedder)) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requests_to_notify.push_back(*i);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i->id().Equals(id)) {
170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // The infobar that called us is i->infobar(), and it's currently in
171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // either Accept() or Cancel(). This means that RemoveInfoBar() will be
172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // called later on, and that will trigger a notification we're
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // observing.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++i;
175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      } else if (i->has_infobar()) {
176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // This infobar is for the same frame/embedder pair, but in a different
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // tab. We should remove it now that we've got an answer for it.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        infobars_to_remove.push_back(*i);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++i;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // We haven't created an infobar yet, just remove the pending request.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i = pending_infobar_requests_.erase(i);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Remove all infobars for the same |requesting_frame| and |embedder|.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingInfoBarRequests::iterator i = infobars_to_remove.begin();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != infobars_to_remove.end(); ++i)
192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    GetInfoBarService(i->id())->RemoveInfoBar(i->infobar());
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send out the permission notifications.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingInfoBarRequests::iterator i = requests_to_notify.begin();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != requests_to_notify.end(); ++i)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->RunCallback(allowed);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
200a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::Observe(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We will receive this notification for all infobar closures, so we need to
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // check whether this is the geolocation infobar we're tracking. Note that the
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // InfoBarContainer (if any) may have received this notification before us and
208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // caused the infobar to be deleted, so it's not safe to dereference the
209ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // contents of the infobar. The address of the infobar, however, is OK to
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use to find the PendingInfoBarRequest to remove because
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending_infobar_requests_ will not have received any new entries between
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the NotificationService's call to InfoBarContainer::Observe and this
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // method.
214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  InfoBarDelegate* infobar =
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<InfoBarRemovedDetails>(details)->first;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->infobar() == infobar) {
219a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      PermissionRequestID id(i->id());
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_infobar_requests_.erase(i);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ShowQueuedInfoBarForTab(id);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
227a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool PermissionQueueController::AlreadyShowingInfoBarForTab(
228a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) const {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingInfoBarRequests::const_iterator i(
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pending_infobar_requests_.begin());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->id().IsForSameTabAs(id) && i->has_infobar())
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
238a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::ShowQueuedInfoBarForTab(
239a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!AlreadyShowingInfoBarForTab(id));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
242558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // We can get here for example during tab shutdown, when the InfoBarService is
243558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // removing all existing infobars, thus calling back to Observe().  In this
244558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // case the service still exists, and is supplied as the source of the
245558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // notification we observed, but is no longer accessible from its WebContents.
246558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // In this case we should just go ahead and cancel further infobars for this
247558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // tab instead of trying to access the service.
248558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  //
249558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Similarly, if we're being destroyed, we should also avoid showing further
250558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // infobars.
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InfoBarService* infobar_service = GetInfoBarService(id);
252558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!infobar_service || in_shutdown_) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearPendingInfoBarRequestsForTab(id);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ++i) {
259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i->id().IsForSameTabAs(id) && !i->has_infobar()) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RegisterForInfoBarNotifications(infobar_service);
261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      i->CreateInfoBar(
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this, profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UnregisterForInfoBarNotifications(infobar_service);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
270a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::ClearPendingInfoBarRequestsForTab(
271a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const PermissionRequestID& id) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != pending_infobar_requests_.end(); ) {
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (i->id().IsForSameTabAs(id)) {
275ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      DCHECK(!i->has_infobar());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = pending_infobar_requests_.erase(i);
2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
283a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::RegisterForInfoBarNotifications(
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!registrar_.IsRegistered(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<InfoBarService>(infobar_service))) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   content::Source<InfoBarService>(infobar_service));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
294a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::UnregisterForInfoBarNotifications(
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (registrar_.IsRegistered(
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<InfoBarService>(infobar_service))) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Remove(this,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      content::Source<InfoBarService>(infobar_service));
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
305a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PermissionQueueController::UpdateContentSetting(
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& requesting_frame,
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& embedder,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool allowed) {
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (requesting_frame.GetOrigin().SchemeIsFile()) {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Chrome can be launched with --disable-web-security which allows
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // geolocation requests from file:// URLs. We don't want to store these
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // in the host content settings map.
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentSetting content_setting =
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(requesting_frame.GetOrigin()),
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(embedder.GetOrigin()),
321a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      type_,
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string(),
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content_setting);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325