Index: chrome/browser/permissions/permission_queue_controller.cc |
diff --git a/chrome/browser/permissions/permission_queue_controller.cc b/chrome/browser/permissions/permission_queue_controller.cc |
deleted file mode 100644 |
index 269e7b20bff15c3a0968157412e782428bc44b81..0000000000000000000000000000000000000000 |
--- a/chrome/browser/permissions/permission_queue_controller.cc |
+++ /dev/null |
@@ -1,418 +0,0 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/permissions/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_factory.h" |
-#include "chrome/browser/geolocation/geolocation_infobar_delegate.h" |
-#include "chrome/browser/infobars/infobar_service.h" |
-#include "chrome/browser/media/midi_permission_infobar_delegate.h" |
-#include "chrome/browser/notifications/notification_permission_infobar_delegate.h" |
-#include "chrome/browser/permissions/permission_context_uma_util.h" |
-#include "chrome/browser/permissions/permission_request_id.h" |
-#include "chrome/browser/profiles/profile.h" |
-#include "chrome/browser/storage/durable_storage_permission_infobar_delegate.h" |
-#include "chrome/browser/tab_contents/tab_util.h" |
-#include "chrome/common/pref_names.h" |
-#include "components/content_settings/core/browser/host_content_settings_map.h" |
-#include "components/content_settings/core/common/content_settings.h" |
-#include "components/infobars/core/infobar.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" |
-#include "content/public/common/url_constants.h" |
- |
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
-#include "chrome/browser/media/protected_media_identifier_infobar_delegate.h" |
-#endif |
- |
-namespace { |
- |
-InfoBarService* GetInfoBarService(const PermissionRequestID& id) { |
- content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( |
- id.render_process_id(), id.render_frame_id()); |
- return web_contents ? InfoBarService::FromWebContents(web_contents) : NULL; |
-} |
- |
-bool ArePermissionRequestsForSameTab( |
- const PermissionRequestID& request, |
- const PermissionRequestID& other_request) { |
- content::WebContents* web_contents = tab_util::GetWebContentsByFrameID( |
- request.render_process_id(), request.render_frame_id()); |
- content::WebContents* other_web_contents = tab_util::GetWebContentsByFrameID( |
- other_request.render_process_id(), other_request.render_frame_id()); |
- |
- return web_contents == other_web_contents; |
-} |
- |
-} // anonymous namespace |
- |
-class PermissionQueueController::PendingInfobarRequest { |
- public: |
- PendingInfobarRequest(ContentSettingsType type, |
- const PermissionRequestID& id, |
- const GURL& requesting_frame, |
- const GURL& embedder, |
- const 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_; } |
- infobars::InfoBar* infobar() { return infobar_; } |
- |
- void RunCallback(ContentSetting content_setting); |
- void CreateInfoBar(PermissionQueueController* controller, |
- const std::string& display_languages); |
- |
- private: |
- ContentSettingsType type_; |
- PermissionRequestID id_; |
- GURL requesting_frame_; |
- GURL embedder_; |
- PermissionDecidedCallback callback_; |
- infobars::InfoBar* infobar_; |
- |
- // Purposefully do not disable copying, as this is stored in STL containers. |
-}; |
- |
-PermissionQueueController::PendingInfobarRequest::PendingInfobarRequest( |
- ContentSettingsType type, |
- const PermissionRequestID& id, |
- const GURL& requesting_frame, |
- const GURL& embedder, |
- const PermissionDecidedCallback& callback) |
- : type_(type), |
- id_(id), |
- requesting_frame_(requesting_frame), |
- embedder_(embedder), |
- 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( |
- ContentSetting content_setting) { |
- callback_.Run(content_setting); |
-} |
- |
-void PermissionQueueController::PendingInfobarRequest::CreateInfoBar( |
- PermissionQueueController* controller, |
- const std::string& display_languages) { |
- // Controller can be Unretained because the lifetime of the infobar |
- // is tied to that of the queue controller. Before QueueController |
- // is destroyed, all requests will be cancelled and so all delegates |
- // will be destroyed. |
- PermissionInfobarDelegate::PermissionSetCallback callback = |
- base::Bind(&PermissionQueueController::OnPermissionSet, |
- base::Unretained(controller), |
- id_, |
- requesting_frame_, |
- embedder_); |
- switch (type_) { |
- case CONTENT_SETTINGS_TYPE_GEOLOCATION: |
- infobar_ = GeolocationInfoBarDelegate::Create( |
- GetInfoBarService(id_), requesting_frame_, |
- display_languages, callback); |
- break; |
-#if defined(ENABLE_NOTIFICATIONS) |
- case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: |
- infobar_ = NotificationPermissionInfobarDelegate::Create( |
- GetInfoBarService(id_), requesting_frame_, |
- display_languages, callback); |
- break; |
-#endif // ENABLE_NOTIFICATIONS |
- case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: |
- infobar_ = MidiPermissionInfoBarDelegate::Create( |
- GetInfoBarService(id_), requesting_frame_, |
- display_languages, type_, callback); |
- break; |
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
- case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: |
- infobar_ = ProtectedMediaIdentifierInfoBarDelegate::Create( |
- GetInfoBarService(id_), requesting_frame_, |
- display_languages, callback); |
- break; |
-#endif |
- case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE: |
- infobar_ = DurableStoragePermissionInfoBarDelegate::Create( |
- GetInfoBarService(id_), requesting_frame_, |
- display_languages, type_, callback); |
- break; |
- default: |
- NOTREACHED(); |
- break; |
- } |
-} |
- |
- |
-PermissionQueueController::PermissionQueueController(Profile* profile, |
- ContentSettingsType type) |
- : profile_(profile), |
- type_(type), |
- in_shutdown_(false) { |
-} |
- |
-PermissionQueueController::~PermissionQueueController() { |
- // Cancel all outstanding requests. |
- 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 PermissionDecidedCallback& callback) { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- |
- if (requesting_frame.SchemeIs(content::kChromeUIScheme) || |
- embedder.SchemeIs(content::kChromeUIScheme)) |
- return; |
- |
- pending_infobar_requests_.push_back(PendingInfobarRequest( |
- type_, id, requesting_frame, embedder, callback)); |
- if (!AlreadyShowingInfoBarForTab(id)) |
- ShowQueuedInfoBarForTab(id); |
-} |
- |
-void PermissionQueueController::CancelInfoBarRequest( |
- const PermissionRequestID& id) { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- |
- for (PendingInfobarRequests::iterator i(pending_infobar_requests_.begin()); |
- i != pending_infobar_requests_.end(); ++i) { |
- if (id != i->id()) |
- continue; |
- |
- InfoBarService* infobar_service = GetInfoBarService(id); |
- if (infobar_service && i->has_infobar()) |
- infobar_service->RemoveInfoBar(i->infobar()); |
- else |
- pending_infobar_requests_.erase(i); |
- return; |
- } |
-} |
- |
-void PermissionQueueController::OnPermissionSet( |
- const PermissionRequestID& id, |
- const GURL& requesting_frame, |
- const GURL& embedder, |
- bool update_content_setting, |
- bool allowed) { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- |
- // TODO(miguelg): move the permission persistence to |
- // PermissionContextBase once all the types are moved there. |
- if (update_content_setting) { |
- UpdateContentSetting(requesting_frame, embedder, allowed); |
- if (allowed) |
- PermissionContextUmaUtil::PermissionGranted(type_, requesting_frame); |
- else |
- PermissionContextUmaUtil::PermissionDenied(type_, requesting_frame); |
- } else { |
- PermissionContextUmaUtil::PermissionDismissed(type_, requesting_frame); |
- } |
- |
- // Cancel this request first, then notify listeners. TODO(pkasting): Why |
- // is this order important? |
- PendingInfobarRequests requests_to_notify; |
- PendingInfobarRequests infobars_to_remove; |
- std::vector<PendingInfobarRequests::iterator> pending_requests_to_remove; |
- for (PendingInfobarRequests::iterator i = pending_infobar_requests_.begin(); |
- i != pending_infobar_requests_.end(); ++i) { |
- if (!i->IsForPair(requesting_frame, embedder)) |
- continue; |
- requests_to_notify.push_back(*i); |
- if (!i->has_infobar()) { |
- // We haven't created an infobar yet, just record the pending request |
- // index and remove it later. |
- pending_requests_to_remove.push_back(i); |
- continue; |
- } |
- if (id == i->id()) { |
- // The infobar that called us is i->infobar(), and its delegate is |
- // currently in either Accept() or Cancel(). This means that |
- // RemoveInfoBar() will be called later on, and that will trigger a |
- // notification we're observing. |
- continue; |
- } |
- |
- // This infobar is for the same frame/embedder pair, but in a different |
- // tab. We should remove it now that we've got an answer for it. |
- infobars_to_remove.push_back(*i); |
- } |
- |
- // Remove all infobars for the same |requesting_frame| and |embedder|. |
- for (PendingInfobarRequests::iterator i = infobars_to_remove.begin(); |
- i != infobars_to_remove.end(); ++i) |
- GetInfoBarService(i->id())->RemoveInfoBar(i->infobar()); |
- |
- // PermissionContextBase needs to know about the new ContentSetting value, |
- // CONTENT_SETTING_DEFAULT being the value for nothing happened. The callers |
- // of ::OnPermissionSet passes { true, true } for allow, { true, false } for |
- // block and { false, * } for dismissed. The tuple being |
- // { update_content_setting, allowed }. |
- ContentSetting content_setting = CONTENT_SETTING_DEFAULT; |
- if (update_content_setting) { |
- content_setting = allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; |
- } |
- |
- // Send out the permission notifications. |
- for (PendingInfobarRequests::iterator i = requests_to_notify.begin(); |
- i != requests_to_notify.end(); ++i) |
- i->RunCallback(content_setting); |
- |
- // Remove the pending requests in reverse order. |
- for (int i = pending_requests_to_remove.size() - 1; i >= 0; --i) |
- pending_infobar_requests_.erase(pending_requests_to_remove[i]); |
-} |
- |
-void PermissionQueueController::Observe( |
- int type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) { |
- DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type); |
- // We will receive this notification for all infobar closures, so we need to |
- // check whether this is the geolocation infobar we're tracking. Note that the |
- // InfoBarContainer (if any) may have received this notification before us and |
- // caused the infobar to be deleted, so it's not safe to dereference the |
- // contents of the infobar. The address of the infobar, however, is OK to |
- // use to find the PendingInfobarRequest to remove because |
- // pending_infobar_requests_ will not have received any new entries between |
- // the NotificationService's call to InfoBarContainer::Observe and this |
- // method. |
- infobars::InfoBar* infobar = |
- content::Details<infobars::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 (ArePermissionRequestsForSameTab(i->id(), id) && i->has_infobar()) |
- return true; |
- } |
- return false; |
-} |
- |
-void PermissionQueueController::ShowQueuedInfoBarForTab( |
- const PermissionRequestID& id) { |
- DCHECK(!AlreadyShowingInfoBarForTab(id)); |
- |
- // We can get here for example during tab shutdown, when the InfoBarService is |
- // removing all existing infobars, thus calling back to Observe(). In this |
- // case the service still exists, and is supplied as the source of the |
- // notification we observed, but is no longer accessible from its WebContents. |
- // In this case we should just go ahead and cancel further infobars for this |
- // tab instead of trying to access the service. |
- // |
- // Similarly, if we're being destroyed, we should also avoid showing further |
- // infobars. |
- 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 (ArePermissionRequestsForSameTab(i->id(), 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 (ArePermissionRequestsForSameTab(i->id(), 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()) { |
- // Chrome can be launched with --disable-web-security which allows |
- // geolocation requests from file:// URLs. We don't want to store these |
- // in the host content settings map. |
- return; |
- } |
- |
- ContentSetting content_setting = |
- allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; |
- |
- ContentSettingsPattern embedder_pattern = |
- (type_ == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) ? |
- ContentSettingsPattern::Wildcard() : |
- ContentSettingsPattern::FromURLNoWildcard(embedder.GetOrigin()); |
- |
- HostContentSettingsMapFactory::GetForProfile(profile_)->SetContentSetting( |
- ContentSettingsPattern::FromURLNoWildcard(requesting_frame.GetOrigin()), |
- embedder_pattern, |
- type_, |
- std::string(), |
- content_setting); |
-} |