Index: chrome/browser/permissions/permission_infobar_request.cc |
diff --git a/chrome/browser/permissions/permission_infobar_request.cc b/chrome/browser/permissions/permission_infobar_request.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..cc781c35616d8d1a4615ca4bb736d35c9c973525 |
--- /dev/null |
+++ b/chrome/browser/permissions/permission_infobar_request.cc |
@@ -0,0 +1,252 @@ |
+// Copyright 2015 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_infobar_request.h" |
+ |
+#include "base/prefs/pref_service.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_manager.h" |
+#include "chrome/browser/permissions/permission_manager_factory.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/storage/durable_storage_permission_infobar_delegate.h" |
+#include "chrome/common/pref_names.h" |
+#include "components/content_settings/core/browser/host_content_settings_map.h" |
+#include "components/infobars/core/infobar.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/permission_type.h" |
+#include "content/public/browser/web_contents.h" |
+#include "content/public/common/permission_status.mojom.h" |
+ |
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
+#include "chrome/browser/media/protected_media_identifier_infobar_delegate.h" |
+#endif |
+ |
+using content::PermissionStatus; |
+using content::PermissionType; |
+ |
+namespace { |
+ |
+PermissionType ContentSettingsTypeToPermissionType(ContentSettingsType type) { |
+ switch (type) { |
+ case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: |
+ return PermissionType::MIDI_SYSEX; |
+ case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: |
+ return PermissionType::NOTIFICATIONS; |
+ case CONTENT_SETTINGS_TYPE_GEOLOCATION: |
+ return PermissionType::GEOLOCATION; |
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
+ case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: |
+ return PermissionType::PROTECTED_MEDIA_IDENTIFIER; |
+#endif |
+ case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE: |
+ return PermissionType::DURABLE_STORAGE; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ return PermissionType::GEOLOCATION; |
+} |
+ |
+ContentSetting PermissionStatusToContentSetting(PermissionStatus status) { |
+ switch (status) { |
+ case content::PERMISSION_STATUS_GRANTED: |
+ return CONTENT_SETTING_ALLOW; |
+ case content::PERMISSION_STATUS_DENIED: |
+ return CONTENT_SETTING_BLOCK; |
+ case content::PERMISSION_STATUS_ASK: |
+ return CONTENT_SETTING_ASK; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ return CONTENT_SETTING_BLOCK; |
+} |
+ |
+} // anonymous namespace |
+ |
+PermissionInfoBarRequest::PermissionRequest::PermissionRequest( |
+ ContentSettingsType type, |
+ const PermissionDecidedCallback& callback) |
+ : type_(type), |
+ callback_(callback) { |
+} |
+ |
+PermissionInfoBarRequest::PermissionRequest::~PermissionRequest() { |
+} |
+ |
+PermissionInfoBarRequest::PermissionInfoBarRequest( |
+ int request_id, |
+ const GURL& requesting_origin, |
+ const GURL& embedding_origin, |
+ const base::Closure& callback) |
+ : infobar_(nullptr), |
+ request_id_(request_id), |
+ requesting_origin_(requesting_origin), |
+ embedding_origin_(embedding_origin), |
+ callback_(callback), |
+ weak_factory_(this) { |
+} |
+ |
+PermissionInfoBarRequest::~PermissionInfoBarRequest() { |
+} |
+ |
+void PermissionInfoBarRequest::AddPermission( |
+ const ContentSettingsType type, |
+ const PermissionDecidedCallback& callback) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ DCHECK(!infobar_); |
+ |
+ requests_.push_back(PermissionRequest(type, callback)); |
+} |
+ |
+bool PermissionInfoBarRequest::ShowInfobar( |
+ content::WebContents* web_contents) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ DCHECK(!infobar_); |
+ |
+ Profile* profile = |
+ Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
+ DCHECK(profile); |
+ |
+ // After pruning if there is nothing left then just ignore this request. |
+ PruneAnsweredPermissions(profile); |
+ if (requests_.size() == 0) |
+ return false; |
+ |
+ InfoBarService* infobar_service = |
+ InfoBarService::FromWebContents(web_contents); |
+ DCHECK(infobar_service); |
+ |
+ std::string display_languages = |
+ profile->GetPrefs()->GetString(prefs::kAcceptLanguages); |
+ if (requests_.size() == 1) { |
+ CreateInfoBar( |
+ infobar_service, |
+ requests_[0], |
+ display_languages, |
+ base::Bind(&PermissionInfoBarRequest::OnPermissionSet, |
+ weak_factory_.GetWeakPtr())); |
+ return true; |
+ } |
+ |
+ // TODO(lalitm) once multiple permissions is ready to land, this |
+ // should be implemented properly. |
+ NOTIMPLEMENTED(); |
+ for (size_t i = 0; i < requests_.size(); ++i) |
+ requests_[i].callback().Run(false, CONTENT_SETTING_DEFAULT); |
+ return false; |
+} |
+ |
+void PermissionInfoBarRequest::AcceptForTests() { |
+ OnCancel(); |
+ OnPermissionsSet(true, |
+ std::vector<ContentSetting>(requests_.size(), CONTENT_SETTING_ALLOW)); |
+} |
+ |
+void PermissionInfoBarRequest::ClosingForTests() { |
+ OnCancel(); |
+ OnPermissionsSet(false, |
+ std::vector<ContentSetting>(requests_.size(), CONTENT_SETTING_DEFAULT)); |
+} |
+ |
+void PermissionInfoBarRequest::Cancel() { |
+ OnCancel(); |
+ callback_.Run(); |
+} |
+ |
+void PermissionInfoBarRequest::OnCancel() { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ DCHECK(infobar_); |
+ |
+ infobar_->RemoveSelf(); |
+ infobar_ = nullptr; |
+} |
+ |
+void PermissionInfoBarRequest::OnPermissionSet( |
+ bool update_content_setting, |
+ bool allowed) { |
+ OnPermissionsSet(update_content_setting, |
+ std::vector<ContentSetting>(1, |
+ allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK)); |
+} |
+ |
+void PermissionInfoBarRequest::OnPermissionsSet( |
+ bool update_content_setting, |
+ const std::vector<ContentSetting>& result) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ |
+ // Set the infobar to nullptr so there is no attempt to remove it later. |
+ infobar_ = nullptr; |
+ |
+ for (size_t i = 0; i < requests_.size(); ++i) { |
+ if (!update_content_setting) |
+ DCHECK_EQ(CONTENT_SETTING_DEFAULT, result[i]); |
+ requests_[i].callback().Run(update_content_setting, result[i]); |
+ } |
+ callback_.Run(); |
+} |
+ |
+void PermissionInfoBarRequest::PruneAnsweredPermissions( |
+ Profile* profile) { |
+ for (auto it = requests_.begin(); it != requests_.end();) { |
+ PermissionStatus status = PermissionManagerFactory::GetForProfile(profile) |
+ ->GetPermissionStatus( |
+ ContentSettingsTypeToPermissionType(it->type()), |
+ requesting_origin_, |
+ embedding_origin_); |
+ if (status == content::PERMISSION_STATUS_GRANTED || |
+ status == content::PERMISSION_STATUS_DENIED) { |
+ it->callback().Run(true, |
+ PermissionStatusToContentSetting(status)); |
+ it = requests_.erase(it); |
+ } else { |
+ ++it; |
+ } |
+ } |
+} |
+ |
+void PermissionInfoBarRequest::CreateInfoBar( |
+ InfoBarService* infobar_service, |
+ const PermissionRequest& request, |
+ const std::string& display_languages, |
+ const PermissionInfobarDelegate::PermissionSetCallback& callback) { |
+ switch (request.type()) { |
+ case CONTENT_SETTINGS_TYPE_GEOLOCATION: |
+ infobar_ = GeolocationInfoBarDelegate::Create( |
+ infobar_service, requesting_origin_, |
+ display_languages, callback); |
+ break; |
+#if defined(ENABLE_NOTIFICATIONS) |
+ case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: |
+ infobar_ = NotificationPermissionInfobarDelegate::Create( |
+ infobar_service, requesting_origin_, |
+ display_languages, callback); |
+ break; |
+#endif // ENABLE_NOTIFICATIONS |
+ case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: |
+ infobar_ = MidiPermissionInfoBarDelegate::Create( |
+ infobar_service, requesting_origin_, |
+ display_languages, request.type(), callback); |
+ break; |
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
+ case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: |
+ infobar_ = ProtectedMediaIdentifierInfoBarDelegate::Create( |
+ infobar_service, requesting_origin_, |
+ display_languages, callback); |
+ break; |
+#endif |
+ case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE: |
+ infobar_ = DurableStoragePermissionInfoBarDelegate::Create( |
+ infobar_service, requesting_origin_, |
+ display_languages, request.type(), callback); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+} |