This source file includes following definitions.
- GetInfoBarService
- id
- requesting_frame
- has_infobar
- infobar
- infobar_
- IsForPair
- RunCallback
- CreateInfoBar
- in_shutdown_
- CreateInfoBarRequest
- CancelInfoBarRequest
- CancelInfoBarRequests
- OnPermissionSet
- Observe
- AlreadyShowingInfoBarForTab
- ShowQueuedInfoBarForTab
- ClearPendingInfobarRequestsForTab
- RegisterForInfoBarNotifications
- UnregisterForInfoBarNotifications
- UpdateContentSetting
#include "chrome/browser/content_settings/permission_queue_controller.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/geolocation/geolocation_infobar_delegate.h"
#include "chrome/browser/infobars/infobar.h"
#include "chrome/browser/infobars/infobar_manager.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/media/midi_permission_infobar_delegate.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/common/content_settings.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#if defined(OS_ANDROID)
#include "chrome/browser/media/protected_media_identifier_infobar_delegate.h"
#endif
namespace {
InfoBarService* GetInfoBarService(const PermissionRequestID& id) {
content::WebContents* web_contents =
tab_util::GetWebContentsByID(id.render_process_id(), id.render_view_id());
return web_contents ? InfoBarService::FromWebContents(web_contents) : NULL;
}
}
class PermissionQueueController::PendingInfobarRequest {
public:
PendingInfobarRequest(ContentSettingsType type,
const PermissionRequestID& id,
const GURL& requesting_frame,
const GURL& embedder,
const std::string& accept_button_label,
PermissionDecidedCallback callback);
~PendingInfobarRequest();
bool IsForPair(const GURL& requesting_frame,
const GURL& embedder) const;
const PermissionRequestID& id() const { return id_; }
const GURL& requesting_frame() const { return requesting_frame_; }
bool has_infobar() const { return !!infobar_; }
InfoBar* infobar() { return infobar_; }
void RunCallback(bool allowed);
void CreateInfoBar(PermissionQueueController* controller,
const std::string& display_languages);
private:
ContentSettingsType type_;
PermissionRequestID id_;
GURL requesting_frame_;
GURL embedder_;
std::string accept_button_label_;
PermissionDecidedCallback callback_;
InfoBar* infobar_;
};
PermissionQueueController::PendingInfobarRequest::PendingInfobarRequest(
ContentSettingsType type,
const PermissionRequestID& id,
const GURL& requesting_frame,
const GURL& embedder,
const std::string& accept_button_label,
PermissionDecidedCallback callback)
: type_(type),
id_(id),
requesting_frame_(requesting_frame),
embedder_(embedder),
accept_button_label_(accept_button_label),
callback_(callback),
infobar_(NULL) {
}
PermissionQueueController::PendingInfobarRequest::~PendingInfobarRequest() {
}
bool PermissionQueueController::PendingInfobarRequest::IsForPair(
const GURL& requesting_frame,
const GURL& embedder) const {
return (requesting_frame_ == requesting_frame) && (embedder_ == embedder);
}
void PermissionQueueController::PendingInfobarRequest::RunCallback(
bool allowed) {
callback_.Run(allowed);
}
void PermissionQueueController::PendingInfobarRequest::CreateInfoBar(
PermissionQueueController* controller,
const std::string& display_languages) {
switch (type_) {
case CONTENT_SETTINGS_TYPE_GEOLOCATION:
infobar_ = GeolocationInfoBarDelegate::Create(
GetInfoBarService(id_), controller, id_, requesting_frame_,
display_languages, accept_button_label_);
break;
case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
infobar_ = MidiPermissionInfoBarDelegate::Create(
GetInfoBarService(id_), controller, id_, requesting_frame_,
display_languages);
break;
#if defined(OS_ANDROID)
case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
infobar_ = ProtectedMediaIdentifierInfoBarDelegate::Create(
GetInfoBarService(id_), controller, id_, requesting_frame_,
display_languages);
break;
#endif
default:
NOTREACHED();
break;
}
}
PermissionQueueController::PermissionQueueController(Profile* profile,
ContentSettingsType type)
: profile_(profile),
type_(type),
in_shutdown_(false) {
}
PermissionQueueController::~PermissionQueueController() {
in_shutdown_ = true;
while (!pending_infobar_requests_.empty())
CancelInfoBarRequest(pending_infobar_requests_.front().id());
}
void PermissionQueueController::CreateInfoBarRequest(
const PermissionRequestID& id,
const GURL& requesting_frame,
const GURL& embedder,
const std::string& accept_button_label,
PermissionDecidedCallback callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
for (PendingInfobarRequests::const_iterator i(
pending_infobar_requests_.begin());
i != pending_infobar_requests_.end(); ++i)
DCHECK(!i->id().Equals(id));
pending_infobar_requests_.push_back(PendingInfobarRequest(
type_, id, requesting_frame, embedder,
accept_button_label, callback));
if (!AlreadyShowingInfoBarForTab(id))
ShowQueuedInfoBarForTab(id);
}
void PermissionQueueController::CancelInfoBarRequest(
const PermissionRequestID& id) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
for (PendingInfobarRequests::iterator i(pending_infobar_requests_.begin());
i != pending_infobar_requests_.end(); ++i) {
if (i->id().Equals(id)) {
if (i->has_infobar())
GetInfoBarService(id)->infobar_manager()->RemoveInfoBar(i->infobar());
else
pending_infobar_requests_.erase(i);
return;
}
}
}
void PermissionQueueController::CancelInfoBarRequests(int group_id) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
PendingInfobarRequests infobar_requests_to_cancel;
for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
i != pending_infobar_requests_.end();) {
if (i->id().group_id() == group_id) {
if (i->has_infobar()) {
infobar_requests_to_cancel.push_back(*i);
++i;
} else {
i = pending_infobar_requests_.erase(i);
}
} else {
++i;
}
}
for (PendingInfobarRequests::iterator i = infobar_requests_to_cancel.begin();
i != infobar_requests_to_cancel.end();
++i) {
GetInfoBarService(i->id())->infobar_manager()->RemoveInfoBar(i->infobar());
}
}
void PermissionQueueController::OnPermissionSet(
const PermissionRequestID& id,
const GURL& requesting_frame,
const GURL& embedder,
bool update_content_setting,
bool allowed) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (update_content_setting)
UpdateContentSetting(requesting_frame, embedder, allowed);
PendingInfobarRequests requests_to_notify;
PendingInfobarRequests infobars_to_remove;
for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
i != pending_infobar_requests_.end(); ) {
if (i->IsForPair(requesting_frame, embedder)) {
requests_to_notify.push_back(*i);
if (i->id().Equals(id)) {
++i;
} else if (i->has_infobar()) {
infobars_to_remove.push_back(*i);
++i;
} else {
i = pending_infobar_requests_.erase(i);
}
} else {
++i;
}
}
for (PendingInfobarRequests::iterator i = infobars_to_remove.begin();
i != infobars_to_remove.end(); ++i)
GetInfoBarService(i->id())->infobar_manager()->RemoveInfoBar(i->infobar());
for (PendingInfobarRequests::iterator i = requests_to_notify.begin();
i != requests_to_notify.end(); ++i)
i->RunCallback(allowed);
}
void PermissionQueueController::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type);
InfoBar* infobar = content::Details<InfoBar::RemovedDetails>(details)->first;
for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
i != pending_infobar_requests_.end(); ++i) {
if (i->infobar() == infobar) {
PermissionRequestID id(i->id());
pending_infobar_requests_.erase(i);
ShowQueuedInfoBarForTab(id);
return;
}
}
}
bool PermissionQueueController::AlreadyShowingInfoBarForTab(
const PermissionRequestID& id) const {
for (PendingInfobarRequests::const_iterator i(
pending_infobar_requests_.begin());
i != pending_infobar_requests_.end(); ++i) {
if (i->id().IsForSameTabAs(id) && i->has_infobar())
return true;
}
return false;
}
void PermissionQueueController::ShowQueuedInfoBarForTab(
const PermissionRequestID& id) {
DCHECK(!AlreadyShowingInfoBarForTab(id));
InfoBarService* infobar_service = GetInfoBarService(id);
if (!infobar_service || in_shutdown_) {
ClearPendingInfobarRequestsForTab(id);
return;
}
for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
i != pending_infobar_requests_.end(); ++i) {
if (i->id().IsForSameTabAs(id) && !i->has_infobar()) {
RegisterForInfoBarNotifications(infobar_service);
i->CreateInfoBar(
this, profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
return;
}
}
UnregisterForInfoBarNotifications(infobar_service);
}
void PermissionQueueController::ClearPendingInfobarRequestsForTab(
const PermissionRequestID& id) {
for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin();
i != pending_infobar_requests_.end(); ) {
if (i->id().IsForSameTabAs(id)) {
DCHECK(!i->has_infobar());
i = pending_infobar_requests_.erase(i);
} else {
++i;
}
}
}
void PermissionQueueController::RegisterForInfoBarNotifications(
InfoBarService* infobar_service) {
if (!registrar_.IsRegistered(
this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
content::Source<InfoBarService>(infobar_service))) {
registrar_.Add(this,
chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
content::Source<InfoBarService>(infobar_service));
}
}
void PermissionQueueController::UnregisterForInfoBarNotifications(
InfoBarService* infobar_service) {
if (registrar_.IsRegistered(
this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
content::Source<InfoBarService>(infobar_service))) {
registrar_.Remove(this,
chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
content::Source<InfoBarService>(infobar_service));
}
}
void PermissionQueueController::UpdateContentSetting(
const GURL& requesting_frame,
const GURL& embedder,
bool allowed) {
if (requesting_frame.GetOrigin().SchemeIsFile()) {
return;
}
ContentSetting content_setting =
allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
profile_->GetHostContentSettingsMap()->SetContentSetting(
ContentSettingsPattern::FromURLNoWildcard(requesting_frame.GetOrigin()),
ContentSettingsPattern::FromURLNoWildcard(embedder.GetOrigin()),
type_,
std::string(),
content_setting);
}